Skip to main content
Fulfillment é a ação que acontece depois do pagamento: liberar acesso, reservar estoque, emitir ingresso, iniciar serviço ou marcar um pedido como pago. Essa decisão deve acontecer no seu backend a partir de um webhook assinado — nunca apenas porque o comprador chegou à success_url.

Escolha o sinal correto

checkout.session.status: "complete" significa que o comprador concluiu o formulário. Não significa, sozinho, que Pix ou boleto foi pago. Confira sempre payment_status ou aguarde o evento assíncrono de sucesso.
Trials e compras de valor zero podem chegar a no_payment_required. Trate esse caso como uma regra explícita de acesso, separada da confirmação de dinheiro recebido. No checkout hospedado, a Chargefy tenta entregar checkout.session.completed imediatamente e aguarda um 2xx por até 10 segundos antes de seguir para a success_url. Responda somente depois de persistir o evento de forma durável, mas não execute trabalho demorado dentro dessa resposta. Se o endpoint falhar ou estourar o prazo, a fila continua as tentativas sem bloquear o comprador. Para ligar esse processamento à experiência do comprador, siga o guia Após receber com um Checkout. Ele mostra como usar uma tela de ativação, polling no seu backend e reconciliação sem transformar um atraso em uma nova tentativa de compra.

Fluxo recomendado

1

Correlacione com seu pedido

Salve um identificador estável, como order_id, em metadata ao criar a checkout session, o payment intent ou a invoice daquele pedido. Em payment links reutilizáveis, use metadata apenas para campanha ou canal e correlacione a compra pela checkout session materializada em cada acesso. No webhook, use esses dados para localizar o pedido sem depender de busca por e-mail ou valor.
2

Verifique e deduplique

Valide a assinatura sobre o corpo bruto. Depois, tente inserir o id do evento em uma tabela com restrição de unicidade. Se ele já existe, responda 2xx e não repita o processamento.
3

Confirme o estado financeiro

Confira o status no data.object. Se eventos chegaram fora de ordem ou o objeto local está desatualizado, consulte o recurso atual pela API antes de tomar uma decisão irreversível.
4

Trave a operação de negócio

Atualize o pedido com uma condição atômica, por exemplo de awaiting_payment para fulfilling. Se outro worker já mudou o estado, encerre sem executar a entrega novamente.
5

Registre o resultado

Guarde o recurso financeiro usado, o momento da entrega e a chave do efeito externo. Isso permite suporte, retry controlado e conciliação posterior.

Duas camadas de idempotência

Deduplique em dois níveis:
  1. Evento: o mesmo evt_... pode ser reentregue. Uma chave única impede que o mesmo payload rode duas vezes.
  2. Ação de negócio: eventos diferentes podem representar o mesmo resultado, e endpoints distintos recebem IDs próprios. Uma restrição por pedido, invoice ou período impede duas ativações, dois ingressos ou duas remessas.
Esse segundo nível é essencial para plataformas e para fluxos que escutam tanto eventos de checkout quanto de payment intent.

Não dependa da ordem

Eventos diferentes não têm garantia de ordem global. Um worker pode ver payment.intent.succeeded antes de outro evento criado segundos antes. Modele handlers como aplicação de estado:
  • estados finais não voltam para estados anteriores;
  • uma duplicata é sucesso sem novo efeito;
  • um evento antigo não desfaz uma decisão mais recente;
  • quando a ordem importa, consulte o objeto atual pela API.

Falha durante a entrega

Separar “pagamento confirmado” de “produto entregue” permite retry sem cobrar de novo. Se seu provedor de e-mail, estoque ou acesso falhar:
  • mantenha o pedido em um estado intermediário, como fulfilling ou fulfillment_failed;
  • repita apenas o efeito de fulfillment, usando uma chave idempotente própria;
  • não crie outro payment intent;
  • alerte a operação depois do limite de tentativas.

Reembolsos e disputas

Fulfillment não termina no evento de sucesso. Defina uma política separada para:
  • refund.* ou charge.refunded: cancelar acesso, registrar devolução ou iniciar logística reversa quando aplicável;
  • charge.dispute.*: restringir benefício, preservar evidências e acionar o fluxo de contestação;
  • reembolso parcial: ajustar apenas a parte do pedido ligada ao valor devolvido.
Não apague o histórico de entrega. Registre a compensação como uma nova transição auditável.

Plataformas

Em endpoints com events_from: platform, leia o campo top-level organization antes de resolver o pedido. Ele identifica a organização conectada que originou o evento. Valide que o pedido pertence à mesma organização antes de liberar qualquer coisa.

Após receber com um Checkout

Conecte webhook, worker e página de ativação sem depender do redirect.

Entrega de webhooks

Implemente assinatura, reentrega e deduplicação.

Ciclo de pagamento

Entenda qual objeto é fonte da verdade em cada etapa.

Reembolsar pagamento

Devolva valores e acompanhe o resultado financeiro.

Responder a disputas

Organize evidências, prazos e estados da contestação.