مراحل نشاط الاشتراك

يمكن أن تمرّ عمليات شراء الاشتراكات بعدة حالات مختلفة خلال مراحلها، استنادًا إلى العديد من العوامل، بما في ذلك سلوك التجديد التلقائي وحالات رفض الدفع وإجراءات إدارة المطوّرين.

إدارة مراحل نشاط الاشتراكات التي يتم تجديدها تلقائيًا

عندما تتغير حالة اشتراك المستخدم، يتلقّى خادم الخلفية رسالة SubscriptionNotification.

الشكل 1. حالات مراحل النشاط وأحداث النقل لعمليات شراء الاشتراكات التي يتم تجديدها تلقائيًا

لتعديل الحالة في الخلفية، يجب استدعاء واجهة برمجة التطبيقات purchases.subscriptionsv2.get وتضمين الرمز المميّز للشراء في الإشعار. توفّر نقطة النهاية هذه أحدث حالة اشتراك يتم منحها رمز شراء مميّز وهي مصدر الحقيقة لإدارة الاشتراك.

يكون الرمز المميّز للشراء صالحًا ابتداءً من الاشتراك حتى 60 يومًا بعد انتهاء صلاحيته. وبعد هذا التاريخ، لا يصبح الرمز المميّز للشراء صالحًا للاستخدام من أجل طلب البيانات من Google Play Developer API.

عمليات شراء الاشتراكات الجديدة التي يتم تجديدها تلقائيًا

عندما يشتري مستخدم اشتراكًا، يتم إرسال رسالة SubscriptionNotification من النوع SUBSCRIPTION_PURCHASED إلى عميل RTDN. سواء تلقّيت هذا الإشعار أو سجّلت عملية شراء جديدة داخل التطبيق من خلال PurchasesUpdatedListener أو جلب عمليات الشراء يدويًا في طريقة onResume() في تطبيقك، عليك معالجة عملية الشراء الجديدة في الخلفية الآمنة. لإجراء هذا، اتبع الخطوات التالية:

  1. أرسِل طلب بحث عن نقطة نهاية purchases.subscriptionsv2.get للحصول على مورد للاشتراك يتضمّن أحدث حالة اشتراك.
  2. تأكَّد من أنّ قيمة الحقل subscriptionState هي SUBSCRIPTION_STATE_ACTIVE.
  3. أثبِت عملية الشراء.
  4. امنح المستخدم إمكانية الوصول إلى المحتوى. يمكن تحديد حساب المستخدم المرتبط بعملية الشراء بالكائن ExternalAccountIdentifiers من مورد الاشتراك في حال ضبط المعرّفات في وقت الشراء باستخدام setObfuscatedAccountId وsetObfuscatedProfileId.

تتضمن "مكتبة الفوترة في Play" أيضًا طريقة للموافقة على الاشتراك، acknowledgePurchase()، وطريقة للتحقّق من حالة الإقرار، isAcknowledged(). ومع ذلك، ننصحك بالتعامل مع معالجة عمليات الشراء في الخلفية للحصول على مستوى أمان أفضل.

يبدو مورد الاشتراك لعمليات الشراء الجديدة مشابهًا للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  "startTime": "2022-04-22T18:39:58.270Z",
  "regionCode": "US",
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  "latestOrderId": "GPA.3333-4137-0319-36762",
  "acknowledgementState": "ACKNOWLEDGEMENT_STATE_PENDING", // need to acknowledge new purchases
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": next_renewal_date,
      "autoRenewingPlan": {
        "autoRenewEnabled": true
      }
    }
  ],
}

عمليات تجديد الاشتراك

يتم إرسال إشعار SUBSCRIPTION_RENEWED عند تجديد اشتراك يتم تجديده تلقائيًا. تأكَّد من أنّ المستخدم لا يزال يحق له الحصول على الاشتراك، ثم عدِّل حالة الاشتراك من خلال إضافة expiryTime الجديدة الواردة في مورد الاشتراك الذي تم إرجاعه من واجهة برمجة التطبيقات Google Play Developer API. يبدو مورد الاشتراك مشابهًا للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  "startTime": "2022-04-22T18:39:58.270Z",
  "regionCode": "US",
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  "latestOrderId": "GPA.3333-4137-0319-36762",
  "acknowledgementState": "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED",
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": next_renewal_date,
      "autoRenewingPlan": {
        "autoRenewEnabled": true
      }
    }
  ]
}

لست بحاجة إلى الإقرار بتجديد الاشتراك.

فترة السماح

إذا حدثت مشاكل في الدفع مقابل تجديد الاشتراك، ترسل Google إشعارًا إلى المستخدم وتحاول بشكل دوري تجديد الاشتراك لبعض الوقت قبل انتهاء صلاحية الاشتراك. يمكن أن تتألف فترة الاسترداد هذه من فترة سماح متبوعة بفترة تعليق الحساب. خلال فترة السماح، ينبغي أن يظل بإمكان المستخدم الوصول إلى استحقاق الاشتراك.

