EngEd Community

Section’s Engineering Education (EngEd) Program fosters a community of university students in Computer Science related fields of study to research and share topics that are relevant to engineers in the modern technology landscape. You can find more information and program guidelines in the GitHub repository. If you're currently enrolled in a Computer Science related field of study and are interested in participating in the program, please complete this form .

Integrating Razorpay in a React-Django Application

June 10, 2022

Razorpay is an Indian digital payment API that offers online invoices, payments, and financial management tools. The solution helps buyers worldwide pay for goods and services securely through their websites and mobile applications without worrying about currency conversions or bank charges.

Before integrating the Razorpay payment gateway into your application, you should understand how the payment process flows. Below is a high-level representation of the payment process.

Razorpay Payment Flow

The process can be broken down into five simple steps as follows:

  1. A customer selects the item to buy on your website/app.
  2. The Razorpay instance creates an order in the backend/server.
  3. You pass the order ID generated by the Razorpay instance, the amount and currency to the checkout method.
  4. The payment is authenticated by verifying the signature returned by Razorpay when the transaction is successful.
  5. The payment is confirmed on the Razorpay Dashboard.

Prerequisites

To follow along with this tutorial, the reader will need the following:

Goals of the tutorial

By the end of this tutorial, the reader should be able to:

  • Integrate the Razorpay payment gateway into an application.
  • Work with React and Django REST Framework.
  • Use axios to fetch and post data to an API.

Creating a Razorpay account

Open the Razorpay sign up page and create an account. After providing all the required information, you will be redirected to the dashboard.

Scroll down the left sidebar and select Settings. Then, select API Keys and click on Generate Test Key on the main content page.

Razorpay Dashboard

ClickDownload Key Details to download the Key Id and Key Secret displayed on the modal as they are only displayed once.

Setting up the frontend

Navigate to the directory of your choice, then create a folder named react-django-razorpay. Open this folder in the terminal and run the following command to create a React app named client with yarn.

yarn create-react-app client

Navigate into the client folder and open it in a code editor. The command below works if you have VS Code installed.

code .

Open the integrated terminal and run the command below to install Axios as a dependency. Then, we will use it to make requests to the server.

yarn add axios

Next, open the App.js file and replace the existing code with the below code.

import axios from 'axios';
import { useState, useEffect } from 'react'
import './App.css'
import logo from './logo.svg'

function App() {
    const [productDetails, setProductDetails] = useState()
    const [selectedItemAmount, setSelectedItemAmount] = useState()

    useEffect(() => {
        getProduct()
    }, [])

    const getProduct = () => {
        return axios
        .get(`https://fakestoreapi.com/products/${Math.floor(Math.random() * 10) + 11}`)
        .then((res) => {
            setProductDetails(res.data)
            setSelectedItemAmount((res.data.price * 75.61 * 100).toFixed(2))
        })
        .catch((err) => console.log(err))
    }

  return (
    <div className="App">
    {
      productDetails && (
        <div className="card">
          <img src={productDetails.image} alt="Denim Jeans" />
          <div className='details'>
            <h1>{productDetails.title.substring(0, 20) + "..."}</h1>
            <p className="price">{"₹ " + (productDetails.price * 75.61).toFixed(2)}</p>
            <p>{productDetails.description.substring(0, 70) + "..."}</p>
            <button onClick={displayRazorpay}>BUY</button>
          </div>
        </div>
      )
    }
  </div> 
  );
}

export default App;

We have two states in the code snippet above; first, the ’ productDetails’ state holds the data fetched from the Fake Store API. The second is the selectedItemAmount state that holds the price of the item selected by the user. Then the price is sent to the server to create an order.

We also have the getProduct() function that fetches a random item from the API. Now we can use Axios to make a GET request to the API and save the data returned to the productDetails state.

Fetching a random product is made possible by the Math.floor(Math.random() * 10) + 11 expression that returns a random number between 1 and 20.

The getProduct() function is called once the page reloads. We achieve this using the useEffect() hook. We also use conditional rendering in the JSX to ensure that the product is only displayed if the productDetails state contains the required data.

The price of the items fetched from the API is in USD, so we multiply it by 75.61 to convert it to Indian Rupees. When clicked, the BUY button calls the displayRazorpay() function.

This function is discussed below. Paste the following code outside(on top) of the App() function.

function loadScript(src) {
	return new Promise((resolve) => {
		const script = document.createElement('script')
		script.src = src
		script.onload = () => {
			resolve(true)
		}
		script.onerror = () => {
			resolve(false)
		}
		document.body.appendChild(script)
	})
}

