Módulo: Cartão de Crédito
Documentação completa do módulo de controle e liquidação de pagamentos via cartão de crédito.
Sumário
- Visão Geral
- Arquitetura e Fluxo
- Regras de Negócio
- Tabelas
- Endpoints
- Job D+1 (Automático)
- Glossário de Status
Visão Geral
O módulo de Cartão de Crédito implementa um ledger segregado para pagamentos realizados via cartão, separado do ledger financeiro global (transactions).
O fluxo possui dois momentos distintos:
- Entrada — Quando uma cobrança é paga via cartão, o valor é registrado em
card_transactionscom statusPENDING. O saldo global ainda não é afetado. - Saída / Retirada — Quando um
card_withdrawalé criado (manual ou automaticamente via job D+1), os valores pendentes são consolidados, umatransactionglobal é gerada e os registros são marcados comoWITHDRAWN.
Arquitetura e Fluxo
Cobrança paga via CREDIT_CARD
│
▼ [ChargeObserver — automático]
card_transactions
(status: PENDING)
│
├─── Job D+1 ────────────────────────────── diário, 06:00, dias úteis
│
└─── POST /card-withdrawals ─────────────── manual, acionado pelo operador
│
▼
card_withdrawals (tipo: AUTOMATIC | MANUAL)
│
▼
transactions (ledger global, tipo: credit-card-settlement)Separação de responsabilidades:
| Tabela | Responsabilidade |
|---|---|
card_transactions | Registra cada pagamento recebido via cartão. Valores bruto, taxa e líquido segregados. |
card_withdrawals | Consolida N transações de cartão em uma única retirada. |
transactions | Ledger global do sistema. Recebe o valor líquido da retirada. |
Regras de Negócio
RN-01 — Criação automática de card_transaction
Quando uma Charge tem seu status_id atualizado para paid e o campo payment_method for CREDIT_CARD, CARD ou DEBIT_CARD, o ChargeObserver cria automaticamente um registro em card_transactions.
- O
gross_amounté o valor pago (amount_paidda cobrança). - O
fee_amounté calculado com base na taxa do gateway (por padrão0até integração completa). - O
net_amount=gross_amount−fee_amount. - O
expected_settlement_dateé calculado como D+1 útil a partir dopayment_date. - O status inicial é sempre
PENDING.
RN-02 — Validação de idempotência
Antes de criar qualquer transaction global durante uma retirada, o sistema verifica se há registros PENDING no período solicitado. Se não houver, retorna 200 OK sem criar registros.
RN-03 — Retirada Manual (tipo MANUAL)
Acionada via POST /consolidation/card-withdrawals. O operador pode opcionalmente:
- Definir
payment_date_untilpara retirar apenas pagamentos até uma data específica. - Adicionar uma
notesexplicativa.
Todos os card_transactions com status = PENDING e payment_date <= payment_date_until da conta autenticada são incluídos.
RN-04 — Liquidação Automática D+1 (tipo AUTOMATIC)
O job ConsolidateCardTransactionsJob é agendado para rodar todo dia útil às 06:00.
- Agrupa
card_transactionscomstatus = PENDINGepayment_date <= ontem. - Processa cada conta em transação de banco separada (
DB::transaction). - Falhas em uma conta não afetam as demais.
- Logs são gravados em canal
daily.
RN-05 — Imutabilidade após retirada
Uma vez que um card_transaction é marcado como WITHDRAWN, ele não pode mais ser incluído em novas retiradas. O card_withdrawal_id é usado para rastreabilidade completa.
RN-06 — Geração da transaction global
A Transaction global criada na retirada segue os mesmos padrões do ledger existente:
type_id→TransactionTypecom slugcredit-card-settlement(criado automaticamente na primeira vez).value→net_amounttotal da retirada.balance→ calculado comosaldo_atual + net_amount.sequence→ incrementa o últimosequenceda conta.txid→ gerado com prefixoCC-SETTLE-(automático) ouCC-WITHDRAW-(manual).
RN-07 — Acesso por conta
Todos os endpoints são protegidos pelo middleware auth:sanctum + SetActiveAccountMiddleware + InjectAccountIntoRequest. Cada conta só enxerga seus próprios registros.
Tabelas
card_transactions
| Coluna | Tipo | Descrição |
|---|---|---|
id | bigint | PK |
account_id | FK | Conta proprietária |
charge_id | FK (nullable) | Cobrança que originou o pagamento |
acquirer | string | Gateway: pagmaxx, stripe, cielo |
acquirer_tid | string | ID da venda no gateway |
acquirer_nsu | string | NSU da transação |
brand | string | Bandeira: visa, mastercard, elo |
installments | tinyint | Número de parcelas (padrão: 1) |
payer_name | string | Nome do pagador |
payer_document | string | CPF/CNPJ do pagador |
gross_amount | decimal | Valor bruto cobrado |
fee_amount | decimal | Taxa do gateway |
net_amount | decimal | Valor líquido (gross − fee) |
status | enum | PENDING | WITHDRAWN |
payment_date | date | Data do pagamento |
expected_settlement_date | date | D+1 útil previsto |
card_withdrawal_id | FK (nullable) | Retirada que liquidou este registro |
metadata | json | Resposta bruta do gateway |
card_withdrawals
| Coluna | Tipo | Descrição |
|---|---|---|
id | bigint | PK |
account_id | FK | Conta |
transactions_count | int | Quantidade de card_transactions incluídos |
gross_amount | decimal | Soma dos valores brutos |
fee_amount | decimal | Soma das taxas |
net_amount | decimal | Valor líquido transferido |
period_start | date | Menor payment_date incluído |
period_end | date | Maior payment_date incluído |
type | enum | AUTOMATIC | MANUAL |
status | enum | COMPLETED |
transaction_id | FK (nullable) | Transaction global gerada |
requested_by | FK (nullable) | Usuário que solicitou (retiradas manuais) |
notes | text | Observações |
Endpoints
URL base:
\{base_url\}/consolidation
Autenticação: Bearer Token (Sanctum)
Headers obrigatórios:Authorization: Bearer \{token\},X-Account-Id: \{account_id\}
Transações de Cartão
GET /consolidation/card-transactions
Lista paginada das transações de cartão da conta autenticada.
Query Params
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
status | string | Não | PENDING ou WITHDRAWN |
payment_date_start | date (Y-m-d) | Não | Data inicial do pagamento |
payment_date_end | date (Y-m-d) | Não | Data final do pagamento |
per_page | integer | Não | Itens por página (padrão: 15, máx: 500) |
page | integer | Não | Página atual |
Response 200 OK
{
"success": true,
"message": "Transações de cartão recuperadas com sucesso.",
"data": {
"data": [
{
"id": 1,
"acquirer": "pagmaxx",
"acquirer_tid": "TID_ABC123",
"acquirer_nsu": "NSU_001",
"brand": "visa",
"installments": 1,
"payer": {
"name": "João Silva",
"document": "12345678900"
},
"amounts": {
"gross": 150.00,
"fee": 4.50,
"net": 145.50
},
"status": "PENDING",
"payment_date": {
"raw": "2026-04-05",
"formatted": "05/04/2026",
"iso": "2026-04-05T00:00:00.000Z"
},
"expected_settlement_date": {
"raw": "2026-04-06",
"formatted": "06/04/2026",
"iso": "2026-04-06T00:00:00.000Z"
},
"card_withdrawal_id": null,
"charge_id": 501
}
],
"current_page": 1,
"per_page": 15,
"total": 42
}
}GET /consolidation/card-transactions/summary
Totalizador do período: valores brutos, taxas e líquidos separados por status.
Query Params
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
payment_date_start | date (Y-m-d) | Não | Data inicial |
payment_date_end | date (Y-m-d) | Não | Data final |
Response 200 OK
{
"success": true,
"message": "Resumo das transações de cartão.",
"data": {
"total": {
"count": 18,
"gross": 3200.00,
"fee": 96.00,
"net": 3104.00
},
"pending": {
"count": 5,
"net": 725.50
},
"withdrawn": {
"count": 13,
"net": 2378.50
}
}
}Retiradas (Withdrawals)
GET /consolidation/card-withdrawals
Histórico de retiradas realizadas pela conta.
Query Params
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
created_at_start | date (Y-m-d) | Não | Data inicial de criação |
created_at_end | date (Y-m-d) | Não | Data final de criação |
per_page | integer | Não | Itens por página (padrão: 15) |
Response 200 OK
{
"success": true,
"message": "Retiradas de cartão recuperadas com sucesso.",
"data": {
"data": [
{
"id": 3,
"type": "MANUAL",
"status": "COMPLETED",
"transactions_count": 5,
"amounts": {
"gross": 850.00,
"fee": 25.50,
"net": 824.50
},
"period": {
"start": { "raw": "2026-04-01", "formatted": "01/04/2026" },
"end": { "raw": "2026-04-04", "formatted": "04/04/2026" }
},
"transaction_id": 9012,
"transaction": {
"id": 9012,
"txid": "CC-WITHDRAW-A1B2C3D4",
"description": "Retirada de Cartão Manual — 5 transação(ões)...",
"value": 824.50,
"balance": 10824.50
},
"notes": "Retirada quinzenal",
"created_at": { "raw": "2026-04-06", "formatted": "06/04/2026" }
}
],
"total": 3
}
}POST /consolidation/card-withdrawals
Cria uma retirada manual. Consolida todos os card_transactions com status = PENDING e payment_date <= payment_date_until.
Importante: Esta operação é atômica. Cria o
CardWithdrawal, aTransactionglobal e marca as transações comoWITHDRAWNem uma única transação de banco. Em caso de erro, tudo é revertido.
Request Body
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
payment_date_until | date (Y-m-d) | Não | Inclui transações até esta data (padrão: ontem) |
notes | string | Não | Observação sobre a retirada (máx. 500 caracteres) |
Exemplo
{
"payment_date_until": "2026-04-05",
"notes": "Retirada quinzenal de cartão"
}Response 201 Created
{
"success": true,
"message": "Retirada realizada com sucesso! Saldo transferido para o ledger global.",
"data": {
"id": 4,
"type": "MANUAL",
"status": "COMPLETED",
"transactions_count": 7,
"amounts": {
"gross": 1200.00,
"fee": 36.00,
"net": 1164.00
},
"period": {
"start": { "raw": "2026-03-30", "formatted": "30/03/2026" },
"end": { "raw": "2026-04-05", "formatted": "05/04/2026" }
},
"transaction_id": 9100,
"transaction": {
"id": 9100,
"txid": "CC-WITHDRAW-F5E4D3C2",
"value": 1164.00,
"balance": 12988.00
}
}
}Erro — Sem saldo pendente (200 OK)
{
"success": true,
"message": "Não há transações de cartão pendentes para retirada neste período.",
"data": null
}GET /consolidation/card-withdrawals/\{id\}
Detalhe de uma retirada específica, incluindo a lista de card_transactions liquidadas.
Path Params
| Parâmetro | Tipo | Descrição |
|---|---|---|
id | integer | ID da retirada |
Response 200 OK — igual ao POST, com cardTransactions adicionado.
POST /consolidation/card-withdrawals/run-d1-job
Dispara manualmente o job D+1 de liquidação automática. Uso administrativo.
Não requer body. O job é enfileirado na fila padrão do sistema.
Response 200 OK
{
"success": true,
"message": "Job de liquidação D+1 disparado com sucesso.",
"data": null
}Job D+1 Automático
ConsolidateCardTransactionsJob
Arquivo: app/Jobs/ConsolidateCardTransactionsJob.php
Agendamento: Todo dia útil às 06:00 (configurado em routes/console.php)
Fila: padrão
Tentativas: 3 (backoff: 60 segundos)
Processo:
1. Define `until` = ontem (Carbon::yesterday())
2. Busca account_ids com card_transactions PENDING até `until`
3. Para cada conta:
a. Inicia DB::transaction
b. Coleta os IDs dos card_transactions a liquidar
c. Cria Transaction global (tipo: credit-card-settlement)
d. Cria CardWithdrawal (tipo: AUTOMATIC)
e. Atualiza card_transactions → status=WITHDRAWN, card_withdrawal_id=N
f. Commit
4. Erros por conta são logados no canal `daily` sem interromper as demaisTransactionType criado automaticamente:
| Slug | Name |
|---|---|
credit-card-settlement | Liquidação Cartão de Crédito |
Glossário de Status
card_transactions.status
| Valor | Descrição |
|---|---|
PENDING | Recebido, aguardando retirada. Não impacta o saldo global. |
WITHDRAWN | Liquidado e incluído em um card_withdrawal. |
card_withdrawals.type
| Valor | Descrição |
|---|---|
AUTOMATIC | Gerado pelo job D+1 |
MANUAL | Criado via endpoint pelo operador |
card_withdrawals.status
| Valor | Descrição |
|---|---|
COMPLETED | Retirada concluída e Transaction global criada |