تستمر الطريقة queryPurchasesAsync() في عرض عمليات الشراء التي تمت في فترة السماح. إذا كان تطبيقك يعتمد على queryPurchasesAsync فقط للتحقّق مما إذا كان المستخدم مخوّلاً للاشتراك، من المفترض أن يعالج تطبيقك فترات السماح تلقائيًا، لأنّ هذه الاشتراكات تظهر على أنّها نشطة من خلال Play Billing Library.

ومن خلال مزامنة حالة الاشتراك مع الخلفية، يمكنك أن تصبح أكثر وعيًا بحالات رفض الدفعات، كما توفر لك سياقًا إضافيًا عند محاولة الحد من الإيقاف الإجباري للاشتراك. الاستماع إلى رسائل SubscriptionNotification من النوع SUBSCRIPTION_IN_GRACE_PERIOD ليتم إعلامك عندما يدخل المستخدم فترة سماح. وعندما يكون المستخدم في فترة سماح، يحتوي مورد الاشتراك على autoRenewEnabled = true. ويعمل Google Play على تمديد قيمة expiryTime ديناميكيًا إلى أن تنتهي فترة السماح لأن فترة السماح يجب أن تظل سارية إلى أن يلغي المستخدم اشتراكه أو حتى انتهاء فترة السماح لأقصى مدة. وقيمة الحقل subscriptionState خلال هذه الفترة هي SUBSCRIPTION_STATE_IN_GRACE_PERIOD. يبدو مورد الاشتراك مشابهًا للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_IN_GRACE_PERIOD",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": timestamp_in_future,
      "autoRenewingPlan": {
        "autoRenewEnabled": true
      }
    }
  ],
}

يُعلِم Play المستخدمين الذين دخلوا في فترة سماح بأنّه تم رفض عملية الدفع، ويطلب منهم حلّ المشاكل المتعلّقة بطريقة الدفع في "متجر Play". عندما يدخل أحد المستخدمين في فترة سماح، يجب عليك أيضًا تشجيع المستخدم على إصلاح طريقة الدفع في حالة ما إذا كان هذا الفشل لا إرادي. وهناك طريقة مباشرة لإجراء ذلك وهي استخدام واجهة برمجة التطبيقات الخاصة بخدمة "مراسلة داخل التطبيق". إذا استدعيت واجهة برمجة التطبيقات هذه عندما يفتح المستخدم تطبيقك، ستظهر له رسالة من Play في شريط صغير مؤقت لإعلامه بأنّه تم رفض عملية الدفع. تتضمّن هذه الرسالة أيضًا رابطًا لصفحة معيّنة لكي يتمكن المستخدم من حلّ المشكلة في طريقة الدفع على Google Play.

وعندما يصلح المستخدم طريقة الدفع، يتم تجديد الاشتراك بتاريخ التجديد الأصلي، ويمكنك معالجة عملية التجديد كما هو موضّح في عمليات التجديد.

إذا لم يُصلح المستخدم طريقة الدفع خلال فترة السماح، يدخل الاشتراك في فترة تعليق الاشتراك وسيفقد استحقاقه.

الوصول إلى فترة السماح واستردادها

يوضّح الشكل 2 جدولاً زمنيًا للاشتراك الذي يدخل في فترة سماح ثم يسترد الأموال عندما يصلح المستخدم طريقة الدفع. بعد انتهاء فترة السماح، من المفترَض أن يفقد المستخدم مزايا الاشتراك وسيخضع لعملية تعليق الحساب.

الشكل 2. المخطط الزمني للاشتراك الذي يدخل في فترة سماح وتسترد قيمته قبل انتهائها.

من المهم تذكر النقاط التالية:

  • وخلال فترة السماح، سيحتفظ المستخدم بإمكانية الوصول إلى مزايا الاشتراك.
  • وعند استعادة الاشتراك خلال فترة السماح، لا تتم إعادة ضبط تاريخ التجديد.
  • في حال زيادة فترة السماح، على سبيل المثال، من 7 أيام إلى 14 يومًا، سيحصل المستخدمون في فترة سماح على إمكانية وصول موسّعة إلى مزايا الاشتراك.
  • في حال تقليل فترة السماح، سيتم على الفور إبطال مزايا الاشتراك بالنسبة إلى المستخدمين الذين مرّوا بما يكفي في فترة السماح القديمة لتجاوز فترة السماح الجديدة. على سبيل المثال، في حال تقليل فترة السماح من 14 يومًا إلى 7 أيام، سيتم إبطال مزايا الاشتراك للمستخدمين الذين مرّوا في الأيام 8 إلى 14 من فترة السماح القديمة على الفور.
  • سيظل الاشتراك في حالة نشطة ولن تحصل على فترة سماح لفترة السماح حتى انتهاء فترة السماح الصامتة.

فترة سماح صامتة

يمكنك تحديد فترة سماح مدتها 0 يوم، ولكن سينتظر Play يومًا واحدًا على الأقل لضمان الحصول على وقت كافٍ لإعادة محاولة الدفع. توفّر فترة السماح الصامتة هذه شبكة أمان لمعالجة الدفعات. خلال هذه الفترة التي تبلغ 24 ساعة، يبقى الاشتراك في حالة ACTIVE.

