Assinatura
X-Webhook-Signature = sha256= + HMAC-SHA256 do corpo exato com o segredo do webhook. Recuse o evento quando não bater.
Node.js
import crypto from "node:crypto";
// corpoBruto: o corpo EXATO recebido (Buffer), antes de qualquer JSON.parse.
// segredo: o segredo do webhook, mostrado uma vez quando você o criou.
export function assinaturaValida(corpoBruto, cabecalho, segredo) {
if (!Buffer.isBuffer(corpoBruto)) return false;
const esperado = "sha256=" + crypto.createHmac("sha256", segredo).update(corpoBruto).digest("hex");
const a = Buffer.from(String(cabecalho || ""));
const b = Buffer.from(esperado);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}- Calcule sobre os bytes recebidos, antes de qualquer
JSON.parse. - Compare em tempo constante (
timingSafeEqual). - O segredo aparece uma vez, quando você cria o webhook no painel.