GH GambleHub

Webhooks e Idempotação de eventos

TL; DR

Um bom webhook é um evento assinado (HMAC/mTLS), resumido e idumpotente, entregue por at-least-once, com backoff exponencial e dedução do destinatário. Negocie sobre um envelope ('event _ id', 'tipo', 'ts', 'version', 'attempt',' signatura '), uma janela de tempo (≤5 min), códigos de resposta, retais, DLQ e status-endpoint.


1) Papéis e modelo de entrega

Remetente (você/provedor): forma evento, assina, tenta entregar até 2xx, retraita a 3xx/4xx/5xx (exceto «não aceite» explícito), conduz DLQ, dá replay API.
Destinatário (parceiro/seu serviço): verifica a assinatura/janela temporária, faz o deduzimento e o processamento idumportante, atende com o código correto, fornece/status e/ack replay por 'event _ id'.

Garantia: at-least-once. O destinatário deve ser capaz de processar duplicados e mudar de ordem.


2) Envelope evento (envelope)

json
{
"event_id": "01HF7H9J9Q3E7DYT5Y6K3ZFD6M",
"type": "payout.processed",
"version": "2025-01-01",
"ts": "2025-11-03T12:34:56.789Z",
"attempt": 1,
"producer": "payments",
"tenant": "acme",
"data": {
"payout_id": "p_123",
"status": "processed",
"amount_minor": 10000,
"currency": "EUR"
}
}

Os campos obrigatórios são 'event _ id', 'tipo', 'version', 'ts', 'attempt'.
Regras de evolução: adicionando campos; remover/alterar tipos - apenas com o novo «versão».


3) Segurança: assinaturas e vinculação

3. 1 assinatura HMAC (recomendada por padrão)

Títulos:

X-Signature: v1=base64(hmac_sha256(<secret>, <canonical>))
X-Timestamp: 2025-11-03T12:34:56Z
X-Event-Id: 01HF7...
Linha canônica:

<timestamp>\n<method>\n<path>\n<sha256(body)>
Verificação do destinatário:
  • abs(now − `X-Timestamp`) ≤ 300s
  • 'X-Event-Id' não foi processado anteriormente (Dedup)
  • 'X-Score' corresponde (com uma comparação de tempo seguro)

3. 2 Dopp. medidas

para webhooks altamente sensíveis.
IP/ASN allow-list.
DPoP (opcional) para sender-constrained se o webhook iniciar as chamadas invertidas.


4) Idempotidade e dedução

4. 1 Idempotidade do evento

O evento com o mesmo 'event _ id' não deve alterar novamente o status. Destinatário:
  • armazenando 'event _ id' em um cajo idumpotente (KV/Redis/BD) em TTL ≥ 24-72 h;
  • salva o resultado do processamento (sucesso/erro, artefatos) para o retorno.

4. 2 Idempotidade dos comandos (chamadas de volta)

Se o webhook forçar o cliente a fazer API (por exemplo, «confirmar payout»), use 'Idempotency-Key' na chamada REST, armazene o resultado no lado do serviço (exactly-once outcome).

Modelo KV (mínimo):

key: idempotency:event:01HF7...
val: { status: "ok", processed_at: "...", handler_version: "..." }
TTL: 3d

5) Retraias e backoff

Horário recomendado (exponencial com jitter):
  • '5s, 15s, 30s, 1m, 2m, 5m, 10m, 30m, 1h, 3h, 6h, 12h, 24h' (seguir diárias para N dias)
Soluções de código:
  • 2xx - sucesso, parar com o retrai.
4xx:
  • '400/ 401/403/404/422' não é retrátil se a assinatura/formato de ok (erro de cliente).
  • '429' - Retraim por 'Retry-After' ou backoff.
  • 5xx/rede - Retraim.

Os cabeçalhos do remetente são "Usuário-Agente", "X-Webhook-Producer", "X-Attempt'.


6) Processamento no lado do destinatário

Pseudopipline:
pseudo verify_signature()
if abs(now - X-Timestamp) > 300s: return 401

if seen(event_id):
return 200 // идемпотентный ответ

begin transaction if seen(event_id): commit; return 200 handle(data)       // доменная логика mark_seen(event_id)    // запись в KV/DB commit return 200

Transacionalidade: O rótulo «seen» deve ser atômico com o efeito da operação (ou após a fixação do resultado) para evitar o duplo processamento em caso de falha.


7) Garantias de ordem e súmulos

A ordem não é garantida. Use «ts» e «seq »/« version» em «data» para verificar a relevância.
Para longas lajes/perdas - Adicione/replay junto ao remetente e/resync junto ao destinatário (obter snapshots e delta na janela de tempo/ID).


8) Status, replay e DLQ

8. 1 Endpointos do remetente

'POST/webhooks/replay' - na lista 'event _ id' ou na janela do tempo.
'GET/webhooks/events/id' - mostrar o pacote de origem e o histórico de tentativas.
DLQ: eventos «mortos» (limite de retais esgotado) → armazenamento separado, alertas.

8. 2 Endpointos do destinatário

`GET /webhooks/status/:event_id` — `seen=true/false`, `processed_at`, `handler_version`.
'POST/webhooks/ack' - (opcional) confirmação de processamento manual a partir do DLQ.


