# وصفة: اشتراك SaaS

> خطة شهرية أو سنوية بالعملات المشفرة. كل فترة فاتورة مع تذكيرات؛ ويسأل التطبيق Perly Pay عمّن يملك الوصول.

لا يمكن سحب العملات المشفرة من محفظة، لذا يتجدد الاشتراك بالفاتورة: قبل نهاية الفترة يتلقى المشتري الفاتورة التالية، ثم تذكيرات حتى تُدفع. لا خصم تلقائي. لا يحسب التطبيق الأيام بنفسه — بل يسأل `entitlements.check`.

> **ملاحظة:** مع مساعد: تنفّذ هذه الوصفة في مشروعك مهارة `sell-subscription` من إضافة Perly Pay. المثال القابل للتشغيل هو `examples/saas-subscription` (MIT) في مستودع الإضافة.

## كيف يعمل

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` من خادمك.
