Como a assinatura é montada
Toda entrega chega com o header:v1 é:
Dois detalhes que fazem a conferência funcionar
1. Use o corpo bruto, antes de desserializar. O HMAC é calculado sobre os bytes exatos que enviamos. Desserializar e reserializar muda espaçamento e ordem de chaves, e aí a conta não fecha — é a causa mais comum de “minha assinatura nunca bate”. Na prática:$request->getContent() no Laravel, express.raw() no Express e request.get_data()
no Flask, em vez de ->all(), express.json() ou request.json.
2. Aceite só timestamps dos últimos 5 minutos.
A assinatura de uma entrega continua válida para sempre, então a janela de tempo é o que impede que
uma entrega antiga de charge.paid seja reenviada mais tarde. São duas linhas, e é o que separa uma
verificação decorativa de uma que protege de verdade.
Implementação
Repare que os três exemplos comparam em tempo constante —
hash_equals,
crypto.timingSafeEqual, hmac.compare_digest. Uma comparação comum de strings para no primeiro
byte diferente, e essa diferença de tempo é suficiente para alguém descobrir a assinatura correta
byte a byte. Vale manter essa parte como está ao adaptar o código.Depois de conferir
Com a assinatura confirmada, desserialize e siga: responda2xx rápido e deixe o processamento para
uma fila. O padrão está em Entregas e retentativas.
Se a assinatura não bater, responda 400 e registre o X-Vext-Delivery no seu log. Os dois motivos
possíveis são um evento adulterado ou um segredo desatualizado, e o log com o X-Vext-Delivery é o
que nos permite dizer qual dos dois foi.
Veja também
Visão geral
Os três eventos e o envelope.
Checkout PIX
O fluxo completo, da criação à liberação.
Ficou algo de fora? Escreva para suporte@usevext.com. Se o assunto for uma chamada específica, informe o horário dela; se for uma entrega de webhook, informe o
X-Vext-Delivery — é por ele que localizamos a tentativa, a resposta do seu servidor e o horário.