Tentativas de Pagamento (Payment Retry)
O sistema de retry processa automaticamente tentativas de cobrança para faturas em atraso.
Estados da Tentativa
| Status | Descrição |
|---|---|
pending | Aguardando processamento |
processing | Sendo processada (reivindicada pelo worker) |
succeeded | Pagamento bem-sucedido |
failed | Pagamento recusado, mais tentativas disponíveis |
exhausted | Máximo de tentativas atingido |
Campos da Tentativa
| Campo | Descrição |
|---|---|
| Fatura | Fatura associada |
| Pagamento | Registro de pagamento criado |
| Número da tentativa | Sequencial (1, 2, 3...) |
| Método de pagamento | Método utilizado na tentativa |
| Valor (centavos) | Valor a ser cobrado |
| Código de falha | Motivo da recusa |
| Mensagem de falha | Descrição detalhada do erro |
| Agendado para | Data/hora da tentativa |
| Processado em | Data/hora do processamento |
| Próximo retry em | Quando a próxima tentativa será feita |
Worker de Retry
O worker executa a cada 6 horas e:
- Busca tentativas com
status=pendingescheduledFor ≤ agora - Reivindica atomicamente cada tentativa (
pending → processing) para evitar duplicação - Para cada tentativa:
- Verifica se a fatura já foi paga (pula)
- Cria registro de pagamento
- Processa o pagamento via gateway
- Em caso de sucesso:
- Marca a fatura como paga
- Cria registro de recuperação
- Remove a conta da lista de inadimplentes
- Em caso de falha:
- Se há tentativas restantes: agenda a próxima
- Se esgotou tentativas: marca como
exhaustede suspende a conta (se configurado)
Prevenção de Condições de Corrida
O sistema usa updateMany atômico com verificação de status para garantir que apenas um worker processe cada tentativa:
WHERE id = X AND status = 'pending'
SET status = 'processing'
Se count = 0, outro worker já reivindicou a tentativa.
Retry para Parcelas
Tentativas também podem ser direcionadas a parcelas específicas:
- O
metadata.installmentIdidentifica a parcela - O valor da tentativa é o da parcela, não o da fatura inteira