¿Cómo Conectar Stripe a Django Rest Framework?
Por:
Denisse Abreu
Mar 7, 2022 8pm ET
Eng/Spa 4-min
Hola 🖐🏼, esta es la segunda parte de nuestra guía, ¿Cómo conectar Stripe a una tienda en línea hecha con Vue 2?. En este blog, conectaremos Stripe al servidor; Asumiremos que sabe cómo trabajar con proyectos en Django y Django Rest Framework. Si aún no tienes un proyecto, puedes copiar el mío aquí : Django Shopping Store.
- Comenzamos instalando la libreria de Stripe y Django Rest Framework a través de pip.
Instalar a través de pippip install --upgrade stripe pip install djangorestframework
En el archivo urls dentro de users app, añadimos el url secret, por este url vamos a recibir el Axios request que nos envió Vuex.
users/urlsurlpatterns = [ path("secret/", views.secret) ]
- Importa todas las librerías que necesites.
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
En el siguiente código usamos el decorador @api_view
de Django Rest Framework sobre la función
secret. Extraemos el Stripe API key de settings.py
y dividimos individualmente el diccionario por cada
valor con su llave. Usamos el "list comprehension" para iterar a través de los valores "name" y "qty" que se
encuentran adentro del diccionario cart. El tax_list
cámbialo al de tu estado o país.
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]
En el siguiente código comenzamos a iterar dentro del diccionario cart, extraemos de este diccionario el item_id
y el qty,
Importamos el Product Model y extraemos el producto de la base de datos usando el item_id
. Luego de extraer el
producto de la base de datos, vamos a validar que el inventario de este producto no este en cero; si lo está, salimos de la función
enviando status 409 a la interfaz (Vue js); si todo está bien, multiplicamos el precio del product por la cantidad que escogio el cliente y la
enviamos a la lista de subtotal.
users/viewssubtotal = [] for i in cart: item_id = i.get('itemId') qty = i.get('qty') p = Product.objects.get(pk=item_id) # Valida el inventario de productos 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)
Ahora que tenemos la lista de subtotales, podemos comenzar a hacer cálculos. Comienza importando la libreria Decimal de python. Esta libreria es importante cuando vas a trabajar con valores monetarios. Para enviar el total a Stripe tenemos que convertirlo a un número entero, ya que Stripe no trabaja con decimales.
users/views# cálculo del total tax = round(sum(subtotal) * Decimal(tax_list[0]), 2) total = round(Decimal(sum(subtotal) + tax), 2) stripe_total = int(total*100)
Esta es la última parte de nuestra integración en el servidor. Crea la intención de pago (payment intent) usando el total de la transacción convertido a decimal y la moneda del país en el que te encuentras. Consulta la lista de parámetros que puedes enviar a Stripe aquí: Create a PaymentIntent. Si quieres repasar la conexión con Vuejs puedes hacerlo aquí: ¿Cómo conectar Stripe a una tienda en línea hecha con Vue 2?.
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)
Si desea modificar la intención de pago (payment intent) para agregar más parámetros, use la función de Stripe PaymentIntent.modify()
.
Cree una nueva ruta, envíe el client secret y divídala usando la función de python split()
para obtener solo el número del payment intent.
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)
- Copia el código completo aquí 👇.
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) # Valida el inventario de productos 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) # calcula el total 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)