Skip to content

Webhooks y eventos

El webhook es la fuente de verdad de un pago. El redirect de vuelta del navegador no confirma nada: solo la notificación firmada de la pasarela cambia el estado del Payment.

Ruta

POST /webhooks/:gateway

El :gateway identifica la pasarela (stripe, redsys, paypal). El core enruta la petición al gateway correspondiente y llama a su parseWebhook.

Qué hace la librería al recibir un webhook

  1. Verifica la firma sobre el rawBody (por eso necesitas rawBody: true). Firma inválida → 400.
  2. Traduce la notificación a un WebhookEvent genérico (captured / failed).
  3. Casa el evento con el Payment por su gateway_ref.
  4. Impone idempotencia por (gateway, event_id): reenviar el mismo evento responde 200 sin re-procesar.
  5. Emite el evento de dominio correspondiente.

Eventos de dominio

Escúchalos con @OnEvent de @nestjs/event-emitter:

ts
import { OnEvent } from '@nestjs/event-emitter'
import { PaymentEventPayload, PAYMENT_EVENTS } from '@kaizen/payments-gateway'

@Injectable()
export class MiListener {
  @OnEvent('payment.captured')
  onCaptured(p: PaymentEventPayload) { /* pago confirmado */ }

  @OnEvent('payment.failed')
  onFailed(p: PaymentEventPayload) { /* pago rechazado */ }
}

Estados de un pago

Un Payment recorre estos estados (PaymentStatus):

EstadoSignificado
pendingCreado; esperando que el usuario complete el pago
authorizedAutorizado pero no capturado
capturedCobrado con éxito (evento payment.captured)
failedRechazado o fallido (evento payment.failed)

Cómo llevas al usuario a pagar

Sea cual sea la pasarela, POST /payments/charge te devuelve siempre el mismo formato y tú siempre haces lo mismo: redirigir el navegador al redirect_url.

json
{
  "payment_id": "b9c1…",
  "gateway": "stripe",
  "status": "pending",
  "redirect_url": "https://…"
}

Lo que hay detrás de ese redirect_url cambia según la pasarela, pero eso lo resuelve la librería, no tú:

PasarelaA dónde apunta el redirect_url
StripeAl Checkout hospedado por Stripe
PayPalA la página de aprobación de PayPal
RedsysA una página que sirve la propia librería y que auto-envía el formulario firmado al TPV

En Redsys y PayPal, tras pagar, el navegador vuelve por la librería (que finaliza el cobro) y acaba en tu success_url / cancel_url. Detalles en cada pasarela: Stripe, Redsys y PayPal.