الفوترة والمدد والانقطاع
الأسبوع المجاني، ومدة 12 شهرًا، وإلغاء التجديد، وعدم الاسترداد، والوحدات التي تملكها مساحة العمل، وما يحدث عند فشل الدفع.
تشترك مساحة العمل في أساس واحد، خطة أو حزمة قطاع، بالإضافة إلى الإضافات. وهي معًا تقرر أي وحدات تملكها. ثم يكون لكل وحدة حالة فوترة، لا يكتبها إلا نظام الفوترة (دور الخدمة)، وليس شخصًا داخل التطبيق.
الأسبوع المجاني
تبدأ كل عملية شراء بـ تجربة مجانية مدتها 7 يومًا، واحدة لكل عميل. تأتي التواريخ من trialSchedule(purchaseDay) في @callwise/pricing:
- عند إتمام الشراء يُدخل العميل بيانات الدفع ويضع علامة في مربع الموافقة. تُحفظ وسيلة الدفع ويُحصَّل $0 اليوم. يعرض إتمام الشراء
اليوم: $0 · أول تحصيل في <date>والمبلغ. - اليوم 7 (اليوم الذي يلي آخر يوم مجاني): يُحصَّل الإجمالي السنوي مرة واحدة، وتبدأ مدة 12 شهرًا في ذلك اليوم. عملية شراء في 16 أكتوبر 2026 مجانية من 16 إلى 22 أكتوبر، وتُحصَّل في 23 أكتوبر 2026، وتجري مدتها من 23 أكتوبر 2026 إلى 22 أكتوبر 2027، وتتجدد في 23 أكتوبر 2027.
- الإلغاء أثناء التجربة لا يكلف شيئًا. على الموقع هذا هو إلغاء تجربة (
/account/trial، رقم الطلب + البريد)، وهو يستدعيcancelTrial()في@callwise/store: مسموح فقط ما دام الطلبtrialingوقبل يوم أول تحصيل؛ ويُبطل الوسيلة المحفوظة ولا يحصّل شيئًا. بعد أول تحصيل تكون المدة غير قابلة للاسترداد ولا يمكن إلغاء إلا التجديد. - تجربة واحدة لكل عميل، تُحسب بالبريد المُطبَّع عبر الطلبات المخزّنة (أحرف صغيرة، ومسافات طرفية محذوفة، و
+tagsمُسقطة، ونقاط Gmail متجاهلة). ليس للعملية الثانية تجربة: تُحصَّل عند إتمام الشراء وتبدأ مدتها ذلك اليوم (termFrom(today))، ويقول إتمام الشراء «استُخدمت تجربتك المجانية في طلب سابق: يُحصَّل اليوم».
حالات الطلب في @callwise/store: trialing (الوسيلة محفوظة، ولم يُحصَّل شيء) → active (أُخذ أول تحصيل)، أو trialing → trial_cancelled (لم يُحصَّل شيء، أبدًا). يخزّن كل طلب trial: { start, end, firstChargeOn } وamountToday وfirstCharge: { amount, on, idempotencyKey, status } وتواريخ المدة.
مهمة تحصيل اليوم 7
تحصّل runDueTrialCharges(now) كل طلب trialing يوافق يوم أول تحصيل له اليوم أو ما قبله، مرة واحدة بالضبط، وتنقله إلى active. تُتخطى التجارب الملغاة؛ وتُترك الطلبات التي ما زال يومها 7 مقبلًا. وهي متماثلة المفعول: الطلب المحصَّل لم يعد trialing، ويحمل كل تحصيل مفتاح تماثل مفعول واحدًا لكل طلب (first-charge:<orderId>)، لذا تشغيلها مرتين، أو بعد انهيار بين التحصيل والحفظ، لا يحصّل مرتين أبدًا. يبقى التحصيل الفاشل trialing ويُعاد في التشغيل التالي.
pnpm --filter @callwise/store charge-due # against apps/site/.data/orders.json
pnpm --filter @callwise/store charge-due -- --now 2026-10-23 # pretend it is day 7مزودو الدفع
لواجهة PaymentProvider الدوال setupPaymentMethod (تحفظ وسيلة، $0) وcharge (تحصّل الآن، لعملية شراء بلا تجربة) وchargeFirst(order) (تحصيل اليوم 7) وvoidOnCancel(order). ليس لها استدعاء استرداد. لا يُشحن في هذا الإصدار إلا المزود التجريبي: لا يُبقي نموذج البطاقة التجريبي في إتمام الشراء (4242 4242 4242 4242) إلا العلامة التجارية وآخر 4 أرقام وتاريخ الانتهاء، ولا الرقم الكامل ولا CVC أبدًا، ولا يتحرك مال.
غير مبني وغير متحقق منه (verified: false في الشيفرة):
- Stripe: اشتراك مع
trial_period_days=7على وسيلة محفوظة بـ SetupIntent؛ وتكون حقول البطاقة Stripe Elements، فلا تصل أرقام البطاقات إلى خادمنا أبدًا. - المصارف بلا فوترة متكررة: تفويض مسبق بـ 3D Secure للإجمالي السنوي عند إتمام الشراء، يُلتقط في اليوم 7 بالمهمة المجدولة ويُبطل عند الإلغاء.
المدة
- كل خطة وحزمة وإضافة هي عقد بحد أدنى 12 شهرًا، تُفوتر سنويًا مقدمًا، وتبدأ بعد الأسبوع المجاني (أو عند إتمام الشراء لعميل سبق أن حصل على واحد). لا يوجد خيار شهر بشهر.
- تُعرض الأسعار شهريًا: سعر القائمة مطروحًا منه 12%. رسم المدة هو اثنا عشر من تلك، تُؤخذ مقدمًا. انظر الأسعار.
- تعطي
termFrom(start)في@callwise/pricingالتواريخ: تنتهي المدة في اليوم السابق للذكرى الأولى، وتتجدد في الذكرى. مدة تبدأ في 16 أكتوبر 2026 تنتهي في 15 أكتوبر 2027 وتتجدد في 16 أكتوبر 2027. تُضبط نهايات الأشهر (31 يناير → تتجدد في 31 يناير، وتنتهي في 30 يناير). - يخزّن
cw_subscriptionsالحقولterm_startوterm_endوrenewal_cancelled_at.
إلغاء التجديد
يعني الإلغاء إلغاء التجديد، ولا شيء غيره. يفعله مالك من الإعدادات ← الفوترة ← إلغاء التجديد. الإجراء:
- يضبط
renewal_cancelled_at(يصبح تاريخ التجديد فارغًا)، - يُبقي كل وحدة نشطة حتى
term_end، - لا يحصّل شيئًا ولا يسترد شيئًا.
بعد term_end يُفترض أن تصبح مساحة العمل الملغاة للقراءة فقط، مثل المنقطعة أدناه. في هذا الإصدار لا شيء يقلب الحالة في ذلك التاريخ بعد (لا مهمة فوترة مجدولة)؛ والقاعدة مكتوبة حتى تتبعها المهمة.
لا استرداد
بعد أخذ أول تحصيل سنوي، تكون المدفوعات غير قابلة للاسترداد (الإلغاء أثناء الأسبوع المجاني لا يكلف شيئًا، فلا شيء يُسترد): لا استرداد كامل ولا جزئي لأشهر غير مستخدمة، أو أرصدة غير مستخدمة، أو إضافات لم تعد تُستخدم، أو الانتقال إلى خطة أصغر (وهو يسري عند التجديد التالي). ليس في الشيفرة مسار استرداد: تصدّر @callwise/pricing القيمة REFUNDS = 'none' ولا دالة استرداد، وليس لدى @callwise/store ولا PaymentProvider دالة استرداد على الإطلاق، وتحمل الطلبات refund: 'never'.
موافقة إتمام الشراء
لدى إتمام الشراء في الموقع مربع اختيار مطلوب يبدأ غير معلَّم. تسمّي جملته الأسبوع المجاني، وتاريخ أول تحصيل ومبلغه، وأن الإلغاء أثناء التجربة لا يكلف شيئًا، والحد الأدنى 12 شهرًا الذي يبدأ بعد التجربة، والفوترة السنوية مقدمًا، والتجديد التلقائي وعدم الاسترداد، وتربط الشروط وسياسة الإلغاء والاسترداد. تُبنى الجملة لكل طلب بواسطة consentText(offer)؛ ولعميل عائد تقول إن التجربة استُخدمت وإن التحصيل اليوم. يعيد الخادم حساب العرض، ويرفض طلبًا بلا المربع أو بجملة مختلفة، ويخزّن على الطلب:
{ "accepted": true, "at": "2026-10-16T09:30:00.000Z", "termsVersion": "2026-10-16", "text": "I agree to the Terms and …" }إصدار الشروط في هذا الإصدار هو 2026-10-16b. يُرفض طلب أُرسل من صفحة عرضت نصًا أقدم أو إصدارًا أقدم.
حالات الفوترة
| الحالة | تأتي من | يستطيع الأشخاص |
|---|---|---|
locked | الوحدة ليست في الخطة أو الحزمة أو إضافة | لا شيء. تعرض الصفحة أي خطة تفتحها. |
active | مدفوعة، أو في الأسبوع المجاني | كل ما يسمح به مستوى وصولهم |
grace | فشل الدفع حديثًا | كل شيء، ريثما يُصلح الدفع |
read_only | فشل الدفع منذ مدة، أو انتهت المدة بلا تجديد | العرض فقط. لا تعديلات، ولا نشر. |
يستطيع المالك أيضًا إطفاء وحدة active في الإعدادات، وهو يخفيها عن الجميع. ترفض قاعدة البيانات تشغيل وحدة locked.
عندما يفشل الدفع
تأتي الأرقام أدناه من LAPSE_RULES في @callwise/pricing.
| Days after a failed payment | Status | Module state | What happens |
|---|---|---|---|
| 0 | active | active | Full access. |
| 1–7 | past_due | grace | Full access while the payment is fixed. |
| 8–30 | read_only | read_only | Data visible, no edits. Calls forward to the fallback number. |
| after 30 | lapsed | read_only | Still read-only. Data is kept for 90 days. |
بينما تكون مساحة العمل للقراءة فقط، لا تُسقط المكالمات: تُحوَّل إلى رقم الاحتياط المضبوط في الإعدادات ← أرقام الهاتف. تُبقى البيانات لمدة 90 يومًا بعد الانقطاع أو بعد انتهاء مدة بلا تجديد، حتى يمكن تصديرها.
الأرصدة
لكل خطة وحزمة رصيد أرصدة مشترك واحد في الشهر، تستخدمه كل وحدة وكل نموذج ذكاء اصطناعي (انظر الأسعار ونماذج الذكاء الاصطناعي والأرصدة). تستهلك المكالمات الأرصدة بمعدل النماذج التي يستخدمها وكيلها. لا تُرحَّل الأرصدة إلى الشهر التالي. يتلقى المالكون تنبيهًا عند 80% وعند 100%. بعد 100%، تُحوَّل المكالمات إلى أرقام الاحتياط ما لم تكن مساحة العمل قد اختارت الاستهلاك الزائد بسعر $0.03 للرصيد.
من يستطيع تغيير الخطة
لا أحد من داخل التطبيق. تعيش الخطة والحالة والمدة ومخصص الرصيد في cw_subscriptions، ويستطيع المستخدمون الذين سجّلوا الدخول قراءته لا كتابته؛ والكتابة الوحيدة في الفوترة التي يستطيعها مالك هي إلغاء التجديد. في هذا الإصدار لا يوجد دفع حقيقي: يسجّل متجر الموقع طلبات تجريبية، وفي الوضع التجريبي يُحاكى تغيير الخطة، وفي وضع قاعدة البيانات المحلية يُكتب بدور الخدمة.