¿Cómo Conectar Django a Stripe?

¿Cómo Conectar Stripe a Django Rest Framework?

Denisse Avatar

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.

Instalar a través de pip
pip 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/urls
urlpatterns = [ path("secret/", views.secret) ]
  • Importa todas las librerías que necesites.
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

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

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

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/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)
  • Copia el código completo aquí 👇.
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) # 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)