Pagamentos para 2.100+ lojistas numa plataforma com 7.000+ restaurantes
KotlinAndroidStone SDKJavaQuarkusKafka
>Contexto
A Yooga é um sistema operacional para restaurantes, com 7.000+ restaurantes. Pagamentos é a área que recebe o dinheiro das vendas e repassa ao lojista: 2.100+ lojistas estavam integrados na solução de pagamentos.
Entrei em setembro de 2023 como Senior Software Engineer em Pagamentos. Construí os fluxos centrais de transação do lojista, ciclos de cobrança e conciliação financeira, enquanto o domínio saía de um monólito para serviços. Em maio de 2025 fui promovido a Tech Lead e liderei o time de 5 engenheiros até agosto de 2026: arquitetura, roadmap com produto, suporte e comercial, padrões de code review e onboarding de quem chegava.
O bug que mais importava era o comum: o mesmo webhook entregue duas vezes, ou o cliente tocando em pagar de novo. Boa parte do trabalho foi tornar cada transação segura para rodar duas vezes, em dois provedores.
Também arquitetei e construí o SmartPOS, que leva a Yooga para dentro da maquininha: o app roda a Yooga no terminal e integra com o pagamento da própria maquininha pelo SDK da Stone.
>Arquitetura (HLD)
Os pagamentos rodavam em serviços Java 21 e Quarkus, em contêineres no Kubernetes, na AWS. Os serviços usavam MySQL e MongoDB. A observabilidade era New Relic, Prometheus/Grafana e OpenTelemetry.
Uma cobrança sai dos canais da Yooga, entra no serviço de pagamentos com chave de idempotência e vai ao provedor por drivers plugáveis: Pix direto com o Itaú; cartões, Apple Pay e Google Pay via Tuna e Pagar.me, com antifraude. O status volta por webhooks assinados de Tuna e Pagar.me, validados antes de mudar estado e seguros para chegar duas vezes. O SmartPOS é um app Kotlin/Android na própria maquininha: usa as APIs da Yooga e cobra pelo SDK da Stone.
Fora do caminho da cobrança, o trabalho é assíncrono. Jobs agendados montam os lotes de saque, calculam a data do repasse com feriados e fins de semana, pagam por Pix via Itaú, rodam a conciliação e mandam um relatório diário no Slack. A camada de eventos em Kafka leva pedidos e status entre os microsserviços e os conectores de delivery (iFood e parceiros), com SASL/SSL, ordenação, replay e consumo idempotente. Mudanças iam para produção atrás de feature toggles, com liberação gradual.
Passe o mouse ou foque uma peça: ela acende com as ligações.
14 peças13 ligações4 áreas
Componentes
Serviço de pagamentos :: Serviço Java 21/Quarkus no Kubernetes da AWS que registra cada cobrança com chave de idempotência e chama o provedor pelo driver certo.
Drivers de provedor :: Pix direto com o Itaú e cartões, Apple Pay e Google Pay via Tuna e Pagar.me, com antifraude que coleta dados da sessão no início da transação e usa os motores dos dois provedores.
Handlers de webhook :: Validam a assinatura de Tuna e Pagar.me antes de processar e tratam a reentrega como caso normal, sem cobrança duplicada nem estado inconsistente.
Repasse automatizado :: Jobs agendados montam lotes de saque por lojista, calculam a data com feriados e fins de semana, pagam por Pix via Itaú, conciliam e mandam o relatório diário no Slack.
Credenciamento self-service :: Cadastro do lojista com validação de CPF/CNPJ, verificação da conta bancária e integração direta com a API de lojistas da Tuna.
Camada de eventos em Kafka :: Eventos de pedido e status entre os microsserviços e os conectores de delivery (iFood e parceiros), com SASL/SSL, ordenação, replay e consumo idempotente.
SmartPOS :: App Kotlin/Android com Clean Architecture e Jetpack Compose que roda a Yooga em maquininhas Sunmi, Positivo e Tectoy, usa as APIs da Yooga e cobra pelo SDK da Stone.
>Trade-offs
Tratar a segunda entrega como caso normal: chave de idempotência em cada transação e webhook assinado validado antes de mudar estado.
Alternativa descartada: Confiar que o provedor entrega cada webhook uma vez e que o cliente toca em pagar uma vez só.
Por quê: O bug que mais importava era o mesmo webhook chegando duas vezes ou o cliente tocando em pagar de novo. Nos dois provedores, foi a idempotência que acabou com cobrança duplicada, corrida e estado inconsistente.
Drivers plugáveis por provedor dentro do serviço de pagamentos.
Alternativa descartada: Concentrar todos os métodos de pagamento num único provedor.
Por quê: O Pix, com 98% do volume de transações, ia direto pelo Itaú, e os cartões passavam por Tuna e Pagar.me, todos atrás da mesma arquitetura de drivers plugáveis.
Consumo idempotente com replay na camada de Kafka.
Alternativa descartada: Assumir que o broker entrega cada evento exatamente uma vez.
Por quê: Em sistema orientado a eventos qualquer passo pode rodar duas vezes. Com o handler desenhado para a segunda entrega desde o início, um incidente no broker nunca gerou pedido duplicado ou perdido.
>Destaques
>US$70M+ processados em 6M+ transações para 2.100+ lojistas
>Pix com integração direta ao Itaú: 98% do volume de transações
>800+ testes automatizados cobrindo fluxos de pagamento e webhooks
>SmartPOS em maquininhas de 3 fabricantes: Sunmi, Positivo e Tectoy
>Time de 5 engenheiros liderado por 1 ano e 4 meses
>Claude Code e Cursor como ferramentas centrais: velocidade de entrega do time 3x maior