How To Connect Django to Stripe?

How to Connect Stripe to Django Rest Framework?

Denisse Avatar

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 Vuejs Options API Shopping Store. In this blog, we'll connect Stripe to the "backend" 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.

Install through pip
pip 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/urls
urlpatterns = [ path("secret/", views.secret) ]
  • Import all the necessary libraries.
users/views
import 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 function secret. 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/views
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)

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 Vuejs

users/views
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)

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/views
secret = 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/views
import 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)