Django/Payments/Stripe/
2022-10-17T07:19:50.262848Z
Published on
With Subscriptions, customers make recurring payments for access to a product. Subscriptions require you to retain more information about your customers than one-time purchases do because you need to charge customers in the future.
Stripe account
Stripe package
Python – Stripe ( stripe )
React – Stripe ( npm: @stripe/react-stripe-js )
If you don't have an Stripe account ( Stripe | Payment Processing Platform for the Internet ), please proceed with the signup option, otherwise, log in with your existing credentials.
In the Stripe dashboard click Developers
Then, click API keys, In the API keys section, find the Publishable key and Secret key. Copy them and paste it into a local text file. These Key`s will be used to interact with Stripe
Your Secret key used in backend only . Don't use in frontend
To add subscription in your project , first you need to create a product
In stripe dashboard , click Products > Add a product
On the next page fill the following details (i.e. Name , Pricing model , Price , Billing period )
After filling the details click Save product
To check your products , In Stripe dashboard go to Products.
Click the product which you created in the above step . Yow will find the price id. Copy them and use it in your front end to access the subscription.
Create a django project named stripe_django using the following command.
1django-admin startproject stripe_django
Navigate to the project directory which you have created in the above step and create an app named subscription using the following command.
1cd stripe_django
2python manage.py startapp subscription
The project structure is given below
Install the stripe python package using pip
1pip install --upgrade stripe
Update the django settings.py file with following items.
In INSTALLED_APPS
section add your app name (i.e. subscription)
Append STRIPE_SECRET_KEY
(i.e. from Step 2: Retrieve the Stripe API Keys ) at end of settings.py file to allow django to access stripe.
1#settings.py
2
3INSTALLED_APPS = [
4 .....
5 'subscription'
6]
7.
8.
9.
10
11#stripe
12STRIPE_SECRET_KEY = <YOUR_STRIPE_SECRET_KEY>
A sample settings.py file can be found in the following git repository file.
Navigate to subscription django app directory, and create a CreateSubscription class in views.py.
To access stripe in your class. Import it (i.e. import stripe) and add your API key with stripe( stripe.api_key = <your_stripe_secret_key>
1import stripe
2
3stripe.api_key = settings.STRIPE_SECRET_KEY
4
5class CreateSubscription(APIView):
6 def post(self , request):
7 data = request.data
8 try:
9 checkout_session = stripe.checkout.Session.create(
10 line_items = [
11 {
12 'price' : data['price_id'],
13 'quantity' : 1
14 }
15 ],
16 mode = 'subscription',
17 success_url = FRONTEND_SUBSCRIPTION_SUCCESS_URL +"?session_id={CHECKOUT_SESSION_ID}",
18 cancel_url = FRONTEND_SUBSCRIPTION_CANCEL_URL
19 )
20 return redirect(checkout_session.url , code=303)
21 except Exception as err:
22 raise err
A sample views.py file can be found in the following git repository file.
After creating the class add urls.py file under your subscription django app.
In your core folder navigate to urls.py and add your path with <appname> and <url_filename>(i.e. created in the above step) .Your core urls.py settings like below.
1from django.contrib import admin
2from django.urls import path , include
3
4urlpatterns = [
5 path('admin/', admin.site.urls),
6 path('subscription/', include('<your_app_name>.<url_filename>')),
7]
A sample urls.py(core folder) file can be found in the following git repository file.
Now , In your subscription app urls.py add your path with the class CreateSubscription
1from subscription import views
2from django.urls import path
3from .views import*
4
5
6urlpatterns = [
7 path('create-subscription/' , CreateSubscription.as_view()),
8]
A sample urls.py(subscription) file can be found in the following git repository file.
A webhook is an endpoint on your server that receives requests from Stripe, notifying you about events that happen on your account such as a customer disputing a charge or a successful recurring payment.
Navigate to checkout django app directory, and create a Webhook Class in views.py.
1class WebHook(APIView):
2 def post(self , request):
3 """
4 This API handling the webhook .
5
6 :return: returns event details as json response .
7 """
8 request_data = json.loads(request.body)
9 if webhook_secret:
10 # Retrieve the event by verifying the signature using the raw body and secret if webhook signing is configured.
11 signature = request.META['HTTP_STRIPE_SIGNATURE']
12 try:
13 event = stripe.Webhook.construct_event(
14 payload=request.body,
15 sig_header=signature,
16 secret=webhook_secret
17 )
18 data = event['data']
19 except ValueError as err:
20 raise err
21 except stripe.error.SignatureVerificationError as err:
22 raise err
23 # Get the type of webhook event sent - used to check the status of PaymentIntents.
24 event_type = event['type']
25 else:
26 data = request_data['data']
27 event_type = request_data['type']
28 data_object = data['object']
29
30 if event_type == 'checkout.session.completed':
31 # Payment is successful and the subscription is created.
32 # You should provision the subscription and save the customer ID to your database.
33 print("-----checkout.session.completed----->",data['object']['customer'])
34 elif event_type == 'invoice.paid':
35 # Continue to provision the subscription as payments continue to be made.
36 # Store the status in your database and check when a user accesses your service.
37 # This approach helps you avoid hitting rate limits.
38 print("-----invoice.paid----->", data)
39 elif event_type == 'invoice.payment_failed':
40 # The payment failed or the customer does not have a valid payment method.
41 # The subscription becomes past_due. Notify your customer and send them to the
42 # customer portal to update their payment information.
43 print("-----invoice.payment_failed----->",data)
44 else:
45 print('Unhandled event type {}'.format(event_type))
46
47 return JsonResponse(success=True, safe=False)
A sample views.py file can be found in the following git repository file.
Now , In your checkout app urls.py add your path with the class WebHook
1from subscription import views
2from django.urls import path
3from .views import*
4
5urlpatterns = [
6 path('create-subscription/' , CreateSubscription.as_view()),
7 path('webhook-test/' , WebHook.as_view()) ,
8]
A sample urls.py(subscription) file can be found in the following git repository file.
In stripe dashboard click Developers > Webhooks > Test in a local environment
After clicking Test in local environment button, the following screen will appear, which will explain the steps needs to connect the django with stripe webhook.
Follow the instructions mentioned in above screen.
Click the Download CLI from the above screen, Download the CLI. unzip it and run the executable file (i.e. In my case its windows system, therefore I am gonna run stripe.exe file)
Navigate to the CLI tool installation directory(i.e. stripe.exe file location)
Open the Windows Command prompt and proceed with the following steps
Log in Stripe account using the below command
1stripe login
You will get a pairing code like below , press Enter
After press Enter , It will redirect to stripe and ask to Verify that the pairing code screen like below. click Allow access
After clicking Allow access . you will get a screen like below
Forward events to your webhook
1stripe listen --forward-to localhost:8000/<your_webhook_api_url>
2
3For example:
4stripe listen --forward-to localhost:8000/webhook-test/
After executing above command, webhook signing secret is generated. ( for example <whsec_15441... >). Copy them and paste it in a text file. This key used to handle the webhook.
Also add your webhook signing secret in settings.py file.
1#stripe
2STRIPE_SECRET_KEY = <YOUR_STRIPE_SECRET_KEY>
3STRIPE_WEBHOOK_SECRET = <YOUR_WEBHOOK_SECRET>
A sample settings.py file can be found in the following git repository file.
Trigger events with the CLI
1stripe trigger payment_intent.succeeded
After completing the steps . Click Done
Complete Django example in the following github repo.
Run the following command to create a React project.
1npx create-react-app stripe_react
Navigate to the created project directory
1cd stripe_react
Add a .env file and add your Stripe Publishable key
1REACT_APP_STRIPE_KEY=pk_test_<YOUR_PUBSHICHABLE_KEY>
A sample .env file can be found in the following git repository file.
Create a Config folder under src . After, under the Config folder create config.js file . This file can connect with the backend.
1export const API_URL = process.env.REACT_APP_API_URL || 'http://localhost:8000'
2export const REACT_APP_STRIPE_KEY = process.env.REACT_APP_STRIPE_KEY || 'pk_test_<YOUR_PUBSHICHABLE_KEY>'
A sample config.js file can be found in the following git repository file.
Under the src folder create a folder named Component that contains Subscription.js , Success and failure redirect .js files.
Final project structure is given below
In your package.json add the following dependencies
1{
2 "name": "stripe-react",
3 "version": "0.1.0",
4 "private": true,
5 "dependencies": {
6 "@stripe/react-stripe-js": "^1.8.1",
7 "@stripe/stripe-js": "^1.31.0",
8 "@stripe/stripe-react-native": "^0.12.0",
9 ...
10 ...
11 "react-router-dom": "^6.3.0",
12 }
Module not found: Error: Can't resolve '@stripe/stripe-js/pure' – >npm install @stripe/stripe-js
Module not found: Error: Can't resolve 'react-router-dom' – > npm install react-router-dom
In subscription.js add two subscription option (for example , monthly and yearly subscription). These two forms having the hidden input field with price id to get the subscription. In form action add your backend api URL(for example – http://localhost:8000/subscription/create-subscription/ )
Add two buttons monthly and yearly subscription
1import { API_URL } from '../Config/config';
2
3const Subscription = () => {
4 return (
5 <>
6 <h1>Subscription</h1>
7 <div className='subscription'>
8 <div className='starter-div' >
9 <h2>Starter plan</h2>
10 <img className='month-img' src='https://img.freepik.com/free-vector/subscriber-concept-illustration_114360-3453.jpg?t=st=1654685116~exp=1654685716~hmac=b67fdd003003bc4f477b5184b2201a36a5a88ebefc2552ee7f4f723a2acef85f&w=740'></img>
11
12 <form action={`${API_URL}/subscription/create-subscription/`} method="POST">
13 <input type="hidden" name="price_id" value="price_1LaFt5SE9c6We7uyk0J5QRnG" />
14 <button className="btn-month" type="submit" >₹30 / Month</button>
15 </form>
16 </div>
17 <br></br>
18 <div className='premium-div'>
19 <h2>Premium plan</h2>
20 <img className='year-img' src='https://img.freepik.com/free-vector/subscriber-concept-illustration_114360-2949.jpg?t=st=1654651458~exp=1654652058~hmac=fc1ea117f4198608284f1fea2f5af8f4c50f75692b80c711ad5c93793d0f3ab0&w=740'></img>
21 <form action={`${API_URL}/subscription/create-subscription/`} method="POST">
22 <input type="hidden" name="price_id" value="price_1LaFt5SE9c6yk0J5QRnG" />
23 <button className="btn-year" type="submit" >₹350 /Year</button>
24 </form>
25 </div>
26
27 </div>
28 <br>
29 </br>
30 </>
31 );
32}
33
34export default Subscription;
A sample Subscription.js file can be found in the following git repository file.
When you click the button it calls backend api. In backend performs stripe subscription.
After completing your payment you need to redirect based on subscription status. So , you have to add Success.js and Cancel.js
In success.js add some success message like Subscription successful.
1import { API_URL } from '../Config/config';
2
3const Success = () => {
4
5 return (
6 <>
7 <section>
8 <div class="product Box-root">
9
10 <div class="description Box-root">
11 <h3>Your plan Subscribed successful!</h3>
12 </div>
13 </div>
14 </section>
15 </>
16 )
17}
18
19export default Success
In Cancel.js add some failure messages like subscription failed.
1const Cancel = () => {
2 return (
3 <>
4 <section>
5 <p>Subscription Failed . back to pay!</p>
6 </section>
7 </>
8 )
9}
10
11export default Cancel
In App.js add some routing for pages which you created in above steps.
1import './index.css'
2import React from 'react'
3import { Elements } from '@stripe/react-stripe-js'
4import { loadStripe } from "@stripe/stripe-js/pure"
5import Subscription from "./Component/Subscription"
6import Success from './Component/Success'
7import Cancel from './Component/Cancel'
8import { BrowserRouter as Router, Routes, Route } from "react-router-dom"
9import { REACT_APP_STRIPE_KEY } from './Config/config';
10
11const stripe_key = REACT_APP_STRIPE_KEY
12const stripePromise = loadStripe(stripe_key)
13
14function App() {
15 return (
16 <>
17 <Elements stripe={stripePromise} >
18 <Router>
19 <Routes>
20 <Route exact path='subscription/' index element={<Subscription />} />
21 <Route exact path='subscription/success/' element={<Success/>} />
22 <Route exact path='subscription/failed/' element={<Cancel/>} />
23 </Routes>
24 </Router>
25
26 </Elements>
27 </>
28 );
29}
30
31export default App;
loadStripe
– It will load stripe payment pages in React.
run the project using following command.
1npm start
After running the command . It will redirect to the browser ( http://localhost:3000 )
In browser check url – http://localhost:3000/subscription
Click monthly or yearly button , it will redirect to the stripe payment page
Complete React example in the following github repo.
After run both backend and frontend , If we click on the monthly or yearly button, it will redirect to the stripe payment page See the below image:
In Payment page give some testing data and click Subscribe
If payment success it will redirect the success page
Check in your stripe dashboard if subscription created status . In stripe dashboard click Payments > Subscriptions
Comments