Onde vive cada segredo

CLIENT_SECRET e WEBHOOK_SECRET nunca podem aparecer no código do frontend nem no bundle enviado ao browser. Só a PUBLISHABLE_KEY é pública.

Verificação do webhook (HMAC SHA-256)

A FaciPay assina cada webhook. O header x-facipay-content-token contém o HMAC SHA-256 do body cru calculado com o seu WEBHOOK_SECRET. A ordem dos passos é crítica.
1

Leia o body CRU antes de qualquer parser JSON

Se fizer JSON.parse primeiro, o HMAC não vai bater certo.
2

Calcule o HMAC e compare em tempo constante

Use crypto.timingSafeEqual. Se os tamanhos diferirem, devolva 401 antes de comparar.
3

Só agora faça JSON.parse e processe

Localize a ordem por externalTransactionId e deduplique por paymentId + paymentStatus. Responda 200 em < 5s.
Nomes de headers HTTP são case-insensitive. Em Node, req.headers['x-facipay-content-token'] funciona porque o runtime normaliza tudo para minúsculas.

Por framework

Outras boas práticas

  • Valide a origem do popup. Ao ouvir postMessage, confirme event.origin contra o domínio oficial do checkout antes de confiar na mensagem (ver Eventos).
  • Recalcule o total no servidor. Nunca aceite o amount vindo do cliente.
  • Trate o webhook como idempotente. Reprocessar não pode duplicar fulfillment.
  • HTTPS em produção. Obrigatório para a SDK e para receber webhooks.

Próximo passo: Go-live

Checklist para passar de sandbox a produção.