surfaai · parte 2 de 8
Por que Stripe Connect Express em vez de split manual
01 de outubro de 20265 min de leituraCesar Eduardo Sturmer
Quando você monta o pagamento de um marketplace, a primeira ideia que aparece é quase sempre a mesma: cobrar o valor cheio do comprador, guardar o dinheiro na conta da plataforma e, depois, transferir a parte do vendedor.
Chamo isso de split manual. Parece simples porque você já sabe fazer as duas pontas: receber um pagamento e mandar uma transferência. O que não é óbvio é tudo que mora no meio.
Este artigo é sobre por que não fiz isso no surfaai — e o que eu teria assumido se tivesse feito.
O que "split manual" realmente exige
No momento em que o dinheiro do provider passa pela sua conta, você deixa de ser uma plataforma de software. Você vira, na prática, um intermediário financeiro. Isso traz uma lista de responsabilidades que não aparecem no diagrama de arquitetura:
Custódia. O dinheiro do provider está na sua conta, misturado com o seu. Se a empresa tiver qualquer problema de fluxo de caixa, o dinheiro de terceiros está exposto. Separar isso corretamente é um problema contábil e jurídico, não técnico.
KYC e KYB. Para repassar dinheiro a alguém, você precisa saber quem é essa pessoa. Documento, validação, verificação de titularidade da conta bancária, checagem de listas restritivas. E isso não é "uma vez": precisa ser monitorado e reverificado.
Reconciliação. Para cada pagamento, você precisa saber quanto entrou, quanto é seu, quanto é do provider, quanto já foi repassado e quanto falta. Com estorno parcial, chargeback e parcelamento no meio, essa conta fica difícil rápido.
Timing. Transfere quando? Na confirmação do pagamento? Depois do serviço prestado? Em D+30? Cada resposta é uma regra de negócio que vira código, e cada regra tem um caso de borda que você vai descobrir em produção.
Falha e retentativa. A transferência falhou porque a conta do provider estava errada. E agora? Quem detecta, quem notifica, quem reprocessa, e como você garante que a retentativa não transfere duas vezes.
Nenhum desses problemas é sobre o seu produto. Todos consomem tempo de engenharia que não vai para o produto.
As três portas do Connect
O Stripe Connect resolve isso, mas oferece três tipos de conta, e a escolha importa:
| Standard | Express | Custom | |
|---|---|---|---|
| Quem faz o onboarding | o próprio provider, na Stripe | Stripe, dentro do seu fluxo | você, via API |
| Dashboard do provider | completo, da Stripe | reduzido, da Stripe | nenhum, você constrói |
| Responsabilidade por KYC | Stripe | Stripe | sua |
| Esforço de implementação | baixo | baixo | alto |
| Controle da experiência | baixo | médio | total |
Standard exige que o provider tenha ou crie uma conta Stripe completa. Para um instrutor que quer só receber pelas aulas, é fricção demais — ele abandona no meio.
Custom devolve para você exatamente o que eu queria evitar: a responsabilidade de KYC e a construção de toda a interface de onboarding, extrato e saque.
Express fica no meio: o provider passa por um fluxo de onboarding hospedado pela Stripe, curto e em português, e ganha um painel simples para ver os recebimentos. Eu não vejo nem armazeno documento nenhum. A Stripe assume o KYC.
Para um produto tocado por uma pessoa, essa divisão é a diferença entre o projeto existir e não existir.
O que o código vira
Com Express e destination charges, o repasse inteiro cabe em duas propriedades do PaymentIntent:
const paymentIntent = await stripe.paymentIntents.create({
amount: calculation.amountInCents,
currency: "brl",
application_fee_amount: calculation.applicationFeeAmount,
transfer_data: {
destination: stripeAccountId,
},
description,
metadata: { serviceId, providerId /* ... */ },
});application_fee_amount é o que fica comigo. transfer_data.destination é a conta do provider. A Stripe cobra do aluno, retém minha taxa e credita o líquido ao provider — sem nenhuma rotina de repasse minha, sem o dinheiro passar pela minha conta como custódia.
O artigo seguinte da série detalha essa mecânica e a matemática das taxas.
O que eu abri mão
Seria desonesto apresentar isso como escolha sem custo.
Perdi o controle do timing. Com destination charges, o repasse acontece quando o pagamento é capturado. Se eu quisesse segurar o valor até a aula acontecer — um escrow — precisaria de outro desenho, provavelmente separate charges and transfers.
Fiquei preso à Stripe. As contas Connect são da Stripe. Migrar de gateway com providers já onboardados significa refazer o onboarding de todos. É um custo de saída real, e eu já paguei um parecido quando migrei de Asaas para Stripe — o artigo 7 conta essa história.
Dependo do onboarding deles. Se o fluxo da Stripe rejeitar um provider, ou pedir um documento que ele não tem à mão, eu não tenho como contornar. Já aconteceu.
Foram trade-offs aceitáveis para este produto. Num marketplace onde o dinheiro precisa ficar retido até a entrega, a conta seria outra.
A regra que ficou
A decisão de arquitetura mais importante quase nunca é qual ferramenta usar. É onde traçar a linha entre o que você constrói e o que você delega — e, principalmente, quais responsabilidades você aceita junto com o código que escreve.
Custódia de dinheiro de terceiros e verificação de identidade são responsabilidades caras, contínuas e completamente fora do meu produto. Delegar isso não foi preguiça de engenharia. Foi a escolha de gastar o tempo de engenharia no que o aluno e o provider realmente veem.