Payment Service Multi-Provider
Plataforma de pagamentos em Spring Boot com arquitetura gateway-agnostic: o core de cobrança, assinatura, checkout, créditos e webhooks é independente do provedor, com Asaas como primeiro adapter real e suporte arquitetural para novos gateways sem reescrever regras de negócio.
O Problema
Sistemas de pagamento costumam nascer acoplados ao primeiro provedor integrado. Isso espalha regras específicas do gateway pelo domínio, dificulta testes, trava migrações futuras e torna webhooks, erros, status e fluxos de cobrança difíceis de manter quando o produto cresce.
A Solução
- Arquitetura modular por capacidades de negócio, com cada domínio isolado em seu próprio módulo e fronteiras explícitas
- Core de aplicação protegido por ports e adapters, isolando regras de negócio dos detalhes do provedor de pagamento
- Asaas implementado como primeiro adapter concreto, sem transformar o domínio em uma extensão da API do provedor
- Webhooks externos traduzidos para fluxos internos normalizados, com idempotência, rastreabilidade e tolerância a reentregas
- Fluxos críticos desenhados para evitar transações longas envolvendo chamadas externas ao gateway
- Contratos de erro padronizados com ProblemDetail e separação clara entre API, application, domain e infra
Arquitetura
- Modular Monolith
Java 21 / Spring Boot / Maven
O sistema é organizado por módulos de negócio, não por camadas globais genéricas. Cada módulo concentra sua API, aplicação, domínio, infraestrutura, testes e contratos.
- Core
Ports & Adapters
Casos de uso dependem de portas de saída por fronteira, como gateway, repository, cliente, assinatura, notificação e fiscal, mantendo detalhes externos fora das regras centrais.
- Adapter Asaas
Asaas API
Primeiro provedor real da plataforma, responsável por cobranças, assinaturas, Pix, boleto, cartão, tokenização, webhooks, clientes e integrações fiscais.
- Persistência
MySQL / Flyway
Modelo relacional versionado por migrations, com atenção a idempotência, histórico de processamento, status financeiros e rastreabilidade operacional.
- Eventos
Outbox / Mensageria / SQS
Fluxos assíncronos são usados para efeitos colaterais e integração interna/externa, reduzindo acoplamento entre módulos e evitando processamento frágil em cadeia síncrona.
- Observabilidade
OpenTelemetry, métricas e logs estruturados
Operações críticas são rastreadas com correlationId, métricas por fluxo e logs úteis para diagnóstico de falhas parciais, webhooks duplicados e inconsistências de gateway.
Serviços Utilizados
- Asaas

- Amazon SQS
- Amazon S3
Testes
- JUnit 5

- ArchUnit

- Testcontainers

Desafios & Decisões
Como manter o sistema independente do gateway sem cair em abstrações genéricas demais?
A solução foi criar portas orientadas às necessidades reais do domínio, e não simplesmente espelhar a API do provedor. O adapter Asaas traduz comandos e respostas externas para objetos internos mais estáveis.
Como lidar com webhooks enviados várias vezes ou fora de ordem?
Os eventos recebidos passam por controle de idempotência, validação e normalização antes de alterar estados internos. O sistema trata reentregas como comportamento esperado, não como exceção.
Como evitar inconsistência entre banco local e gateway externo?
Fluxos críticos evitam manter transação de banco aberta durante chamadas externas. A persistência local, sincronização de status e tratamento de falhas são separados para melhorar rastreabilidade e recuperação.
Como evoluir assinatura, cobrança, crédito, cupom e fiscal sem criar um serviço gigante e acoplado?
Cada capacidade foi isolada em módulo próprio, com fronteiras explícitas. Comunicação síncrona acontece via ports quando há necessidade de resposta imediata; efeitos colaterais podem ser tratados por eventos ou processamento assíncrono.
Como preparar o sistema para novos gateways sem implementar todos no início?
O projeto nasceu gateway-agnostic por arquitetura, mas com entrega incremental. O Asaas é o primeiro provider real; novos provedores entram como adapters quando houver demanda concreta.
Resultados
- Core financeiro desacoplado do provedor inicial de pagamento
- Asaas integrado como adapter real sem contaminar domínio e casos de uso com DTOs externos
- Fluxos de assinatura, cobrança, checkout, créditos e webhooks organizados por módulos de negócio
- Processamento mais seguro contra reentregas, retentativas e falhas parciais
- Base preparada para múltiplos gateways sem reescrever regras centrais
- Arquitetura testável, documentada e adequada para evolução incremental
Screenshots
Lições Aprendidas
- Ser gateway-agnostic não significa implementar vários provedores no começo; significa impedir que o primeiro provedor vire o centro da arquitetura
- Ports devem representar fronteiras reais do sistema, não interfaces decorativas criadas por padrão
- Webhooks precisam ser tratados como fonte assíncrona, duplicável e eventualmente fora de ordem
- Idempotência em pagamento não é detalhe técnico, é regra fundamental de arquitetura
- Modular monolith é uma escolha mais pragmática do que microserviços quando o time precisa evoluir rápido mantendo consistência transacional e baixa complexidade operacional
- Separar API, application, domain e infra evita que DTOs externos, entidades JPA e contratos de gateway vazem para o núcleo do sistema