The above code creates and appends a script tag in the body of the HTML document using a JavaScript Promise. This script is the Razorpay checkout script that does all the work behind the scenes. The script src will be passed from the function that calls it.

Paste in the code below under the getProduct() function.

async function displayRazorpay() {
		const res = await loadScript('https://checkout.razorpay.com/v1/checkout.js')

		if (!res) {
			alert('Failure loading the Razorpay SDK. PLease make sure you are connected to the internet')
			return
		}
    
    const orderData = await axios.post('http://127.0.0.1:8000/createOrder/', {
      amount: selectedItemAmount
    })

    const { amount, currency, order_id } = orderData.data

    
		const options = {
            key: "rzp_test_7nUVLAb4PYi83N", // Enter the Key ID generated from the Dashboard
            amount: amount.toString(),
            currency: currency,
            name: "Test Company",
            description: "Test Transaction",
            image: logo,
            order_id: order_id,
            handler: async function (response) {
                const razorpay_paymentId = response.razorpay_payment_id
                const razorpay_orderId = response.razorpay_order_id
                const razorpay_signature = response.razorpay_signature

                const res = await axios.post('http://127.0.0.1:8000/verifySignature/', {
                  razorpay_paymentId,
                  razorpay_orderId,
                  razorpay_signature
                })

                alert(res.data.status)
            },
            prefill: {
                name: "John Doe",
                email: "doejon@example.com",
                contact: "9999999999",
            },
            theme: {
                color: "#61dafb",
            },
        };
		const paymentObject = new window.Razorpay(options)
		paymentObject.open()
	}

The code above is an async function that calls the loadScript() function and passes the Razorpay script src. The function then makes a POST request to a route(http://127.0.0.1:8000/createOrder/) on the server to create an order and also sends the price of the selected product.

This POST request returns the amount, currency, and the order_id. We then create an options object and provide it with all the data required to complete the transaction.

For a successful payment, the check out will return razorpay_payment_id, razorpay_order_id, and razorpay_signature. These values can be accessed inside the handler property in the options object and can be used to verify the transaction in the backend.

In the options object, we include the theme that defines the UI’s color and the prefill to pass user information used in the form.

Your App.js file should have the following code:

import axios from 'axios';
import { useState, useEffect } from 'react'
import './App.css'
import logo from './logo.svg'

function loadScript(src) {
	return new Promise((resolve) => {
		const script = document.createElement('script')
		script.src = src
		script.onload = () => {
			resolve(true)
		}
		script.onerror = () => {
			resolve(false)
		}
		document.body.appendChild(script)
	})
}

function App() {
    const [productDetails, setProductDetails] = useState()
    const [selectedItemAmount, setSelectedItemAmount] = useState()

    useEffect(() => {
        getProduct()
    }, [])

    const getProduct = () => {
        return axios
        .get(`https://fakestoreapi.com/products/${Math.floor(Math.random() * 10) + 11}`)
        .then((res) => {
            setProductDetails(res.data)
            setSelectedItemAmount((res.data.price * 75.61 * 100).toFixed(2))
        })
        .catch((err) => console.log(err))
    }

    async function displayRazorpay() {
		const res = await loadScript('https://checkout.razorpay.com/v1/checkout.js')

		if (!res) {
			alert('Failure loading the Razorpay SDK. PLease make sure you are connected to the internet')
			return
		}
    
    const orderData = await axios.post('http://127.0.0.1:8000/createOrder/', {
      amount: selectedItemAmount
    })

    const { amount, currency, order_id } = orderData.data

    
		const options = {
            key: "<key_id>", // Enter the Key ID generated from the Dashboard
            amount: amount.toString(),
            currency: currency,
            name: "Test Company",
            description: "Test Transaction",
            image: logo,
            order_id: order_id,
            handler: async function (response) {
                const razorpay_paymentId = response.razorpay_payment_id
                const razorpay_orderId = response.razorpay_order_id
                const razorpay_signature = response.razorpay_signature

                const res = await axios.post('http://127.0.0.1:8000/verifySignature/', {
                  razorpay_paymentId,
                  razorpay_orderId,
                  razorpay_signature
                })

                alert(res.data.status)
            },
            prefill: {
                name: "John Doe",
                email: "doejon@example.com",
                contact: "9999999999",
            },
            theme: {
                color: "#61dafb",
            },
        };
		const paymentObject = new window.Razorpay(options)
		paymentObject.open()
	}
  return (
    <div className="App">
    {
      productDetails && (
        <div className="card">
          <img src={productDetails.image} alt="Denim Jeans" />
          <div className='details'>
            <h1>{productDetails.title.substring(0, 20) + "..."}</h1>
            <p className="price">{"₹ " + (productDetails.price * 75.61).toFixed(2)}</p>
            <p>{productDetails.description.substring(0, 70) + "..."}</p>
            <button onClick={displayRazorpay}>BUY</button>
          </div>
        </div>
      )
    }
  </div> 
  );
}

export default App;

Setting up the Server

Open the react-django-razorpay folder we created earlier in the terminal and run the commands below to create a virtual environment and activate it.

python3 -m venv razorpay-env

source ./razorpay-env/bin/activate

With the virtual environment active, run the commands below to install Django, create a new project, and open it in VS Code.

python3 -m pip install django

django-admin startproject server

code server

Then, create a new app that will handle all the frontend API requests using the command below.

django-admin startapp api

Run the commands below to install the dependencies needed in the project.

pip install djangorestframework

python3 -m pip install django-cors-headers

pip install razorpay
  • djangorestframework: will allow you to create an API with the Django framework.
  • django-cors-headers: will allow communication between the React frontend and the Django backend.
  • razorpay: will allow us to perform interactions with the Razorpay API programmatically.

Modifying ‘settings.py’ file

Modify the settings.py file with the code snippets provided below.

For the INSTALLED_APPS:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'api.apps.ApiConfig', #registers the api app
    'rest_framework', #registers the django rest framework as dependency
    'corsheaders' #registers corheaders as dependency
]

