Recetor de webhooks fiável: assinatura, idempotência, fila e retentativas

Implementa um endpoint de webhooks que verifica a assinatura HMAC, responde depressa, põe o trabalho em fila, ignora duplicados e repete com backoff e fila de mensagens falhadas. Pensado para ChatGPT, Claude, Gemini e Microsoft Copilot. Inclui 4 variáveis personalizáveis e pode copiá-lo gratuitamente com um clique.

Avançado · Código · Pendente de revisão editorial

Prompt

Atua como engenheiro backend com experiência em integrações e sistemas distribuídos.

Preciso de receber webhooks de forma fiável:
- Fornecedor e forma de assinatura: {{fornecedor}}
- Eventos que me interessam e o que faço com cada um: {{eventos}}
- Stack: {{stack}}
- Sistema de filas disponível: {{fila}}

Entregáveis:
1. Um diagrama em texto do fluxo: receção, verificação, persistência, colocação em fila, processamento, retentativas e fila de falhados.
2. O endpoint recetor:
   - Lê o corpo em bruto antes de o interpretar e verifica a assinatura HMAC com comparação em tempo constante.
   - Rejeita pedidos com marca temporal fora de uma janela curta, para evitar ataques de repetição.
   - Guarda o evento e responde 2xx em poucos milissegundos; nada de lógica pesada no pedido.
3. Idempotência: tabela de eventos com o id do fornecedor como chave única, estados (recebido, em processamento, concluído, falhado) e o que fazer se o mesmo evento chegar duas vezes.
4. Worker: processamento com backoff exponencial e jitter, limite de tentativas, distinção entre erros transitórios e permanentes, e fila de falhados com forma de os reprocessar.
5. Ordem de chegada: como tratar eventos fora de ordem (por exemplo, verificar a versão ou a data do recurso, ou voltar a consultá-lo na API do fornecedor).
6. Registos e alertas: o que registar sem guardar dados sensíveis e que métricas vigiar.
7. Testes: assinatura válida e inválida, evento duplicado, marca temporal antiga, falha transitória que recupera e falha permanente que acaba na fila de falhados.
8. Como testar em local (túnel ou reencaminhamento de eventos) sem expor o segredo.

Restrições:
- Não adivinhes o formato exato da assinatura nem os nomes dos cabeçalhos do fornecedor: se não os indicar, marca como [PREENCHER] e diz-me onde os consultar na documentação.
- O segredo é lido de variáveis de ambiente ou de um gestor de segredos, nunca do código.
- Se faltar informação essencial, pergunta-me antes de escrever código.

Como utilizar

  1. Copia da documentação do fornecedor o cabeçalho de assinatura e o algoritmo usado.
  2. Enumera os eventos de que precisas e a ação de negócio de cada um.
  3. Testa em local com eventos reencaminhados e provoca falhas de propósito para ver as retentativas.
  4. Vigia a fila de falhados depois de publicar.

Exemplo de utilização

Fornecedor: gateway de pagamentos que assina com HMAC-SHA256 num cabeçalho · Eventos: pagamento confirmado, reembolso · Stack: Python com FastAPI · Fila: Celery com Redis.

Exemplo de resultado

1. Fluxo

Gateway → POST /webhooks/pagamentos → verificar assinatura + timestamp → INSERT evento (único)
        → commit → 200 → Celery: processar → retries com backoff → dead-letter

2. Endpoint de receção

@router.post("/webhooks/pagamentos")
async def receber(request: Request, db: AsyncSession = Depends(get_db)) -> dict:
    bruto = await request.body()                      # corpo bruto, antes do parsing
    ts = request.headers.get("[COMPLETAR: cabeçalho de timestamp]", "")
    assinatura = request.headers.get("[COMPLETAR: cabeçalho de assinatura]", "")
    if not ts.isdigit() or abs(time.time() - int(ts)) > 300:
        raise HTTPException(400, "timestamp em falta ou expirado")

    # Formato da mensagem assinada segundo a documentação do fornecedor: [COMPLETAR]
    esperada = hmac.new(settings.webhook_secret.encode(),
                        f"{ts}.".encode() + bruto, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(esperada, assinatura): # comparação em tempo constante
        raise HTTPException(400, "assinatura inválida")

    evento = json.loads(bruto)
    stmt = (insert(WebhookEvent)
            .values(provider_event_id=evento["id"], tipo=evento["type"],
                    payload=evento, estado="recebido")
            .on_conflict_do_nothing(index_elements=["provider_event_id"])
            .returning(WebhookEvent.id))
    novo_id = (await db.execute(stmt)).scalar_one_or_none()
    await db.commit()
    if novo_id is not None:                           # duplicado → não volta à fila
        processar_evento.delay(novo_id)
    return {"ok": True}

Enfileira-se depois do commit para que o worker nunca leia um evento que ainda não existe…

Dados-chave

Categoria
Programação e desenvolvimento · APIs
Tipo de resultado
Código
Nível
Avançado
Pensado para
ChatGPT, Claude, Gemini e Microsoft Copilot
Verificado em
Pendente de verificação editorial
Variáveis
Fornecedor e assinatura, Eventos e ações, Stack e Sistema de filas
Idioma
Português
Preço
Gratuito, sem registo
Atualizado
07/11/2026

Perguntas frequentes

Porquê responder 2xx antes de processar o evento?

Muitos fornecedores consideram falhado um webhook demasiado lento e reenviam-no, o que gera duplicados e carga extra. Guardar e pôr em fila permite responder logo e processar com calma.

Porquê verificar a assinatura com o corpo em bruto?

A assinatura é calculada sobre os bytes exatos enviados. Se interpretares e voltares a serializar o JSON, mudam espaços ou a ordem das chaves e a verificação falha.

Para que serve este prompt?

Implementa um endpoint de webhooks que verifica a assinatura HMAC, responde depressa, põe o trabalho em fila, ignora duplicados e repete com backoff e fila de mensagens falhadas.

Com que ferramentas de IA funciona?

Foi pensado para ChatGPT, Claude, Gemini e Microsoft Copilot. Ainda não o verificámos nestas ferramentas, pelo que os resultados podem variar entre elas.

Como personalizo o prompt?

Clique em “Personalizar” e preencha as variáveis (Fornecedor e assinatura, Eventos e ações, Stack e Sistema de filas). O texto atualiza-se instantaneamente e pode depois copiá-lo com um clique. Os valores ficam guardados apenas no seu navegador.

Preciso de experiência para o utilizar?

É de nível avançado: destina-se a pessoas com experiência no tema, capazes de avaliar e ajustar o resultado.

Este prompt é gratuito?

Sim. Todos os prompts do HomeCasa Prompts são gratuitos, sem registo nem subscrição. Pode também utilizá-los em projetos profissionais.

Posso confiar no resultado da IA?

Trate-o como um rascunho de qualidade: verifique sempre os dados, os números e as afirmações importantes antes de publicar ou tomar decisões.

Prompts relacionados