إنّ أفضل طريقة للبقاء على اطّلاع على التغييرات في حالة الاشتراك هي الاستماع إلى إشعارات المطوِّرين (RTDN) والتفاعل معها في الوقت الفعلي. يمكنك استدعاء الإجراء purchases.subscriptionsv2.get() في وقت RTDN بدلاً من وقت انتهاء الصلاحية للاطّلاع على حالة أكثر دقة للاشتراك.

وبناءً على حالة الاشتراك بعد انتهاء فترة السماح الصامتة التي تبلغ 24 ساعة، من المفترَض أن تتلقّى أحد الإشعارات التالية:

  • SUBSCRIPTION_ON_HOLD (في حال التفعيل)
  • SUBSCRIPTION_CANCELED (في حال الإلغاء)
  • SUBSCRIPTION_EXPIRED (إذا انتهت الصلاحية)
  • SUBSCRIPTION_RENEWED (في حال تجديده بنجاح)

يمكنك أيضًا طلب الطريقة subscriptionV2.get() في أي وقت بعد انتهاء فترة السماح الصامتة التي تبلغ 24 ساعة للاطّلاع على أحدث حالة للاشتراك.

فترة تعليق الاشتراك

إذا حدثت مشاكل في الدفع أثناء تجديد الاشتراك، تبدأ فترة تعليق الاشتراك بعد انتهاء أي فترة سماح. عندما يدخل اشتراك في فترة تعليق الاشتراك، عليك حظر الوصول إلى استحقاق الاشتراك.

أثناء فترة تعليق الاشتراك، عليك مواصلة معالجة أي عمليات عمليات إلغاء أو استردادات أو عمليات إعادة شراء لاشتراكاتك حسب الحاجة، لأنّه من الممكن أن يجري المستخدم هذه التغييرات أثناء تعليق الاشتراك.

ستُعلِمك ميزة RTDN عندما يدخل المستخدم فترة تعليق الاشتراك، كي تتمكّن من إعلامه في أقرب وقت ممكن بسبب تعليق إمكانية وصوله إلى الاشتراك. ويمكن إجراء ذلك مباشرةً باستخدام واجهة برمجة التطبيقات خدمة المراسلة داخل التطبيق. وعند استدعاء واجهة برمجة التطبيقات هذه عندما يفتح المستخدم التطبيق، سيعرض المستخدم رسالة في شريط صغير مؤقت تخبره برفض عملية الدفع. تتضمن هذه الرسالة أيضًا رابطًا لصفحة في التطبيق لكي يتمكن المستخدم من إصلاح طريقة الدفع لديه على Google Play.

في حال تمكُّن المستخدمين من الوصول إلى المحتوى المتاح من خلال الاشتراك خارج تطبيقك، قد يكتشفون أنّهم قد فقدوا إمكانية الوصول إليه على مساحات العرض المختلفة. يمكنك إرسال إشعار فوري أو رسالة إلكترونية إلى المستخدم لإعلامه بأنّ اشتراكه لم يعُد نشطًا بسبب رفض الدفعة.

لا يتم إرجاع الاشتراك من خلال طريقة queryPurchasesAsync() أثناء تعليق الحساب، لذلك إذا كان تطبيقك يعتمد على هذه الطريقة لعرض عمليات الشراء الحالية، يجب إتاحة تعليق الحساب تلقائيًا.

من خلال إشعارات في الوقت الفعلي الخاصة بالمطوّرين، ستتلقّى رسالة SubscriptionNotification من النوع SUBSCRIPTION_ON_HOLD عندما يتضمّن الاشتراك فترة تعليق الاشتراك. عليك استدعاء الإجراء purchases.subscriptionsv2.get من خادم الخلفية الآمنة لاسترداد معلومات الاشتراك الجديدة. أثناء فترة تعليق الاشتراك في الحساب، يتم ضبط الحقل expiryTime في مورد الاشتراك على طابع زمني سابق، ويتم ضبط الحقل subscriptionState على SUBSCRIPTION_STATE_ON_HOLD:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ON_HOLD",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": timestamp_in_past,
      ...
    }
  ],
}

لاستعادة إمكانية وصولهم، على المستخدمين تصحيح طريقة الدفع. يُعلِم Play المستخدمين المعلّقين برفض الدفعة، وعليك أيضًا تشجيعهم على حلّ طريقة الدفع التي يستخدمونها.

بعد أن ينتهي المستخدم من تصحيح طريقة الدفع، يعود الاشتراك إلى حالة الاشتراك الداعم، وينبغي بعدها استعادة إمكانية الوصول إلى المحتوى الذي تم الاشتراك فيه. في هذه الحالة، يكون الرمز المميّز للشراء مطابقًا لما كان عليه قبل بدء تعليق الحساب بسبب استرداد عملية الشراء نفسها، وستتلقّى RTDN من النوع SUBSCRIPTION_RECOVERED.

