Paypal Rest API

I’m trying to implement Paypal payment using the rest api. I’m following the tutorial from this article I can get the token from Paypal without a problem. The issue comes when I try to get links back from paypal for my payment. I get a 400 error and Paypal lists other info it should show, but the response I get is just <response [400]>. I can’t find on the paypal site the format for the message. I am running this from localhost. I’ve run the json through verification. I did notice the stack trace shows it in single-quotes. Not sure if this can be an issue.

This is the stack trace

            response = self.handle_exception(exc) …
Local vars
/Users/tim/env/nyc/lib/python3.9/site-packages/rest_framework/views.py, line 469, in handle_exception
            self.raise_uncaught_exception(exc) …
Local vars
/Users/tim/env/nyc/lib/python3.9/site-packages/rest_framework/views.py, line 480, in raise_uncaught_exception
        raise exc …
Local vars
/Users/tim/env/nyc/lib/python3.9/site-packages/rest_framework/views.py, line 506, in dispatch
            response = handler(request, *args, **kwargs) …
Local vars
/Users/tim/websites/nycenv/NebraskaYouthCamp/registration/views.py, line 369, in get
        order_id = response.json()['id'] …
Local vars
Variable	Value
headers	
{'Authorization': 'Bearer '
                  'xxxxxxxxxxxxxxxxxxxxxx',
 'Content-Type': 'application/json'}
json_data	
{'application_context': {'brand_name': 'Nebraska Youth Camp',
                         'cancel_url': 'http://www.nebraskayouthcamp.com',
                         'landing_page': 'BILLING',
                         'return_url': 'http://www.nebraskayouthcamp.com',
                         'shipping_preference': 'NO_SHIPPING',
                         'user_action': 'CONTINUE'},
 'intent': 'CAPTURE',
 'purchase_units': [{'amount': {'currency_code': 'USD', 'value': '200'},
                     'custom_id': 'Camp Session',
                     'description': 'Summer Camp',
                     'reference_id': '294375635',
                     'soft_descriptor': 'Camp Session'}]}
request	
<rest_framework.request.Request: GET '/registration/paypal/create/order'>
response	
<Response [400]>
self	
<registration.views.CreateOrderViewRemote object at 0x1048d2700>
token	
'xxxxxxxxxxxxxxxx'
url	
'https://api-m.sandbox.paypal.com/v2/checkout/orders'

and the code

def PaypalToken(client_ID, client_Secret):

    url = "https://api-m.sandbox.paypal.com/v1/oauth2/token"

    data = {
                "client_id":client_ID,
                "client_secret":client_Secret,
                "grant_type":"client_credentials"
            }
    headers = {
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Basic {0}".format(base64.b64encode((client_ID + ":" + client_Secret).encode()).decode())
            }

    token = requests.post(url, data, headers=headers)
    return token.json()['access_token']

class CreateOrderViewRemote(APIView):
    def get(self, request):
        url = "https://api-m.sandbox.paypal.com/v2/checkout/orders"
        token = PaypalToken(clientID, clientSecret)
        headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer "+token
        }
        json_data = {
             "intent":"CAPTURE",
             "application_context": {
                 "return_url": "http://www.nebraskayouthcamp.com",
                 "cancel_url": "http://www.nebraskayouthcamp.com",
                 "brand_name": "Nebraska Youth Camp",
                 "landing_page": "BILLING",
                 "shipping_preference": "NO_SHIPPING",
                 "user_action": "CONTINUE"
             },
             "purchase_units": [
                 {
                     "reference_id": "294375635",
                     "description": "Summer Camp",
                     "custom_id": "Camp Session",
                     "soft_descriptor": "Camp Session",
                     "amount": {
                         "currency_code": "USD",
                         "value": "200"
                     }
                 }
             ]
         }
        response = requests.post(url, json_data, headers=headers)
        print("json response " + str(response))
        order_id = response.json()['id']
        linkForPayment = response.json()['links'][1]['href']
        return linkForPayment

Thanks for your help.

You should print either the response.text or response.json() to see what’s actually returned from their side

1 Like

That’s helpful, thanks. Unfortunately it didn’t get me any further. I’ve used curl like they show on their example page and it works fine. So something is amiss between the the post and when paypal gets it.

The dictionary item with the json needs to be converted to a json object using json.dumps(json_data)

When you receive a 400 status code, normally they give some advice on what’s wrong.
One thing that can be the cause is this line.

You need to pass json_data as a keyword argument named json. This will make requests properly handle the payload and transform it into json. If you pass the argument positionally that will go to the data parameter of the request, and that can be converted to some sort of form-data. So in the end you can try this:

response = requests.post(url, json=json_data, headers=headers)