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

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

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

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

وأفضل طريقة للبقاء على اطّلاع بالتغييرات التي تطرأ على حالة الاشتراك هي الاستماع إلى إشعارات المطوّر في الوقت الفعلي (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 Billing Library الاشتراك مرة أخرى من خلال طريقة 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 في مورد الاشتراك الذي تم إرجاعه من واجهة برمجة تطبيقات Google Play Developer API على SUBSCRIPTION_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 لأنّ اشتراك الأقساط لا يزال نشطًا حتى نهاية مدة الاشتراك. ومع ذلك، هناك عنصر فارغ في انتظار الإلغاء. يتم إرسال إشعار 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.subscriptions.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,
      ...
    }
  ]
}

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

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

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

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

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

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

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

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

عند إيقاف اشتراك المستخدم مؤقتًا، لا تعرض Play Billing Library الاشتراك من خلال الطريقة 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
      ...
    }
  ],
}

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

إذا تم ضبط خطة أساسية تتجدّد تلقائيًا باستخدام 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 في مورد الاشتراك.

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