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
src/api/checkout/services/stripe.ts
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
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
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
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:
- 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
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:
- 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
} 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
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
POST http://localhost:1337/api/create-checkout-sessionPayload 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
{ "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" }}