Backend · Pagos

¿Cómo hacer un webhook de Dodo Payments idempotente?

IndiePack··8 min lectura

Para hacer idempotente un webhook de Dodo Payments en Next.js y Supabase, verifica la firma sobre el cuerpo crudo, procesa solo el evento de pago completado y guarda el identificador del pago con una restricción única. Si llega el mismo evento otra vez, la inserción se ignora y no repites la entrega ni la atribución.

La regla: recibir dos veces debe dejar exactamente el mismo estado que recibir una. El email no es una clave idempotente; una persona puede comprar más de una vez. Usa el identificador del pago.

Índice

  1. ¿Cómo se verifica el evento?
  2. ¿Cuál es la forma rápida con IndiePack?
  3. ¿Cómo se evitan duplicados?
  4. ¿Qué efectos deben separarse?
  5. ¿Cómo se prueba antes de producción?

¿Cómo se verifica el evento antes de tocar la base de datos?

El evento se verifica con el secreto del webhook y las cabeceras de Standard Webhooks sobre el cuerpo crudo de la petición. Si el framework transforma primero el JSON, la firma puede dejar de coincidir; por eso la ruta debe desactivar el parser automático cuando corresponda y leer el stream original.

Una firma inválida termina en una respuesta de error y no ejecuta ninguna escritura. Tras verificar, extrae el tipo de evento, el pago, el cliente y los metadatos. Procesa únicamente el evento que representa un pago conseguido y exige los campos imprescindibles antes de continuar.

¿Cuál es la forma rápida: partir del flujo de IndiePack?

La forma rápida es usar IndiePack, donde Dodo Payments, Supabase y el despliegue en Vercel forman parte del stack documentado. El patrón de webhook firmado e idempotente queda conectado al checkout y a los referidos, en vez de resolverse como un fragmento aislado.

Ver el packConsultar precio

¿Cómo se evitan duplicados en Supabase?

Los duplicados se evitan almacenando el identificador de pago en una columna única y haciendo la inserción con resolución de conflicto. El primer evento crea la fila; cualquier reintento con el mismo identificador no crea otra y, por tanto, tampoco vuelve a disparar automatismos ligados a una inserción nueva.

Guarda solo lo necesario: email, código de referido validado, importe e identificador. La clave de servicio se queda en el servidor. Si Supabase es opcional para una fase inicial, define conscientemente qué ocurre al faltar la configuración; no confirmes entregas importantes si no puedes registrar el estado que las hace trazables.

¿Qué efectos secundarios deben separarse del guardado?

La concesión de acceso, el email y la comisión deben diseñarse para tolerar reintentos igual que la fila principal. Primero registra el hecho de negocio de forma única; después activa acciones que consulten ese estado o tengan su propia clave de idempotencia.

No conviertas una respuesta lenta de correo en un reintento de todo el pago. La guía de emails transaccionales con Next.js ayuda a separar la entrega de mensajes del registro del cobro. Y si necesitas el contexto general de checkout y portal, revisa la arquitectura de suscripciones en Next.js: la idea de confiar en webhooks, no en redirecciones, es la misma.

¿Cómo se prueba el webhook antes de producción?

Se prueba enviando un evento válido, repitiéndolo con el mismo identificador, alterando la firma y enviando un tipo que no deba procesarse. Después comprueba que solo existe una fila y que los efectos asociados suceden una sola vez.

IndiePack convierte estas comprobaciones en parte del camino de lanzamiento: un pago no está terminado cuando abre el checkout, sino cuando el backend puede verificarlo, persistirlo y recuperarse de un reintento sin sorpresas.