# Receita: assinatura SaaS

> Um plano mensal ou anual em cripto. Cada período é uma fatura com lembretes; o seu app pergunta ao Perly Pay quem tem acesso.

Não dá para cobrar cripto de uma carteira, então uma assinatura renova por fatura: antes de o período acabar, o comprador recebe a próxima e depois lembretes até pagar. Não há cobrança automática. O seu app não conta os dias: ele pergunta a `entitlements.check`.

> **Nota:** Com um assistente: a skill `sell-subscription` do plugin do Perly Pay faz esta receita no seu projeto. O exemplo executável é `examples/saas-subscription` (MIT) no repositório do plugin.

## Como funciona

1. **Um plano** — Um produto e um preço com `model: "subscription"` e `recurring.interval` (`month`, `year`…), com dias de teste e de carência, se quiser.
2. **Uma assinatura** — Uma fatura desse preço com o seu usuário como cliente abre a assinatura e a primeira fatura dela. Quando é paga, o plano fica ativo.
3. **Acesso a recursos** — `entitlements.check({ customer_external_id, product })` → `has_access` e `ends_at`, no servidor, a cada visita ou com um cache curto.
4. **Escute** — `invoice.fulfilled` para o primeiro pagamento e cada renovação; `subscription.past_due`, `subscription.unpaid` e `subscription.ended` para avisar e encerrar.
5. **Controles para o comprador** — Um link para o portal do cliente (`portalSessions.create`): pagar uma renovação aberta, pagar adiantado ou cancelar.

**Subscribe, then gate**

```js
const invoice = await pay.invoices.create(
  { line_items: [{ price: PRO_MONTHLY }], customer: customer.id, metadata: { user: userId }, return_url },
  { idempotencyKey: `subscribe-${userId}-${today}` },
);
redirect(invoice.url); // invoice.subscription is the new subscription

const { has_access } = await pay.entitlements.check({ customer_external_id: userId, product: PRO });
```

Os dias de carência, as mudanças de plano e os status estão em [Subscriptions and reminders](https://pay.perly.io/docs/subscriptions.md).

## Execute o exemplo

1. **Instale** — `npm install` em `examples/saas-subscription` (Node 20.12+).
2. **Chave** — Copie `.env.example` para `.env` e coloque uma chave de teste (`sk_test_…`) em `PERLY_PAY_SECRET_KEY`.
3. **Prepare** — `npm run setup` cria o produto e o preço com a sua chave e imprime os ids deles para o `.env`.
4. **Execute** — `npm start` (ou `npm run dev`), como diz o README dele.
5. **Pague sem carteira** — Assine na página principal, clique em **Simulate payment** na fatura e depois abra `/pro?user=you@example.com`: o Pro fica aberto até o fim do período.

## Erros comuns

- Prometer “vamos cobrar da sua carteira”. Nada é cobrado; diga “renova por fatura”.
- Um e-mail do cliente que falta ou é inventado: as faturas de renovação e os lembretes vão para ele.
- Retirar o acesso no primeiro minuto de atraso. Decida o que `past_due` significa (dentro dos dias de carência).
- Liberar o acesso quando o comprador volta do checkout. “Pago” só significa um webhook `invoice.fulfilled` verificado ou `entitlements.check` a partir do seu servidor.
