# Rezept: SaaS-Abo

> Ein Monats- oder Jahrestarif gegen Krypto. Jeder Zeitraum ist eine Rechnung mit Erinnerungen; Ihre App fragt Perly Pay, wer Zugang hat.

Krypto lässt sich nicht von einer Wallet einziehen, daher verlängert sich ein Abo per Rechnung: Vor dem Ende des Zeitraums erhält der Käufer die nächste, dann Erinnerungen, bis sie bezahlt ist. Keine automatische Abbuchung. Ihre App zählt keine Tage selbst – sie fragt `entitlements.check`.

> **Hinweis:** Mit einem Assistenten: Dieses Rezept setzt der Skill `sell-subscription` des Perly-Pay-Plugins in Ihrem Projekt um. Ein lauffähiges Beispiel ist `examples/saas-subscription` (MIT) im Repository des Plugins.

## So funktioniert es

1. **Ein Tarif** — Ein Produkt und ein Preis mit `model: "subscription"` und `recurring.interval` (`month`, `year`…), optional Test- und Kulanztage.
2. **Das Abo** — Eine Rechnung auf diesen Preis mit dem Nutzer als Kunden eröffnet das Abo und seine erste Rechnung. Ihre Bezahlung macht den Tarif aktiv.
3. **Zugang zu Funktionen** — `entitlements.check({ customer_external_id, product })` → `has_access` und `ends_at`, auf dem Server, bei jedem Besuch oder mit kurzem Cache.
4. **Zuhören** — `invoice.fulfilled` – die erste Zahlung und jede Verlängerung; `subscription.past_due`, `subscription.unpaid` und `subscription.ended` – um zu warnen und zu sperren.
5. **Verwaltung für den Käufer** — Ein Link zum Kundenportal (`portalSessions.create`): eine offene Verlängerung bezahlen, im Voraus zahlen oder kündigen.

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

Kulanztage, Tarifwechsel und Status stehen unter [Subscriptions and reminders](https://pay.perly.io/docs/subscriptions.md).

## Beispiel starten

1. **Installieren** — `npm install` in `examples/saas-subscription` (Node 20.12+).
2. **Schlüssel** — Kopieren Sie `.env.example` nach `.env` und tragen Sie einen Testschlüssel (`sk_test_…`) in `PERLY_PAY_SECRET_KEY` ein.
3. **Vorbereiten** — `npm run setup` legt mit Ihrem Schlüssel Produkt und Preis an und gibt ihre IDs für `.env` aus.
4. **Starten** — `npm start` (oder `npm run dev`), wie seine README sagt.
5. **Ohne Wallet bezahlen** — Abonnieren Sie auf der Startseite, klicken Sie auf der Rechnung auf **Simulate payment** und öffnen Sie dann `/pro?user=you@example.com`: Pro ist bis zum Ende des Zeitraums frei.

## Fallstricke

- Versprechen „wir buchen automatisch von Ihrer Wallet ab“. Nichts wird eingezogen; sagen Sie „verlängert sich per Rechnung“.
- Fehlende oder erfundene E-Mail des Kunden: Verlängerungsrechnungen und Erinnerungen gehen dorthin.
- Den Zugang in der ersten Minute der Verspätung sperren. Entscheiden Sie, was `past_due` bedeutet (innerhalb der Kulanztage).
- Zugang freischalten, wenn der Käufer vom Bezahlen zurückkommt. „Bezahlt“ heißt nur ein verifizierter Webhook `invoice.fulfilled` oder `entitlements.check` von Ihrem Server.
