Django/Payments/Razorpay/Subscription/
2022-10-17T07:13:58.381366Z
Published on
Razorpay is one of the modern payment gateways widely used in India. It is more reliable than its compitors. Also, it is developer-friendly and easy to integrate with any technology stack. Also, they provide so many modes of payment like UPI, Debit cards, Credit cards, Internet banking and digital wallets and QR scanner code.
With the help of Razorpay subscription API, we can integrate a regular subscription payment model to Sass or product-based applications.
How it works (Sequence diagram) :
Razorpay public and private keys ( How to get Razorpay public and private keys? )
Basic Django project setup
Basic React.js project setup
In this tutorial the payments are done in Test mode, not in production mode.
The source code for both Django and react are given here: https://github.com/episyche/razorpay_subscription_django_reactjs_example
Setup instructions for Django and React.js are given in the GitHub Readme file.
API keys are a unique identification number used to link your Razorpay account with any development platform like Python, Java, Ruby, Node.js etc.
If you don’t have a Razorpay account click here (How to create a Razorpay account ?)
If you don’t have Razorpay API Keys click here (How to generate Razorpay API keys ?)
Go to the subscription section
Select Plans Tab.
Click on New Plan Button.
In the Popup window :
Enter the Plan name. (for eg: Monthly Membership)
Plan Description for internal use
Enter the Billing Frequency of the plan. ( for eg: every 1st of a month )
Enter the plan price (Billing Amount). ( for eg: ₹ 30 )
After the Successful creation of the plan, copy the plan id for payment integration purposes. The plan id is the unique identification number.
Using the plan Id we decide to activate monthly or yearly subscriptions.
Create an empty folder with the project name.
1mkdir <project-name>
2cd <project-name>
3
4For example:
5mkdir backend
6cd backend
Inside the folder backend (project-folder) create the Django project.
1django-admin startproject core .
a. core: main app name.
b. (.) the dot symbol at the end indicates not to create a new folder. Generate files on the working directory.
c. Once the files are generated, It will be looking like the below screenshot example.
Create a Django app for handling payment logic. The name of the app is “payment_razorpay”.
1cd /<project-folder>
2
3for example :
4cd /backend
1python3 manage.py startapp payment_razorpay
a. After executing the above command an app named “payment_razorpay” will be created. An example screenshot is given below:
Add the payment_razorpay app to the INSTALLED_APPS
list in settings.py
backend/core/settings.py (<project-folder>/core/settings.py)
1
2INSTALLED_APPS = [
3 'django.contrib.admin',
4 'django.contrib.auth',
5 'django.contrib.contenttypes',
6 'django.contrib.sessions',
7 'django.contrib.messages',
8 'django.contrib.staticfiles',
9 'payment_razorpay', # <<< newly added line
10]
Sample code for the above use case can be found in the following GitHub URL.
Add a new URL path for the payment_razorpay
app, to the base app ( main app ) urls.py file.
backend/core/urls.py (<project-folder/core/urls.py)
1from django.contrib import admin
2from django.urls import path, include # <<< newly added line
3
4urlpatterns = [
5 path('admin/', admin.site.urls),
6 path('payment/', include('payment_razorpay.urls')), # <<< newly added line
7]
Sample code for the above use case can be found in the following GitHub URL.
Create a new urls.py file under the payment_razorpay app that we just created.
Install Razorpay SDK using pip
1pip install razorpay
Create a new function API “create_subscription” under the payment_razorpay app to handle new subscription requests.
<project_folder> payment_razorpay > views.py > create_subscription (function API)
backend > payment_razorpay > views.py > create_subscription (function API)
1
2@csrf_exempt
3def create_subscription(request):
4 if request.method == "POST":
5
6 amount = int(request.POST['price'])
7 product_name = request.POST['product_name']
8 plan_id = request.POST['plan_id']
9
10 razorpay_subscription_res = razorpay_client.subscription.create({
11 'plan_id': plan_id,
12 'total_count': 30,
13 'addons': [{
14 'item': {
15 'name': product_name,
16 'currency': 'INR',
17 "amount": int(amount) * 100,
18 }
19 }],
20 })
21
22 response_data = {
23 "callback_url": "http://127.0.0.1:8000/payment/callback",
24 "razorpay_key": "rzp_test_XjxJeSspeBN1S6",
25 "order": razorpay_subscription_res,
26 "product_name": product_name
27 }
28
29 print(response_data)
30
31 return JsonResponse(response_data)
Sample code for the above use case can be found in the following GitHub URL.
To handle the response from Razorpay payment gateway create a new function API named “subscription_callback“.
After successful payment, Razorpay sends payment-related information to a backend API that we specified in the callback URL. Using the data we get from Razorpay we can verify the payment status and write business logic according to the payment status.
The data we get from Razorpay is given below:
1{
2 "razorpay_payment_id": "pay_29QQoUBi66xm2f",
3 "razorpay_subscription_id": "sub_KC6omw8UVrX72h",
4 "razorpay_signature": "9ef4dffbfd84f1318f6739a3ce19f9d85851857ae648f114332d8401e0949a3d"
5}
1@csrf_exempt
2def subscription_callback(request):
3 if request.method == "POST":
4 if "razorpay_signature" in request.POST:
5 payment_verification = razorpay_client.utility.verify_payment_signature(request.POST)
6 if payment_verification:
7 return JsonResponse({"res":"Subscription is now active"})
8 # Logic to perform is payment is successful
9 # Activate logic
10 else:
11 return JsonResponse({"res":"failed"})
12 # Logic to perform is payment is unsuccessful
Sample code for the above use case can be found in the following GitHub URL.
Set up CROS in Django, In order to avoid CROS problems between the frontend(React.js) and backend (Django).
pip install
1pip install django-cors-headers
Add CROS to MIDDLEWARE in settings.py
backend<project-name>/ core / settings.py
1MIDDLEWARE = [
2 'django.middleware.security.SecurityMiddleware',
3 'django.contrib.sessions.middleware.SessionMiddleware',
4 'django.middleware.common.CommonMiddleware',
5 'django.middleware.csrf.CsrfViewMiddleware',
6 'django.contrib.auth.middleware.AuthenticationMiddleware',
7 'django.contrib.messages.middleware.MessageMiddleware',
8 'django.middleware.clickjacking.XFrameOptionsMiddleware',
9 'corsheaders.middleware.CorsMiddleware', # <<< new line added
10]
Sample code for the above use case can be found in the following GitHub URL.
Add another variable at the end of the setings.py file.
backend<project-name>/ core / settings.py
1CORS_ORIGIN_ALLOW_ALL = True # <<< append to the end of the settings.py
Sample code for the above use case can be found in the following GitHub URL.
In this tutorial, a new component is created “Music_box.jsx”. Here we write the logic to handle the Razorpay subscription payment gateway process.
There is no package available in npm to install for Razorpay. We have to integrate the Razorpay from CDN using useEffect hook. The example code is given below.
1const loadScript = (src) => {
2 return new Promise((resolve) => {
3 const script = document.createElement("script");
4 script.src = src;
5 script.onload = () => {
6 resolve(true);
7 };
8 script.onerror = () => {
9 resolve(false);
10 };
11 document.body.appendChild(script);
12 });
13 };
14
15 useEffect(() => {
16 loadScript("https://checkout.razorpay.com/v1/checkout.js");
17 });
Sample code for the above use case can be found in the following GitHub URL.
In react.js to initialize the Razorpay payment gateway, we need some additional information they are provided from the backend. Here is the list of the information we need :
Razorpay key id
Amount
Product name
currency
callback URL ( Django URL)
subscription_id
From the frontend(react.js) we should send the subscription plan id which is going to be activated.
1import Book1Img from './img/image1.png';
2import { useEffect } from 'react';
3
4export default function Music_box(){
5
6 const loadScript = (src) => {
7 return new Promise((resolve) => {
8 const script = document.createElement("script");
9 script.src = src;
10 script.onload = () => {
11 resolve(true);
12 };
13 script.onerror = () => {
14 resolve(false);
15 };
16 document.body.appendChild(script);
17 });
18 };
19
20 useEffect(() => {
21 loadScript("https://checkout.razorpay.com/v1/checkout.js");
22 });
23
24
25 function makePayment(e, price, product_name, plan_id){
26
27 e.preventDefault();
28
29
30 let formData = new FormData();
31 formData.append('price', price);
32 formData.append('product_name', product_name);
33 formData.append('plan_id', plan_id);
34
35 async function paymentGateway() {
36 const url = 'http://127.0.0.1:8000/payment/new-subscription' // <<< new-subscription backend api url path
37 const res = await fetch(url, { method: 'POST', body: formData ,
38 })
39 const jsonRes = await res.json()
40 return jsonRes
41 }
42
43 paymentGateway().then((res) =>{
44 //_________ call razorpay gateway ________
45 var options = {
46 "key": res['razorpay_key'],
47 "amount": res['order']['amount'],
48 "currency": res['order']['currency'],
49 "callback_url": res['callback_url'],
50 prefill: {
51 "email": "nosob88243@xitudy.com",
52 "contact": "1234567890"
53 },
54 "name": res['product_name'],
55 "subscription_id": res['order']['id'],
56 };
57
58 var rzp1 = new window.Razorpay(options);
59 rzp1.open();
60 })
61
62 }
63
64
65 return(
66 <>
67 <section className='flex justify-center mt-52'>
68 <div className='rounded px-10 py-5 text-center drop-shadow-xl bg-zinc-50'>
69 <h2 className='text-3xl mb-10'>Monthly Subscription</h2>
70 <img className='w-48 mx-auto' src={Book1Img} alt="" />
71 <p className='mt-5 text-lg'>Price : ₹ 30</p>
72 <button type='button' className="mt-2 mb-2 inline-flex items-center px-2.5 py-1.5 border border-transparent text-lg font-medium rounded shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
73 onClick={e=>{makePayment(e, 1, "Monthly Subscription", "plan_KBo1U1fwUwehqK")}}
74 >Proceed to Buy</button>
75 </div>
76 </section>
77 </>
78 )
79
80}import Book1Img from './img/image1.png';
81import { useEffect } from 'react';
82
83export default function Music_box(){
84
85 const loadScript = (src) => {
86 return new Promise((resolve) => {
87 const script = document.createElement("script");
88 script.src = src;
89 script.onload = () => {
90 resolve(true);
91 };
92 script.onerror = () => {
93 resolve(false);
94 };
95 document.body.appendChild(script);
96 });
97 };
98
99 useEffect(() => {
100 loadScript("https://checkout.razorpay.com/v1/checkout.js");
101 });
102
103
104 function makePayment(e, price, product_name, plan_id){
105
106 e.preventDefault();
107
108
109 let formData = new FormData();
110 formData.append('price', price);
111 formData.append('product_name', product_name);
112 formData.append('plan_id', plan_id);
113
114 async function paymentGateway() {
115 const url = 'http://127.0.0.1:8000/payment/new-subscription' // <<< new-subscription backend api url path
116 const res = await fetch(url, { method: 'POST', body: formData ,
117 })
118 const jsonRes = await res.json()
119 return jsonRes
120 }
121
122 paymentGateway().then((res) =>{
123 //_________ call razorpay gateway ________
124 var options = {
125 "key": res['razorpay_key'],
126 "amount": res['order']['amount'],
127 "currency": res['order']['currency'],
128 "callback_url": res['callback_url'],
129 prefill: {
130 "email": "nosob88243@xitudy.com",
131 "contact": "1234567890"
132 },
133 "name": res['product_name'],
134 "subscription_id": res['order']['id'],
135 };
136
137 var rzp1 = new window.Razorpay(options);
138 rzp1.open();
139 })
140
141 }
142
143
144 return(
145 <>
146 <section className='flex justify-center mt-52'>
147 <div className='rounded px-10 py-5 text-center drop-shadow-xl bg-zinc-50'>
148 <h2 className='text-3xl mb-10'>Monthly Subscription</h2>
149 <img className='w-48 mx-auto' src={Book1Img} alt="" />
150 <p className='mt-5 text-lg'>Price : ₹ 30</p>
151 <button type='button' className="mt-2 mb-2 inline-flex items-center px-2.5 py-1.5 border border-transparent text-lg font-medium rounded shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
152 onClick={e=>{makePayment(e, 1, "Monthly Subscription", "plan_KBo1U1fwUwehqK")}}
153 >Proceed to Buy</button>
154 </div>
155 </section>
156 </>
157 )
158
159}
Sample code for the above use case can be found in the following GitHub URL.
To run Django development server:
1cd <project-folder>
2
3for example:
4cd backend
1python3 manage.py runserver
To run React.js development server:
1cd <project-folder>
2
3for example:
4cd frontend
1npm start
Select the subscription plan of your choice.
Select UPI ID as the payment mode.
Enter the following UPI ID provided by Razorpay for Testing purposes. (success@razorpay)
After successful payment, you will get a success message as a response from the backend (Django).
Check subscription status on the Razorpay dashboard.
Comments