بعد الاسترداد، تعرض "مكتبة الفوترة في Play" الاشتراك مرة أخرى من خلال طريقة queryPurchasesAsync(). إذا كنت تستعين بهذه الطريقة لتحديد ما إذا كان المستخدم يحق له الحصول على اشتراك، يجب أن يعالج تطبيقك تلقائيًا الاشتراك الذي يسترد من فترة تعليق الاشتراك.

استمع إلى رسالة SubscriptionNotification من النوع SUBSCRIPTION_RECOVERED ليتم إعلامك عند استعادة اشتراك ويجب أن يستعيد المستخدم إمكانية الوصول. إذا طلبت الحصول على اشتراك بعد تلقّي هذا الإشعار، سيتم ضبط الحقل expiryTime على طابع زمني في المستقبل وسيتم ضبط الحقل subscriptionState على SUBSCRIPTION_STATE_ACTIVE مرة أخرى:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": next_renewal_date,
      ...
    }
  ],
}

وإذا لم يُصلح المستخدم طريقة الدفع قبل نهاية فترة تعليق الحساب، ستتلقّى بدلاً من ذلك رقم RTDN من النوع SUBSCRIPTION_CANCELED. للحصول على تعليمات بشأن كيفية التعامل مع عملية الإلغاء، يُرجى الاطّلاع على عمليات الإلغاء. عند إجراء طلب بحث عن اشتراك تم إلغاؤه بهذه الطريقة، يتم ضبط حقل expiryTime الذي تم عرضه على طابع زمني سابق:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_CANCELED",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": timestamp_in_past,
      ...
    }
  ],
}

بعد أن يتم إعلامك بالإلغاء مباشرةً أثناء تعليق الحساب، سيصلك أيضًا إشعار RTDN من النوع SUBSCRIPTION_EXPIRED لأنّ المستخدم لا يملك استحقاق مدفوعًا وتوقف الاشتراك بسبب الإلغاء. يمكنك معالجة تاريخ انتهاء الصلاحية هذا بالطريقة المعتادة.

يمكن للمستخدم استعادة إمكانية استخدام التطبيق من خلال إعادة شراء خطة الاشتراك نفسها أو أي خطة أخرى تقدّمها من خلال التطبيق خلال فترة تعليق الاشتراك من عملية الشراء الأصلية. في هذه الحالة، يتم إصدار رمز شراء جديد وعرض القيمة الجديدة كجزء من حدث SUBSCRIPTION_PURCHASED الذي يمثّل هذا الحدث الجديد.

الوصول إلى تعليق الحساب واسترداده

يوضّح الشكل 3 جدولاً زمنيًا للاشتراك يخضع لتعليق الحساب ثم يسترد الأموال عندما يصلح المستخدم طريقة الدفع.

الشكل 3. المخطط الزمني للاشتراك الذي يدخل في فترة تعليق الاشتراك ويسترد قيمته قبل انتهائها

على غرار المثال السابق، يوضّح الشكل 4 جدولاً زمنيًا للاشتراك الذي يدخل أولاً في فترة سماح قبل الدخول في فترة سماح قبل الدخول في فترة تعليق الاشتراك، ثم يسترد الأموال أثناء تعليقها.

الشكل 4. المخطط الزمني للاشتراك الذي يدخل في فترة سماح، ثم يدخل في فترة تعليق الاشتراك، ويسترد في النهاية فترة تعليق الاشتراك قبل انتهاء فترة تعليقه.

من المهم تذكر النقاط التالية:

  • قبل دخول الاشتراك في تعليق الحساب، يجري Google Play محاولات إضافية لتحصيل الرسوم من طريقة الدفع لمدة تصل إلى 48 ساعة. يحتفظ المستخدم بمزايا الاشتراك خلال هذه الفترة. بعد انقضاء فترة إعادة المحاولة هذه، يدخل الاشتراك في فترة تعليق الاشتراك ومن المفترض أن يفقد المستخدم إمكانية الوصول إلى مزايا الاشتراك.
  • يدخل الاشتراك في تعليق الحساب مباشرةً عند استئنافه من حالة الإيقاف المؤقت مع تعذّر الدفع باستخدام طريقة الدفع.
  • وعند استرداد الاشتراك من فترة تعليق الاشتراك، تتم إعادة ضبط تاريخ التجديد.

فترات انتهاء الصلاحية

وبعد انتهاء صلاحية الاشتراك، من المفترض أن يفقد المستخدم إمكانية الوصول إلى الاشتراك. يتم إرسال رسالة SubscriptionNotification من النوع SUBSCRIPTION_EXPIRED في هذه الحالة. عند تلقّي هذا الإشعار، يمكنك إجراء طلب بحث في Google Play Developer API للحصول على أحدث مورد للاشتراك. بعد التأكد من أنّ السمة subscriptionState هي SUBSCRIPTION_STATE_EXPIRED، أزِل الاستحقاق وسجِّل حالة الشراء باعتبارها غير صالحة في الخلفية. يبدو مورد الاشتراك مشابهًا للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_EXPIRED",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": expiration_time_in_past,
      ...
    }
  ],
}

عمليات إلغاء الاشتراكات

