Payment Config
Visão Geral
Múltiplos gateways de pagamento (Stripe, Stone, Rede, MercadoPago, MFE/SAT) coexistem e podem ser selecionados por canal e filial. O PaymentConfigService é o roteador que decide qual gateway atende cada transação.
Princípio de cascata: se gateway primário falha (timeout, taxa de erro alta), o sistema automaticamente tenta o próximo configurado. Operação não para por outage de um único provider.
Localização
| Camada | Arquivo |
|---|---|
| Module | backend/src/payment-config/payment-config.module.ts |
| Service | backend/src/payment-config/payment-config.service.ts |
| Schema | backend/src/payment-config/schemas/payment-config.schema.ts |
| Health monitor | backend/src/payment-config/gateway-health.service.ts |
| View | frontend-react/src/views/admin/PaymentConfigView.tsx |
Rota
/t/:slug/admin/payment-config (sub-aba dentro de Configurações)
PaymentConfig Schema
| Campo | Tipo | Descrição |
|---|---|---|
tenant | ObjectId | Tenant |
branch | ObjectId? | null = configuração default do tenant; setado = override por filial |
channel | enum | pdv | balcao | kiosk | delivery | online_checkout |
paymentMethod | enum | credit | debit | pix | voucher | cash |
cascade | object[] | Ordem de gateways a tentar (com fallback) |
active | boolean |
Cada item da cascade:
| Campo | Tipo |
|---|---|
provider | enum: stripe | stone | rede | mercadopago | sitef | rede_tef |
priority | number (1 = primeiro a tentar) |
credentialsRef | string (ref para integration record) |
enabled | boolean |
maxRetries | number |
timeoutMs | number |
Flow de Roteamento
PaymentConfigService.resolveGateway(tenantId, branchId, channel, method):
- Lookup PaymentConfig com
(tenant, branch, channel, method). Se não existir, fallback(tenant, null, channel, method)— config default. - Lê
cascadeordenada por priority - Para cada gateway, verifica:
enabled: truegatewayHealth.isHealthy(provider, last5min)— circuit breaker integrado
- Retorna o primeiro healthy. Se nenhum, retorna o primeiro do cascade (best-effort).
Result:
{
provider: 'stripe',
credentials: { ... },
fallbackChain: ['stone', 'rede'], // próximas tentativas se stripe falhar
}PaymentService consome esse resultado e tenta a transação. Em failure, automaticamente tenta fallbackChain[0], e assim por diante.
Circuit Breaker
GatewayHealthService mantém em Redis sliding-window 5min:
gateway:{provider}:errors_5min— counter de falhasgateway:{provider}:total_5min— counter total
isHealthy(provider) retorna false quando errors_5min / total_5min > 0.3 (>30% error rate).
Gateway entra em half-open após 60s — permite 1 transação de teste; sucesso fecha o circuit, falha mantém aberto.
Visualização: Sistema → Pagamentos → Health mostra status por gateway com sparkline de error rate.
Endpoints
| Método | Rota | Permissão |
|---|---|---|
GET | /admin/payment-config | settings.manage.integrations |
PUT | /admin/payment-config | settings.manage.integrations |
GET | /admin/payment-config/health | audit_log.view |
POST | /admin/payment-config/test/:provider | settings.manage.integrations |
POST .../test/:provider faz uma transação de R$ 0,01 com auto-reverso para validar credenciais sem custo real.
Configurações Comuns
Default do tenant (sem branch override)
{
"channel": "pdv",
"paymentMethod": "credit",
"cascade": [
{ "provider": "stone", "priority": 1, "enabled": true },
{ "provider": "rede", "priority": 2, "enabled": true },
{ "provider": "stripe", "priority": 3, "enabled": false }
]
}PDV cartão crédito: tenta Stone primeiro (terminal físico TEF), Rede como backup, Stripe nunca (não usado em PDV físico).
Filial específica com gateway próprio
Filial centro tem contrato com Cielo (gateway proprietário não suportado nativamente). Override:
{
"branch": "<centro>",
"channel": "pdv",
"paymentMethod": "credit",
"cascade": [
{ "provider": "rede", "priority": 1, "enabled": true }
]
}Resto das filiais segue o default do tenant.
Online checkout com Pix Stripe
{
"channel": "online_checkout",
"paymentMethod": "pix",
"cascade": [
{ "provider": "mercadopago", "priority": 1 },
{ "provider": "stripe", "priority": 2 }
]
}MP é primeira escolha para PIX brasileiro (UX melhor); Stripe BR como backup.
Race Conditions
Gateway resolution + transaction submission não é atômico. Cenário:
- T0: resolveGateway returns
stripe - T1: stripe entra em outage (3s depois)
- T2: transação é submetida → falha
- PaymentService captura erro, marca circuit, tenta
fallbackChain[0](stone)
Tempo total adicional: ~3s timeout + 100ms retry. Aceitável para fluxo síncrono de PDV.
Para PDV TEF (Sitef/Rede via terminal físico), cascade não funciona — operador escolhe manualmente o terminal usado. Cascade é apenas para gateways de internet.
Audit
Cada mudança em PaymentConfig é audit-logged:
payment_config.cascade.updatedpayment_config.gateway.disabledpayment_config.test.executed
Mudança de cascade é alta criticidade — se admin desabilita um gateway acidentalmente, pode parar pagamentos. Audit + alerta verbal no UI ("Confirmar — esta ação afeta pagamentos imediatamente").
Limitações
- Cascade não considera latência — só health (binary). Gateway lento mas online é tratado como healthy. Roadmap: latency-aware routing.
- Fees/taxas não influenciam roteamento — se Stone cobra 1.99% e Rede 2.5%, sistema prefere o de menor priority (admin escolheu manualmente). Otimização por custo é manual.
- Crypto/USDT/etc. — não suportado. Se aparecer demanda, abrir feature request.
Roadmap
- Roteamento por menor custo total (taxa + tempo) — feature flag-gated
- Health beyond circuit breaker — incluir P95 latency + auth-failure-rate
- Per-customer routing — VIP cliente recebe gateway de menor latência mesmo que mais caro