El patrón correcto para webhooks
Procesar webhooks incorrectamente puede resultar en pedidos no procesados, suscripciones no activadas o cobros duplicados. El patrón correcto sigue tres principios: respuesta rápida, idempotencia y procesamiento en background.
Principio 1: Responde en menos de 5 segundos
Los proveedores de webhooks (incluido Stripe) reintentan el envío si no reciben una respuesta 200 OK en tiempo. Responde inmediatamente y procesa en background:
app.post('/webhook', async (req, res) => {
res.sendStatus(200); // Responde inmediatamente
await processEvent(req.body); // Procesa en background
});
Principio 2: Idempotencia
El mismo evento puede llegar más de una vez. Usa el ID del evento como clave de idempotencia:
const eventId = event.id;
const existing = await db.processedEvents.findUnique({ where: { id: eventId } });
if (existing) return; // Ya procesado
Principio 3: Verifica la firma
Nunca proceses un webhook sin verificar que realmente viene de Stripe:
const sig = req.headers['stripe-signature'];
const event = stripe.webhooks.constructEvent(req.body, sig, process.env.WEBHOOK_SECRET);
Cola de reintentos
Para producción, usa una cola (BullMQ, SQS) que reintente automáticamente los eventos fallidos con backoff exponencial.