KasyKasy

Stripe (web)

Assinaturas web via Stripe Checkout + Customer Portal. Do teste à produção.

O módulo Stripe cobre assinaturas na web (quando o usuário está no navegador ou PWA). No mobile (iOS/Android), o kit usa RevenueCat.

Mobile usa RevenueCat. Você pode ligar só Stripe (app web), só RevenueCat (app mobile) ou os dois juntos. Veja RevenueCat.

Implementação

Pelo MCP do Kasy: peça ao assistente "adiciona stripe no meu projeto" pra ligar a feature no código (add_feature). O MCP da Stripe (abaixo) é outra coisa: cria produto e preços no painel deles. Veja MCP do Kasy.

1. Criar conta na Stripe

Acesse stripe.com e crie sua conta.

2. Criar Produto e Preços (pelo painel ou via MCP)

Pelo painel

  1. Stripe → Products → Add product
  2. Nome / descrição (aparecem no paywall)
  3. Em Pricing, adicione:
    • Um Price mensal recorrente
    • Um Price anual recorrente
  4. (Opcional) Em Features do Produto, liste os benefícios, que viram a lista do paywall
  5. Copie o prod_… do produto (você vai precisar como STRIPE_PRODUCT_ID)
Produto na Stripe com preços mensal e anual
Stripe: produto com os dois Prices recorrentes (mensal e anual)

O kit usa só planos recorrentes (mensal/anual). Não use Prices one-time.

Via MCP do Stripe (mais rápido)

Prefere configurar pela IA em vez do painel? Siga MCP do Stripe, na seção Informações abaixo, e volte pro passo 3 quando terminar.

3. Registrar o webhook

O webhook é obrigatório: é ele que grava a assinatura no banco.

  1. Stripe → Webhooks → Add endpoint
  2. Cole a URL do webhook do seu backend:
BackendURL
Firebasehttps://<region>-<projectId>.cloudfunctions.net/stripeFunctions-stripeWebhook
Supabasehttps://<project-ref>.supabase.co/functions/v1/stripe-webhook

kasy doctor mostra a URL do webhook do seu projeto.

  1. Em Select events, marque os 3 eventos:
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
  2. Salve → copie o Signing secret (whsec_...)
Endpoint de webhook na Stripe com os 3 eventos selecionados
Stripe: endpoint com os 3 eventos customer.subscription.* e o Signing secret

4. Configurar as chaves no backend

Você vai precisar de 3 valores:

ChaveFormatoOnde pega
STRIPE_SECRET_KEYsk_test_... / sk_live_...Stripe → API keys
STRIPE_WEBHOOK_SECRETwhsec_...Stripe → Developers → Webhooks → seu endpoint → Signing secret
STRIPE_PRODUCT_IDprod_...do seu Produto (opcional; em branco lista todos)
Página de API keys da Stripe
Stripe: Developers → API keys, onde fica a sk_test_
# Firebase: configura os secrets e faz o deploy
kasy configure stripe   # pede as 3 chaves
kasy deploy             # publica as funções com os secrets

# Supabase: configura os secrets
supabase secrets set STRIPE_SECRET_KEY=sk_test_xxx
supabase secrets set STRIPE_WEBHOOK_SECRET=whsec_xxx
supabase secrets set STRIPE_PRODUCT_ID=prod_xxx   # opcional

Pelo MCP: no Firebase, cole as 3 chaves no chat e peça "configura o Stripe". O assistente grava com configure_project_keys (o kasy deploy pra publicar as funções ainda é um passo separado). Veja MCP do Kasy.

API REST: você implementa 4 endpoints no seu servidor:

EndpointO que faz
GET /stripe/list-pricesDevolve os Prices recorrentes ativos da sua conta
POST /stripe/checkout-sessionCria sessão de Checkout e devolve { url }
POST /stripe/portal-sessionCria sessão do Customer Portal e devolve { url }
POST /webhooks/stripeRecebe os 3 eventos customer.subscription.* e grava em subscriptions (store=STRIPE)

A STRIPE_SECRET_KEY e a STRIPE_WEBHOOK_SECRET ficam no seu servidor, nunca no app. O contrato completo (payload de cada endpoint) está no README.md gerado dentro do seu projeto Kasy.

5. Testar

kasy run --web    # abre em localhost:5555

Abra o paywall → escolha um plano → você cai no Checkout da Stripe.

Use os cartões de teste da Stripe:

  • Número: 4242 4242 4242 4242
  • Validade: qualquer data futura
  • CVC: qualquer 3 dígitos
Stripe Checkout com cartão de teste preenchido
Checkout da Stripe com o cartão de teste 4242 preenchido

Confirme que a tabela subscriptions recebeu store='STRIPE' e o app virou premium. Se sim, terminou o modo teste.

6. Ir pra produção

  1. No painel Stripe, desligue o Test mode (Live)
  2. Recrie (ou ative) Produto + Prices em live
  3. Pegue sk_live_... e atualize no backend
  4. Registre um novo endpoint de webhook em live e pegue o novo whsec_...
  5. Refaça o deploy
  6. Faça uma compra real de validação

Se a compra real cair como premium na conta, a implementação está completa.

