Skip to content

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 vertical para 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-session

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

{
"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"
}
}