Skip to content

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:

  1. Faz requisição HTTP para API externa
  2. Recebe lista de boletos pagos
  3. Para cada boleto:
    • Verifica se já existe (por external_id)
    • Atualiza ou cria registro
    • Define status como aguardando_processamento
  4. 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_processamento

Job 2: ProcessBoletosJob.php

Responsabilidade: Processar boletos e criar toda a estrutura financeira

Execução: A cada 5 minutos (configurável)

Processo:

  1. Busca boletos com status aguardando_processamento
  2. Processa cada boleto em chunks de 50
  3. 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
  4. Após commit da transação:
    • Dispara evento BoletoProcessado
  5. 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: created

Event: 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:

  1. Verifica se o cliente tem webhook configurado
  2. Prepara payload com dados do pagamento
  3. Envia requisição HTTP POST
  4. Registra resposta (sucesso/falha)
  5. 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:

  1. Verifica se o cliente tem email configurado
  2. Busca template de email
  3. Substitui variáveis (nome, valor, data)
  4. Envia email via queue
  5. 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          DATETIME

Tabela: 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          DATETIME

Tabela: 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 updateOrCreate e 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

  1. Boletos sincronizados (Job 1)
  2. Boletos processados (Job 2)
  3. Webhooks enviados com sucesso
  4. Emails enviados com sucesso
  5. Jobs que falharam
  6. 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

FastGivr API Documentation