Servicio de Checkout con Stripe
Este servicio encapsula toda la lógica necesaria para crear una sesión de pago en Stripe. Se encuentra diseñado para funcionar dentro del entorno de Strapi y se invoca desde el controlador de checkout. Su objetivo es mantener la lógica separada, limpia y reutilizable.
Archivo
Section titled “Archivo”src/api/checkout/services/stripe.ts
Checkout Service
Section titled “Checkout Service”import Stripe from "stripe";import { DNI, LABEL_DNI, TYPE_TEXT, CUSTOM, AUTO, REQUIRED, PAYMENT_SAVE, PAYMENT_FILTERS, FUTURE_USSAGE,} from "../../../constants/structures/collections/checkout";import { selectStripeCrm } from "../../../utils/stripe-crm";import { StripeCrmName } from "../../../type/stripe";
export default () => ({ async createCheckoutSession( customer: Stripe.Customer, payment_method_types: Stripe.Checkout.SessionCreateParams.PaymentMethodType[], line_items: Stripe.Checkout.SessionCreateParams.LineItem[], mode: Stripe.Checkout.SessionCreateParams.Mode, success_url: string, cancel_url: string, payment_intent_data: Stripe.Checkout.SessionCreateParams.PaymentIntentData, validVertical: string, origin: StripeCrmName ): Promise<Stripe.Checkout.Session | undefined> { const stripe = await selectStripeCrm(origin);
try { const checkout = await stripe.checkout.sessions.create({ customer: customer.id, custom_fields: [ { key: DNI, label: { custom: LABEL_DNI, type: CUSTOM, }, type: TYPE_TEXT, }, ],
payment_method_types, line_items, mode, success_url, cancel_url, payment_intent_data, saved_payment_method_options: { payment_method_save: PAYMENT_SAVE, allow_redisplay_filters: PAYMENT_FILTERS, }, payment_method_options: { card: { setup_future_usage: FUTURE_USSAGE, }, }, automatic_tax: { enabled: true }, customer_update: { name: AUTO, address: AUTO }, billing_address_collection: REQUIRED, allow_promotion_codes: true, metadata: { vertical: validVertical }, }); return checkout; } catch (error) { console.error(error); } },});-Este es el servicio que se encarga de crear el checkout como tal
Inicialización de Stripe
Section titled “Inicialización de Stripe”const stripe = await selectStripeCrm(origin);Se inicializa una instancia de Stripe usando una clave secreta definida en las variables de entorno.
Esta clave se extrae usando la función selectStripeCrm y enviando el origin
Exportación por defecto del servicio
Section titled “Exportación por defecto del servicio”export default () => ({ ... })Esta función devuelve un objeto con los métodos disponibles del servicio. Esto permite inyectar o instanciar el servicio según sea necesario.
Método: createCheckoutSession
Section titled “Método: createCheckoutSession”async createCheckoutSession( customer: Stripe.Customer, payment_method_types: Stripe.Checkout.SessionCreateParams.PaymentMethodType[], line_items: Stripe.Checkout.SessionCreateParams.LineItem[], mode: Stripe.Checkout.SessionCreateParams.Mode, success_url: string, cancel_url: string, payment_intent_data: Stripe.Checkout.SessionCreateParams.PaymentIntentData, validVertical: string, origin: StripeCrmName,): Promise<Stripe.Checkout.Session | undefined>Esta función es la encargada de crear la sesión de pago con todos los parámetros necesarios. Está fuertemente tipada usando los tipos del SDK de Stripe.
Parámetros:
Section titled “Parámetros:”- customer: objeto del cliente de Stripe.
- payment_method_types: métodos de pago permitidos (por ejemplo:
['card']). - line_items: productos o servicios a pagar.
- mode: modo de la sesión (
payment,subscription, etc). - success_url: URL a redirigir tras pago exitoso.
- cancel_url: URL si el usuario cancela.
- payment_intent_data: metadatos y configuraciones del intent de pago.
- validVertical: categoría del negocio, como ‘Hospitales’, ‘Veterinarias’, etc.
Lógica interna
Section titled “Lógica interna”1. Creación de la sesión
Section titled “1. Creación de la sesión”const checkout = await stripe.checkout.sessions.create({ customer: customer.id, custom_fields: [ { key: DNI, label: { custom: LABEL_DNI, type: CUSTOM, }, type: TYPE_TEXT, }, ], payment_method_types, line_items, mode, success_url, cancel_url, payment_intent_data, saved_payment_method_options: { payment_method_save: PAYMENT_SAVE, allow_redisplay_filters: PAYMENT_FILTERS, }, payment_method_options: { card: { setup_future_usage: FUTURE_USSAGE, }, }, automatic_tax: { enabled: true }, customer_update: { name: AUTO, address: AUTO }, billing_address_collection: REQUIRED, allow_promotion_codes: true, metadata: { vertical: validVertical },});Explicación detallada:
Section titled “Explicación detallada:”- custom_fields: se agrega un campo adicional para solicitar el DNI, CURP, o similar, según lo requerido por el negocio.
- saved_payment_method_options: permite guardar métodos de pago para uso futuro.
- payment_method_options: configura opciones para tarjetas como el uso “off_session”, es decir que se almacene el metodo de pago para compras automaticas, esto unicamente para compras hechas con “Card”.
- automatic_tax: activa el cálculo automático de impuestos según la ubicación del cliente.
- customer_update: permite a Stripe actualizar automáticamente nombre y dirección del cliente si es necesario.
- billing_address_collection: obliga al usuario a ingresar su dirección de facturación.
- allow_promotion_codes: habilita el uso de cupones.
- metadata: agrega el campo
verticalpara identificar a qué vertical pertenece la transacción.
2. Manejo de errores
Section titled “2. Manejo de errores”} catch (error) { console.error(error);}Cualquier error que ocurra durante la creación de la sesión se captura e imprime en consola. Esto ayuda a depurar errores sin interrumpir por completo el flujo del servidor.
Ejemplo de uso en pruebas
Section titled “Ejemplo de uso en pruebas”A continuación, se muestra un ejemplo de cuerpo (payload) que puedes enviar en una solicitud POST para probar el endpoint de creación de sesión de checkout:
URL del endpoint
Section titled “URL del endpoint”POST http://localhost:1337/api/create-checkout-sessionPayload de ejemplo Alebat
Section titled “Payload de ejemplo Alebat”{ "payment_method_types": ["card", "paypal"], "mode": "payment", "success_url": "https://edificiohospital.alebateducation.com/gracias/?message=purchase", "cancel_url": "https://edificiohospital.alebateducation.com/carrito", "payment_intent_data": {}, "origin": "Alebat", "vertical": "Edificio Hospital", "customer_email": "patricia.puerto@alebateducation.com", "line_items": [ { "price_data": { "currency": "eur", "product": "prod_Ryf8NItzQxisnM", "unit_amount_decimal": 2000 }, "quantity": 1, "adjustable_quantity": { "enabled": false } } ], "metadata": { "laab_fetch": "[{\"id_stripe\":\"prod_QCTeVuDgvAZVer\",\"price\":100,\"discount_percentage\":10,\"SKU\":\"FOR-MA-AR-12\"}]", "vertical": "Edificio Hospital", "origin": "Alebat" }}Payload de ejemplo Inspiria
Section titled “Payload de ejemplo Inspiria”{ "payment_method_types": ["card", "paypal"], "mode": "payment", "success_url": "https://edificiohospital.alebateducation.com/gracias/?message=purchase", "cancel_url": "https://edificiohospital.alebateducation.com/carrito", "payment_intent_data": {}, "origin": "Inspiria", "vertical": "Edificio Hospital", "customer_email": "patricia.puerto@alebateducation.com", "line_items": [ { "price_data": { "currency": "eur", "product": "prod_S0cvoGuLErm7gQ", "unit_amount_decimal": 2000 }, "quantity": 1, "adjustable_quantity": { "enabled": false } } ], "metadata": { "laab_fetch": "[{\"id_stripe\":\"prod_QCTeVuDgvAZVer\",\"price\":100,\"discount_percentage\":10,\"SKU\":\"FOR-MA-AR-12\"}]", "vertical": "Edificio Hospital", "origin": "Inspiria" }}