2xx encerra a entrega. Qualquer coisa fora dessa faixa — inclusive um timeout —
agenda nova tentativa.
Responda rápido, processe depois
O padrão que resolve isso tem três passos:1
Confira a assinatura
Antes de qualquer outra coisa. Ver Verificar a assinatura.
2
Grave o evento e responda 200
Grave o
id e o corpo. Responda imediatamente. Nada de liberar produto aqui.3
Processe em fila
O trabalho de verdade acontece fora do ciclo da requisição, onde demorar não custa uma
retentativa.
Deduplique pelo id do evento
O id (evt_…) é estável entre as retentativas da mesma entrega. Uma entrega que desistiu depois
das retentativas pode ser reenviada à mão pelo painel — e o id continua o mesmo, justamente para a
sua idempotência reconhecê-lo.
Use uma restrição de unicidade no banco, e não uma consulta seguida de inserção. Duas entregas que
chegam ao mesmo tempo passam as duas pela consulta antes de qualquer uma inserir — e o produto é
liberado duas vezes.
Depurando uma entrega
Cada tentativa tem umX-Vext-Delivery. É por ele que localizamos a tentativa, a resposta do seu
servidor e o horário. Registre-o em log mesmo quando tudo dá certo: quando algo der errado, ele é a
diferença entre um chamado de cinco minutos e uma tarde de investigação.
O corpo pode chegar reduzido
Escreva o handler para tolerar umcharge com menos campos do que o normal, e ele sobrevive ao dia
ruim. Quando a montagem do corpo completo falha do nosso lado, o evento sai numa versão reduzida em
vez de não sair — um charge.paid menor ainda avisa que a venda foi paga, e nenhum evento deixaria
você sem saber.
O corpo reduzido mantém o essencial para você reencontrar o pedido, metadata inclusive. O restante
está em GET /v1/charges/{code}, e é de lá que você completa.
O schema ChargeMinimal na spec diz exatamente o que vem.
É um caminho de exceção, não o normal. Ele importa porque um handler escrito contra o corpo cheio
quebraria justamente quando algo já deu errado — e o evento perdido seria um pagamento que o seu
sistema nunca registrou.
O que não é entregue
Os estados intermediários de saque (processing, pending) não geram evento. Eles não pedem ação
do seu lado, e cada entrega tem custo de retentativa. Só withdrawal.paid é enviado.
Veja também
Verificar a assinatura
O passo que vem antes de tudo.
Idempotência
O mesmo princípio, na direção oposta.
Ficou algo de fora? Chame no WhatsApp. 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.