Cómo funciona la comprobación de la firma de un webhook
Una firma de webhook es una prueba breve de que el evento provino del proveedor de pagos y no de una solicitud POST cualquiera. El proveedor firma la carga útil con un secreto compartido o una clave privada, y luego tu aplicación verifica esa firma antes de confiar en el evento. Si necesitas comprobar firma webhook, la respuesta más segura es un 401 o un 400 y no actualizar ningún pedido.
Suena sencillo. Rara vez lo es.
En la práctica, la comprobación de la firma te protege de facturas falsificadas, reembolsos inventados y cargas útiles manipuladas que a primera vista parecen legítimas. Un webhook que dice “pago completado” no sirve de mucho si cualquiera puede falsificarlo. Para los equipos que usan una guía de pasarela de pago con criptomonedas para ecommerce, esta comprobación se sitúa justo entre la aceptación del pago y el cumplimiento del pedido, por eso una sola suposición equivocada puede detener todo el flujo.
La mayoría de los proveedores firman el cuerpo completo en bruto, una marca de tiempo, o ambas cosas. Algunos usan HMAC-SHA256; otros, un encabezado versionado con varios valores de firma. Un solo desajuste basta. El proveedor puede estar en lo correcto y tu aplicación seguir rechazando el evento si alteraste incluso un byte.
Primero, confirma que el fallo sea realmente por la firma
Los registros deberían responder esto en menos de 5 minutos. Si no lo hacen, no son lo bastante detallados.
Empieza por el código de respuesta exacto y el texto del error. Un 400 con “firma no válida” apunta en una dirección; un 500 o un timeout, en otra. Los fallos de entrega, las rutas incorrectas, los errores TLS y los timeouts del proxy pueden parecer problemas de webhook desde el panel, pero no son el mismo problema. Si el proveedor muestra “entregado” y tu endpoint devuelve 200, probablemente la verificación de la firma no sea el origen del problema.
Comprueba tres cosas juntas: el registro de entrega del proveedor, el registro de tu aplicación y, si tienes uno, el del proxy inverso. Una solicitud que nunca llega a tu código no puede fallar una comprobación de firma. Una solicitud que llega a tu código pero devuelve 401, normalmente sí. Hay un detalle importante aquí: si ves el evento en los registros pero no aparece un error firma webhook, puede que tu código esté rechazando la carga útil más adelante, después de la fase de verificación.
En resumen: confirma el síntoma antes de cambiar código.
Comprueba el secreto compartido o la clave de firma
Este es el error más común, y es lo bastante aburrido como para ser peligroso. El secreto del webhook en tu aplicación debe coincidir exactamente con el secreto actual del panel del proveedor de pagos, incluidos los espacios ocultos copiados desde un campo de texto. Si el proveedor rotó el secreto el martes pasado, la clave antigua seguirá en tu entorno a menos que alguien la haya actualizado.
Compara el secreto del panel con el de tu entorno de despliegue, no solo con el de tu portátil. Producción, staging y desarrollo local deberían tener cada uno su propio valor. Un equipo que copia un secreto de prueba en producción puede pasar 2 horas persiguiendo un fallo de firma causado por una sola cadena pegada. Ese tipo de problema es común durante los lanzamientos y durante las migraciones de un procesador a otro. Para los equipos que usan la guía de pasarela de pago con criptomonedas para ecommerce, los desajustes de secretos suelen aparecer justo después de una nueva versión del checkout.
Mantén las claves antiguas solo si el proveedor admite rotación de claves con solapamiento. Si la clave antigua y la nueva son válidas durante una breve ventana, tu verificador debería probar primero la clave activa y luego la anterior. Si el proveedor no admite solapamiento, elimina la antigua de todos los entornos. Sin adivinar.
Reconstruye exactamente el cuerpo bruto de la solicitud tal como se recibió
Aquí es donde fallan muchas buenas implementaciones. Las comprobaciones de firma suelen depender de los bytes brutos exactos que envió el proveedor, no del objeto JSON que generó tu framework tras el parseo. Si tu código convierte números, reordena campos, elimina espacios en blanco o normaliza finales de línea, la firma calculada puede cambiar aunque la carga útil “parezca” idéntica.
Algunos frameworks leen el cuerpo una vez y luego descartan el flujo original. Otros autoanalizan el JSON antes de que se ejecute tu middleware. Eso significa que el verificador recibe un objeto reconstruido, no el cuerpo bruto. La solución suele ser capturar primero la carga útil intacta y luego pasar ese buffer exacto a la función de verificación de firma. Un ajuste del framework puede decidir si el cuerpo se conserva o se reescribe.
Por ejemplo, una carga útil con 14 campos puede llegar en un orden de bytes concreto que tu código nunca verá si el analizador ordena las claves. Una línea nueva al final puede importar. Una sola conversión a UTF-8 puede importar. Sí, un carácter invisible puede romper toda la comprobación.
Si tu pila lo permite, registra la longitud del cuerpo y un hash del cuerpo bruto de la solicitud antes de analizarlo. No registres secretos. Sí registra la ruta exacta del código que lee el flujo. Eso facilita mucho rastrear por qué cómo probar un pago con criptomonedas a veces funciona en Postman pero falla con un webhook real del proveedor.
Valida la marca de tiempo, la sincronización del reloj y la protección contra reenvíos
Muchos esquemas de webhook incluyen una marca de tiempo para que los eventos antiguos no puedan reproducirse más tarde. Tu verificador puede rechazar una solicitud si la marca de tiempo queda fuera de una ventana de tolerancia, a menudo 5 minutos u otro límite definido por el proveedor. Eso protege contra ataques de repetición, pero también significa que el reloj de tu servidor debe ser correcto.
Comprueba el reloj del sistema en todos los servidores que gestionan webhooks. Si el reloj se desvía 3 minutos, la firma puede fallar incluso cuando la carga útil es correcta. Si el servidor se ejecuta en un contenedor, verifica también la hora del host. NTP u otro servicio de sincronización horaria debería estar activo en la máquina que toma la decisión de verificación. Un servidor con 10 minutos de desfase puede convertir un webhook válido en un falso fallo.
La protección contra reenvíos también importa aquí. Si tu código almacena en caché firmas o IDs de evento vistos, asegúrate de que el TTL de la caché coincida con la ventana de repetición esperada por el proveedor. Una entrada obsoleta de caché puede hacer que un reintento válido se rechace. Un reintento del proveedor no es lo mismo que un reenvío malicioso, así que el código debe entender ambos casos. Es un detalle pequeño con grandes consecuencias.
Asegúrate de que el encabezado de la firma se analiza correctamente
No todos los encabezados de firma tienen la misma forma. Algunos proveedores envían un solo encabezado con un hash único, mientras que otros envían una lista separada por comas de pares clave-valor, una etiqueta de versión y una marca de tiempo. Tu analizador debe coincidir con ese formato exacto. Si espera v1= y el proveedor envía t= más varias versiones, la comprobación fallará antes incluso de que empiece la criptografía.
Ojo con los errores de recorte. Los espacios al principio o al final importan. También los errores de codificación cuando un framework decodifica los encabezados como Latin-1 en lugar de UTF-8. Un salto de línea sobrante copiado en una variable de entorno puede hacer que la comparación falle. No normalices el encabezado a menos que el proveedor diga que puedes hacerlo. No conviertas a minúsculas un valor que deba ser seguro para datos binarios. Esas dos líneas causan más problemas de los que deberían.
Los esquemas múltiples también requieren un manejo cuidadoso. Algunos proveedores publican una firma actual y otra anterior durante periodos de transición. Tu verificador debería saber qué versión está usando y rechazar de forma limpia las versiones desconocidas. Si el encabezado incluye tanto una marca de tiempo como una firma, verifica ambas. Si el proveedor documenta un prefijo de firma, úsalo exactamente como está escrito. Para más información sobre el manejo seguro de webhooks, consulta mejores prácticas de seguridad para pagos con criptomonedas.
Prueba con un evento de webhook conocido y válido
Un evento conocido y válido ahorra tiempo. Vuelve a enviarlo desde el panel del proveedor o usa una carga útil de ejemplo documentada y compara la firma esperada con la que calcula tu código. Si el ejemplo se verifica pero el tráfico real no, probablemente el problema sea de configuración, entorno o rotación de secretos. Si ninguno se verifica, la ruta de código es incorrecta.
Usa un ID de evento y una marca de tiempo. Luego compara cuatro cosas: el cuerpo bruto, el valor del encabezado, el secreto y el reloj. Eso basta para aislar la mayoría de los fallos. Una carga útil de prueba copiada en un archivo local puede incluir un formato que tu endpoint real nunca ve, así que siempre es mejor usar la herramienta de reenvío del proveedor cuando exista. Un solo reenvío vale más que 20 suposiciones.
Si el proveedor ofrece un calculador de firmas, ejecuta la misma carga útil a través de él. Si tu salida difiere aunque sea en un carácter, tienes un problema de análisis o de preservación del cuerpo. Si la salida coincide pero el proveedor sigue rechazando la solicitud, el secreto o el análisis del encabezado están mal. Esa división te indica dónde mirar después.
Este también es el punto en el que staging y producción deberían separarse claramente. Un evento de staging enviado a un secreto de producción fallará siempre, y el fallo parecerá idéntico a una firma rota hasta que compruebes la etiqueta del entorno.
Refuerza y supervisa el endpoint del webhook
Cuando la comprobación de la firma funcione, mantén su funcionamiento. Registra el ID del evento, el resultado de la verificación, el nombre del proveedor y el nombre del entorno. No registres el secreto completo. No registres el cuerpo bruto completo si contiene datos sensibles de clientes. Usa un mensaje de error breve y legible para los operadores y un rechazo simple para el proveedor.
Rota el secreto del webhook con un calendario y documenta la transición. Un proceso de rotación en 2 pasos es más seguro: añade la nueva clave, confirma que ambas funcionan si hay solapamiento, y luego elimina la antigua. Separa los endpoints de prueba y producción para que un error en staging no toque pedidos reales. Suena obvio; aun así, los equipos los mezclan.
Genera alertas ante un aumento de fallos de firma, no ante un único intento fallido. Un fallo puede ser simplemente un mal reintento. Cinco fallos en 1 minuto merecen atención. Incluye la ruta, el proveedor y el código de respuesta en la alerta para que la persona de guardia pueda saber si el problema es un desajuste de secreto, un error del analizador o un problema de reloj. Si todavía estás configurando el endpoint, el artículo cómo configurar pagos con criptomonedas puede ayudarte a mantener simple la ruta del webhook desde el principio.
Último punto: mantén un pequeño runbook con los pasos exactos para cómo corregir una firma fallida de webhook de pago con criptomonedas, incluyendo dónde vive el secreto, cómo reenviar un evento y qué línea de registro confirma la verificación. Un runbook de 10 líneas ahorra una hora a las 2 de la mañana.




Comentarios