How to connect Stripe to Django Rest Framework?
By:
Denisse Abreu
Mar 7, 2022 8pm ET
Eng/Spa 4-min
Hello 🖐🏼, this is the second part of our guide, How to Connect Stripe to a Vue 2 Online Shopping Store?. In this blog, we'll connect Stripe to the server; We'll assume that you know how to work with projects in Django and Django Rest Framework. If you don't have any project, you can fork mine here: Django Shopping Store.
- Start by installing the Stripe library and Django Rest Framework through pip.
Install through pippip install --upgrade stripe pip install djangorestframework
In the urls file inside the users app, add the secret URL; through this URL we are going to receive the Axios request from Vuex.
users/urlsurlpatterns = [ path("secret/", views.secret) ]
- Import all the necessary libraries.
users/viewsimport stripe from decimal import Decimal from django.conf import settings from rest_framework.response import Response from rest_framework.decorators import api_view
In the following code, Use Django Rest Framework @api_view
decorator over the secret()
function.
Extract the Stripe API key from settings.py
and individually get the values of the dictionary.
Use a list comprehension to iterate through the name and qty of the cart dictionary.
Change the tax_list
to your state or country.
users/views@api_view(['POST']) def secret(request, format=None): if request.method == 'POST': stripe.api_key = settings.STRIPE_SECRET user = request.data.get('user') cart = request.data.get('cart') tax_list = [0.115 if user['state'] == 'PR' else 0] items = [c["name"] for c in cart] qty = [c["qty"] for c in cart]
In the following code, Start to iterate inside the cart dictionary; Extract from the dictionary the item_id
and the qty
;
import the Product Model and extract the product from the database using the item_id
key. After accessing the product from the database,
validate that the inventory of this product is not zero; if it is, exit the function and send status 409 to the frontend; if everything is good,
multiply the price of the product by the quantity, and sent it to the subtotal list.
users/viewssubtotal = [] for i in cart: item_id = i.get('itemId') qty = i.get('qty') p = Product.objects.get(pk=item_id) # Validate product inventory if p.inventory == 0: return Response(data={ 'message': 'One of your products is sold out' }, status=status.HTTP_409_CONFLICT) subtotal.append(p.price * qty)
Now that we have the subtotal list, we can start to make calculations. Start by importing the Decimal library from python. This Decimal library is recommended when you are dealing with money. To send the total to Stripe, we have to convert it to a whole number since Stripe does not work with decimals.
users/views# total calculations tax = round(sum(subtotal) * Decimal(tax_list[0]), 2) total = round(Decimal(sum(subtotal) + tax), 2) stripe_total = int(total*100)
This is the last part of our server integration. Create the payment intent using the transaction total converted to decimal and the currency of the country you are in. Checkout the list of parameters that you can send to Stripe here: Create a PaymentIntent. If you want to review the client-side integration do it here: How to Connect Stripe to a Vue 2 Online Shopping Store?
users/viewsintent = stripe.PaymentIntent.create( amount=stripe_total, currency="usd", automatic_payment_methods={"enabled": True}, ) return Response(data={ 'tax': tax, 'client_secret': intent.client_secret }, status=status.HTTP_201_CREATED)
If you want to modify the payment intent to add more parameters, use Stripe's PaymentIntent.modify()
function.
Build a new route, send the client secret, and split it using the python split()
function to get only the payment intent number.
users/viewssecret = request.data.get('client_secret') spl_secret = secret['clientSecret'].split('_') stripe.PaymentIntent.modify( 'pi_'+str(spl_secret[1]), amount=stripe_total, description=description, ) return Response(data={ 'tax': tax, 'client_secret': secret['clientSecret'] }, status=status.HTTP_201_CREATED)
- Copy the complete code here 👇.
users/viewsimport stripe from decimal import Decimal from django.conf import settings from rest_framework.response import Response from rest_framework.decorators import api_view @api_view(['POST']) def secret(request, format=None): if request.method == 'POST': stripe.api_key = settings.STRIPE_SECRET user = request.data.get('user') cart = request.data.get('cart') tax_list = [0.115 if user['state'] == 'PR' else 0] items = [c["name"] for c in cart] qty = [c["qty"] for c in cart] subtotal = [] for i in cart: item_id = i.get('itemId') qty = i.get('qty') p = Product.objects.get(pk=item_id) # Validate product inventory if p.inventory == 0: return Response( data={ 'message': 'One of your products is sold out'}, status=status.HTTP_409_CONFLICT) subtotal.append(p.price * qty) # total calculations tax = round(sum(subtotal) * Decimal(tax_list[0]), 2) total = round(Decimal(sum(subtotal) + tax), 2) stripe_total = int(total*100) intent = stripe.PaymentIntent.create( amount=stripe_total, currency="usd", automatic_payment_methods={"enabled": True}, ) return Response(data={ 'tax': tax, 'client_secret': intent.client_secret }, status=status.HTTP_201_CREATED) return Response(status=status.HTTP_400_BAD_REQUEST)