Imagem com o logo do Laravel.

Carteira Digital Desenvolvimento Back-end / Engenharia de Software

API REST para gerenciamento seguro de carteiras em BRL, com autenticação, depósitos, transferências, reversões administrativas, ledger imutável, idempotência e proteção contra concorrência.

Feito com

  • PHP
  • Laravel
  • PostgresSQL
  • Docker
  • Nginx
  • OpenAPI
  • Sanctum

Contexto

Operações financeiras exigem mais do que a simples atualização de um campo de saldo. Requisições repetidas, acessos concorrentes, falhas durante transferências e alterações indevidas no histórico podem provocar duplicidade de operações ou inconsistências contábeis.

O projeto foi desenvolvido como uma API REST de carteira digital em BRL, com o objetivo de explorar esses problemas por meio de garantias aplicadas tanto no código quanto no banco de dados.

Objetivo

O objetivo foi construir uma API segura e previsível para o cadastro de usuários, a consulta de saldo, a realização de depósitos e transferências e o processamento de reversões administrativas. A solução deveria impedir o gasto duplo, processar requisições repetidas de maneira idempotente, preservar todo o histórico financeiro e disponibilizar um ambiente local reproduzível e documentado.

Processo

A implementação começou pela modelagem das entidades centrais, como usuários, carteiras, transações, lançamentos contábeis e chaves de idempotência. As regras de negócio foram organizadas em Actions, enquanto Controllers, Form Requests e DTOs ficaram responsáveis pelo transporte e pela validação dos dados. As operações financeiras foram executadas dentro de transações do PostgreSQL, utilizando bloqueios pessimistas e restrições de integridade para proteger os dados.

Em seguida, foram adicionados autenticação com Laravel Sanctum, permissões específicas para cada operação, autorização administrativa, eventos publicados somente após a confirmação das transações, logs estruturados, reconciliação de saldo, documentação OpenAPI e uma suíte automatizada de testes. Os valores monetários foram armazenados como números inteiros em centavos para evitar erros de ponto flutuante, enquanto cada alteração de saldo passou a gerar lançamentos contendo os valores anterior e posterior.

O histórico financeiro foi estruturado como um ledger append-only, protegido por gatilhos do PostgreSQL contra alterações, exclusões e truncamentos. Depósitos, transferências e reversões passaram a exigir uma chave de idempotência. As transferências também foram implementadas com o bloqueio das carteiras em uma ordem determinística, reduzindo a possibilidade de deadlocks. Além disso, as reversões foram modeladas como novas transações compensatórias, preservando integralmente as operações originais.

Decisões técnicas

O projeto adota valores monetários representados em centavos inteiros para evitar erros de ponto flutuante. Utiliza transações e bloqueios pessimistas do PostgreSQL para garantir a consistência em situações de concorrência e mantém um ledger imutável, protegido por constraints e triggers, como fonte de verdade das movimentações.

Depósitos, transferências e reversões são idempotentes, impedindo o processamento duplicado de operações. As reversões geram lançamentos compensatórios sem apagar ou modificar o histórico original.

A arquitetura separa as responsabilidades entre Controllers, Form Requests, DTOs e Actions. Além disso, combina o Laravel Sanctum com roles e abilities para controlar a autorização, publica eventos somente após a confirmação da transação e utiliza o Docker Compose para disponibilizar um ambiente local reproduzível.

Desafios

O principal desafio foi garantir a consistência quando duas operações tentavam movimentar o mesmo saldo simultaneamente. Esse problema foi tratado com transações, bloqueios pessimistas e uma ordem determinística para bloquear as carteiras envolvidas. Outro ponto importante foi assegurar que a repetição de uma requisição não movimentasse dinheiro duas vezes. Para isso, a solução associou a chave de idempotência ao usuário e ao conteúdo da solicitação, permitindo reproduzir a resposta original e rejeitar a reutilização da mesma chave com dados diferentes.

As reversões também exigiram atenção especial. Em vez de apagar ou modificar uma operação anterior, o sistema passou a criar lançamentos opostos, mantendo toda a trilha de auditoria. A autorização administrativa combinou as permissões do token com o papel persistido no banco de dados, enquanto os eventos financeiros foram publicados somente após a confirmação definitiva da transação.

Resultados e aprendizados

O resultado foi uma API com autenticação, depósitos, transferências, histórico financeiro, reversões administrativas, reconciliação e documentação reproduzível em OpenAPI e Postman. O ambiente local foi organizado com Docker Compose, reunindo aplicação, worker, Nginx, PostgreSQL e Redis. As regras financeiras críticas ficaram protegidas em múltiplas camadas, envolvendo aplicação, transações, restrições de integridade e gatilhos do banco de dados.

A suíte automatizada de testes passou a abranger autenticação, autorização, consulta e movimentação de saldo, idempotência, rollback, concorrência, publicação de eventos e integridade do ledger. O projeto reforçou que sistemas financeiros devem tratar o histórico como fonte de verdade, representar valores monetários sem ponto flutuante e considerar a concorrência, as falhas e a repetição de requisições desde o início da arquitetura.