Verificar la firma
Tu endpoint es una URL pública: cualquiera que la descubra puede mandarle un JSON que diga “esta compra se aprobó”. La firma es lo que te deja distinguir un aviso nuestro de uno inventado.La cabecera
t— el momento del envío, en segundos Unix.v1— HMAC-SHA256 en hexadecimal de{t}.{cuerpo}, usando el secreto de tu endpoint.
v1, separados por espacio. Aceptá el mensaje si alguno coincide.
Los tres pasos
1
Leé el cuerpo SIN parsear
La firma se calcula sobre los bytes exactos que te llegaron. Si serializás de nuevo el JSON ya parseado, cambian los espacios o el orden de las claves y la firma nunca va a coincidir.
2
Recalculá el HMAC
HMAC-SHA256(secreto, "{t}.{cuerpo}") y comparalo con v1 en tiempo constante.3
Chequeá el timestamp
Rechazá si
t está a más de unos minutos de tu reloj. Sin esto, quien haya capturado un envío viejo puede reproducirlo tal cual para siempre.Node.js / Express
Python / Flask
PHP
Rotar el secreto
Desde API y Webhooks, botón Rotar. Los envíos nuevos se firman con el secreto nuevo, así que actualizá tu servidor en el momento de rotar. Rotá si el secreto se filtró o si cambió el equipo que lo tenía.Errores frecuentes
La firma nunca coincide
La firma nunca coincide
Casi siempre es que estás firmando el JSON re-serializado en vez del cuerpo crudo. Un middleware de body-parsing antes de tu handler es suficiente para romperlo. En Express usá
express.raw, en Flask request.get_data().Funcionaba y de golpe todo da 401
Funcionaba y de golpe todo da 401
¿Rotaste el secreto? Los envíos posteriores van firmados con el nuevo.
Nos marcan como caídos pero recibimos todo
Nos marcan como caídos pero recibimos todo
Estás procesando antes de responder y te pasás de los 10 segundos. Contestá 200 primero, procesá después.
Nos llegan eventos repetidos
Nos llegan eventos repetidos
Es esperable: la entrega es al menos una vez. Guardá los
id procesados y descartá los repetidos.
