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

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

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

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

subs-auto-renew-state
الشكل 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". عندما يدخل المستخدم فترة سماح، عليك أيضًا تشجيعه على حلّ مشكلة طريقة الدفع في حال كان الخطأ غير مقصود. إحدى الطرق المباشرة لتنفيذ ذلك هي استخدام In-App Messaging API. إذا طلبت تنفيذ هذه الطريقة عند فتح المستخدم لتطبيقك، ستظهر له رسالة من Play في شريط إشعارات مؤقت لإعلامه بأنّه تم رفض دفعه. تتضمّن هذه الرسالة أيضًا رابطًا لصفحة معيّنة يمكن للمستخدم الانتقال إليها لحلّ المشكلة في طريقة الدفع على Google Play.

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

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

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

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

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

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

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

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

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

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

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

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

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

تعليق الحساب

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

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

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

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

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

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

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

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

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

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

{
  "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
      }
    }
  ],
}

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

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

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

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

التعامل مع تأكيد المستخدم لتغيير السعر الذي يتطلب موافقة

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

التعامل مع عمليات التجديد بعد تطبيق تغيير السعر

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

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

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

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

بموجب اللوائح التنظيمية الجديدة في كوريا الجنوبية (KR)، يجب أن يوافق المستخدمون الذين لديهم اشتراكات في منطقة كوريا الجنوبية على أي زيادات في الأسعار ستحدث بعد انتهاء الفترة التجريبية المجانية أو الفترة التمهيدية.

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

عندما تبدأ فترة الموافقة أو يقدّم المستخدم موافقته، ستتلقّى رسالة SubscriptionNotification من النوع SUBSCRIPTION_PRICE_STEP_UP_CONSENT_UPDATED.

الفرق بين زيادة السعر وتغيير السعر

يشير price step-up إلى زيادة في سعر الاشتراك بسبب الانتقال من مرحلة عرض إلى أخرى. على سبيل المثال، اشتراك يتم تحويله من فترة تجريبية مجانية إلى سعر عادي.

ومع ذلك، يشير price change إلى تعديلات الأسعار التي تبدأها أنت (المطوّر) لسعر الخطة الأساسية للاشتراك. على سبيل المثال، زيادة في السعر تتطلّب موافقة أو زيادة في السعر لا تتطلّب موافقة.

التعامل مع مراحل النشاط في خطط الدفع المُسبَق

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

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

الشكل 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 في مورد الاشتراك.

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

حقول SubscriptionPurchaseV2 لخطط الدفع المُسبَق

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

  • [حقل جديد] lineItems[0].prepaid_plan.allowExtendAfterTime: يشير إلى الوقت الذي سيُسمح فيه للمستخدم بشراء رصيد إضافي لتمديد خطة الدفع المُسبَق، إذ يُسمح للمستخدم بالحصول على رصيد إضافي واحد فقط لم يتم استخدامه في كل مرة.
  • [حقل جديد] SubscriptionState: يحدّد حالة عنصر الاشتراك. بالنسبة إلى خطط الدفع المُسبق، تكون هذه القيمة دائمًا ACTIVE أو PENDING أو CANCELED.
  • lineItems[0].expiryTime: يتوفّر هذا الحقل دائمًا للخطط المدفوعة مسبقًا.
  • paused_state_context: لا يظهر هذا الحقل أبدًا، لأنّه لا يمكن إيقاف الخطط المدفوعة مسبقًا مؤقتًا.
  • lineItems[0].auto_renewing_plan: غير متوفّر لخطط الدفع المُسبَق.
  • canceled_state_context: لا يظهر هذا الحقل في الخطط المدفوعة مسبقًا، لأنّه ينطبق فقط على المستخدمين الذين يلغون الاشتراك بشكل نشط.
  • lineItems[0].productId: يحلّ هذا الحقل محل subscriptionId من الإصدارات السابقة.