For the MIDDLEWARE:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
     "corsheaders.middleware.CorsMiddleware", #to listen in on responses
    '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',
]

To allow the React frontend IP address, add the following code at the bottom of the settings.py file.

CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
    "http://127.0.0.1:3000",
]

Now we can replace the code in the server/urls.py file with the code below to route all the requests to the api app we created.

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

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

Working on the Views

Open the api/views.py file and modify it with the code below.

from django.shortcuts import redirect
from rest_framework.response import Response
from rest_framework.decorators import api_view
import razorpay

# Create your views here.
@api_view(['POST'])
def createOrder(request):
    global client
    data = request.data

    amount = int(float(data['amount']))

    client = razorpay.Client(auth=("<key_id>", "<key_secret>"))

    data = {"amount" : amount, "currency" : "INR"}
    payment = client.order.create(data=data)

    return Response({'order_id': payment['id'], 'amount': payment['amount'], 'currency':payment['currency']})

@api_view(['POST'])
def verifySignature(request):
    res = request.data

    params_dict = {
        'razorpay_payment_id' : res['razorpay_paymentId'],
        'razorpay_order_id' : res['razorpay_orderId'],
        'razorpay_signature' : res['razorpay_signature']
    }

    # verifying the signature
    res = client.utility.verify_payment_signature(params_dict)

    if res == True:
        return Response({'status':'Payment Successful'})
    return Response({'status':'Payment Failed'})

In the code above, we have two views; the createOrder() is used to create an order on the server. In addition, it has a global variable client to create a Razorpay instance.

To create a Razorpay instance, we use razorpay.Client(auth=("<key_id>", "<key_secret>")). Replace the key_id and the key_secret with your key values from the Razorpay dashboard.

To create an order, use client.order.create(data=data) and pass in the data variable that contains the amount of the item selected from the Frontend and the currency used. Then return the order_id, amount, and currency from the order to the Frontend.

The verifySignature() view is used to verify a transaction. After the user makes the payment, the razorpay_payment_id, razorpay_order_id and the razorpay_signature from the transaction are sent to the server to verify the transaction using the client.utility.verify_payment_signature(params_dict) which returns a Boolean. If it returns True, the transaction was successful.

Working on the URLs

Open the api/urls.py file and modify it with the code below, exposing the API endpoints.

from django.urls import path
from . import views

urlpatterns = [
    path('createOrder/', views.createOrder),
    path('verifySignature/', views.verifySignature),
]

Testing the application

To run the Django backend server, navigate to the server directory and run the command below:

python3 manage.py runserver

To run the React frontend, navigate to the client directory and run the command below:

yarn start

This command opens the application on http://localhost:3000/. Open this URL on the browser, and you will be presented with a product as shown below:

test product

Click on the BUY button, and a payment modal pops up.

payment modal

An alert with a Payment Successful message pops up upon successful transaction.

success alert

Payments log

You can view the received payments on the Razorpay dashboard by clicking on Transactions on the left sidebar.

payments

To learn how to use the Razorpay dashboard, click this link.

Conclusion

In this article, we learned how to create a Razorpay account, how to obtain the keys from the dashboard, create an order, verify a signature and check the payment logs. You can implement the Razorpay payment gateway in your React-Django application with this knowledge.

Happy coding!


Peer Review Contributions by: Mercy Meave