Processamento de pagamentos resiliente, idempotente e escalΓ‘vel.
Este projeto Γ© um Processador de Eventos de Pagamento de alta performance, projetado para resolver um dos problemas mais crΓticos em sistemas financeiros modernos: a confiabilidade no recebimento de Webhooks.
Imagine que o Stripe (ou qualquer gateway) envia uma notificaΓ§Γ£o de "Pagamento Confirmado", mas seu servidor cai no meio do processamento. Ou pior, ele envia a mesma notificaΓ§Γ£o duas vezes e vocΓͺ libera o produto em dobro para o cliente. Este microserviΓ§o foi construΓdo com foco obsessivo em Garantia de Entrega e ConsistΓͺncia de Dados.
Webhooks sΓ£o comunicaΓ§Γ΅es assΓncronas entre servidores que podem falhar por diversos motivos: instabilidade na rede, picos de trΓ‘fego ou erros temporΓ‘rios no banco de dados. Um sistema financeiro nΓ£o pode simplesmente "perder" um evento.
Este projeto implementa:
- IdempotΓͺncia: Garante que mesmo que um evento seja recebido 10 vezes, ele serΓ‘ processado apenas uma vez.
- ResiliΓͺncia: Se o processamento falhar por um erro temporΓ‘rio, o sistema tenta novamente de forma inteligente (Backoff Exponencial).
- Observabilidade: Monitoramento em tempo real de mΓ©tricas, erros e saΓΊde do sistema.
Escolhi cada tecnologia com o objetivo de equilibrar performance, tipagem forte e confiabilidade:
- Linguagem: Go (Golang) - Escolhida pela sua concorrΓͺncia nativa (Goroutines) e baixo consumo de memΓ³ria.
- Banco de Dados: PostgreSQL - Para garantir transaΓ§Γ΅es ACID e persistΓͺncia robusta dos eventos.
- Fila/Mensageria: Redis Streams - Utilizado para processamento em background, garantindo que o Gateway receba um
202 AcceptedinstantΓ’neo enquanto o Worker processa a lΓ³gica pesada. - Infraestrutura: Docker & Docker Compose - Para abstraΓ§Γ£o de ambiente e facilidade de deploy.
- PadrΓ΅es: Clean Architecture, Repository Pattern e Middleware para seguranΓ§a (HMAC-SHA256).
Para este projeto, fiz questΓ£o de aplicar conceitos que demonstram meu compromisso com a excelΓͺncia tΓ©cnica:
- SeguranΓ§a com HMAC: Cada requisiΓ§Γ£o Γ© validada usando assinaturas criptogrΓ‘ficas para garantir que os dados realmente vieram do provedor de pagamentos.
- Tratamento de Erros SemΓ’ntico: Diferencio erros "Transientes" (conectividade) de "Permanentes" (dados invΓ‘lidos), evitando retries inΓΊteis em dados corrompidos.
- Dead Letter Queue (DLQ): Eventos que falham apΓ³s todas as tentativas nΓ£o sΓ£o descartados; eles vΓ£o para uma fila de anΓ‘lise manual.
- PadrΓ£o de Tabelas Cruas (Raw Events): Salvo o payload original antes de qualquer processamento, permitindo auditoria e "replay" de eventos se as regras de negΓ³cio mudarem.
Este projeto Γ© um reflexo da minha jornada no desenvolvimento de software. Acredito que um bom programador nΓ£o Γ© aquele que apenas escreve cΓ³digo que funciona, mas aquele que:
- Antecipa erros (O que acontece se o banco ficar lento?).
- Escreve cΓ³digo para humanos (Nomes de variΓ‘veis intuitivos e estrutura limpa).
- Γ obcecado por testes (Este projeto possui testes unitΓ‘rios e de integraΓ§Γ£o).
Estou em constante evoluΓ§Γ£o, explorando padrΓ΅es de alta disponibilidade e sistemas distribuΓdos. Este projeto foi uma oportunidade incrΓvel para aprofundar meu conhecimento em Go e sistemas orientados a eventos.
Explore as pastas para entender a organizaΓ§Γ£o:
internal/domain: O coraΓ§Γ£o do projeto, onde as regras de negΓ³cio vivem.internal/middleware: Camada de seguranΓ§a e validaΓ§Γ£o.internal/worker: LΓ³gica asΓncrona de consumo de fila.
Este Γ© um projeto de portfΓ³lio. Para ver o cΓ³digo completo ou discutir oportunidades, sinta-se Γ vontade para entrar em contato!
# VariΓ‘veis
TIMESTAMP=$(date +%s)
SECRET="whsec_test_secret_key_for_development"
PAYLOAD='{"id":"evt_test_123","type":"payment_succeeded","created":1704672000,"data":{"object":{"id":"in_abc","subscription":"sub_xyz","customer_email":"[email protected]","amount":9900,"currency":"brl","plan_id":"plan_pro"}}}'
# Gerar assinatura
SIGNATURE=$(echo -n "${TIMESTAMP}.${PAYLOAD}" | openssl dgst -sha256 -hmac "${SECRET}" | cut -d' ' -f2)
# Enviar webhook
curl -X POST http://localhost:8080/webhooks/payments \
-H "Content-Type: application/json" \
-H "X-Webhook-Signature: sha256=${SIGNATURE}" \
-H "X-Webhook-Timestamp: ${TIMESTAMP}" \
-d "${PAYLOAD}"# Executar script de teste
.\scripts\test-webhook.ps1 -EventType "payment_succeeded"
# Ou manualmente
$timestamp = [int][double]::Parse((Get-Date -UFormat %s))
$secret = "whsec_test_secret_key_for_development"
$payload = '{"id":"evt_test_123","type":"payment_succeeded","created":1704672000,"data":{"object":{"id":"in_abc","subscription":"sub_xyz","customer_email":"[email protected]","amount":9900,"currency":"brl"}}}'
$signedPayload = "$timestamp.$payload"
$hmac = New-Object System.Security.Cryptography.HMACSHA256
$hmac.Key = [System.Text.Encoding]::UTF8.GetBytes($secret)
$hash = $hmac.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($signedPayload))
$signature = [BitConverter]::ToString($hash).Replace("-","").ToLower()
Invoke-RestMethod -Uri "http://localhost:8080/webhooks/payments" `
-Method Post `
-Headers @{
"Content-Type" = "application/json"
"X-Webhook-Signature" = "sha256=$signature"
"X-Webhook-Timestamp" = "$timestamp"
} `
-Body $payloadpayment-event-processor/
βββ cmd/
β βββ api/
β β βββ main.go # HTTP API server
β βββ worker/
β βββ main.go # Queue consumer worker
βββ internal/
β βββ config/ # ConfiguraΓ§Γ£o via env vars
β βββ database/ # ConexΓ£o PostgreSQL
β βββ domain/ # Entidades de domΓnio
β βββ handler/ # HTTP handlers
β βββ middleware/ # Auth, rate limit, logging
β βββ queue/ # Redis Streams
β βββ repository/ # Acesso a dados
β βββ worker/ # Processamento de eventos
βββ migrations/ # SQL migrations
βββ examples/ # Payloads de exemplo
βββ scripts/ # Scripts de teste
βββ docker-compose.yml
βββ Dockerfile
βββ Makefile
βββ go.mod
| VariΓ‘vel | DescriΓ§Γ£o | Default |
|---|---|---|
PORT |
Porta do servidor HTTP | 8080 |
ENV |
Ambiente (development/production) | development |
DATABASE_URL |
URL de conexΓ£o PostgreSQL | - |
DATABASE_MAX_CONNS |
ConexΓ΅es mΓ‘ximas do pool | 10 |
REDIS_URL |
URL de conexΓ£o Redis | - |
WEBHOOK_SECRET |
Secret HMAC para verificaΓ§Γ£o | - |
WEBHOOK_TOLERANCE_SECONDS |
TolerΓ’ncia de timestamp | 300 |
RATE_LIMIT_REQUESTS |
Requests por janela | 100 |
RATE_LIMIT_WINDOW_SECONDS |
Janela de rate limit | 60 |
WORKER_CONCURRENCY |
NΓΊmero de workers | 5 |
WORKER_MAX_RETRIES |
Retries antes do DLQ | 3 |
WORKER_RETRY_BASE_DELAY_MS |
Delay base para retry | 1000 |
make up # Iniciar todos os serviΓ§os
make down # Parar e remover containers
make build # Build dos binΓ‘rios
make test # Rodar testes
make test-coverage # Testes com coverage
make logs # Ver logs de todos serviΓ§os
make logs-api # Ver logs da API
make logs-worker # Ver logs do Worker
make migrate # Rodar migrations
make seed # Popular dados iniciais
make health # Verificar health
make metrics # Ver mΓ©tricas
make help # Ver todos comandos| Tipo | AΓ§Γ£o |
|---|---|
payment_succeeded |
Marca invoice como paid, subscription como active, incrementa receita |
payment_failed |
Marca invoice como failed, subscription como past_due |
charge_refunded |
Marca invoice como refunded, incrementa reembolsos |
ββββββββββββββββ
β Stripe β
ββββββββ¬ββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββ
β API Server β
β ββββββββββββββ ββββββββββββββ βββββββββββ β
β β Signature β β Rate Limit β β Logging β β
β βββββββ¬βββββββ βββββββ¬βββββββ ββββββ¬βββββ β
β βββββββββββββββββΌββββββββββββββββ β
β βΌ β
β βββββββββββββββββββ β
β β Webhook Handler β β
β ββββββββββ¬βββββββββ β
βββββββββββββββββββββββββΌββββββββββββββββββββββββ
β
ββββββββββββββ΄βββββββββββββ
βΌ βΌ
βββββββββββββββ βββββββββββββββ
β PostgreSQL β β Redis β
β (raw_events)β β (Streams) β
βββββββββββββββ ββββββββ¬βββββββ
β
βΌ
βββββββββββββββββββββββββββββ
β Workers β
β βββββββββββββββββββββββ β
β β payment_succeeded β β
β β payment_failed β β
β β charge_refunded β β
β βββββββββββ¬ββββββββββββ β
ββββββββββββββΌβββββββββββββββ
β
ββββββββββββββ΄βββββββββββββ
βΌ βΌ
βββββββββββββββ βββββββββββββββ
β PostgreSQL β β DLQ β
β (updates) β β (failures) β
βββββββββββββββ βββββββββββββββ
MIT