Blog

Autorização e captura: dois eventos, dois riscos.

Pagamento com cartão parece uma operação: o cliente paga.

São duas, separadas no tempo, e cada uma tem um risco diferente. Sistema que modela como uma coisa só acaba com duas categorias de problema que ninguém consegue explicar depois.

O que cada uma significa

Autorização é uma reserva. O emissor confirma que o limite existe e bloqueia o valor. O dinheiro não saiu de lugar nenhum: ficou comprometido.

Captura é a cobrança de fato. Você diz ao adquirente “pode levar”, e aí o valor entra no fluxo de liquidação.

Entre uma e outra pode passar um segundo ou vários dias. E a autorização expira sozinha, tipicamente numa janela de dias que varia por bandeira e por tipo de transação.

Se você capturar depois da expiração, a captura falha. O cliente já viu o valor bloqueado no cartão dele e você não recebeu nada.

Por que separar

O modelo de captura automática, tudo junto, é o certo pra venda digital com entrega imediata. Não separe se você não precisa.

A separação vale em três situações.

Quando existe risco de não conseguir entregar. Produto físico com estoque incerto: autoriza no checkout, captura no envio. Se o estoque falhar, você cancela a autorização em vez de cobrar e estornar.

Quando o valor final muda. Combustível, hotel, aluguel de carro. Autoriza uma estimativa, captura o valor real.

Quando existe análise antifraude demorada. Autoriza, analisa, captura se aprovar.

Em todas, a lógica é a mesma: reservar o dinheiro é barato e reversível, cobrar não é.

Cancelar não é estornar

Distinção que gera confusão e custa dinheiro.

Cancelamento é desfazer a autorização antes da captura. O bloqueio some, nenhum dinheiro se moveu, e o custo é próximo de zero.

Estorno é devolver depois da captura. O dinheiro já circulou, tem taxa envolvida em muitos arranjos, e aparece no extrato do cliente como duas linhas.

Sistema que só implementa estorno acaba capturando e devolvendo em situações onde bastava cancelar. Isso custa taxa, gera confusão no cliente e polui a conciliação.

O modelo de dados

O erro estrutural mais comum é uma tabela payments com uma coluna status.

-- não representa a realidade
create table payments (
  id uuid primary key,
  order_id uuid,
  amount_minor bigint,
  status text  -- 'authorized' | 'captured' | 'refunded' ...
);

Isso não representa captura parcial, não representa duas capturas da mesma autorização, e não representa estorno parcial. Todas as três são situações normais.

O que representa:

create table payment_authorization (
  id                uuid primary key,
  order_id          uuid not null,
  provider          text not null,
  provider_auth_id  text not null,
  amount_minor      bigint not null,
  captured_minor    bigint not null default 0,
  status            text not null,   -- 'authorized','expired','cancelled','captured'
  authorized_at     timestamptz not null,
  expires_at        timestamptz not null,
  unique (provider, provider_auth_id)
);

create table payment_capture (
  id                uuid primary key,
  authorization_id  uuid not null references payment_authorization(id),
  provider_capture_id text not null,
  amount_minor      bigint not null,
  captured_at       timestamptz not null,
  unique (provider, provider_capture_id)
);

Uma autorização, N capturas. Cada captura com seu identificador do provedor e sua constraint única, que é o que impede notificação reenviada de virar dinheiro contado duas vezes.

E cada uma dessas operações gera lançamento no ledger, em contas diferentes: autorização não é receita, é compromisso.

A expiração é problema seu

O adquirente não vai te avisar que a autorização venceu. Ela simplesmente para de funcionar.

Um job que roda todo dia procurando autorização perto do vencimento sem captura é obrigatório em qualquer sistema com captura postergada:

select * from payment_authorization
where status = 'authorized'
  and captured_minor = 0
  and expires_at < now() + interval '24 hours';

Cada linha é uma decisão pendente: capturar, cancelar ou reautorizar. Deixar vencer em silêncio é a forma mais comum de perder venda que já estava aprovada.

A janela em que tudo dá errado

Entre autorizar e capturar, três coisas podem acontecer, e o sistema precisa de resposta pra todas.

O cliente cancela o pedido. Você cancela a autorização, não estorna.

O estoque acabou. Mesma coisa, e é o caso que justifica a separação existir.

O cartão foi bloqueado por fraude entre os dois momentos. A captura falha, e o pedido precisa voltar pra um estado que permita nova tentativa de pagamento, não sumir.

Esse terceiro caso é o mais esquecido, e produz o pedido que fica preso em “aguardando pagamento” pra sempre, até alguém do suporte mexer na mão.

O que registrar

Cada mudança de estado precisa virar evento, com o payload cru do provedor guardado.

Seis meses depois, quando alguém perguntar por que aquele pedido foi entregue sem pagamento, a resposta vai estar na sequência de eventos ou não vai existir. Escrevi sobre esse desenho em log append-only.

E guarde sempre os identificadores do provedor, mesmo os que você não usa hoje. É a única chave que permite conciliar depois, e recuperar isso retroativamente é impossível.

← Voltar pro blog