Por que cobrar na web também. Compra feita dentro do app passa pela Apple ou pela Google e elas retêm uma comissão de cada pagamento. A mesma assinatura vendida pelo navegador via Stripe tem uma taxa bem menor. Por isso muitos apps mantêm os dois caminhos: RevenueCat no celular e Stripe no site.

Informações

Como funciona

  • O app chama o backend que cria uma sessão de Stripe Checkout e devolve a URL.
  • O app abre essa URL no navegador. Toda a parte de cartão / PCI fica na Stripe.
  • Quando o usuário paga, o webhook da Stripe chama o backend e grava a assinatura.
  • O app detecta a mudança e vira premium. O cliente nunca escreve "sou premium": não dá pra forjar.

Os planos do paywall são buscados automaticamente dos Prices recorrentes ativos da sua conta Stripe. Você não digita preço no código.

O que a CLI configura automaticamente

Ao escolher Stripe no kasy new ou kasy add stripe:

  • Liga a flag withStripe no app
  • Embarca a camada de pagamento (checkout, portal, busca de preços)
  • Instala as funções de backend (Firebase Cloud Functions ou Supabase Edge Functions)
  • Configura a injeção por plataforma: web usa Stripe, mobile usa RevenueCat (se ligado)

MCP do Stripe

A Stripe tem um servidor MCP que deixa a IA criar produtos, preços e webhooks na sua conta, sem abrir o painel. Use como alternativa ao passo 2.

Configurar o MCP

Cole na sua IA (troque pela sua chave de teste):

Configure o MCP da Stripe (modo teste) nesta máquina, no Claude Code.
Use o pacote oficial @stripe/mcp via npx, com a chave no env STRIPE_SECRET_KEY.
Minha chave de teste é: sk_test_XXXXXXXX
Adicione um servidor MCP chamado "stripe-test" que roda:
    npx -y @stripe/mcp     (com env STRIPE_SECRET_KEY = a minha chave acima)
NÃO use @stripe/agent-toolkit (é biblioteca, dá "Connection closed").
No fim, me avise pra eu reiniciar o Claude Code.

Reinicie o Claude Code. O MCP só carrega em sessão nova.

Ou use o MCP remoto oficial (mais simples, sem chave em arquivo):

{
  "mcpServers": {
    "stripe": { "url": "https://mcp.stripe.com" }
  }
}

Criar o catálogo pela IA

Com o MCP conectado, cole na IA (ajuste preços e nomes):

Com o MCP da Stripe conectado (modo teste), crie meu catálogo de assinatura:
- 1 Produto "Pro" com descrição curta e 3 benefícios (viram a lista do paywall)
- 2 preços recorrentes: mensal R$ 19,90 e anual R$ 199 (moeda BRL)
- 7 dias de trial grátis (metadata trial_days=7 no produto)
Liste os preços ativos e me dê o STRIPE_PRODUCT_ID (prod_...) para configurar no backend.

Volte pro passo 3 quando o catálogo estiver criado.

Período de teste gratuito (trial)

O trial é lido do Price da Stripe e aparece no paywall automaticamente.

Duas formas de configurar:

  1. metadata trial_days: no Price (ou no Produto), adicione metadata trial_days = 7
  2. Trial nativo do Price: configure o free trial direto no painel do Price

O backend devolve trialDays em listPrices e a UI mostra "7 dias grátis" automaticamente.

Feature flags

Em lib/core/config/features.dart:

FlagPadrãoO que faz
withStripenenhumLiga o módulo Stripe
withStripePromoCodestrueExibe campo de cupom no Checkout
withStripePlanSwitchingtrueHabilita upgrade/downgrade no Customer Portal

Como funciona o pagamento (detalhes)

  1. App cria sessão de Checkout → abre o Stripe numa nova aba
  2. O e-mail vem preenchido com o e-mail da conta do usuário
  3. A tela do app fica em espera e faz polling a cada 5s no backend
  4. Quando a pessoa paga, o webhook grava subscriptions → o polling detecta → app vira premium
  5. Timeout: após ~10 min sem confirmação, app volta ao paywall com toast "se já pagou, toque em Restaurar"

No mobile (nativo), se o usuário assinou via Stripe na web, o app mostra um diálogo: "Esta assinatura foi feita em outra plataforma. Gerencie onde você comprou." Isso é exigido pelas políticas da Apple e do Google.

Troubleshooting

Paywall vazio (sem planos) na web

  • Não há Price recorrente ativo na conta
  • STRIPE_PRODUCT_ID aponta pra um produto sem Prices recorrentes
  • STRIPE_SECRET_KEY é de test mode mas os produtos estão em live (ou vice-versa)

Webhook não grava a assinatura

  • STRIPE_WEBHOOK_SECRET errado ou de outro modo (teste vs live)
  • Os 3 eventos customer.subscription.* não foram selecionados no endpoint
  • No Firebase: falta o deploy após configurar os secrets

Premium não ativa mesmo após pagar

  • Verifique se o webhook chegou: Stripe → Developers → Webhooks → logs do endpoint
  • Verifique se o uid no metadata bate com o usuário logado

"No Stripe customer for user" ao abrir o Portal

  • O usuário ainda não passou pelo Checkout. O Portal só funciona após a primeira assinatura.

Atualizado em 03/11/2026