← REST APIs: integrar aplicações e diagnosticar falhas
12 / 12 · 60 MIN

Webhooks assinados e recuperação local

Verifica origem e âmbito, preserva identidade de eventos e separa commit local de entrega a sistemas externos.

Separar a entrega do evento

Um evento lógico pode chegar várias vezes. O recetor precisa de distinguir o envelope de cada tentativa da identidade que representa o trabalho. A documentação Stripe ilustra assinaturas sobre o corpo original e entregas que podem repetir ou chegar fora de ordem. O laboratório usa um contrato próprio, sem SDK Stripe: X-Lab-Time e X-Lab-Signature autenticam timestamp, um ponto e os bytes do corpo com HMAC SHA-256. A chave é pública e didática. A janela temporal usa relógio sintético; a assinatura e a frescura não substituem deduplicação nem autorização do produtor sobre os recursos.

Validar antes de persistir

O ensaio rejeita ausência de assinatura, chave errada, corpo alterado e envelope antigo antes de inserir na inbox. A comparação usa hmac.compare_digest. Depois valida o schema, os tipos, os limites e o âmbito do produtor: a chave fictícia só autoriza tenant A. Um evento assinado para B1 continua proibido. A identidade do evento é estável entre tentativas. Se o mesmo ID reaparecer com outros bytes, o contrato didático devolve 409 e preserva o estado anterior. Esta regra é deliberadamente estrita; uma implementação real precisa de definir a equivalência de payloads e a resposta a conflitos.

Confirmar efeitos locais numa transação

A base SQLite mantém objetos, inbox e outbox. BEGIN IMMEDIATE inicia a decisão de escrita; a chave única da inbox e a transação coordenam os pedidos concorrentes deste ficheiro. Um evento novo pode atualizar o objeto e guardar intenção de notificação na outbox antes do commit. A falha didática before-commit provoca rollback dos três conjuntos de dados. Repetir depois permite executar a operação completa. Este desenho seria insuficiente se um efeito externo já tivesse ocorrido entre essas escritas. A outbox permite guardar intenção local; enviar, recuperar e reconciliar o destino exige trabalho adicional.

Tratar ordem segundo garantias explícitas

Neste contrato fictício, cada evento contém o estado completo e uma versão monotónica do recurso. Se a versão 2 já foi aplicada, a versão 1 é registada como antiga e não volta a alterar o montante. Não transportes esta regra para eventos delta: ignorar uma alteração incremental pode perder trabalho. Também não assumes que created ou o timestamp da assinatura ordenam todas as alterações de negócio. Quando o produtor não oferece a garantia necessária, define reconciliação com a fonte autoritativa. Dois IDs diferentes do mesmo tipo podem representar alterações legítimas distintas, pelo que deduplicar apenas por tipo seria destrutivo.

Comparar observações antes e depois do reinício

O código da aula anterior envia dois pedidos HTTP simultâneos com E3. Um fica aceite e outro duplicado; objeto, inbox e outbox terminam com o mesmo resultado de uma aceitação local. Depois termina o processo de forma limpa, inicia outro com o mesmo ficheiro e repete E3. A nova resposta continua a ser duplicado e a outbox não cresce. Isto demonstra persistência nesse reinício, não perda de energia, replicação ou recuperação regional. Examina evidence.json e regista a versão efetiva de Python e SQLite. O programa fecha os processos e remove a base temporária no fim.

Preparar o contrato operacional

Antes de uma integração real, define a retenção de identidades de acordo com reenvios, recuperação e obrigações aplicáveis. Se a inbox expirar antes do último reenvio permitido, uma tentativa antiga pode voltar a produzir efeitos. A monitorização deve distinguir mensagens recusadas, duplicadas, antigas, aceites localmente e pendentes de entrega. Um 200 não prova conclusão financeira. A oficina desta aula pede uma matriz de evidência e um plano para dispatcher, reconciliação e testes autorizados do destino. Todos os exemplos bancários são fictícios e não descrevem processos internos BNP Paribas. Revisão especializada independente permanece pendente.

OFICINA / WORKSHOP: 40 minutos / 40 minutes
Dados fictícios; não usar APIs bancárias ou credenciais reais.
Fictional data; do not use banking APIs or real credentials.

0-8: Guardar o código da aula anterior como run.py. Executar:
     Save the preceding lesson code as run.py. Execute:
     python3 run.py --output evidence.json
     Registar runtime, sqliteVersion, runnerSha256 e passed.
     Record runtime, sqliteVersion, runnerSha256, and passed.

8-18: Comparar / Compare:
      - raw byte change invalidates signature: 400
      - signed producer outside allowed tenant: 403
      - no untrusted event reached inbox: 0
      Explicar porque assinatura, âmbito e deduplicação são decisões separadas.
      Explain why signature, scope, and deduplication are separate decisions.

18-28: Relacionar / Relate:
       - fault rolled back inbox state and outbox
       - retry after rollback can be accepted
       - concurrent local effects occur once
       - new HTTP process deduplicates replay
       Para cada observação: identidade, estado antes/depois e limite demonstrado.
       For each observation: identity, before/after state, and demonstrated limit.

28-36: Desenhar aceitação do dispatcher sem executar pedidos externos:
       Design dispatcher acceptance without sending external requests:
       timeout após efeito / timeout after effect;
       reenvio com identidade estável / replay with stable identity;
       destino indisponível / unavailable destination;
       retenção e reconciliação / retention and reconciliation.
       Definir responsável, evidência e critério de reabertura para cada caso.
       Define an owner, evidence, and reopening criterion for each case.

36-40: Entregar matriz PT ou EN com observações e trabalho pendente.
       Deliver a PT or EN matrix with observations and remaining work.
       Não afirmar entrega externa, recuperação regional ou autenticação real.
       Do not claim external delivery, regional recovery, or real authentication.
NA PRÁTICA

E1 confirma versão 2 e uma intenção de outbox. E1 repetido não acrescenta efeitos; E0 versão 1 fica registado sem regredir o objeto.

Armadilhas comuns

Assumir execução única universal, ordenar por assinatura, deduplicar só por tipo ou confundir uma linha de outbox com entrega confirmada.

Tópicos relacionados: Pedidos e resultados · Cache e paginação · Alterações concorrentes e recuperação verificável

Leva esta ideia contigo

A evidência local deve demonstrar identidade, atomicidade e recuperação; cada sistema externo precisa de um contrato de entrega observável.

Criar conta

Referência: Receive Stripe events in your webhook endpoint · HTTP semantics RFC9110; OpenAPI3.2.1; selected primary standards and provider contracts consulted2026-09-30