¿Cómo hacer que un webhook de pago o WhatsApp sea idempotente?
Share

In this article
Asigna a cada webhook un ID único proporcionado por el remitente, como un ID de pedido o un ID de mensaje, y ejecuta sus efectos secundarios solo una vez. Una entrega repetida detecta que el ID ya fue procesado y no hace nada. Publica el trabajo real en una cola en lugar de hacerlo en línea, para que el remitente no tenga que esperar.
¿Por qué los webhooks llegan más de una vez?
Los remitentes reintentan en caso de tiempos de espera, fallos de red y respuestas que no sean 2xx, y prefieren entregar dos veces a no entregar nunca. Tanto las pasarelas de pago como WhatsApp funcionan así. Un manejador que actúe en cada entrega emitirá tickets duplicados, confirmaciones de reserva dobles o cargos repetidos.
¿Cuál debe ser la clave de idempotencia?
Usa el identificador que el remitente garantiza que es estable en los reintentos: el ID de pedido para webhooks de pago, el ID de mensaje para WhatsApp. Guarda las claves procesadas y verifica antes de actuar. Una clave que generes tú mismo por entrega no funciona, porque cada reintento parecería un evento nuevo.
¿Por qué publicar en una cola en lugar de hacer el trabajo en el manejador?
Generar un ticket y enviar un correo electrónico en línea hace que la pasarela espere por un trabajo que no le interesa, lo que provoca tiempos de espera y más reintentos. Reconoce rápido, publica un evento de pago confirmado en RabbitMQ y deja que un consumidor haga el trabajo. Una entrega repetida publica solo una vez; la segunda es una operación sin efecto.
¿Dónde se usa esto en producción?
En FindYourVibe el webhook de pago es idempotente con el ID de pedido y publica en RabbitMQ antes de que un consumidor emita el ticket. En Trexind, cada manejador de webhook de WhatsApp es idempotente con el ID de mensaje, por lo que una entrega reintentada actualiza el estado una vez en lugar de reactivar efectos secundarios de reserva o facturación.
¿Cómo pruebas que un webhook es idempotente?
Envía la misma carga útil dos veces, idealmente de forma concurrente, y verifica que el efecto secundario ocurrió solo una vez: un ticket, una reserva, un cargo. Luego reproduce una carga antigua después de que la primera se haya procesado completamente. Si algún conteo es mayor que uno, la verificación de la clave está compitiendo o falta una restricción única.
Publicado originalmente en sakshamjain.codes/blog/idempotent-payment-and-whatsapp-webhooks. ¿Necesitas esto implementado? Consulta mis servicios en NexoRush o envíame un mensaje.