Para associar um pagamento cripto ao pedido correto, crie primeiro o pedido no sistema do lojista e atribua um ID estável. Envie esse ID como contexto de uma payment invoice separada e salve o invoice ID retornado no pedido. Quando uma consulta autenticada ou webhook assinado informar paid, localize o pedido pela referência, confirme o estado da invoice, registre token, rede, valor e tx hash e execute o fulfilment de forma idempotente. A relação confiável é merchant order ID → payment invoice ID → confirmed blockchain transaction.
| Registro | O que comprova | O que não comprova sozinho |
|---|---|---|
| Pedido do lojista | Cliente, obrigação e regra de fulfilment | Que os fundos chegaram on-chain |
| Payment invoice | Token, rede, valor e janela esperados | Que o lojista entregou o produto |
| Blockchain transaction | Transferência pública de tokens | Qual pedido comercial deveria pagar |
| Evento assinado | Associação entre invoice, estado e transação | Que o efeito downstream aconteceu uma única vez |
A blockchain não contém o seu pedido
Uma blockchain registra movimento de ativos. O evento ERC-20 Transfer contém remetente, destinatário e valor; o padrão ERC-20 não contém order number, cliente, SKU ou regra de entrega. Ver 100 USDC na carteira prova uma transferência, mas não diz se ela paga ORDER-4821, uma invoice antiga ou outra obrigação.
Crie a ligação antes de entregar o checkout ao cliente. Tentar inferir depois por endereço, valor ou horário transforma qualquer coincidência em trabalho manual.
Não use address, amount ou screenshot como chave
O receiving address pode ser compartilhado por vários pagamentos. Dois clientes podem enviar o mesmo valor, alguém pode reutilizar instruções antigas e o mesmo formato 0x pode existir em redes EVM diferentes. O valor também não é único: existem preços iguais, underpayment, overpayment e arredondamento. Valores decimais incomuns podem reduzir colisões, mas não substituem foreign keys.
Quando o valor verificado for diferente da fatura, use o fluxo para pagamentos insuficientes e excessivos e mantenha o pedido fora do fulfilment automático normal.
Timestamp e sender address são apenas evidência auxiliar. Exchanges podem atrasar e agrupar saques. Screenshot não é prova e até um tx hash real pode mostrar token, recipient ou rede errada, ou já ter sido usado em outro pedido. Use o guia de verificação manual para validar a transferência.
Ligue três registros com IDs explícitos
| Campo | Onde guardar | Finalidade |
|---|---|---|
| Local order ID | Banco do lojista e payment context | Lookup e fulfilment estáveis |
| Payment invoice ID | Pedido e provedor | Consulta direta e suporte |
| Expected business amount | Pedido | Obrigação comercial |
| Payable token amount | Invoice | Valor exato do checkout |
| Token e network | Invoice e payment record | Separar rotas diferentes |
| Status e history | Payment record | Controlar a próxima ação |
| Transaction hash | Payment record final | Localizar evidência pública |
| Paid/expiry timestamps | Payment record | Tratar pagamentos atrasados |
| Event/delivery key | Webhook inbox | Evitar efeitos repetidos |
Use um database ID imutável ou UUID, não um número de exibição editável. Não coloque secret, private key ou dados pessoais desnecessários em metadata. Assim que criar a invoice, salve o ID do provedor no pedido para permitir navegação nos dois sentidos.
Crie a invoice com idempotência
O site deve validar a compra, criar o local order em payment_pending, gerar um idempotency key para aquele pedido e tentativa, criar a payment invoice com o order ID, salvar invoice ID e checkout URL e só depois redirecionar.
Timeout é ambíguo: a invoice pode ter sido criada mesmo sem a resposta chegar. Repetir com outra chave cria dois checkouts. No GramPayBot, a referência vai em payload; o mesmo Idempotency-Key com os mesmos parâmetros devolve a invoice original, enquanto a reutilização com parâmetros diferentes gera conflict. Consulte API quickstart e API reference.
Um pedido pode ter várias tentativas: order → attempt 1 expired → attempt 2 paid. Não sobrescreva a anterior. Apenas uma tentativa pode fechar o pedido automaticamente; as antigas permanecem para late-payment review.
Deixe a transição final no servidor
Browser return page não é autoridade. Use API autenticada ou webhook server-to-server assinado. Um handler seguro lê o raw body, verifica HMAC em constant time, persiste delivery e body, deduplica por chave estável, responde 2xx rapidamente e processa o pedido em worker assíncrono.
O GramPayBot pode repetir eventos reais até 17 vezes ao longo de aproximadamente quatro dias. Duplicate delivery é um mecanismo normal. As práticas oficiais de webhook da Stripe também recomendam registrar IDs processados.
Deduplicar delivery não basta: webhook e polling podem observar a mesma invoice paga. Proteja o efeito comercial com unique constraint ou conditional transition. O pedido só deve mudar a partir de payment_pending, e deve existir uma única fulfilment job por order ID. A meta é at-least-once delivery com exactly-once business effect.
Mapeie estados a ações permitidas
| Estado | Significado | Ação automática |
|---|---|---|
active | Solicitação válida sem pagamento aceito | Manter o pedido pending |
paid | Invoice atingiu a confirmação exigida | Permitir fulfilment idempotente |
expired | Janela terminou sem match aceito | Bloquear entrega normal e revisar late payment |
cancelled | Solicitação foi encerrada | Não aceitar como tentativa atual |
Payment state e order state podem ser diferentes. Uma invoice paga pode mover o pedido para ready_for_review quando há estoque ou compliance. Uma invoice expirada pode permitir nova tentativa. Preserve status history, motivo e responsável por qualquer override.
Mantenha exceções visíveis
Wrong token contract, wrong network, underpayment, overpayment, late payment, duplicate tx hash e paid invoice sem local order devem entrar em estado de exceção, não no caminho normal. Preserve a transação e deixe uma pessoa autorizada decidir entre aceitar, pedir diferença ou refund. No modelo direct-to-wallet, o lojista assina o refund; o monitor não reverte blockchain.
Operational matching também não substitui contabilidade. Finance pode precisar de fiat value, fee, conversão, documentos e histórico de refund. Faça reconciliação periódica entre paid payment attempts e paid orders, buscando registros órfãos e hashes duplicados. Os tokens EVM aparecem em smart-contract event logs, mas esses logs não conhecem o significado comercial do pedido.
Exemplo com GramPayBot
O SaaS cria ORDER-4821. O backend chama createInvoice com payload: "ORDER-4821" e Idempotency-Key: ORDER-4821:crypto:1, salva public_id e checkout URL. O cliente paga USDC em Base. O GramPayBot confirma a transação e envia invoice_paid assinado com order reference, token, rede e tx hash. O endpoint verifica, persiste e responde 2xx; o worker bloqueia o pedido pending e cria uma única ativação. Retries não ativam o plano novamente.
O guia de verificação automática explica a detecção mais ampla, e o caso de uso para sites mostra a aplicação comercial.
Antes do lançamento, repita invoice creation com a mesma chave, entregue o mesmo webhook duas vezes, deixe uma invoice expirar e teste valor incorreto sem fulfilment. A integração está pronta quando todo pedido pago pode ser seguido até uma invoice e uma transação aceita, e todo retry produz um no-op seguro ou um review item visível.
Próximo passo
Automatize a verificação no seu site
Crie uma invoice por pedido, use hosted checkout e receba um resultado ligado ao pedido.
Ver pagamentos no site →