يمكن للمستخدم إلغاء اشتراكه طوعًا من مركز اشتراكات Play أو إلغاء اشتراكه تلقائيًا إذا لم يتم استرداده بعد وضع تعليق الحساب. ويمكن للمطوّرين أيضًا إلغاء الاشتراك من خلال purchases.subscriptions.cancel. عند إلغاء الاشتراك، يحتفظ المستخدم بإمكانية الوصول إلى المحتوى حتى نهاية دورة الفوترة الحالية. عند انتهاء دورة الفوترة، ينبغي إبطال إمكانية الوصول.

يؤدي إلغاء اشتراك إلى ظهور إشعار "SUBSCRIPTION_CANCELED". وعند تلقّي هذا الإشعار، يتم ضبط الحقل subscriptionState على SUBSCRIPTION_STATE_CANCELED في مورد الاشتراك المعروض من واجهة برمجة التطبيقات Google Play Developer API، ويحتوي الحقل expiryTime على التاريخ الذي يجب أن يفقد فيه المستخدم إمكانية الوصول إلى الاشتراك. إذا كان هذا التاريخ في الماضي، فمن المفترض أن يفقد المستخدم استحقاقه على الفور. قد يحدث هذا، على سبيل المثال، إذا ألغى المستخدم اشتراكًا أثناء تعليق الحساب بسبب رفض الدفعة.

يبدو مورد الاشتراك لعملية شراء تم إلغاؤها مشابهًا للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_CANCELED",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": expiration_time,
      ...
    }
  ],
}

يمكنك الاطّلاع على حقل canceledStateContext في مورد الاشتراك لمعرفة سبب إلغاء الاشتراك (على سبيل المثال، ما إذا تم إلغاء الاشتراك من قِبل المستخدم أو من قِبل النظام أو من قِبلك). إذا ألغى المستخدم الاشتراك، يمكنك مراجعة الحقل userInitiatedCancellation لمعرفة سبب إلغاء المستخدم للاشتراك. يمكن أن يساعد هذا في إثراء استراتيجيات الاتصال.

عند إلغاء اشتراك بدون أن تنتهي صلاحيته بعد، يظلّ إرجاعه ساريًا من queryPurchasesAsync(). وقد تحتاج إلى عرض رسالة في تطبيقك تخبر المستخدم بأنّه تم إلغاء اشتراكه وتمنحه تاريخ انتهاء الصلاحية.

عمليات الإبطال

يمكن إلغاء الاشتراك لعدة أسباب، منها إلغاء الاشتراك من خلال خلفيته purchases.subscriptions.revoke أو استرداد المبلغ المدفوع مقابل عملية الشراء. في هذه الحالة، قم بإبطال إذن المستخدم على الفور. يتم إرسال رسالة SubscriptionNotification من النوع SUBSCRIPTION_REVOKED عند حدوث ذلك. عند تلقّي هذا الإشعار، يتم ضبط الحقل subscriptionState على SUBSCRIPTION_STATE_EXPIRED في مورد الاشتراك الذي تم إرجاعه من واجهة برمجة التطبيقات Google Play Developer API.

يبدو مورد الاشتراك الخاص بعملية شراء تم إبطالها مشابهًا للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_EXPIRED",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": expiration_time,
      ...
    }
  ]
}

الاشتراكات المؤجَّلة

هناك مجموعة متنوعة من الأسباب التي قد تدفعك إلى تمديد استحقاق المستخدم. على سبيل المثال، قد ترغب في منح المستخدمين وصولاً مجانيًا كعرض ترويجي خاص، مثل منح أسبوع واحد مجانًا لشراء فيلم أو توفير الوصول المجاني للعملاء كإيماءة حسنة. يمكنك استخدام الإجراء purchases.subscriptions.defer من واجهة برمجة التطبيقات Play Developer API لتحديد تاريخ الفوترة التالي للاشتراك الذي يتم تجديده تلقائيًا. عند إجراء ذلك، يتم إرسال رسالة SubscriptionNotification من النوع SUBSCRIPTION_DEFERRED. أثناء فترة التأجيل، يكون المستخدم مشتركًا في المحتوى الخاص بك مع إمكانية الوصول الكامل ولكن لا يتم تحصيل رسومه. يتم تعديل تاريخ تجديد الاشتراك ليعكس التاريخ الجديد.

بالنسبة إلى خطط الدفع المُسبق، يمكنك استخدام واجهة برمجة تطبيقات تأجيل الفوترة لتأجيل وقت انتهاء الصلاحية.

يبدو مورد الاشتراك الخاص بالاشتراك المؤجَّل مشابهًا للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": timestamp_in_future,
      ...
    }
  ],
}

الاشتراكات المتوقّفة مؤقتًا

يمكنك تقليل إيقاف الاستخدام الطوعي للمستخدمين من خلال السماح لهم بإيقاف اشتراكهم مؤقتًا. عند تفعيل ميزة "الإيقاف المؤقت"، يمكن للمستخدمين اختيار إيقاف اشتراكهم مؤقتًا لمدة تتراوح بين أسبوع وثلاثة أشهر، حسب الفترة المتكرّرة.

