Saudações, equipe BeTalent. Externo meu agradecimento pela oportunidade de participar deste processo seletivo.
Implementei o Nível 3 da especificação. A API gerencia um fluxo completo de pagamentos: o cliente realiza uma compra informando múltiplos produtos com suas quantidades, o sistema calcula o valor total via back-end somando os produtos selecionados e tenta processar a cobrança pelo gateway de maior prioridade, fazendo fallback automático para o próximo em caso de falha. Se o cliente ainda não existir no banco, é criado automaticamente no momento da compra.
Toda a lógica de comunicação com os gateways é isolada via padrão Adapter, tornando simples a adição de novos provedores no futuro. O acesso às rotas privadas é controlado por roles (ADMIN, MANAGER, FINANCE, USER), transações podem ser reembolsadas pelo gateway de origem e o histórico completo de compras fica vinculado ao cliente. A infraestrutura roda inteiramente via Docker Compose com MySQL, aplicação e mock dos gateways.
Já havia trabalhado com APIs de gateway de pagamento usando Fastify, mas não em um cenário multi-gateway com fallback automático, o que tornou esse teste especialmente interessante. A novidade foi o AdonisJS, framework que não fazia parte do meu stack e que definitivamente entrou nele após esse projeto. O que mais me impressionou foi a abordagem batteries-included: CLI, ORM (Lucid), validação (VineJS), serializers e testes integrados nativamente, sem necessidade de configurar ou acoplar peças separadas — um framework com muito mais recursos a explorar, e que certamente vou continuar estudando.
- Stack Tecnológica
- Arquitetura
- Instalação e Execução
- Variáveis de Ambiente
- Banco de Dados
- Autenticação
- Rotas da API
- Roles e Permissões
- Gateways de Pagamento
- Testes
| Tecnologia | Versão | Uso |
|---|---|---|
| Node.js | 24 | Runtime |
| TypeScript | 5.9 | Linguagem |
| AdonisJS | 7 | Framework |
| Lucid ORM | 22 | Queries, migrations e models |
| VineJS | 4 | Validação de dados |
| Japa | 5 | Testes funcionais |
| MySQL | 8.0 | Banco de dados |
| Docker | node:24-alpine | Containerização |
Cada gateway implementa a mesma interface GatewayInterface, isolando as diferenças de protocolo:
GatewayInterface
├── GatewayOneService → Auth: POST /login → JWT Bearer token (60s)
└── GatewayTwoService → Auth: Headers fixos (Auth-Token + Auth-Secret)
- Criar a pasta do gateway em
app/services/gateway_adapters/ - Criar a interface
gateway_example.interface.tsdentro da pasta - Criar o adapter
gateway_example.service.tsimplementandoGatewayInterface - Registrar no
gatewayMapdogateway.service.ts - Adicionar as credenciais no
.env - Inserir o registro no banco via seed ou migration
- Docker e Docker Compose
Node.js não é necessário localmente — tudo roda dentro do container Docker.
git clone https://github.com/nikol4ss/multi-gateway-payment-api.git
cd multi-gateway-payment-apicp .env.example .envEdite o .env com os valores desejados. O .env.example contém todos os campos necessários com referência de nomenclatura.
docker compose up --buildIsso sobe três serviços:
| Container | Porta | Descrição |
|---|---|---|
betalent_app |
3333 | API AdonisJS |
betalent_mysql |
3306 | Banco de dados MySQL 8 |
betalent_gateways |
3001 / 3002 | Mock dos gateways de pagamento |
Aguarde o log
[ info ] started HTTP server on localhost:3333antes de continuar.
docker compose exec app node ace migration:rundocker compose exec app node ace db:seedOs seeds criam:
Usuários:
| Senha | Role | |
|---|---|---|
| admin@betalent.com | admin123 | ADMIN |
| manager@betalent.com | manager123 | MANAGER |
| finance@betalent.com | finance123 | FINANCE |
Produtos:
| Nome | Valor |
|---|---|
| Plano Basic | R$ 49,90 |
| Plano Pro | R$ 99,90 |
| Plano Enterprise | R$ 299,90 |
| Suporte Premium | R$ 19,90 |
Gateways:
| Nome | Prioridade | Status |
|---|---|---|
| Gateway 1 | 1 | Ativo |
| Gateway 2 | 2 | Ativo |
# Node
TZ=UTC
PORT=3333
HOST=localhost
NODE_ENV=development
# App
LOG_LEVEL=info
APP_KEY=YOUR_APP_KEY_HERE
APP_URL=http://${HOST}:${PORT}
# Session
SESSION_DRIVER=cookie
# MySQL
DB_ROOT_PASSWORD=YOUR_DB_ROOT_PASSWORD
DB_DATABASE=YOUR_DATABASE
DB_USER=YOUR_USER
DB_PASSWORD=YOUR_DB_PASSWORD
DB_HOST=mysql
# Gateways mock
GATEWAY_REMOVE_AUTH=false
GATEWAY1_URL=http://gateways
GATEWAY1_EMAIL=YOUR_EMAIL
GATEWAY1_TOKEN=YOUR_TOKEN
GATEWAY2_URL=http://gateways
GATEWAY2_AUTH_TOKEN=YOUR_AUTH_TOKEN
GATEWAY2_AUTH_SECRET=YOUR_AUTH_SECRETDentro do Docker os containers se comunicam pelo nome do serviço definido no
docker-compose.yml. Por issoDB_HOST=mysqleGATEWAY1_URL=http://gateways.
| Tabela | Descrição |
|---|---|
users |
Usuários da plataforma |
auth_access_tokens |
Tokens de acesso Bearer |
clients |
Clientes criados automaticamente via compras |
products |
Produtos disponíveis para venda |
gateways |
Gateways de pagamento cadastrados |
transactions |
Transações realizadas |
transaction_products |
Pivot — produtos por transação com quantidade |
A API utiliza Bearer Token via @adonisjs/auth com Access Tokens armazenados no banco de dados.
POST /api/auth/signup → cria conta (role USER) → retorna user + token
POST /api/auth/login → autentica → retorna user + token
Inclua o token no header Authorization de todas as rotas privadas:
Authorization: Bearer {token}
A API está documentada no Postman. A collection para importação está disponível em
postman/collection.json.
Você também pode acessar a documentação online: Ver documentação
Base URL: http://localhost:3333/api
| Método | Rota | Auth | Descrição |
|---|---|---|---|
| POST | /auth/signup |
Público | Criar conta com role USER |
| POST | /auth/login |
Público | Autenticar e obter token |
| GET | /auth/profile |
Bearer | Dados do usuário autenticado |
| DELETE | /auth/logout |
Bearer | Revogar token |
| Método | Rota | Roles | Descrição |
|---|---|---|---|
| GET | /users |
ADMIN, MANAGER | Listar usuários |
| GET | /users/:id |
ADMIN, MANAGER | Detalhe de usuário |
| POST | /users |
ADMIN, MANAGER | Criar usuário com role |
| PUT | /users/:id |
ADMIN, MANAGER | Atualizar usuário |
| DELETE | /users/:id |
ADMIN, MANAGER | Remover usuário |
| Método | Rota | Roles | Descrição |
|---|---|---|---|
| GET | /products |
ADMIN, MANAGER, FINANCE | Listar produtos |
| GET | /products/:id |
ADMIN, MANAGER, FINANCE | Detalhe de produto |
| POST | /products |
ADMIN, MANAGER, FINANCE | Criar produto |
| PUT | /products/:id |
ADMIN, MANAGER, FINANCE | Atualizar produto |
| DELETE | /products/:id |
ADMIN, MANAGER, FINANCE | Remover produto |
O campo
amounté em centavos. Ex:9990= R$ 99,90.
| Método | Rota | Auth | Descrição |
|---|---|---|---|
| POST | /purchases |
Público | Realizar compra |
| GET | /transactions |
ADMIN, MANAGER, FINANCE | Listar transações |
| GET | /transactions/:id |
ADMIN, MANAGER, FINANCE | Detalhe de transação |
| POST | /transactions/:id/refund |
ADMIN, FINANCE | Reembolsar transação |
| Método | Rota | Roles | Descrição |
|---|---|---|---|
| GET | /clients |
ADMIN, MANAGER, FINANCE | Listar clientes |
| GET | /clients/:id |
ADMIN, MANAGER, FINANCE | Detalhe com transações |
Clientes são criados automaticamente ao realizar uma compra. Não há rota de criação manual.
| Método | Rota | Roles | Descrição |
|---|---|---|---|
| PATCH | /gateways/:id/toggle |
ADMIN | Ativar ou desativar |
| PATCH | /gateways/:id/priority |
ADMIN | Alterar prioridade de execução |
| CVV | Gateway 1 | Gateway 2 | Resultado |
|---|---|---|---|
010 |
Sucesso | Sucesso | Gateway 1 processa |
300 |
Sucesso | Falha | Gateway 1 processa |
100 |
Falha | Sucesso | Fallback para Gateway 2 |
200 |
Falha | Falha | 400 All gateways failed |
cardNumber: 5569000000006063
Os gateways mock são fornecidos pela imagem matheusprotzen/gateways-mock e configurados automaticamente via docker-compose.yml. Para desativar a autenticação nos mocks defina GATEWAY_REMOVE_AUTH=true no .env.
Testes funcionais de integração usando Japa, cobrindo todas as rotas e cenários de erro.
docker compose exec app node ace testdocker compose exec app node ace test --files="tests/functional/auth.spec.ts"| Arquivo | Cenários testados |
|---|---|
auth.spec.ts |
signup, login, profile, logout — sucesso e erros |
user.spec.ts |
CRUD completo, validações, bloqueio por role |
product.spec.ts |
CRUD completo, validações, bloqueio por role |
transaction.spec.ts |
compra, reembolso, duplo reembolso, bloqueio por role |
gateway.spec.ts |
toggle, priority, validação, bloqueio por role |
client.spec.ts |
listagem, detalhe, 404, bloqueio por role |
