How to integrate Razorpay payment gateway with Django REST framework and React.Js

How to integrate Razorpay payment gateway with Django REST framework and React.Js

In this article, we are going to see how to integrate Razorpay with Django RF as backend and React.Js as frontend. We will also be seeing how to set up environment variables for our Razorpay API keys.

medium-image1.jpg About Razorpay:

Razorpay is an online payment solution in India allowing businesses to accept, process, and disburse payments with its product suite.

Razorpay gives you access to all payment modes including credit/debit cards, UPI, Netbanking, PayZapp, JioMoney, Ola Money, Airtel Money etc. So if you want to accept payments in India your first preference should be Razorpay.

SETTING UP RAZORPAY ACCOUNT:

If you haven’t created your Razorpay account, go to razorpay.com and Sign Up there.

After creating an account, login to your Razorpay dashboard and go to

Settings -> API keys -> Generate Keys as shown below.

raz1.png

raz2.png

raz3.png

Save Your Keys somewhere locally for future reference.

LETS BUILD APIs USING DJANGO RF:

Create a Django project:

> mkdir razorpay_integration
> cd razorpay_integration
> django-admin startproject razorpay_backend
> cd razorpay_backend
> python manage.py startapp api

Install all the required packages:

> pip install djangorestframework
> pip install razorpay
> pip install django-environ 
> pip install django-cors-headers

create .env, urls.py and serializers.py files in api folder as shown below:

fol1.png

Include api.urls.py in razorpay_backend/urls.py:

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('razorpay/', include("api.urls")),
]

Now let’s setup cors in settings.py to enable the Cross-origin resource sharing mechanism that will allow our frontend to make HTTP requests to our backend, also we have to register our apps in INSTALLED_APPS:

#  ...rest will be same
CORS_ALLOW_ALL_ORIGINS = True

# Allow the origin from where you are sending the request
CORS_ORIGIN_WHITELIST = [
    'http://localhost:3000',
]

# Application definition
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'api',
    'rest_framework',
    'corsheaders',
]