لا يتم إيقاف الاشتراك مؤقتًا إلا بعد انتهاء المدة الحالية للفوترة. أثناء إيقاف الاشتراك مؤقتًا، لا يمكن للمستخدم الوصول إلى الاشتراك ولن يدفع سعر التجديد. في نهاية فترة الإيقاف المؤقت، يتم استئناف الاشتراك وتحاول Google تجديد الاشتراك. إذا تم إكمال السيرة الذاتية بنجاح، سيصبح الاشتراك نشطًا مرة أخرى. إذا تعذّر السيرة الذاتية بسبب مشكلة في الدفع، يُدخل المستخدم حالة تعليق الحساب كما هو موضح في الشكلين 5 و6:

الشكل 5. يوقف المستخدم اشتراكه مؤقتًا ثم يستأنفه.
الشكل 6. أوقف المستخدم اشتراكه مؤقتًا، ثم يدخل فترة تعليق الاشتراك.

يمكن للمستخدم أيضًا اختيار استئناف الاشتراك يدويًا في أي وقت خلال فترة الإيقاف المؤقت، كما هو موضّح في الشكل 6. عند استئناف المستخدم يدويًا، يتغير تاريخ الفوترة إلى تاريخ الاستئناف اليدوي.

عند إيقاف اشتراك المستخدم مؤقتًا، لا تعرض "مكتبة الفوترة في Play" الاشتراك من خلال طريقة queryPurchasesAsync(). في حال استئناف الاشتراك، ستعرض طريقة queryPurchasesAsync() الاشتراك مرة أخرى.

يجب التنبّه إلى الحالات التي يوقف فيها المستخدم اشتراكه بشكل مؤقت، مع مراعاة أن تكون هذه الطلبات متوافقة مع أوقات محددة. وتتيح لك هذه الإشعارات أيضًا إعلام المستخدمين في تطبيقك بأنّهم قد أوقفوا اشتراكاتهم مؤقتًا وأنّه لا يمكنهم الوصول إليها. عليك أيضًا توفير طريقة تمكّن المستخدم من استئناف اشتراكه يدويًا في أي وقت باستخدام رابط لصفحة في التطبيق إلى Google Play.

يتم إرسال رسالة SubscriptionNotification من النوع SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED عندما يبدأ المستخدم إيقافًا مؤقتًا لاشتراكه. في هذا الوقت، يجب أن يحتفظ المستخدم بإمكانية الوصول إلى اشتراكه حتى تاريخ التجديد التالي، ويحتوي مورد الاشتراك على autoRenewEnabled = true. قيمة الحقل subscriptionState هي SUBSCRIPTION_STATE_ACTIVE في هذه المرحلة.

يتم إرسال رسالة SubscriptionNotification من النوع SUBSCRIPTION_PAUSED عند تفعيل الإيقاف المؤقت. عند حدوث ذلك، من المفترَض أن يفقد المستخدم إمكانية الوصول إلى اشتراكه، ويحتوي مورد الاشتراك على autoRenewEnabled = true، وسيتم ضبط الحقل subscriptionState على SUBSCRIPTION_STATE_PAUSED. يمكنك الاطّلاع على الوقت المتوقّع لتجديد الاشتراك مرة أخرى من خلال وضع علامة في المربّع بجانب عنصر PausedStateContext.

يتم إرسال رسالة SubscriptionNotification من النوع SUBSCRIPTION_RENEWED إذا تم استئناف الاشتراك تلقائيًا في نهاية فترة الإيقاف المؤقت أو إذا اختار المستخدم استئناف الاشتراك يدويًا. ويجب معالجة ذلك على النحو الموضَّح في عمليات التجديد.

يتم إرسال رسالة SubscriptionNotification من النوع SUBSCRIPTION_ON_HOLD في حال حدوث خطأ في عملية الدفع أثناء محاولة استئناف الاشتراك بعد الإيقاف المؤقت. ويجب التعامل مع هذا الأمر على النحو الموضّح في فترة تعليق الاشتراك.

إعادة الاشتراك

في الخطط الأساسية للاشتراكات التي يتم تجديدها تلقائيًا، قد يعرض "متجر Google Play" الزر إعادة الاشتراك. يتيح هذا الزر للمستخدمين استعادة إمكانية الوصول إلى الاشتراك. وقد لا تظهر الصفحة لأسباب مختلفة، مثلاً عندما تنتهي صلاحية الاشتراك منذ وقت طويل.

الشكل 7. قسم الحساب > الاشتراكات في تطبيق "متجر Google Play" يعرض اشتراكًا تم إلغاؤه مع زر إعادة الاشتراك

على الرغم من أنّه تتم تسمية الزر دائمًا باسم إعادة الاشتراك، إلا أنّ وظائفه تعتمد على حالة الاشتراك.

