Pagamentos · modules/billing

Scaffold de adapter

Stripe,
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.

apps/server/.env
 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ória

    Set to stripe

  • STRIPE_SECRET_KEYobrigatória
  • STRIPE_WEBHOOK_SECRETobrigatória

Onde ele vive

  • apps/server/src/modules/billing/infrastructure/providers/stripe-payment-provider.ts
  • apps/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.