DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for PayPal Implementation in Django Rest Framework.
paulsaul621
paulsaul621

Posted on

PayPal Implementation in Django Rest Framework.

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

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')
]
Enter fullscreen mode Exit fullscreen mode

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']
Enter fullscreen mode Exit fullscreen mode

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())
Enter fullscreen mode Exit fullscreen mode

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"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Pay attention to the link below:

{ 
  β€œhref”: β€œhttps://www.paypal.com/checkoutnowtoken=5O190127TN364715T", 
β€œrel”: β€œapprove”, 
β€œmethod”: β€œGET” 
},
Enter fullscreen mode Exit fullscreen mode

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!

Top comments (0)

An Animated Guide to Node.js Event Lop

Node.js doesn’t stop from running other operations because of Libuv, a C++ library responsible for the event loop and asynchronously handling tasks such as network requests, DNS resolution, file system operations, data encryption, etc.

What happens under the hood when Node.js works on tasks such as database queries? We will explore it by following this piece of code step by step.