Webhooks Explicados: Payloads Assinados e Retentativas

Backend2026-11-08TryQuickToolBox

Você acabou de integrar o webhook de um provedor de pagamentos. A documentação diz "faremos um POST no seu endpoint quando um pagamento for bem-sucedido". Simples, certo? Então você percebe eventos duplicados, notificações perdidas e um alerta de segurança sobre requisições forjadas. Webhooks são simples em conceito, mas complicados em produção. Este artigo explica como implementar webhooks corretamente usando payloads assinados e retentativas, para que você possa construir integrações confiáveis e seguras.

O Que São Webhooks?

Um webhook é uma API reversa: em vez de sua aplicação fazer polling em um serviço para obter atualizações, o serviço envia eventos para o seu endpoint via HTTP POST. É eficiente e quase em tempo real. Usos comuns incluem notificações de pagamento, gatilhos de CI/CD e integrações de chat.

Mas webhooks introduzem desafios: como você sabe que a requisição realmente veio do provedor? E se o seu servidor estiver fora do ar? E se o mesmo evento chegar duas vezes? Vamos resolver isso um por um.

Protegendo Webhooks com Payloads Assinados

Qualquer pessoa pode enviar uma requisição HTTP para o seu endpoint. Sem verificação, atacantes poderiam forjar eventos, levando a fraudes ou corrupção de dados. A solução padrão é assinar o payload com um segredo compartilhado.

Como Funcionam as Assinaturas HMAC

O provedor e você compartilham uma chave secreta. Para cada evento, o provedor calcula um HMAC (Hash-based Message Authentication Code) do corpo da requisição usando esse segredo e envia a assinatura em um cabeçalho (por exemplo, X-Signature). Você recalcula o HMAC do seu lado e compara. Se corresponderem, a requisição é autêntica e não foi adulterada.

Aqui está um exemplo mínimo em Python usando Flask:

import hmac
import hashlib
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = b'your_shared_secret'

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Signature')
    if not signature:
        abort(400, 'Missing signature')
    body = request.get_data()
    expected = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, signature):
        abort(401, 'Invalid signature')
    # Process the event
    return '', 200

Sempre use hmac.compare_digest para comparação em tempo constante, a fim de evitar ataques de temporização. Além disso, verifique a assinatura antes de analisar o corpo JSON para evitar processamento desnecessário.

Boas Práticas para Assinaturas

Lidando com Falhas Usando Retentativas

Webhooks são do tipo fire-and-forget da perspectiva do provedor, mas o seu endpoint pode estar temporariamente indisponível. Para garantir a entrega, os provedores implementam políticas de retentativa. Como receptor, você deve estar preparado para retentativas e duplicatas.

Estratégias de Retentativa Usadas pelos Provedores

A maioria dos provedores tenta novamente com backoff exponencial: por exemplo, imediatamente, depois após 1 minuto, 5 minutos, 30 minutos, etc., até um número máximo de tentativas (frequentemente 5–10). Alguns também permitem configurar um cronograma de retentativas. O comportamento exato varia, então leia a documentação do provedor.

Projetando Seu Endpoint para Retentativas

Seu endpoint deve:

Exemplo de verificação de idempotência em Python:

processed_events = set()  # In production, use a database or cache

@app.route('/webhook', methods=['POST'])
def webhook():
    # ... signature verification ...
    event = request.json
    event_id = event['id']
    if event_id in processed_events:
        return '', 200  # Already processed
    # Process event
    processed_events.add(event_id)
    return '', 200

Testando Sua Implementação de Webhook

Antes de entrar em produção, teste seu endpoint minuciosamente:

  1. Simule requisições assinadas: escreva testes unitários que gerem assinaturas válidas e inválidas.
  2. Teste cenários de retentativa: simule falhas e garanta que seu endpoint lide com duplicatas.
  3. Use ferramentas do provedor: muitos provedores oferecem uma CLI ou dashboard para enviar eventos de teste.
  4. Monitore e registre logs: registre eventos recebidos (sem dados sensíveis) e configure alertas para falhas de assinatura ou altas taxas de erro.

Comparação: Polling vs Webhooks

AspectoPollingWebhooks
LatênciaDepende do intervalo (por exemplo, minutos)Quase em tempo real
Carga no servidorAlta (requisições frequentes)Baixa (apenas em eventos)
ComplexidadeSimples de implementarRequer verificação de assinatura e tratamento de retentativas
ConfiabilidadeVocê controla as retentativasO provedor controla as retentativas; você deve lidar com duplicatas

FAQ

Como faço para verificar uma assinatura de webhook?

Calcule o HMAC do corpo bruto da requisição usando o segredo compartilhado e compare com o cabeçalho de assinatura usando uma função de comparação em tempo constante. Sempre verifique antes de processar o payload.

O que meu endpoint deve retornar para confirmar um webhook?

Retorne um código de status 2xx (por exemplo, 200 OK) assim que receber e enfileirar o evento para processamento. Evite processamento longo no handler da requisição para prevenir timeouts.

Como posso lidar com entregas duplicadas de webhook?

Use uma chave de idempotência do payload do evento (ou um ID de evento único) para rastrear eventos processados. Armazene esses IDs em um banco de dados ou cache e pule o processamento se o ID já tiver sido visto antes.

Pronto para testar seus payloads de webhook? Use nosso JSON Formatter para formatar e validar o corpo JSON de webhooks recebidos, facilitando a depuração.