API Pay é uma aplicação NestJS que processar pagamentos utilizando múltiplos provedores e conta com fallback e circuit breaker. Esta aplicação foi desenvolvida como parte de um desafio técnico, e seu objetivo é demonstrar a implementação de estratégias de resiliência e tolerância a falhas em sistemas de pagamentos distribuídos.
Utilizando o design pattern Strategy, a aplicação pode alternar dinamicamente entre diferentes provedores de pagamento em caso de falha.
Além disso, o uso de Circuit Breaker ajuda a prevenir a sobrecarga de provedores que estão enfrentando problemas, bloqueando temporariamente novas chamadas e permitindo uma recuperação gradual.
A aplicação também inclui mocks dos provedores de pagamento para facilitar o desenvolvimento e os testes.
Certifique-se de ter as seguintes ferramentas instaladas no seu ambiente:
- Node.js (versão 18 ou superior)
- npm ou yarn
- Docker e Docker Compose
-
Clone o repositório:
git clone https://github.com/ClaudioMascaro/api-pay-desafio-malga.git cd api-pay-desafio-malga -
Copie o arquivo de exemplo
.enve ajuste as configurações conforme necessário:cp .env.example .env
-
Instale as dependências:
npm install
Ambos métodos de execução abaixo irão subir a aplicação principal e os mocks dos provedores de pagamento com auto-restart ao salvar alterações.
-
Suba a aplicação e os mocks:
make up
-
Acesse a aplicação:
- API principal: http://localhost:3000
- Mocks dos provedores: http://localhost:3001
-
Acompanhe os logs:
make logs
-
Para parar os serviços:
make down
-
Inicie os mocks dos provedores:
npm run start:mocks:dev
-
Em outro terminal, inicie a API principal:
npm run start:dev
- Endpoint:
POST /payments - Body (exemplo):
{
"amount": 1000,
"currency": "USD",
"description": "Compra de produtos",
"paymentMethod": {
"type": "card",
"card": {
"number": "4111111111111111",
"holderName": "John Doe",
"cvv": "123",
"expirationDate": "12/2025",
"installments": 1
}
}
}- Endpoint:
GET /payments/:id - Exemplo de resposta (sucesso):
{
"id": "payment-uuid",
"createdDate": "2024-12-18",
"status": "success",
"amount": 1000,
"originalAmount": 1000,
"currency": "USD",
"description": "Compra de produtos",
"paymentMethod": "card",
"cardId": "mock-card-uuid"
}- Exemplo de resposta (não encontrado):
{
"statusCode": 404,
"message": "Payment not found",
"error": "Not Found"
}- Endpoint:
POST /payments/:id/refund - Body (exemplo):
{
"amount": 500
}- Exemplo de resposta (sucesso):
{
"id": "payment-uuid",
"createdDate": "2024-12-18",
"status": "refunded",
"amount": 500,
"originalAmount": 1000,
"currency": "USD",
"description": "Reembolso parcial",
"paymentMethod": "card",
"cardId": "mock-card-uuid"
}Os provedores de pagamento são simulados para replicar comportamentos reais com falhas e latências ocasionais, proporcionando um ambiente de teste onde é possível avaliar o funcionamento do circuit breaker e fallback.
-
Latência Simulada:
- A resposta pode levar entre 0 a 500 ms.
- Existe uma chance de 10% de a resposta demorar mais de 1200 ms.
-
Erros Intermitentes:
- Há uma chance de 1% de ocorrer um erro de servidor (500).
-
Latência Simulada:
- A resposta pode levar entre 0 a 500 ms.
- Existe uma chance de 5% de a resposta demorar mais de 1200 ms.
-
Erros Intermitentes:
- Há uma chance de 0.5% de ocorrer um erro de servidor (500).
A aplicação utiliza o padrão Strategy para implementar múltiplos provedores de pagamento, permitindo alternância dinâmica entre eles em caso de falha. O fluxo de processamento de pagamento inclui as seguintes etapas principais:
-
Execução com Prioridade:
- A aplicação tenta processar o pagamento com o provedor de maior prioridade.
-
Fallback Automático:
- Caso o primeiro provedor falhe, o próximo é tentado automaticamente.
-
Circuit Breaker:
- Quando falhas consecutivas são detectadas, o circuito do provedor é aberto, bloqueando novas chamadas por um tempo configurado.
- Após o tempo de reset, o circuito entra em estado de teste (half-open), permitindo chamadas limitadas para verificar recuperação.
-
Retentativa:
- Se todos os provedores falharem, a aplicação aguarda o tempo de reset do circuit breaker e tenta novamente, até o número máximo de retentativas configurado (
PAYMENTS_MAX_RETRIES).
- Se todos os provedores falharem, a aplicação aguarda o tempo de reset do circuit breaker e tenta novamente, até o número máximo de retentativas configurado (
Para executar a bateria completa de testes, juntamente com a verificação de cobertura de código:
npm run test:all:covOu, se preferir utilizar o docker-compose, utilize o comando make:
make testPara validação de testes unitários em tempo de desenvolvimento, utilize:
npm run test:unit:watchPara os demais testes:
npm run test:unitnpm run test:e2e| Statements | Branches | Functions | Lines |
|---|---|---|---|
src/- Código principal da aplicação.api/- Lógica da API (controladores, serviços, providers).mocks/- Simulação dos provedores de pagamento.common/- Middleware, validações e utilitários globais.
test/- Configuração e arquivos de teste end-to-end.
Para personalizar os parâmetros e configurações da aplicação, é possível ajustar as seguintes variáveis de ambiente no arquivo .env:
CIRCUIT_BREAKER_TIMEOUT- Tempo limite para o circuit breaker em ms.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE- Percentual de erro para abrir o circuit breaker.CIRCUIT_BREAKER_RESET_TIMEOUT- Tempo para resetar o circuit breaker.PAYMENTS_PROVIDER1_API_URL- URL do provedor de pagamento 1.PAYMENTS_PROVIDER2_API_URL- URL do provedor de pagamento 2.PAYMENTS_MAX_RETRIES- Número máximo de tentativas de fallback.PAYMENTS_REQUEST_TIMEOUT- Tempo limite para requests aos provedores externos, em ms.