لا يزال المستخدم مشتركًا ويتلقّى مزايا الاشتراك على الرغم من إلغاء الاشتراك بدون انتهاء صلاحيته بعد. إذا نقر المستخدم على "إعادة الاشتراك"، يتم التراجع عن الإلغاء، ويستمر تجديد الاشتراك. ويُعرف هذا الإجراء باسم الاستعادة في مستندات المطوِّرين وواجهات برمجة التطبيقات في Play.

بعد انتهاء صلاحية اشتراك يتجدّد تلقائيًا، يمكنك السماح للمستخدمين بشراء الخطة الأساسية نفسها للاشتراك. ويُعرف هذا الإجراء باسم إعادة الاشتراك في مستندات المطوّرين وواجهات برمجة التطبيقات في Play. يمكنك إعداد هذا الخيار لكل خطة أساسية في Play Console أو باستخدام واجهة برمجة التطبيقات.

الاستعادة قبل انتهاء الصلاحية

إذا كان تطبيقك يعتمد فقط على طريقة queryPurchasesAsync() لتحديد ما إذا كان المستخدم مؤهلاً للاشتراك، من المفترض أن يعالج تطبيقك تلقائيًا عمليات الاستعادة لأنّ طريقة queryPurchasesAsync() تستمر في عرض عمليات الشراء المُلغاة قبل تواريخ انتهاء صلاحيتها. يستمر تجديد الاشتراك الذي تمت استعادته كما لو لم يتم إلغاؤه.

إذا كان تطبيقك يزامن حالة الاشتراك مع خلفية، عليك الاستماع إلى رسالة SubscriptionNotification من النوع SUBSCRIPTION_RESTARTED. بعد تلقّي عنوان RTDN هذا، يمكن لتطبيقك الردّ على الإشعار وتسجيل أنّ الاشتراك قد تم ضبطه على تجديد الاشتراك، والتوقف عن عرض رسائل الاستعادة في تطبيقك. ويبدو مورد الاشتراك مشابهًا للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": next_renewal_date
      ...
    }
  ],
}

إعادة الاشتراك بعد انتهاء الصلاحية

إذا تم إعداد خطة أساسية تتجدّد تلقائيًا باستخدام Google Play Console أو واجهة برمجة التطبيقات للسماح بإعادة الاشتراك، يمكن للمستخدمين إعادة شراء اشتراك منتهي الصلاحية من خلال "متجر Google Play".

هذه عمليات شراء جديدة. يصدر Google Play رمز شراء جديدًا تمامًا، وتتلقّى الخلفية الخاصة بك رمز RTDN من النوع SUBSCRIPTION_PURCHASED. لا تشمل حالة الشراء لهذا النوع من الشراء خارج التطبيق linkedPurchaseToken مرتبطًا بعملية الشراء الأصلية في هذه الحالة، لأن الاشتراك الأصلي انتهت صلاحيته بالكامل. إنّها عمليات شراء جديدة يجب على الخلفية معالجتها والإقرار بها مثل أي عملية شراء أخرى.

عمليات الترقية والرجوع إلى الإصدارات السابقة وإعادة الاشتراك

عندما يقوم المستخدم بترقية الاشتراك أو الرجوع إلى إصدار سابق أو اشتراكه بعد الإلغاء من تطبيقك قبل انتهاء صلاحية الاشتراك، يتم إلغاء الاشتراك القديم وإنشاء اشتراك جديد باستخدام رمز شراء جديد.

إضافةً إلى ذلك، يحتوي مورد الاشتراك الذي تم إرجاعه من خلال Google Play Developer API على الحقل linkedPurchaseToken الذي يشير إلى عملية الشراء القديمة التي أجرى المستخدم من خلالها الترقية أو الرجوع إلى إصدار سابق أو إعادة الاشتراك. يمكنك استخدام الرمز المميّز للشراء في هذا الحقل للبحث عن الاشتراك القديم وتحديد حساب المستخدم الحالي كي تتمكَّن من ربط عملية الشراء الجديدة بالحساب نفسه.

قبل توفير خيارات الترقية أو الرجوع إلى إصدار سابق أو إعادة الاشتراك لمستخدم في تطبيقك، عليك الإقرار بالاشتراك الحالي. وسيتم حظر أي تغيير في الخطة أو إعادة الاشتراك إذا كان الاشتراك الحالي لا يزال في انتظار الإقرار.

إذا اشترى المستخدم عملية الترقية أو الرجوع إلى إصدار سابق أو إعادة الاشتراك بنجاح، عليك تأكيد أنّ هذه عملية الشراء جديدة. والطريقة المقترَحة لإجراء ذلك هي باستخدام Google Play Developer API. يبدو مورد الاشتراك مشابهًا للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  "linkedPurchaseToken": old_purchase_token,
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": next_renewal_date,
      "autoRenewingPlan": {
        "autoRenewEnabled": true
      }
    }
  ],
}

تغييرات السعر

يمكنك مراجعة دليل أفضل الممارسات المتعلقة بتغيير الأسعار للتعرّف على كيفية تغيير أسعار الاشتراكات التي يتم تجديدها تلقائيًا وإشعار المستخدمين عندما يكون ذلك مناسبًا.

