Integrating Razorpay in a React-Django Application
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. <!--more--> 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.
The process can be broken down into five simple steps as follows:
- A customer selects the item to buy on your website/app.
- The Razorpay instance creates an order in the backend/server.
- You pass the order ID generated by the Razorpay instance, the amount and currency to the checkout method.
- The payment is authenticated by verifying the signature returned by Razorpay when the transaction is successful.
- The payment is confirmed on the Razorpay Dashboard.
Prerequisites
To follow along with this tutorial, the reader will need the following:
- A basic understanding of the Django REST Framework and React.
- Node.js installed on your machine.
- A browser and a code editor.
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.
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: "[email protected]",
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: "[email protected]",
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:
Click on the BUY
button, and a payment modal pops up.
An alert with a Payment Successful
message pops up upon successful transaction.
Payments log
You can view the received payments on the Razorpay dashboard by clicking on Transactions
on the left sidebar.
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