9) Contratos de erro (resposta do destinatário)

http
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
Retry-After: 120
X-Trace-Id: 4e3f...

{
"error": "invalid_state",
"error_description": "payout not found",
"trace_id": "4e3f..."
}

Recomendações: devolva sempre o código claro e, se possível, «Retry-After». Não devolva detalhes de segurança.


10) Monitoramento e SLO

Métricas (remetente):
  • delivery p50/p95, sucess rate, retrai/evento, drop-rate DLQ, share 2xx/4xx/5xx, janela de atraso de até 2xx.
Métricas (destinatário):
  • verify fail rate (assinatura/hora), dup-rate, latency handler p95, 5xx.
SLO orientações:
  • Entrega: ≥ 99. 9% dos eventos recebem 2xx <3 c p95 (após a primeira tentativa bem sucedida).
  • Kriptoprover, validação da assinatura ≤ 2-5 ms p95.
  • Duplo: 0 efeitos repetidos (exactly-once outcome ao nível do domínio).

11) Segurança de dados e privacidade

Não transmita PAN/PII no corpo do webhook; use os ID e pulo subsequente para obter os detalhes da API autorizada.
Disfarce os campos sensíveis nos logs; guarde os corpos de eventos apenas pelo mínimo, com TTL.
Criptografe o armazenamento DLQ e a réplica.


12) Versionização e compatibilidade

Versão em 'version' (envelope) e no caminho: '/webhooks/v1/payments '.
Novos campos - opcionais; remoção - somente após o período 'Sunset'.
Documente as alterações em machine-readable changelog (para a produção automática).


13) Mala de teste (folha de cheque UAT)

  • Enviar novamente o mesmo 'event _ id' → um efeito e '200' para duplicados.
  • Assinatura: chave certa, chave errada, chave antiga (rotação), 'X-Timestamp' fora da janela.
  • Backoff: o destinatário dá '429' s Retry-After '→ uma pausa correta.
  • Ordem: eventos '... processed' vem antes de '... created' → processamento/espera correto.
  • Falha de BD do destinatário entre o efeito e 'mark _ seen' → atômica/repetição.
  • DLQ e replay manual → uma entrega bem sucedida.
  • Tempestade em massa (o provedor envia pacotes) → sem perda, os limites não sufocam o crítico.

14) Mini-snippets

Assinatura do remetente (pseudo):
pseudo body = json(event)
canonical = ts + "\n" + "POST" + "\n" + path + "\n" + sha256(body)
sig = base64(hmac_sha256(secret, canonical))
headers = {"X-Timestamp": ts, "X-Event-Id": event.event_id, "X-Signature": "v1="+sig}
POST(url, body, headers)
Verificação e dedução do destinatário (pseudo):
pseudo assert abs(now - X-Timestamp) <= 300 assert timingSafeEqual(hmac(secret, canonical), sig)

if kv.exists("idemp:"+event_id): return 200

begin tx if kv.exists("idemp:"+event_id): commit; return 200 handle(event.data)        // доменная логика kv.set("idemp:"+event_id, "ok", ttl=259200)
commit return 200

15) Erros frequentes

Não há dedução → efeitos repetidos (refanda duplo/payout).
Uma assinatura sem timeling/janela → vulnerável a replay.
Armazenamento de um segredo HMAC em todos os parceiros.
Respostas de '200' antes de o resultado ser captado → perda de eventos de crash.
Limpar detalhes de segurança em respostas/logs.
Falta de DLQ/réplica - os incidentes estão pendentes.


16) Varejista de implementação

Segurança: HMAC v1 + 'X-Timestamp' + 'X-Event-Id', janela ≤ 5 min; mTLS/IP allow-list por necessidade.
Конверт: `event_id`, `type`, `version`, `ts`, `attempt`, `data`.
Entrega: at-least-once, backoff com jitter, 'Retry-After', DLQ + replay API.
Idempotidade: KV-kesh 24-72 h, atômico efeito de fixação + 'mark _ seen'.
Observabilidade: métricas de entrega, assinaturas, duplicados; traçado 'trace _ id'.
Documentação: versão, códigos de resposta, exemplos, folha de cheque UAT.


Currículos

Os webhooks resistentes são construídos em três baleias: envelope assinado, at-least-once e processamento idepotente. Formalize o contrato, inclua a HMAC/mTLS e a janela do tempo, implemente retais + DLQ e réplicas, armazene as marcas idumpotentes e capte os efeitos atômicos. Assim, os eventos permanecem confiáveis, mesmo com falhas na rede, picos de carga e raras duplicações do destino.

Contact

Entrar em contacto

Contacte-nos para qualquer questão ou necessidade de apoio.Estamos sempre prontos para ajudar!

Iniciar integração

O Email é obrigatório. Telegram ou WhatsApp — opcionais.

O seu nome opcional
Email opcional
Assunto opcional
Mensagem opcional
Telegram opcional
@
Se indicar Telegram — responderemos também por lá.
WhatsApp opcional
Formato: +indicativo e número (ex.: +351XXXXXXXXX).

Ao clicar, concorda com o tratamento dos seus dados.