عند تطبيق تغييرات الأسعار على المشتركين الحاليين عند الموافقة على السعر، ستتلقّى رسالة RTDN إذا اتّخذ المستخدم إجراءً لتأكيد السعر الجديد أو رفضه.

التعامل مع تأكيد المستخدم على تغيير السعر لتفعيل الميزة

عندما يوافق مستخدم على الزيادة في سعر الاشتراك، ستتلقّى رسالة SubscriptionNotification من النوع SUBSCRIPTION_PRICE_CHANGED_CONFIRMED. عند انخفاض سعر الاشتراك أو عند تجديد زيادة سعر الاشتراك، ستصلك رسالة SubscriptionNotification من النوع SUBSCRIPTION_RENEWED. التعامل مع هذا الإشعار مثل أي تجديد آخر.

معالجة الحالات التي لا يتم فيها قبول زيادة السعر

إذا لم يقبل المستخدم الزيادة في سعر الاشتراك قبل أن يحتاج إلى تجديد الاشتراك بالسعر الأعلى، سيتم إلغاء اشتراكه تلقائيًا وستصلك رسالة SubscriptionNotification من النوع SUBSCRIPTION_CANCELED. تعامل مع هذا الحدث كما هو موضّح في عمليات الإلغاء.

يمكن للمستخدمين أيضًا إلغاء اشتراكاتهم مقابل خيار زيادة السعر باتّباع الآلية نفسها.

معالجة مراحل نشاط خطط الدفع المُسبق

كما هو الحال مع الاشتراكات التي يتمّ تجديدها تلقائيًا، يجب الإقرار بخطط الدفع المُسبق بعد كل عملية شراء جديدة. في حالة خطط الدفع المُسبَق، يجب عليك معالجة كل من عملية الشراء الأولية وأي عمليات إضافة رصيد بالكامل، لأن المستخدم يجب أن يمر بعملية الشراء في كل مرة.

من المهم الإقرار بعملية الشراء في أقرب وقت ممكن بسبب احتمال أن تكون المدة قصيرة لخطط الدفع المُسبَق. يجب الإقرار بخطط الدفع المُسبق التي تبلغ مدتها أسبوع واحد أو أكثر خلال 3 أيام. يجب الإقرار بخطط الدفع المُسبَق التي تبلغ مدتها أقل من أسبوع واحد خلال نصف مدة الخطة. على سبيل المثال، لدى المطوّرين 1.5 يوم للإقرار بشراء خطة الدفع المُسبَق لمدة ثلاثة أيام.

الشكل 8. حالات مراحل النشاط وأحداث النقل لعمليات شراء الاشتراكات.

يتم إرسال رسالة SubscriptionNotification من النوع SUBSCRIPTION_PURCHASED إلى عميل RTDN عند شراء اشتراك في خطة مسبقة الدفع، بما في ذلك كل عملية إضافة. يمكنك استخدام طريقة purchases.subscriptionsv2.get للاطّلاع على حالة الاشتراك في خطة الدفع المُسبَق الأخيرة.

يتم إصدار رمز جديد للشراء لإضافة رصيد، وتتلقّى رمز الشراء السابق في حقل linkedPurchaseToken كجزء من حالة شراء الاشتراك الجديدة. يكون الرمز المميّز للشراء صالحًا من اشتراك الاشتراك حتى 60 يومًا من انتهاء صلاحيته. وبعد هذا التاريخ، يصبح الرمز المميّز للشراء غير صالح للاستخدام لطلب بيانات من Google Play Developer API.

يبدو مورد الاشتراك لشراء خطة مسبقة الدفع مشابهًا للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  "startTime": "2022-04-22T18:39:58.270Z",
  "regionCode": "US",
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  "latestOrderId": "GPA.3333-4137-0319-36762",
  "acknowledgementState": "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED",
  "lineItems": [
    {
      "productId": "prepaid_plan01",
      "expiryTime": expiry_date,
      "prepaidPlan": {
        "allowExtendAfterTime": timestamp_after_which_topups_are_allowed
      }
    }
  ]
}

يمكنك الاطّلاع على وقت انتهاء الاستحقاق في الحقل expiryTime. تؤدي عمليات الشراء التي تتم إضافتها إلى الإضافة إلى زيادة وقت الاستحقاق من خلال تراكمه. هذا يعني أنّه في حال إضافة المستخدم رصيد قبل انتهاء استحقاقه الأصلي، تتم إضافة الوقت الجديد بالإضافة إلى تاريخ انتهاء الصلاحية السابق.

قد تحتاج إلى عرض رسالة في تطبيقك تخبر المستخدم بأنّه يمكن تمديد اشتراكاته المدفوعة مسبقًا من خلال إضافة رصيد. لمعرفة متى سيتمكّن المستخدم من إضافة رصيد، راجِع الحقل allowExtendAfterTime في مورد الاشتراك.

لا يتم تجديد خطط الدفع المُسبق تلقائيًا، وبالتالي لا يمكن إلغاؤها. إذا أراد المستخدم إلغاء خطة الدفع المسبق، يمكنه السماح لها بالوصول إلى تاريخ انتهاء صلاحيتها.