فوترة الاشتراكات
الخطط وحدودها، وصفحة الفوترة، والترقيات التي تُحصَّل فورًا والتخفيضات المجدولة عند التجديد، وصفحة الدفع التجريبية المدمجة وStripe، والتجارب والتجديدات، ورسائل الفوترة، والفواتير بصيغة PDF، وما يغيّره الدفع الفاشل أو الإيقاف.
لحزمة الحزمة الكاملة
الخطط وحدودها
كل مساحة عمل على إحدى ثلاث خطط شهرية، بالدولار الأمريكي:
| الخطة | السعر | المقاعد | طلبات API | التخزين |
|---|---|---|---|---|
| Starter | 29 دولارًا شهريًا | 3 | 10,000 | 5 GB |
| Pro | 99 دولارًا شهريًا | 10 | 100,000 | 20 GB |
| Scale | 249 دولارًا شهريًا | 30 | 500,000 | 100 GB |
- تبدأ مساحة العمل التي تُنشأ في التهيئة على تجربة لخطة Starter، طوال مدة إعداد المنصة مدة التجربة (
trial_days، وهي 14 يومًا في البيانات الأولية). وتضع البيانات الأولية Forma Studio على Pro، مع ثلاث فواتير مدفوعة. - عندما تنتهي التجربة دون خطة مدفوعة، تصبح مساحة العمل متأخرة الدفع من تلك اللحظة، وتبدأ فترة السماح الخاصة بالدفع الفاشل (انظر «الدفع الفاشل» أدناه). تعرض صفحة الفوترة «انتهت التجربة. اختر خطة مدفوعة قبل» نهاية فترة السماح، ويسجّل سجل النشاط «انتهت التجربة دون خطة مدفوعة».
- المقاعد مُلزِمة: تُرفض الدعوة، وقبولها كذلك، بالرمز
seat_limit_reachedعندما تُشغل كل المقاعد. - تحسب طلبات API الاستدعاءات المنفَّذة بمفاتيح API الخاصة بمساحة العمل، ويحسب التخزين ملفات المشاريع التي تحتفظ بها. يُعرض الاثنان مقابل الخطة ويُفحصان قبل التخفيض؛ ولا ترفض واجهة API استدعاءً أو رفع ملف يتجاوز الحد. يعود عدد الطلبات إلى الصفر مع كل فترة فوترة جديدة، ومنها فترة التجربة.
صفحة الفوترة
تعرض الفوترة، في /en/dashboard/billing، اشتراك مساحة العمل:
- الخطة مع حالتها (تجربة أو نشط أو متأخرة الدفع أو تنتهي قريبًا أو ملغاة أو موقوفة)، وسعرها الشهري، والتاريخ التالي المهم، مثل «تتجدد في» أو «تنتهي التجربة في».
- تغيير الخطة (اختر خطة مدفوعة أثناء التجربة، وبعد انتهائها، وبعد إلغاء مساحة العمل) وإدارة وسيلة الدفع، أو استئناف الاشتراك بينما الخطة على وشك الانتهاء.
- بينما ينتظر التخفيض موعد التجديد، تظهر «تنتقل إلى Starter في» مع التاريخ، ومعها الإبقاء على Pro (اسم الخطة الحالية) لإلغاء التخفيض.
- الاستخدام: طلبات API والمقاعد والتخزين مقابل حدود الخطة.
- سجل الفواتير، مع زر تنزيل على كل فاتورة.
- بريد الفوترة، مع تعديل: «تُرسل إشعارات الدفع إلى هذا العنوان، ويُطبع على كل فاتورة.» ويملؤه Stripe Checkout أيضًا.
- إلغاء الاشتراك، ما دامت الخطة في التجربة أو نشطة أو متأخرة الدفع.
العضو الذي يستطيع قراءة الفوترة دون تغييرها يرى الصفحة نفسها مع «يغيّر الخطة المالك وأعضاء الفوترة فقط.» بدل الأزرار.
تغيير الخطة
اختيار خطة
اضغط تغيير الخطة واختر خطة. تعرض النافذة تحت «ما الذي يتغير» ما يُحصَّل اليوم والفاتورة القادمة، وكلاهما من واجهة API. أثناء التجربة، وبعد انتهائها، وبعد إلغاء مساحة العمل، يصبح الزر اختر خطة مدفوعة، ويمكن اختيار أي خطة، ومنها الحالية («خطة تجربتك» أثناء التجربة).
الترقية: تُحصَّل فورًا
تسري الخطة الأغلى فورًا ويبقى موعد التجديد. على اشتراك Stripe قيد العمل تقول النافذة «يسري فورًا. تُحصَّل من البطاقة المحفوظة الفروقات بالتناسب اليوم، ويبقى موعد التجديد.»، ويُحصَّل اليوم هو رقم Stripe نفسه، ويحصّله الترقية والدفع الآن من وسيلة الدفع المحفوظة دون صفحة دفع. وعلى صفحة الدفع التجريبية تقول «يسري فورًا، محسوبًا بالتناسب لبقية هذه الفترة.» ويفتح المتابعة إلى الدفع صفحة الدفع. أما أول دفعة (بعد تجربة أو بعد تجربة منتهية أو لمساحة عمل ملغاة) فتُحصَّل بشهر الخطة كاملًا وتبدأ فترة جديدة من 30 يومًا: «تبدأ الخطة المدفوعة فورًا. يُحتسب الشهر الأول كاملًا.»، ومعها «وتنتهي التجربة» أثناء التجربة.
ادفع ثم عد
صفحة الدفع هي صفحة الدفع التجريبية المدمجة، أو صفحة Stripe نفسها بعد إعداد Stripe. تنتهي الترقية المحصّلة من البطاقة المحفوظة فورًا بالرسالة «أصبحت مساحة العمل على خطة Pro.» وعند العودة إلى صفحة الفوترة من صفحة الدفع تظهر «جارٍ تأكيد الدفع...»، ثم «وصل الدفع. أصبحت مساحة العمل على خطة Pro.» مع الخطة الجديدة وحدودها وفاتورة مدفوعة. وتظهر لصفحة دفع لم تكتمل «بدأت عملية دفع لخطة Pro ولم تكتمل.» حتى تُغلق.
التخفيض: مجدول ولا يُحصَّل شيء
الخطة الأرخص «يسري في» موعد التجديد، و«لا يُحصَّل شيء اليوم.»، ويسجّله جدولة التغيير؛ ثم تقول لوحة الخطة «تنتقل إلى Starter في» ذلك التاريخ. ويلغي الإبقاء على Pro بجانبه التغيير: «تبقى مساحة العمل على خطة Pro.» وإذا كانت المقاعد أو طلبات API أو التخزين فوق حدود الخطة الأصغر، تسرد النافذة كلًا منها وترفض بالرسالة «اخفض الاستخدام إلى حدود الخطة الجديدة أولًا.»
لا تتغير الخطة المشتراة عبر صفحة الدفع إلا عندما يؤكدها مزوّد الدفع: من خطاف Stripe الموقَّع (webhook)، أو عندما تسأل صفحة الفوترة واجهة API عند عودة الزائر فتقرأ واجهة API الجلسة من Stripe نفسه. وعنوان العودة وحده لا يغيّر الخطة أبدًا.
- مع Stripe، تغيّر الترقية الاشتراك القائم في مكانه: يُصدر Stripe فاتورة بالفرق بالتناسب فورًا ويحصّله من وسيلة الدفع المحفوظة. يبقى السعر المعروض صالحًا 30 دقيقة؛ وبعدها تُرفض الترقية («السعر المعروض لم يعد صالحًا. راجع السعر الجديد ثم أكّد مرة أخرى.») وتعرض النافذة الرقم الجديد. وتُرفض البطاقة المرفوضة، أو المصرف الذي يريد تأكيد الدفع، أو غياب وسيلة دفع محفوظة، بجملة تذكر السبب، وتبقى الخطة كما كانت.
- مع Stripe، التخفيض جدول زمني للاشتراك: تحتفظ الفترة الحالية بالسعر الذي دُفع، ويُحاسب التجديد بالسعر الأصغر، ولا شيء يُحسب بالتناسب. عندما يُدفع ذلك التجديد تنتقل مساحة العمل إلى الخطة الجديدة. يُلغي الإبقاء الجدول، وتُسقطه ترقية تحدث بين ذلك (وتعيده إذا فشل التحصيل).
- مع صفحة الدفع التجريبية، تتجدد الفترة من تلقاء نفسها عند نهايتها: فاتورة مدفوعة بسعر الخطة، وفترة الـ 30 يومًا التالية، وعدّاد الاستخدام يعود إلى الصفر، وتُطبَّق التخفيضات المجدولة لها.
صفحة الدفع التجريبية المدمجة
بدون مفتاح Stripe، يمر كل تغيير في الخطة عبر صفحة الدفع التجريبية في لوحة التحكم نفسها على /en/dashboard/billing/checkout/<session>. تعرض مساحة العمل والخطة الحالية والجديدة والمبلغ ومن تُوجَّه إليه الفاتورة، وتقول «هذه صفحة الدفع التجريبية المدمجة. لا تطلب أي بطاقة ولا تحصّل أي مبلغ.»، وتقدّم دفع تجريبي وإلغاء.
- يغيّر دفع تجريبي الخطة فورًا ويكتب فاتورة مدفوعة، تمامًا كما يفعل دفع Stripe المؤكَّد. أما إلغاء فلا يحصّل شيئًا: «أُلغي الدفع. لم يُحصَّل أي مبلغ.»
- لا يفتح هذه الصفحة إلا عضو يُسمح له بإدارة الفوترة في مساحة العمل تلك.
- يُبقي
BILLING_PROVIDER=simulatorفي ملف.envالخاص بواجهة API صفحة الدفع التجريبية حتى مع ضبط مفاتيح Stripe. - تقول إدارة وسيلة الدفع: «الدفع التجريبي لا يحفظ أي بطاقة، فلا توجد وسيلة دفع لإدارتها.»
تحصيل مدفوعات حقيقية عبر Stripe
اضبط STRIPE_SECRET_KEY في ملف .env الخاص بواجهة API ثم أعد تشغيلها. يقول سجل واجهة API عندئذ "Stripe is set up in test mode." لمفتاح sk_test_، أو أنها تحصّل من بطاقات حقيقية لمفتاح sk_live_.
- تفتح أول دفعة Stripe Checkout بوضع الاشتراك للسعر الشهري للخطة، باسم بريد الفوترة. يعيد Stripe المشتري إلى صفحة الفوترة، التي تؤكد الدفع مع واجهة API قبل أن تعرض الخطة الجديدة.
- لا يلزم إنشاء شيء في Stripe أولًا: يُنشأ سعر كل خطة أول مرة تلزم فيها، بمنتج يحمل اسم الخطة (
Northstack Pro) ومفتاح البحثnorthstack_<plan>_usd_<cents>_month(northstack_pro_usd_9900_month)، ثم يُعثر عليه بذلك المفتاح لاحقًا. ينال سعر الخطة الجديد مفتاحًا جديدًا، وتحتفظ الاشتراكات على السعر القديم به. - بعد ذلك، تغيّر الترقية الاشتراك في مكانه وتحصّل من البطاقة المحفوظة، ويُجدول التخفيض عند التجديد، كما في «تغيير الخطة» أعلاه. يجدّد Stripe الاشتراك بنفسه، ويقوم حدثه
invoice.paidبنقل مساحة العمل إلى الفترة التالية. - إذا حلّت صفحة دفع Stripe جديدة محل اشتراك ما زالت مساحة العمل تملكه، تلغي واجهة API الاشتراك القديم، ويُضاف رصيد وقته غير المستخدم إلى فاتورة العميل التالية. وإذا رفض Stripe ذلك الإلغاء، يذكر سجل واجهة API ذلك ويسمّي الاشتراك الذي يجب إلغاؤه في لوحة Stripe.
- بعد أن تدفع مساحة العمل عبر Stripe، تفتح إدارة وسيلة الدفع بوابة العملاء في Stripe وتعود إلى صفحة الفوترة.
- يطلب إلغاء الاشتراك من Stripe إنهاء الاشتراك في نهاية الفترة، ويُسقط تخفيضًا مجدولًا عند التجديد، ويلغي استئناف الاشتراك الإلغاء.
- مع مفاتيح الاختبار لا تنتقل أي أموال: ادفع على صفحة Stripe بالبطاقة
4242 4242 4242 4242وأي تاريخ مستقبلي وأي CVC.
خطاف Stripe (webhook)
قبل الإطلاق، أضف خطافًا في Stripe على العنوان العام لواجهة API وضع سره التوقيعي في STRIPE_WEBHOOK_SECRET. تتشارك الاشتراكات وطلبات تراخيص الموقع نقطة النهاية هذه.
| العنوان | الفعاليات |
|---|---|
https://<your-api>/api/billing/webhooks/stripe | checkout.session.completed, checkout.session.expired, invoice.paid, invoice.payment_failed, customer.subscription.deleted |
- يُفحص كل تسليم أولًا مقابل توقيع Stripe، ويُرفض التوقيع الخاطئ بالرمز 400. ويُطبَّق كل معرّف حدث مرة واحدة، مهما تكرر إرسال Stripe له.
- عند ضبط
STRIPE_SECRET_KEYوتركSTRIPE_WEBHOOK_SECRETفارغًا، يذكر سجل واجهة API ذلك عند بدء التشغيل، ويُرفض كل تسليم بالرمز 400 مع رسالة تسمّيSTRIPE_WEBHOOK_SECRET. وإلى أن يُضبط، لا تُسجَّل التجديدات ولا الدفعات الفاشلة ولا الإلغاءات، ولا يُحتسب الدفع إلا عندما يعود المشتري إلى صفحة الفوترة. - يغيّر
checkout.session.completedالخطة. ويخزّنinvoice.paidفاتورة Stripe مرة واحدة، بمبلغها والفترة التي تدفعها، ويعيد مساحة العمل إلى نشط (أو تنتهي قريبًا إن كانت ملغاة). والفاتورة التي تبدأ فترة تنقل موعد التجديد إلى نهايتها وتعيد عدّاد الاستخدام إلى الصفر، ويطبّق التجديد تخفيضًا مجدولًا له؛ أما فاتورة الترقية بالتناسب فلا تنقل شيئًا. ويضعinvoice.payment_failedمساحة العمل في متأخرة الدفع، ويضعهاcustomer.subscription.deletedفي ملغاة. - على جهازك لا يستطيع Stripe الوصول إلى واجهة API، ومع ذلك يكتمل الدفع التجريبي، لأن صفحة الفوترة تطلب من واجهة API قراءة الجلسة من Stripe عندما يعود المشتري.
الإلغاء والاستئناف
يسأل إلغاء الاشتراك: «إلغاء الاشتراك؟»: تبقى الخطة نشطة حتى موعد التجديد، وبعده تحتفظ مساحة العمل ببياناتها لكنها تتوقف عن الفوترة. تصبح الحالة تنتهي قريبًا، وتقول اللوحة «تنتهي في» مع التاريخ، ويُبقي استئناف الاشتراك الخطة بعد كل شيء. ويُسقط أي تخفيض مجدول للتجديد، إذ لا تجديد يحدث عنده.
مع Stripe، ينهي Stripe الاشتراك في ذلك التاريخ ويضع خطافه مساحة العمل في ملغاة. وعلى صفحة الدفع التجريبية تصبح مساحة العمل ملغاة في نهاية الفترة. تحتفظ مساحة العمل الملغاة بكل صلاحيات القراءة، ولا تستطيع بدء مشاريع أو دعوات أو مفاتيح API جديدة حتى تعود إلى خطة مدفوعة: اختر خطة مدفوعة تشتري أي خطة بسعرها الكامل من ذلك اليوم.
حذف مساحة العمل (يقوم به مالكها، من الإعدادات، منطقة الخطر) ينهي اشتراكها في Stripe فورًا، دون رصيد عن بقية الفترة. وإذا تعذّر الوصول إلى Stripe، يُرفض الحذف بالرمز 409 مع الرسالة «تعذّر إلغاء الاشتراك لدى مزوّد الدفع، لذلك بقيت مساحة العمل. حاول مرة أخرى بعد بضع دقائق.»، فلا تُحاسَب مساحة عمل محذوفة أبدًا.
الفواتير
- تُكتب فاتورة، يبدأ رقمها بـ
INV-ثم السنة ثم رقم متسلسل، في كل مرة يُدفع فيها تغيير خطة، بالمبلغ المحصَّل حينها، وعند كل تجديد في صفحة الدفع التجريبية، ومع Stripe لكل فاتورة يبلّغ Stripe أنها مدفوعة، ومنها التجديدات، بمبلغ Stripe وفترته. تُخزَّن فاتورة Stripe مرة واحدة مهما تكرر الإبلاغ عنها. يسرد سجل الفواتير آخر 36 فاتورة، بتاريخها ومبلغها وحالتها (مدفوعة أو مستحقة أو ملغاة). - يفتح تنزيل الفاتورة بصيغة PDF: الخطة والفترة ومن تُوجَّه إليه الفاتورة والإجمالي. الرابط موقَّع ويعمل خمس دقائق دون تسجيل دخول، فيمكن فتحه في تبويب جديد.
- بريد الفوترة في الصفحة هو العنوان الذي تذكره الفاتورة وهو الذي يملؤه Stripe Checkout.
التجارب والتجديدات عبر الزمن
تطبّق واجهة API بنفسها ما يستحقه التقويم، مرة واحدة لكل أمر: تجربة بلغت نهايتها، وفترة صفحة دفع تجريبية تتجدد، واشتراك مضبوط لينتهي مع فترته. يعمل هذا في كل مرة تُقرأ فيها فوترة مساحة عمل، ومرة كل ساعة لكل مساحة عمل (والمرور الأول بعد دقيقة من بدء واجهة API)، فيلحق الخادم الذي كان متوقفًا بما فاته عند عودته.
- يجدّد Stripe اشتراكاته بنفسه؛ وفيها تتبع واجهة API الحدثين
invoice.paidوinvoice.payment_failedمن Stripe. - يُنفَّذ كل تغيير مرة واحدة حتى لو سوّى طلبان، أو خادما API، مساحة العمل نفسها في اللحظة ذاتها.
- يسجّل سجل النشاط انتهاء تجربة (
billing.trial_ended)، وتغيير خطة (billing.plan_changed، ومنه ما طُبّق عند التجديد)، وتغييرًا مجدولًا أُلغي (billing.schedule_canceled).
رسائل الفوترة
تُرسل أربعة أحداث فوترة بالبريد إلى مالك مساحة العمل وأعضاء الفوترة، كلٌّ بلغته، أو بلغة مساحة العمل إن لم يختر لغة، وإلى بريد الفوترة بلغة مساحة العمل إن لم تكن لغةً لأحدهم، مع رابط إلى صفحة الفوترة:
- دفعة فاشلة، مع نهاية فترة السماح؛
- تجربة انتهت دون خطة مدفوعة، مع التاريخ نفسه؛
- تغيير خطة تم دفعه؛
- تغيير مجدول طُبّق عند التجديد.
يوقف مفتاح إشعارات البريد الخاص بمساحة العمل (الإعدادات ثم الإشعارات) هذه الأحداث الأربعة لكل من في مساحة العمل. أما الدعوات وإعادة تعيين بيانات الدخول وإيصالات التراخيص فتُرسل دائمًا. وبدون إعدادات SMTP تُكتب كل رسالة في سجل واجهة API بدلًا من إرسالها.
دفعة فاشلة
عندما يبلّغ Stripe عن دفعة فاشلة تصبح مساحة العمل متأخرة الدفع، وتقول صفحة الفوترة «تعذّر تحصيل آخر دفعة. حدّث وسيلة الدفع قبل» نهاية فترة السماح. والتجربة التي انتهت دون خطة مدفوعة متأخرة الدفع بالطريقة نفسها، من تاريخ نهايتها.
- خلال فترة السماح، وهي
BILLING_GRACE_DAYSفي ملف.envالخاص بواجهة API (7 افتراضيًا)، يستمر كل شيء في العمل. - بعدها لا تستطيع مساحة العمل بدء مشاريع أو دعوات أو مفاتيح API جديدة؛ وترفضها واجهة API بالرمز
billing_grace_expired. تبقى كل عمليات القراءة وكل السجلات الموجودة تعمل، ولا يُحذف شيء أبدًا بسبب دفعة فاشلة. - تعيد الفاتورة المدفوعة التالية مساحة العمل إلى نشط؛ وبعد تجربة منتهية، تفعل ذلك أول دفعة.
مساحة عمل موقوفة
يستطيع موظفو المنصة إيقاف مساحة عمل من إدارة المنصة. يظل أعضاؤها قادرين على تسجيل الدخول وقراءة كل شيء، ويُرفض كل تغيير بالرمز workspace_suspended، ولا تستطيع مفاتيح API إلا القراءة، وتقول صفحة الفوترة «موقوفة. تواصل مع الدعم لاستعادة مساحة العمل.»
من يستطيع فعل ماذا
| الصلاحية | يتيح | الأدوار الأولية |
|---|---|---|
billing.read | فتح صفحة الفوترة وفواتيرها وتنزيلها | المالك، الفوترة |
billing.manage | تغيير الخطة، والإبقاء على الخطة بدل تغيير مجدول، وصفحة الدفع التجريبية، وبوابة الدفع، والإلغاء، والاستئناف، وبريد الفوترة | المالك، الفوترة |
كلتاهما في مصفوفة أدوار كل مساحة عمل، فيستطيع المالك منحهما لدور آخر. الدور الذي لا يملك أيًا منهما يحصل على مساحة العمل بدون بريد فوترتها (billingEmail: null) من كل مسار لمساحة العمل؛ ولا يزال موظفو المنصة يرونه في صفحة المؤسسة.
المسارات خلفه
- يعيد
GET /api/workspaces/:workspaceId/billingالاشتراك والخطط والاستخدام وأي عملية دفع معلّقة؛ ويعيد.../billing/invoicesآخر 36 فاتورة. - يعيد
POST .../billing/previewمع{ "planId": "pro" }تكلفة التغيير وموعد سريانه. وفي ترقية اشتراك Stripe قيد العمل يحملchargesCardOnFile: trueوquote، صالحًا 30 دقيقة. - يُجري
POST .../billing/checkoutمعplanId(ومعquoteالمذكور) التغيير:upgraded: trueعندما حُصّل من البطاقة المحفوظة، أو صفحة الدفع (url) لعملية دفع، أوscheduled: trueلتخفيض. التخفيض فوق الحدود يعيد 409over_plan_limitمع سردها؛ والعرض المنتهي يعيد 409preview_expired؛ والتحصيل المرفوض يعيد 402payment_declinedأوpayment_needs_actionأوpayment_method_missing. - يلغي
POST .../billing/keep-planتخفيضًا مجدولًا، أو يعيد 409no_scheduled_change. - يقرأ
POST .../billing/checkout/:sessionId/syncعملية دفع عائدة من المزوّد. أماPOST .../billing/portalو.../billing/cancelو.../billing/resumeوPATCH .../billing/emailفتفعل ما تقوله أسماؤها. - يعيد
GET .../billing/invoices/:invoiceId/download-linkرابطًا موقَّعًا إلىGET /api/billing/invoices/download?token=...، صالحًا خمس دقائق. - يستقبل
POST /api/billing/webhooks/stripeأحداث Stripe؛ ويخدمGET /api/billing/simulator/:sessionIdمعPOST .../completeوPOST .../cancelصفحة الدفع التجريبية.
بيع خططك الخاصة
مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.
أين تُعرَّف الخطط، وكل مكان يلزم تغييره لتبيع خططًا خاصة بك.