Sistema de Processamento de Boletos - Arquitetura Completa
📋 Visão Geral
API Externa → Job 1 → Job 2 → Event → Listeners (Webhook + Email + Notificações)
↓ ↓
Boletos Charges + Transactions🗂️ Estrutura de Arquivos
app/
├── Jobs/
│ ├── FetchBoletosJob.php # Job 1: Buscar boletos da API
│ └── ProcessBoletosJob.php # Job 2: Processar boletos
│
├── Events/
│ └── BoletoProcessado.php # Evento disparado após processamento
│
├── Listeners/
│ ├── SendBoletoWebhook.php # Envia webhook
│ └── SendBoletoEmail.php # Envia email
│
├── Models/
│ ├── Boleto.php # Model de Boleto
│ ├── Charge.php # Model de Cobrança
│ └── Transaction.php # Model de Transação
│
├── Services/
│ ├── ExternalBoletoService.php # Integração com API externa
│ └── WebhookService.php # Serviço de envio de webhooks
│
└── Console/
└── Kernel.php # Agendamento dos jobs🔄 Fluxo Detalhado
Job 1: FetchBoletosJob.php
Responsabilidade: Buscar boletos pagos da API externa e sincronizar com o banco de dados
Execução: A cada 15 minutos (configurável)
Processo:
- Faz requisição HTTP para API externa
- Recebe lista de boletos pagos
- Para cada boleto:
- Verifica se já existe (por
external_id) - Atualiza ou cria registro
- Define status como
aguardando_processamento
- Verifica se já existe (por
- Loga quantidade de boletos sincronizados
Características:
- ✅ Idempotente: Pode ser executado múltiplas vezes sem duplicar dados
- ✅ Retry automático: 3 tentativas com backoff exponencial
- ✅ Logging: Registra todas as operações
- ✅ Tratamento de erros: Captura exceções da API
php
Status após Job 1: aguardando_processamentoJob 2: ProcessBoletosJob.php
Responsabilidade: Processar boletos e criar toda a estrutura financeira
Execução: A cada 5 minutos (configurável)
Processo:
- Busca boletos com status
aguardando_processamento - Processa cada boleto em chunks de 50
- Dentro de uma transação de banco de dados:
- Atualiza status do Boleto para
recebido - Busca a Charge relacionada
- Atualiza status da Charge para
paid - Cria uma Transaction associada
- Registra data/hora do processamento
- Atualiza status do Boleto para
- Após commit da transação:
- Dispara evento
BoletoProcessado
- Dispara evento
- Se houver erro, faz rollback completo
Características:
- ✅ Atômico: Tudo ou nada (transação de BD)
- ✅ Batch processing: Processa em lotes
- ✅ Event-driven: Dispara evento após sucesso
- ✅ Idempotente: Verifica se já foi processado
- ✅ Unique lock: Evita processamento concorrente do mesmo boleto
php
Status após Job 2:
- Boleto: recebido
- Charge: paid
- Transaction: createdEvent: BoletoProcessado.php
Responsabilidade: Evento que carrega dados do boleto processado
Dados transportados:
- ID do boleto
- ID da charge
- ID da transaction
- Valor pago
- Data do pagamento
- Dados do cliente
Listener 1: SendBoletoWebhook.php
Responsabilidade: Enviar notificação webhook para o cliente
Execução: Automática ao evento BoletoProcessado
Processo:
- Verifica se o cliente tem webhook configurado
- Prepara payload com dados do pagamento
- Envia requisição HTTP POST
- Registra resposta (sucesso/falha)
- Em caso de falha:
- Tenta novamente (3x com backoff)
- Registra em log para análise manual
Características:
- ✅ Assíncrono: Não bloqueia o processamento
- ✅ Retry automático: 3 tentativas
- ✅ Logging: Registra todas as tentativas
- ✅ Timeout: 10 segundos por requisição
Listener 2: SendBoletoEmail.php
Responsabilidade: Enviar email de confirmação de pagamento
Execução: Automática ao evento BoletoProcessado
Processo:
- Verifica se o cliente tem email configurado
- Busca template de email
- Substitui variáveis (nome, valor, data)
- Envia email via queue
- Registra envio
Características:
- ✅ Assíncrono: Não bloqueia o processamento
- ✅ Queue: Usa fila separada (emails)
- ✅ Template: Usa blade templates
- ✅ Retry automático: 3 tentativas
🗄️ Estrutura de Banco de Dados
Tabela: boletos
sql
id BIGINT PRIMARY KEY
external_id VARCHAR(255) UNIQUE -- ID na API externa
charge_id BIGINT FOREIGN KEY
nosso_numero VARCHAR(255)
valor DECIMAL(10,2)
data_vencimento DATE
data_pagamento DATETIME NULL
valor_pago DECIMAL(10,2) NULL
status ENUM('pendente', 'aguardando_processamento', 'recebido', 'erro')
processed_at DATETIME NULL
created_at DATETIME
updated_at DATETIMETabela: charges
sql
id BIGINT PRIMARY KEY
customer_id BIGINT FOREIGN KEY
valor DECIMAL(10,2)
status ENUM('pending', 'paid', 'cancelled')
tipo ENUM('boleto', 'pix', 'cartao')
created_at DATETIME
updated_at DATETIMETabela: transactions
sql
id BIGINT PRIMARY KEY
charge_id BIGINT FOREIGN KEY
boleto_id BIGINT FOREIGN KEY
tipo VARCHAR(50) -- 'payment'
valor DECIMAL(10,2)
data_transacao DATETIME
status ENUM('pending', 'completed', 'failed')
created_at DATETIME
updated_at DATETIME⚙️ Configuração (Kernel.php)
php
protected function schedule(Schedule $schedule)
{
// Job 1: Buscar boletos da API externa
$schedule->job(new FetchBoletosJob)
->everyFifteenMinutes()
->withoutOverlapping()
->onOneServer();
// Job 2: Processar boletos pendentes
$schedule->job(new ProcessBoletosJob)
->everyFiveMinutes()
->withoutOverlapping()
->onOneServer();
}🔒 Garantias de Segurança
1. Idempotência
- Cada job pode ser executado múltiplas vezes sem duplicar dados
- Uso de
updateOrCreatee verificações de status
2. Atomicidade
- Transações de banco de dados garantem consistência
- Rollback automático em caso de erro
3. Prevenção de Race Conditions
php
// Usa cache lock para evitar processamento concorrente
Cache::lock('process-boleto-' . $boleto->id, 10)->get(function() {
// Processa boleto
});4. Dead Letter Queue
- Jobs que falham após todas as tentativas vão para
failed_jobs - Podem ser reprocessados manualmente
5. Logging Completo
- Todas as operações são logadas
- Facilita auditoria e debugging
📊 Monitoramento
Métricas Importantes
- Boletos sincronizados (Job 1)
- Boletos processados (Job 2)
- Webhooks enviados com sucesso
- Emails enviados com sucesso
- Jobs que falharam
- Tempo médio de processamento
Commands Úteis
bash
# Ver jobs falhados
php artisan queue:failed
# Reprocessar job falhado
php artisan queue:retry \{id\}
# Reprocessar todos
php artisan queue:retry all
# Limpar jobs falhados
php artisan queue:flush🚨 Tratamento de Erros
Cenário 1: API Externa Fora
- ❌ Job 1 falha
- ✅ Retry automático (3x)
- ✅ Se todas falham, job vai para
failed_jobs - ✅ Boletos não são marcados incorretamente
Cenário 2: Erro ao Processar Boleto
- ❌ Job 2 falha no meio da transação
- ✅ Rollback automático do banco
- ✅ Boleto permanece como
aguardando_processamento - ✅ Será reprocessado na próxima execução
Cenário 3: Webhook Falha
- ❌ Webhook retorna erro
- ✅ Não afeta processamento do boleto
- ✅ Retry automático (3x)
- ✅ Registrado para análise manual
Cenário 4: Email Falha
- ❌ SMTP retorna erro
- ✅ Não afeta processamento do boleto
- ✅ Retry automático (3x)
- ✅ Registrado para análise manual