Skip to content

Stripe

Stripe usa Checkout Sessions: el usuario paga en la página hospedada de Stripe y la fuente de verdad es el webhook, nunca el redirect de vuelta.

Configuración

ts
import { StripeGateway } from '@kaizen/payments-gateway'

StripeGateway.register({
  secret_key: process.env.STRIPE_SECRET_KEY!,        // sk_test_… / sk_live_…
  webhook_secret: process.env.STRIPE_WEBHOOK_SECRET!, // whsec_…
})
CampoTipoDescripción
secret_keystringClave secreta de la API de Stripe
webhook_secretstringSecreto del endpoint de webhook, para verificar la firma

Variables de entorno

Los valores los aportas tú desde tu propio entorno y se los pasas a StripeGateway.register():

ini
STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxx
VariableCampoDescripción
STRIPE_SECRET_KEYsecret_keyClave secreta de la API (sk_test_… / sk_live_…)
STRIPE_WEBHOOK_SECRETwebhook_secretSecreto del endpoint de webhook (whsec_…) para verificar la firma

Crear un cobro

bash
curl -X POST http://localhost:3000/payments/charge \
  -H 'content-type: application/json' \
  -d '{
    "gateway": "stripe",
    "amount": 4900,
    "currency": "eur",
    "reference": "pedido-001",
    "redirect": {
      "success_url": "http://localhost:3000/ok",
      "cancel_url": "http://localhost:3000/ko"
    }
  }'
  • amount va en la unidad mínima de la moneda (4900 = 49,00 €).
  • redirect.success_url / cancel_url viajan por pago (en el body), no en la config.
  • La respuesta trae un redirect_url (el Checkout de Stripe): manda ahí al usuario.

La respuesta tiene el mismo formato que el resto de pasarelas:

json
{
  "payment_id": "b9c1…",
  "gateway": "stripe",
  "status": "pending",
  "redirect_url": "https://checkout.stripe.com/c/pay/…"
}

Flujo end-to-end en local (Stripe CLI)

  1. Levanta tu consumidor (pnpm start).

  2. Abre el túnel del Stripe CLI y copia el whsec_… que imprime a STRIPE_WEBHOOK_SECRET; reinicia para que lo tome:

    bash
    stripe listen --events checkout.session.completed \
      --forward-to localhost:3000/webhooks/stripe

    TIP

    --events filtra a lo único que manejamos. Sin él, el CLI reenvía todos los eventos y el gateway responde 400 a los que no soporta.

  3. Crea un pago (el curl de arriba) y abre el redirect_url.

  4. Paga con la tarjeta de prueba 4242 4242 4242 4242, fecha futura y CVC cualquiera.

  5. Stripe dispara checkout.session.completed → el CLI lo reenvía → el gateway verifica la firma sobre el rawBody, el core casa el Payment por gateway_ref (= session.id), lo pasa a captured y emite payment.captured.

  6. Reenviar el mismo evento no re-procesa: la idempotencia por (gateway, event_id) responde 200.

Notas de la integración

  • client_reference_id lleva tu reference dentro de Stripe; gateway_ref es el session.id, que es lo que casa el webhook con el Payment.
  • createPayment manda una Idempotency-Key (tu reference), así los reintentos no crean sesiones de Checkout duplicadas.
  • La firma se verifica siempre con stripe.webhooks.constructEvent sobre el body crudo. Firma inválida → 400.