Webhooks
Conferir a assinatura
Todo envio é assinado com HMAC-SHA256 usando o segredo do webhook.
Como conferir
- Leia o corpo bruto da requisição (antes de converter o JSON).
- Monte o texto
{X-HDL-Timestamp}.{corpo}. - Calcule o HMAC-SHA256 com o segredo e compare com o valor depois de
sha256=emX-HDL-Assinatura, usando comparação de tempo constante. - Recuse timestamps com mais de 5 minutos de diferença (evita reenvio de avisos antigos).
Node.js
import crypto from 'node:crypto';
function assinaturaValida(corpoBruto, cabecalhos, segredo) {
const ts = cabecalhos['x-hdl-timestamp'];
const recebida = (cabecalhos['x-hdl-assinatura'] || '').replace('sha256=', '');
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const esperada = crypto.createHmac('sha256', segredo).update(`${ts}.${corpoBruto}`).digest('hex');
return recebida.length === esperada.length && crypto.timingSafeEqual(Buffer.from(recebida), Buffer.from(esperada));
}PHP
<?php
$corpo = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_HDL_TIMESTAMP'] ?? '';
$recebida = str_replace('sha256=', '', $_SERVER['HTTP_X_HDL_ASSINATURA'] ?? '');
$esperada = hash_hmac('sha256', $ts . '.' . $corpo, getenv('HDL_WEBHOOK_SEGREDO'));
if (abs(time() - (int) $ts) > 300 || !hash_equals($esperada, $recebida)) {
http_response_code(401);
exit;
}
$evento = json_decode($corpo, true);
http_response_code(200);Python
import hashlib, hmac, time
def assinatura_valida(corpo_bruto: bytes, cabecalhos, segredo: str) -> bool:
ts = cabecalhos.get('X-HDL-Timestamp', '')
recebida = cabecalhos.get('X-HDL-Assinatura', '').replace('sha256=', '')
if abs(time.time() - int(ts or 0)) > 300:
return False
esperada = hmac.new(segredo.encode(), f'{ts}.'.encode() + corpo_bruto, hashlib.sha256).hexdigest()
return hmac.compare_digest(esperada, recebida)
Os receptores completos estão em Scripts de teste.
© Hotel das Lojas · API v1.0 · hoteldaslojas.com.br