# Рецепт: SaaS-підписка

> Місячний чи річний план за криптовалюту. Кожен період — рахунок із нагадуваннями; застосунок питає Perly Pay, у кого є доступ.

Криптовалюту не можна стягнути з гаманця, тож підписка поновлюється рахунком: перед кінцем періоду покупець отримує наступний, далі нагадування, доки його не сплачено. Автосписання немає. Застосунок не рахує днів сам — він питає `entitlements.check`.

> **Примітка:** З асистентом: цей рецепт робить у вашому проєкті скіл `sell-subscription` плагіна Perly Pay для Claude Code — плагін і його приклад `examples/saas-subscription` (MIT) уже на шляху. Доти будь-який асистент прочитає той самий скіл з `/.well-known/skills/perly-pay-sell-subscription/SKILL.md`.

## Як це працює

1. **План** — Продукт і ціна з `model: "subscription"` та `recurring.interval` (`month`, `year`…), за бажанням пробні й пільгові дні.
2. **Підписка** — Рахунок на цю ціну з користувачем як клієнтом відкриває підписку і її перший рахунок. Його оплата робить план активним.
3. **Доступ до функцій** — `entitlements.check({ customer_external_id, product })` → `has_access` і `ends_at`, на сервері, на кожен візит або з коротким кешем.
4. **Слухайте** — `invoice.fulfilled` — перша оплата й кожне поновлення; `subscription.past_due`, `subscription.unpaid` і `subscription.ended` — щоб попередити й закрити.
5. **Керування для покупця** — Посилання на кабінет клієнта (`portalSessions.create`): сплатити відкрите поновлення, оплатити наперед або скасувати.

**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 });
```

Пільгові дні, зміну плану й статуси описано в [Subscriptions and reminders](https://pay.perly.io/docs/subscriptions.md).

## Запустіть приклад

1. **Встановіть** — `npm install` у `examples/saas-subscription` (Node 20.12+).
2. **Ключ** — Скопіюйте `.env.example` у `.env` і впишіть тестовий ключ (`sk_test_…`) у `PERLY_PAY_SECRET_KEY`.
3. **Підготуйте** — `npm run setup` створює продукт і ціну вашим ключем та друкує їхні ідентифікатори для `.env`.
4. **Запустіть** — `npm start` (або `npm run dev`), як каже його README.
5. **Сплатіть без гаманця** — Підпишіться на головній, натисніть **Simulate payment** на рахунку, потім відкрийте `/pro?user=you@example.com`: Pro відкрито до кінця періоду.

## Пастки

- Обіцяти «ми самі спишемо з вашого гаманця». Нічого не стягується; кажіть «поновлюється рахунком».
- Відсутня чи вигадана пошта клієнта: рахунки на поновлення й нагадування йдуть туди.
- Закривати доступ у першу ж хвилину запізнення. Вирішіть, що означає `past_due` (у межах пільгових днів).
- Відкривати доступ, коли покупець повернувся з оплати. «Сплачено» означає лише перевірений вебхук `invoice.fulfilled` або `entitlements.check` з вашого сервера.
