Cada webhook de pago necesita tres garantías: autenticidad (la solicitud realmente vino de nosotros), entrega at-least-once (sin eventos perdidos en silencio), e idempotencia (re-entregas no duplican cobros en tu BD).
Autenticidad: cada webhook Baynoy lleva un header X-Baynoy-Signature — sha256(timestamp + '.' + body) con el secreto de tu endpoint. Rechaza si el timestamp es más viejo de 5 minutos (defensa replay) o la firma no compara en tiempo constante. Seguimos el formato exacto de Stripe, así que el middleware de verificación Stripe existente entra sin cambios.
At-least-once: reintentamos con backoff exponencial a 1m, 5m, 30m, 2h, 12h, 24h — con tope de seis intentos. Cada intento escribe una fila en baynoy_webhook_deliveries con el status de respuesta. El botón replay-from-UI en el dashboard pega al mismo pipeline; sin ruta especial.
Idempotencia: cada evento lleva un event.id (UUIDv7 — ordenable, monotónicamente creciente). Persístelo en la primera recepción y rechaza duplicados a nivel BD con un unique constraint. Volveremos a entregar. El constraint es tu red de seguridad.
Tres líneas de middleware y tienes un handler de webhook que sobrevive un outage de 6 horas sin perder una sola notificación de pago.