Skip to main content
Este guia é para desenvolvedores que implementam a integração com o plugin Bank Transfer. Ele cobre os padrões e decisões que vão além de chamadas individuais de endpoint: idempotência, estratégia de retry, gerenciamento de estado e validação de webhooks. Para parâmetros de endpoint e esquemas de resposta, consulte a Referência da API.

Idempotência


Toda requisição de mutação (initiate, process, cancel) requer um cabeçalho X-Idempotency. Se você enviar a mesma chave duas vezes, o plugin retorna a resposta original sem criar uma operação duplicada. Regras:
  • Use um UUID v4 ou um identificador de negócio único (ex: o ID interno do seu pedido)
  • Comprimento máximo: 255 caracteres
  • O plugin atribui cada chave à organização efetiva. A mesma chave de duas organizações conta como duas requisições distintas.
  • O plugin retorna uma resposta em cache durante a janela de idempotência configurada (IDEMPOTENCY_RETRY_WINDOW_SEC, padrão 300 segundos)
  • Uma resposta reenviada é byte-idêntica à original: mesmo status code, mesmo body. A resposta não tem um cabeçalho para marcar um replay, então projete seu cliente para ser seguro em qualquer caso.
Não reutilize chaves de idempotência em operações diferentes. Não reutilize uma chave de initiate para processar ou cancelar a mesma transferência.

Detecção de duplicatas

Além das chaves de idempotência, o plugin detecta duplicatas baseadas em conteúdo. Ele gera um fingerprint a partir de:
  • senderAccountId
  • dados do destinatário (ISPB, agência, conta, documento do titular)
  • valor
  • finalidade
O plugin armazena o fingerprint no Redis por 5 minutos. O padrão é 300 segundos. Os operadores o ajustam por tenant através da configuração de systemplane idempotency.duplicate_guard_ttl_seconds. A organização não faz parte do fingerprint. O isolamento de tenant vem do prefixo da chave Redis. O plugin rejeita a requisição com 409 BTF-0012 se o cliente já enviou uma transferência correspondente dentro da janela. Isso captura casos em que o cliente envia a mesma transferência com uma chave de idempotência diferente. Um exemplo é uma nova tentativa após um timeout, quando o cliente não recebeu a resposta original.

Estratégia de retry


Use backoff exponencial para erros transientes. Não tente novamente todos os erros. Cronograma de backoff recomendado para 5xx/503: 0s, 5s, 25s, 60s, 120s (5 tentativas no total).
Quando o JD SPB está indisponível, a resposta é HTTP 503. O campo error.code carrega então o código do fornecedor JD sem transformação — por exemplo, TRANSPORT para falhas de transporte ou ACE95 para timeouts. O plugin não envelopa as falhas da cadeia JD em um código BTF-. Sinalize a transferência para reconciliação manual depois que as tentativas se esgotarem. Não tente novamente sem limite. A rede JD SPB tem horários de funcionamento definidos.

Gerenciamento de estado


Máquina de estados do TED OUT

As transferências seguem uma progressão estrita. Você não pode cancelar uma transferência depois que ela sai de CREATED ou PENDING.
Máquina de estados TED OUT
O que fazer em cada estado:

Máquina de estados da iniciação

O endpoint de initiate cria uma entidade PaymentInitiation. Essa entidade tem seu próprio ciclo de vida antes de o plugin criar um Transfer.
Máquina de estados da iniciação

Máquina de estados do TED IN

Máquina de estados TED IN

Máquina de estados do P2P

O P2P não tem um estado PENDING. A liquidação é atômica e instantânea.
Máquina de estados P2P

Polling vs. webhooks

Prefira webhooks para status em tempo real. Se você ainda não configurou os webhooks, faça polling em GET /v1/transfers/{transferId}. Use no máximo 10 tentativas com o mesmo cronograma de backoff do retry. Sinalize a transferência para revisão manual após 10 minutos sem um estado terminal (COMPLETED, REJECTED, FAILED, CANCELLED). Consulte Obter Transferência e Webhooks.

Integração com webhooks


Para esquemas de payload de eventos e a lista completa de eventos, consulte Webhooks.

Validação de assinatura

Toda requisição de webhook inclui cabeçalhos que seu endpoint usa para verificar a autenticidade:
  • X-Webhook-Signature — assinatura HMAC-SHA256 versionada no formato v1,sha256=<hex>
  • X-Webhook-Timestamp — timestamp Unix em segundos (UTC) de quando o plugin construiu a requisição
  • X-Webhook-Event — o tipo de evento (por exemplo, transfer.completed). Este cabeçalho não faz parte da assinatura.
O plugin calcula a assinatura assim:
A string assinada tem quatro partes em ordem: o prefixo v1:, o valor do timestamp de X-Webhook-Timestamp, um único ponto ASCII (.) e depois os bytes brutos do corpo da requisição. Use os bytes do corpo exatamente como chegam pelo fio. Não os analise nem os recodifique primeiro. Para validar:
  1. Leia X-Webhook-Signature e X-Webhook-Timestamp dos cabeçalhos da requisição.
  2. Construa a string assinada: "v1:" + timestamp + "." + rawBody.
  3. Calcule HMAC-SHA256 sobre a string assinada com seu WEBHOOK_SIGNING_SECRET, depois codifique o resultado em hex.
  4. Anteponha v1,sha256=, depois compare contra X-Webhook-Signature com uma função de igualdade de tempo constante.
  5. Rejeite a requisição se o timestamp estiver fora de uma janela de frescor aceitável (uma tolerância de 5 minutos é típica) para prevenir replay.
Além de X-Webhook-Signature e X-Webhook-Timestamp, o plugin define apenas X-Webhook-Event (o tipo de evento). Ele não envia X-Webhook-Event-Type, X-Webhook-Routing-Key nem X-Webhook-Delivery-Attempt.

Processamento idempotente de webhooks

Seu endpoint pode receber o mesmo evento mais de uma vez (entrega at-least-once). Use transferId + event como chave composta para deduplicar.

Padrões de tratamento de erros


Mapeie códigos de erro da API para ações voltadas ao usuário. Consulte a lista completa de erros para todos os códigos. As respostas de erro seguem esta estrutura:

Checklist para entrar em produção


Antes de habilitar a integração em produção:
  • Envie X-Idempotency em cada requisição de initiate, process e cancel
  • Lógica de retry implementada com backoff exponencial para erros 5xx/503
  • Endpoint de webhook implantado e retornando 200 em até 5 segundos
  • Validação de assinatura ativa no endpoint de webhook
  • Deduplicação de eventos de webhook implementada usando transferId + event
  • Horários de funcionamento validados no lado do cliente antes de chamar initiate (reduz 422s desnecessários)
  • Tanto transferId quanto confirmationNumber armazenados para reconciliação
  • Estados terminais (COMPLETED, REJECTED, FAILED, CANCELLED) tratados na UI
  • Expiração da iniciação (24h) tratada — solicite ao usuário que reinicie quando a janela encerrar
  • Readiness do serviço monitorado no seu sistema de alertas para deployments BYOC
  • Redis acessível e monitorado — o serviço rejeita requisições quando o Redis está fora do ar
  • PLUGIN_AUTH_ENABLED=true configurado em produção, com um PLUGIN_AUTH_ADDRESS válido (HTTPS)