MIDDLEWARE = [
# always keep the cors middleware at the top of MIDDLEWARE
    'corsheaders.middleware.CorsMiddleware',  
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# ...rest will be same

Run initial migrations:

> python manage.py migrate

Create an Order model in api/models.py:

from django.db import models

# Create your models here.

class Order(models.Model):
    order_product = models.CharField(max_length=100)
    order_amount = models.CharField(max_length=25)
    order_payment_id = models.CharField(max_length=100)
    isPaid = models.BooleanField(default=False)
    order_date = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.order_product

Make migrations after creating a model:

> python manage.py makemigrations
> python manage.py migrate
# start the server
> python manage.py runserver

Create serializer class for Order model in api/serializers.py:

from rest_framework import serializers

from .models import Order

class OrderSerializer(serializers.ModelSerializer):
    order_date = serializers.DateTimeField(format="%d %B %Y %I:%M %p")

    class Meta:
        model = Order
        fields = '__all__'
        depth = 2

Register Order model in api/admin.py:

from django.contrib import admin

from .models import Order

admin.site.register(Order)

Setup urls for payment in api/urls.py:

from django.urls import path

from .views import *

urlpatterns = [
    path('pay/', start_payment, name="payment"),
    path('payment/success/', handle_payment_success, name="payment_success")
]

Setup environment variables in api/.env:

PUBLIC_KEY=**your razorpay key ID**
SECRET_KEY=**your razorpay key secret**

Now let’s write our payment logic in api/views.py:

import json

import environ
import razorpay
from rest_framework.decorators import api_view
from rest_framework.response import Response

from .models import Order
from .serializers import OrderSerializer

env = environ.Env()

# you have to create .env file in same folder where you are using environ.Env()
# reading .env file which located in api folder
environ.Env.read_env()


@api_view(['POST'])
def start_payment(request):
    # request.data is coming from frontend
    amount = request.data['amount']
    name = request.data['name']

    # setup razorpay client this is the client to whome user is paying money that's you
    client = razorpay.Client(auth=(env('PUBLIC_KEY'), env('SECRET_KEY')))

    # create razorpay order
    # the amount will come in 'paise' that means if we pass 50 amount will become
    # 0.5 rupees that means 50 paise so we have to convert it in rupees. So, we will 
    # mumtiply it by 100 so it will be 50 rupees.
    payment = client.order.create({"amount": int(amount) * 100, 
                                   "currency": "INR", 
                                   "payment_capture": "1"})

    # we are saving an order with isPaid=False because we've just initialized the order
    # we haven't received the money we will handle the payment succes in next 
    # function
    order = Order.objects.create(order_product=name, 
                                 order_amount=amount, 
                                 order_payment_id=payment['id'])

    serializer = OrderSerializer(order)

    """order response will be 
    {'id': 17, 
    'order_date': '23 January 2021 03:28 PM', 
    'order_product': '**product name from frontend**', 
    'order_amount': '**product amount from frontend**', 
    'order_payment_id': 'order_G3NhfSWWh5UfjQ', # it will be unique everytime
    'isPaid': False}"""

    data = {
        "payment": payment,
        "order": serializer.data
    }
    return Response(data)


@api_view(['POST'])
def handle_payment_success(request):
    # request.data is coming from frontend
    res = json.loads(request.data["response"])

    """res will be:
    {'razorpay_payment_id': 'pay_G3NivgSZLx7I9e', 
    'razorpay_order_id': 'order_G3NhfSWWh5UfjQ', 
    'razorpay_signature': '76b2accbefde6cd2392b5fbf098ebcbd4cb4ef8b78d62aa5cce553b2014993c0'}
    this will come from frontend which we will use to validate and confirm the payment
    """

    ord_id = ""
    raz_pay_id = ""
    raz_signature = ""

    # res.keys() will give us list of keys in res
    for key in res.keys():
        if key == 'razorpay_order_id':
            ord_id = res[key]
        elif key == 'razorpay_payment_id':
            raz_pay_id = res[key]
        elif key == 'razorpay_signature':
            raz_signature = res[key]

    # get order by payment_id which we've created earlier with isPaid=False
    order = Order.objects.get(order_payment_id=ord_id)

    # we will pass this whole data in razorpay client to verify the payment
    data = {
        'razorpay_order_id': ord_id,
        'razorpay_payment_id': raz_pay_id,
        'razorpay_signature': raz_signature
    }

    client = razorpay.Client(auth=(env('PUBLIC_KEY'), env('SECRET_KEY')))

    # checking if the transaction is valid or not by passing above data dictionary in 
    # razorpay client if it is "valid" then check will return None
    check = client.utility.verify_payment_signature(data)

    if check is not None:
        print("Redirect to error url or error page")
        return Response({'error': 'Something went wrong'})

    # if payment is successful that means check is None then we will turn isPaid=True
    order.isPaid = True
    order.save()

    res_data = {
        'message': 'payment successfully received!'
    }

    return Response(res_data)

NOW LETS SETUP OUR REACT.JS FRONTEND:

Create react app:

> npx create-react-app razorpayfrontend
> cd razorpayfrontend
> npm start

Install the required dependencies for our project:

> npm install axios

Add Bootstrap CDN in public/index.html (optional):

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">

Create server.js file in src and add your backend server url as shown below (We are doing this to keep the backend URL centralized throughout the app):

export const server = "http://127.0.0.1:8000";

Create .env file in your project/root directory to store the environment variables:

REACT_APP_PUBLIC_KEY=** your razorpay key id **
REACT_APP_SECRET_KEY=** your razorpay key secret **

Now create a component in src/App.js that will handle the payment logic when the user clicks the “Pay with razorpay” button:

import Axios from "axios";
import React, { useState } from "react";
import "./App.css";
import { server } from "./server";

function App() {
  const [name, setName] = useState("");
  const [amount, setAmount] = useState("");

// this function will handel payment when user submit his/her money
// and it will confim if payment is successfull or not
  const handlePaymentSuccess = async (response) => {
    try {
      let bodyData = new FormData();

      // we will send the response we've got from razorpay to the backend to validate the payment
      bodyData.append("response", JSON.stringify(response));

      await Axios({
        url: `${server}/razorpay/payment/success/`,
        method: "POST",
        data: bodyData,
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
      })
        .then((res) => {
          console.log("Everything is OK!");
          setName("");
          setAmount("");
        })
        .catch((err) => {
          console.log(err);
        });
    } catch (error) {
      console.log(console.error());
    }
  };

  // this will load a script tag which will open up Razorpay payment card to make //transactions
  const loadScript = () => {
    const script = document.createElement("script");
    script.src = "https://checkout.razorpay.com/v1/checkout.js";
    document.body.appendChild(script);
  };

  const showRazorpay = async () => {
    const res = await loadScript();

    let bodyData = new FormData();

    // we will pass the amount and product name to the backend using form data
    bodyData.append("amount", amount.toString());
    bodyData.append("name", name);

    const data = await Axios({
      url: `${server}/razorpay/pay/`,
      method: "POST",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      data: bodyData,
    }).then((res) => {
      return res;
    });

    // in data we will receive an object from the backend with the information about the payment
    //that has been made by the user

    var options = {
      key_id: process.env.REACT_APP_PUBLIC_KEY, // in react your environment variable must start with REACT_APP_
      key_secret: process.env.REACT_APP_SECRET_KEY,
      amount: data.data.payment.amount,
      currency: "INR",
      name: "Org. Name",
      description: "Test teansaction",
      image: "", // add image url
      order_id: data.data.payment.id,
      handler: function (response) {
        // we will handle success by calling handlePaymentSuccess method and
        // will pass the response that we've got from razorpay
        handlePaymentSuccess(response);
      },
      prefill: {
        name: "User's name",
        email: "User's email",
        contact: "User's phone",
      },
      notes: {
        address: "Razorpay Corporate Office",
      },
      theme: {
        color: "#3399cc",
      },
    };

    var rzp1 = new window.Razorpay(options);
    rzp1.open();
  };

  return (
    <div className="container" style={{ marginTop: "20vh" }}>
      <form>
        <h1>Payment page</h1>

        <div className="form-group">
          <label htmlFor="name">Product name</label>
          <input
            type="text"
            className="form-control"
            id="name"
            value={name}
            onChange={(e) => setName(e.target.value)}
          />
        </div>
        <div className="form-group">
          <label htmlFor="exampleInputPassword1">Amount</label>
          <input
            type="text"
            className="form-control"
            id="amount"
            value={amount}
            onChange={(e) => setAmount(e.target.value)}
          />
        </div>
      </form>
      <button onClick={showRazorpay} className="btn btn-primary btn-block">
        Pay with razorpay
      </button>
    </div>
  );
}

export default App;

Now you can accept payments through Razorpay!

DEMO:

NOTE: Replace your Test Key Id and Test Key Secret with Live Key Id and Live Key Secret to accept live payments.

you will get your Live Key Id and Live Key Secret in live mode

If you face any problem during this project, you can go ahead and check out the code on my Github .

click here for Django RF code and click here for React.Js code.

Also, make sure to subscribe our newsletter on blog.learncodeonline.in and never miss any upcoming articles related to programming just like this one.

I hope this post will help you in your journey. Keep learning!

My LinkedIn and GitHub .

Did you find this article valuable?

Support Learn Code Online by becoming a sponsor. Any amount is appreciated!