Cada webhook vem com um header X-Astronpay-Signature no formato sha256=<hex>. O valor é o HMAC-SHA256 do body bruto (raw bytes, não JSON parseado), usando o webhookSecret que você configurou.
Valide antes de parsear ou agir. Um webhook sem assinatura válida NÃO é da Astron Pay — descarte.
Algoritmo
- Chave: o
webhookSecret configurado via PATCH /api/v1/webhook/config.
- Dados: o body bruto da requisição (bytes, antes de qualquer parsing).
- Formato:
sha256= + hex lowercase.
Receita
- Leia o header
X-Astronpay-Signature (ex.: sha256=abc123...).
- Remova o prefixo
sha256= para obter o hex recebido.
- Calcule
HMAC_SHA256(webhookSecret, rawBody) e encode como hex.
- Compare os dois com comparação em tempo constante (
crypto.timingSafeEqual ou equivalente).
Node.js
Em um handler Express:
Python (FastAPI)
Idempotência
Use o header X-Astronpay-Delivery (ou o campo deliveryId no payload) para detectar entregas duplicadas. Armazene os IDs já processados e ignore repetições — a Astron Pay pode reenviar o mesmo evento em caso de falha de rede.
Armadilhas comuns
- Body alterado por middleware JSON: use sempre o body raw antes de parsing. Em Express,
express.raw() é obrigatório — express.json() altera os bytes.
- Comparação
== simples: vulnerável a timing attacks. Use timingSafeEqual / hmac.compare_digest.
- Secret errado: se rotacionou o
webhookSecret, atualize imediatamente — o anterior é invalidado na mesma chamada.
- Prefixo
sha256=: lembre de remover antes de comparar os hashes.