Pagamentos · modules/billing
Scaffold de adapterStripe,
atrás de um único contrato.
A UseDeploy modela o billing como um único port IPaymentProvider. O Stripe é um dos adapters que se pluga nele — selecionado por uma env var, compartilhando os mesmos tipos normalizados que o MercadoPago e o Polar, então trocar de provider é uma mudança de um único arquivo.
O que vem pronto e o que você completa
Honestidade primeiro: o adapter do Stripe é um scaffold, não uma integração pronta para usar. A seleção de provider, a validação de config e o caminho do customer portal estão conectados — createCustomerPortalLink importa o SDK do Stripe de forma lazy e chama billingPortal.sessions.create. A criação da sessão de checkout e o parse de webhooks são stubs tipados com as chamadas exatas ao SDK escritas nos comentários. Por que scaffold e não terminar? Porque a base do boilerplate não traz o pacote stripe como dependência. Você o adiciona, completa os dois métodos contra o formato que já está fixado, e todo consumidor do contrato de billing segue funcionando sem mudança. O compromisso que assumimos agora é a interface — para o seu código nunca se acoplar às particularidades do Stripe.
Uma env var seleciona o provider
O composition root constrói exatamente um provider de pagamento a partir de PAYMENT_PROVIDER. Coloque em stripe e forneça os dois secrets; a factory os valida no boot e lança um erro claro se faltar algum.
1 PAYMENT_PROVIDER=stripe
2 STRIPE_SECRET_KEY=sk_live_...
3 STRIPE_WEBHOOK_SECRET=whsec_...
4
5 # Then add the SDK the scaffold expects:
6 # bun add stripe (in apps/server)
O contrato de billing em que o Stripe se pluga
Customer portal — conectado
createCustomerPortalLink importa o SDK do Stripe de forma lazy e retorna uma URL de billing portal hospedado. Zero custo de SDK para deployments que usam outro provider.
Checkout — scaffold
createCheckoutSession retorna um "ainda não implementado" tipado até você conectar stripe.checkout.sessions.create contra o formato de input fixado.
Webhooks — scaffold
parseWebhook está como stub com a chamada exata a fazer: stripe.webhooks.constructEvent(rawBody, sig, secret) mapeada para um BillingEvent normalizado.
Tipos agnósticos de provider
Os tipos de retorno Result<T, DomainError> são idênticos entre Stripe, MercadoPago e Polar, então a camada de aplicação nunca ramifica por provider.
Referência de configuração
Variáveis de ambiente
PAYMENT_PROVIDERobrigatóriaSet to stripe
STRIPE_SECRET_KEYobrigatóriaSTRIPE_WEBHOOK_SECRETobrigatória
Onde ele vive
apps/server/src/modules/billing/infrastructure/providers/stripe-payment-provider.tsapps/server/src/modules/billing/infrastructure/providers/index.ts
Construa o billing sobre um contrato, não sobre um provider.
Publique com Stripe, MercadoPago ou Polar atrás do mesmo port tipado — e nunca reescreva seu app para trocar.