Webhooks: Payloads Assinados e Retentativas
Você acabou de integrar um gateway de pagamento ou um serviço de CI/CD, e agora precisa receber eventos em tempo real. Webhooks são a solução padrão, mas vêm com armadilhas: payloads não autenticados, eventos perdidos e entregas duplicadas. Este artigo explica como os webhooks funcionam, como assinar payloads para evitar adulteração e como implementar retentativas para entrega confiável.
O que são Webhooks?
Um webhook é um callback HTTP definido pelo usuário. Em vez de sua aplicação fazer polling em uma API para obter atualizações, o provedor envia uma requisição HTTP POST para uma URL que você especifica sempre que um evento ocorre. Isso é mais eficiente e permite reações quase em tempo real.
Casos de uso comuns incluem:
- Notificações de pagamento (ex.: Stripe, PayPal)
- Status de build de CI/CD (ex.: GitHub, GitLab)
- Plataformas de mensagens (ex.: Slack, Discord)
- Atualizações de CRM (ex.: Salesforce)
Por que assinar payloads de webhook?
Endpoints de webhook são URLs publicamente acessíveis. Sem verificação, qualquer pessoa pode enviar payloads falsos, levando à corrupção de dados ou violações de segurança. Assinar payloads com um segredo compartilhado garante autenticidade e integridade.
A maioria dos provedores usa HMAC (Hash-based Message Authentication Code) com SHA-256. O provedor calcula uma assinatura sobre o corpo bruto da requisição usando uma chave secreta e a inclui em um cabeçalho (ex.: X-Hub-Signature-256). Seu servidor recalcula a assinatura e compara.
Como verificar uma assinatura
Aqui está um guia passo a passo:
- Recupere o corpo bruto exatamente como enviado. Não o analise ou modifique antes da verificação.
- Extraia a assinatura do cabeçalho.
- Calcule a assinatura esperada usando HMAC-SHA256 com seu segredo.
- Compare usando uma função de tempo constante para prevenir ataques de temporização.
Exemplo em Node.js:
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const digest = 'sha256=' + hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(signature));
}
Em Python:
import hmac
import hashlib
def verify_signature(payload, signature, secret):
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(f'sha256={expected}', signature)
Sempre use uma comparação de tempo constante para evitar vazamento de informações.
Implementando Retentativas para Confiabilidade
Redes falham, servidores reiniciam e implantações acontecem. Um sistema robusto de webhooks deve tentar novamente entregas falhas. Os provedores geralmente tentam novamente com backoff exponencial, mas você também deve lidar com retentativas no seu lado receptor.
Estratégias de Retentativa
- Backoff exponencial: Espere 1s, 2s, 4s, 8s, etc., entre as tentativas.
- Máximo de tentativas: Limite as retentativas para evitar loops infinitos (ex.: 5 tentativas).
- Fila de mensagens mortas: Após o máximo de tentativas, armazene o evento para inspeção manual.
- Idempotência: Garanta que processar o mesmo evento várias vezes não cause efeitos colaterais duplicados.
Chaves de Idempotência
Muitos provedores incluem um ID de evento único (ex.: X-Event-ID). Armazene IDs processados em um banco de dados ou cache para pular duplicatas. Por exemplo, use Redis com um TTL para rastrear IDs vistos.
Comparação: Polling vs Webhooks
| Aspecto | Polling | Webhooks |
|---|---|---|
| Latência | Depende do intervalo | Quase em tempo real |
| Carga do servidor | Alta (requisições constantes) | Baixa (apenas em eventos) |
| Complexidade | Simples de implementar | Requer endpoint, segurança, retentativas |
| Confiabilidade | Perde eventos entre polls | Pode perder se o endpoint estiver fora; retentativas ajudam |
Melhores Práticas para Consumidores de Webhooks
- Responda rapidamente: Retorne 2xx em poucos segundos; processe de forma assíncrona.
- Valide assinaturas: Sempre verifique antes de processar.
- Registre tudo: Mantenha payloads brutos e cabeçalhos para depuração.
- Use HTTPS: Nunca aceite webhooks via HTTP simples.
- Monitore falhas: Configure alertas para falhas repetidas de retentativa.
FAQ
O que é uma assinatura de webhook?
Uma assinatura de webhook é um hash HMAC do payload, criado com um segredo compartilhado. Permite que o receptor verifique que a requisição veio do remetente esperado e não foi adulterada.
Quantas vezes devo tentar novamente um webhook com falha?
Não há um número universal, mas 3–5 retentativas com backoff exponencial é comum. Depois disso, registre o evento em uma fila de mensagens mortas para revisão manual.
Posso usar webhooks sem HTTPS?
Tecnicamente sim, mas é altamente inseguro. Sempre use HTTPS para criptografar payloads e prevenir ataques man-in-the-middle.
Pronto para testar seus endpoints de webhook? Use nosso JSON Formatter para inspecionar e validar payloads rapidamente.