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.
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.
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:
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!