ctx.verify* hace esa verificación en una línea: lee la cabecera de firma, resuelve el secret desde tus secrets y lanza un error si no coincide.
Stripe
index.ts
El
event que recibe tu handler ya es el cuerpo validado con Zod. La plataforma consumió el cuerpo del request para validarlo, así que llamar a request.json() dentro del handler lanza un error — usa el primer parámetro.Proveedores soportados
Stripe además rechaza eventos con más de 5 minutos de antigüedad, lo que impide que alguien reenvíe un evento antiguo capturado.
Otros servicios
Para Twilio, GitHub, Slack o cualquier servicio con firma HMAC-SHA256, usactx.verifyHmac. La cabecera es obligatoria porque no hay un valor por defecto:
Rotar secrets
Durante una rotación, acepta el secret viejo y el nuevo a la vez separándolos por coma:Manejar el fallo
Los verificadores lanzanWebhookVerificationError con un código que indica qué pasó:
Funciones públicas
Los webhooks necesitanconfig.public: true para que el servicio externo pueda llamarlos sin credenciales de Jelou. Esa es justamente la razón por la que la verificación de firma es obligatoria: es el único control de acceso que queda.
Testing
En los tests,createMockContext() deja cada verificador lanzando missing_secret. Para probar el resto del handler, desactiva la verificación:
Funciones públicas
Recibir peticiones sin credenciales de Jelou.
Secrets
Guardar los secrets de cada proveedor.
Ejecuciones diferidas
Agendar un seguimiento al recibir el webhook.
Receptor de webhooks
Ejemplo completo listo para copiar.