PayPal Implementation in Django Rest Framework.
Tags: api, webdev, django, python
Published: 2022-10-31 13:59:53

## Introduction.

If you're a Django developer, then you know that Django Rest Framework is a great tool for building RESTful APIs. But what if you want to add PayPal functionality to your Django Rest Framework-based API?

In this blog post, we'll show you how to integrate PayPal into your Django Rest Framework-based project. We'll cover installing the necessary dependencies, setting up your PayPal account, and configuring your Django project to accept payments via PayPal.

By the end of this blog post, you'll have a Django Rest Framework-based API that supports PayPal payments. Let's get started!

### Step 1: Creating a Sandbox Account

First of all, we need a PayPal Sandbox Account, to create a sandbox account visit PayPal Developer website and click Login or Signup if you do not already have an account set up. You can log in with your existing PayPal account.

After signing in to your account click dashboard and select “Create Account”, after that we can create a business and personal PayPal sandbox accounts.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3fm6bu4dsb1abc6403f.png)

Personal Sandbox account is to pay money through PayPal and the business account used for receiving money (which is a merchant account). Select a merchant account this will open a popup window. Click on the API Credentials tab. You’ll see two API keys for the Test.

Copy those API Credentials which you will have a Client_ID and a Client_Secret.

### Step 2: Integrate in Rest Framework

Open up the Django Rest API Framework that you want to implement PayPal checkout.

In your urls.py add this route

```
from django.urls import path, include, re_path
from django_paypal import views

urlpatterns = [
    path('paypal/create/order', views.CreateOrderViewRemote.as_view(), name='ordercreate'),
    path('paypal/capture/order', views.CaptureOrderView.as_view(), name='captureorder')
]
```

The code above creating a url pattern for the CreateOrderViewRemote view, which is used to create an order, and the CaptureOrderView, which is used to capture an order. The capture order API is used to capture an order that has been authorized by a buyer.

In views.py we can create a new viewset class named CreateOrderViewRemote.
To proceed with the payment we have to call 2 URLs

https://api.sandbox.paypal.com/v1/oauth2/token : This link is used to get the token from PayPal, the token which is used to create order request in PayPal.
https://api-m.sandbox.paypal.com/v2/checkout/orders : This link is used to create an order in which we want to make payment.
In the viewset class, let's create a function which we want to generate the authorization token.

```
import json
import base64


def PaypalToken(client_ID, client_Secret):

    url = "https://api.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']
```

We are creating a function called `PaypalToken()` which takes two arguments: client_ID, client_Secret.

The `url` is the Paypal REST API which we will be calling to get the access token.

The `data` is the data we will be sending to Paypal. We are sending the `client_id`, `client_secret`, and the `grant_type` which is `client_credentials`.

The `headers` is the header of the request. We are setting the `Content-Type` and we are sending the `Authorization` header with the `Base64 Encoded` client_ID and client_Secret.

Finally, we are making a `POST` request to the `url` and sending the `data` and `headers` as arguments. The response will be saved to the `token` variable.

The `token` is of type `dict` and has a `json` format. Since we only need the `access_token`, we only select the `access_token` key and we return it.

```
#DON'T FORGET TO REPLACE THE 'XXX' BELOW WITH YOUR KEYS
clientID = 'XXX'
clientSecret = 'XXX'

class CreateOrderViewRemote(APIView):

    def get(self, request):
        token = PaypalToken(clientID, clientSecret)
        headers = {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer '+token,
        }
        json_data = {
             "intent": "CAPTURE",
             "application_context": {
                 "notify_url": "https://pesapedia.co.ke",
                 "return_url": "https://pesapedia.co.ke",#change to your doma$
                 "cancel_url": "https://pesapedia.co.ke", #change to your domain
                 "brand_name": "PESAPEDIA SANDBOX",
                 "landing_page": "BILLING",
                 "shipping_preference": "NO_SHIPPING",
                 "user_action": "CONTINUE"
             },
             "purchase_units": [
                 {
                     "reference_id": "294375635",
                     "description": "African Art and Collectibles",

                     "custom_id": "CUST-AfricanFashion",
                     "soft_descriptor": "AfricanFashions",
                     "amount": {
                         "currency_code": "USD",
                         "value": "200" #amount,
                     },
                 }
             ]
         }
         response = requests.post('https://api-m.sandbox.paypal.com/v2/checkout/orders', headers=headers, json=json_data)
         order_id = response.json()['id']
         linkForPayment = response.json()['links'][1]['href']
         return linkForPayment

class CaptureOrderView(APIView):
    #capture order aims to check whether the user has authorized payments.
    def get(self, request):
        token = request.data.get('token')#the access token we used above for creating an order, or call the function for generating the token
        captureurl = request.data.get('url')#captureurl = 'https://api.sandbox.paypal.com/v2/checkout/orders/6KF61042TG097104C/capture'#see transaction status
        headers = {"Content-Type": "application/json", "Authorization": "Bearer "+token}
        response = requests.post(captureurl, headers=headers)
        return Response(response.json())
```
Note as a result, we will get a response to a set of URLs. The output would look like as follows:

```
{
  "id": "5O190127TN364715T",
  "status": "CREATED",
  "links": [
    {
      "href": "https://api.paypal.com/v2/checkout/orders/5O190127TN364715T",
      "rel": "self",
      "method": "GET"
    },
    {
      "href": "https://www.paypal.com/checkoutnow?token=5O190127TN364715T",
      "rel": "approve",
      "method": "GET"
    },
    {
      "href": "https://api.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",
      "rel": "capture",
      "method": "POST"
    }
  ]
}
```

Pay attention to the link below:

```
{ 
  “href”: “https://www.paypal.com/checkoutnowtoken=5O190127TN364715T", 
“rel”: “approve”, 
“method”: “GET” 
},
```

This is the link that initiates a payment request in PayPal. When visiting this link it would be redirected to your PayPal account and request you to log in. (Remember: Login using personal sandbox account to pay money). After logging in, the amount which we created for the product would be shown and we can proceed with the payment. If the payment is completed it would be redirected to return_url, if the payment canceled it would redirected to cancel_url.

## Conclusion. 

PayPal is one of the most popular payment processors in the world, and implementing it in Django Rest Framework is a breeze. With just a few simple steps, you can have PayPal up and running in your Django project.

Hope you enjoyed!