Desarrolladores · Webhooks
Verificar la firma
Cada aviso viene firmado con el secreto del webhook. Verifícalo antes de confiar en su contenido.
Los encabezados
Los avisos siguen Standard Webhooks: cualquier biblioteca de esa especificación los verifica con el secreto que te damos al crear el webhook.
webhook-id: el id del evento, igual en cada reintento. Sirve para no procesarlo dos veces.webhook-timestamp: la hora del envío, en segundos. Descarta los avisos de más de 5 minutos.webhook-signature:v1,seguido del HMAC-SHA256 en base64 deid.timestamp.cuerpo.
Verificar en Node, sin bibliotecas
const crypto = require('crypto');
const signed = `${headers['webhook-id']}.${headers['webhook-timestamp']}.${rawBody}`;
const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64');
const expected = crypto.createHmac('sha256', key).update(signed).digest('base64');
const valid = headers['webhook-signature']
.split(' ')
.some((part) => part === `v1,${expected}`);
Usa el cuerpo tal como llegó (rawBody), antes de convertirlo a JSON: cualquier cambio de espacios rompe la firma.
Verificar en Python
import base64, hashlib, hmac
signed = f"{h['webhook-id']}.{h['webhook-timestamp']}.".encode() + raw_body
key = base64.b64decode(secret.removeprefix("whsec_"))
expected = base64.b64encode(hmac.new(key, signed, hashlib.sha256).digest()).decode()
valid = any(part == f"v1,{expected}" for part in h["webhook-signature"].split())
Rotar el secreto
Desde Webhooks puedes rotar el secreto. El anterior sigue firmando 24 horas y el encabezado lleva las dos firmas, así tu sistema no se corta mientras lo actualizas.
Revisado el