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

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

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

عندما تتغيّر حالة اشتراك أحد المستخدمين، يتلقّى خادم الخلفية رسالة 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. امنح المستخدم إذن الوصول إلى المحتوى. يمكن تحديد حساب المستخدم المرتبط بال purchase باستخدام عنصر 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 إشعار عند تجديد الاشتراك. بالنسبة إلى الاشتراكات المدفوعة بالتقسيط، يتم إرسال إشعار 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".

من خلال مزامنة حالة الاشتراك مع الخلفية، يمكنك معرفة المزيد عن حالات رفض الدفع، كما يمنحك ذلك سياقًا إضافيًا عند محاولة خفض معدل الانسحاب العميلي غير الطوعي. انتبِه إلى رسائل 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 من فترة السماح القديمة.
  • يظل الاشتراك نشطًا ولن تتلقّى مهلة RTDN إلى أن تنتهي فترة السماح الصامتة.

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

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

إنّ أفضل طريقة للبقاء على اطّلاع بتغييرات حالة الاشتراك هي الاستماع إلى "الإشعارات في الوقت الفعلي الخاصة بالمطوّرين" والتفاعل معها. يمكنك استدعاء 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 محاولات إضافية لعدة أيام بهدف تحصيل الرسوم من طريقة الدفع. يحتفظ المستخدم بمزايا الاشتراك خلال هذه الفترة. بعد انقضاء فترة إعادة المحاولة هذه، ينتقل الاشتراك إلى وضع التعليق في الحساب، ومن المفترض أن يفقد المستخدم إمكانية الاستفادة من مزايا الاشتراك.
  • يدخل الاشتراك في حالة تعليق الاشتراك مباشرةً عند استئناف الاشتراك من حالة الإيقاف المؤقت باستخدام طريقة دفع تعذّر إتمامها.
  • عندما يتم استرداد اشتراك من فترة تعليق الحساب، تتم إعادة ضبط تاريخ التجديد.

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

بعد انتهاء صلاحية الاشتراك، من المفترض أن يفقد المستخدم إمكانية الوصول إليه. في هذه الحالة، يتم إرسال رسالة 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 في مرجع الاشتراك الذي تم استرجاعه من Google Play Developer APISUBSCRIPTION_STATE_CANCELED، ويحتوي الحقلexpiryTime على تاريخ فقدان المستخدم إمكانية الوصول إلى الاشتراك. إذا كان هذا التاريخ في الماضي، من المفترض أن يفقد المستخدم الإذن على الفور. وقد يحدث ذلك، مثلاً، إذا ألغى مستخدم اشتراكًا أثناء تعليق حسابه بسبب رفض الدفعة.

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

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

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

تبدو مرجع الاشتراك لعملية شراء اشتراك بالتقسيط في انتظار الإلغاء مشابهة للمثال التالي:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  ...
  "lineItems": [
    {
      "productId": "sub_plan01",
      "expiryTime": expiration_time,
      "autoRenewingPlan": {
        "autoRenewEnabled": true,
        "recurringPrice": {
          "currencyCode": "USD",
          "units": "1",
          "nanos": 990000000
        },
        "installmentDetails": {
          "initialCommittedPaymentsCount": 6,
          "remainingCommittedPaymentsCount": 5,
          "pendingCancellation": {}
      ...
        }
      }
    }
  ],
}

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

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

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

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

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

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

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

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

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

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

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

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

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

تكرار الاشتراك أسبوعيًا شهريًا ثلاثة أشهر ستة أشهر السنوية
مدد الإيقاف المؤقت المتاحة* أسبوع واحد
أسبوعان
3 أسابيع
4 أسابيع
شهر واحد
شهران
3 أشهر
شهر واحد
شهران
3 أشهر
شهر واحد
شهران
3 أشهر
لا ينطبق
*يجوز تغيير الأسعار في أي وقت.

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

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

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

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

انتبِه إلى إشارات RTDN لمعرفة الحالات التي يوقف فيها المستخدم اشتراكه مؤقتًا. تتيح لك هذه الإشعارات أيضًا إعلام المستخدمين في تطبيقك بأنّهم أوقفوا اشتراكهم مؤقتًا وأنّه لا يمكنهم الوصول إليه. يجب أيضًا توفير طريقة للمستخدم لاستئناف اشتراكه يدويًا في أي وقت باستخدام رابط لصفحة في التطبيق يؤدي إلى 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
      ...
    }
  ],
}

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

في حال ضبط خطة أساسية تتجدّد تلقائيًا باستخدام 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 إلى عميل الإشعارات في الوقت الفعلي للمطوّرين عند شراء اشتراك في خطة دفع مُسبَق، بما في ذلك كل عملية إضافة رصيد. يمكنك الاتصال بالخدمة باستخدام الأسلوب purchases.subscriptionsv2.get للتحقّق من أحدث حالة اشتراك في الخطة المدفوعة مسبقًا.

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

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

{
  "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 في مرجع الاشتراك.

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