يتيح لك الاشتراك مع ميزات إضافية تجميع منتجات اشتراك متعددة معًا يمكن شراؤها وفوترتها وإدارتها معًا. يمكنك عرض اشتراكاتك الحالية في كتالوج المنتجات كحِزم إضافية بسلاسة بدون الحاجة إلى تحديد أي تفاصيل مسبقًا أو إجراء أي إعدادات إضافية. يمكنك إطلاق مسار شراء يتضمّن عدة منتجات حالية متوفّرة عند الاشتراك، وبيعها كإضافات.
الاعتبارات
يجب مراعاة النقاط التالية عند استخدام ميزة "الاشتراك مع حِزم إضافية":
لا تتوفّر إمكانية الاشتراك مع حِزم إضافية إلا للخطط الأساسية التي يتم تجديدها تلقائيًا.
يجب أن تتضمّن جميع العناصر في عملية الشراء مدة الفوترة المتكرّرة نفسها. على سبيل المثال، لا يمكنك الحصول على اشتراك تتم فوترته سنويًا مع ميزات إضافية تتم فوترتها شهريًا.
يمكن أن يتضمّن الاشتراك 50 منتجًا كحدّ أقصى عند شراء حِزم إضافية.
هذه الميزة غير متوفّرة في منطقة كوريا الجنوبية (KR).
الدمج مع Play Billing Library
يوضّح هذا القسم كيفية دمج ميزة "الاشتراك مع حِزم إضافية" مع "مكتبة الفوترة في Play" (PBL). ويفترض هذا الدليل أنّك على دراية بخطوات الدمج الأولية لمكتبة الفوترة في Google Play، مثل إضافة الاعتمادية على مكتبة الفوترة في Google Play إلى تطبيقك وإعداد BillingClient والربط بخدمة Google Play. يركّز هذا القسم على جوانب دمج PBL الخاصة بالاشتراك مع حِزم إضافية.
بدء مسار شراء
لبدء مسار شراء اشتراك يتضمّن حِزمًا إضافية، اتّبِع الخطوات التالية:
يمكنك جلب جميع منتجات اشتراكك باستخدام طريقة
BillingClient.queryProductDetailsAsync.اضبط عنصر
ProductDetailsParamsلكل سلعة.يمثّل العنصر الذي يمثّله كائن
ProductDetailsParamsعنصر الاشتراك، ويحدّد كلاً منProductDetailsالذي يشير إلى عنصر الاشتراك وofferTokenالذي يختار اشتراكًا معيّنًاbase planأوoffer.حدِّد تفاصيل العنصر في طريقة
BillingFlowParams.Builder.setProductDetailsParamsList. يحدِّد الصفBillingFlowParamsتفاصيل مسار الشراء.تعرض العيّنة التالية كيفية بدء مسار الفوترة لشراء اشتراك يتضمّن منتجات متعددة:
Java
BillingClient billingClient = …; // ProductDetails obtained from queryProductDetailsAsync(). ProductDetailsParams productDetails1 = ...; ProductDetailsParams productDetails2 = ...; ArrayList
productDetailsList = new ArrayList<>(); productDetailsList.add(productDetails1); productDetailsList.add(productDetails2); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsList) .build(); billingClient.launchBillingFlow(billingFlowParams);
القواعد السارية على السلع في عملية الشراء
- لضمان توافق تواريخ تجديد الإضافة مع تاريخ تجديد المنتج الأساسي في النهاية، قد يفرض Google Play رسومًا نسبية بعد أي مراحل تجريبية أو مراحل سعر تمهيدي.
- سيتم تقييم أهلية الاستفادة من العرض لكل سلعة على حدة.
معالجة عمليات الشراء
تتم معالجة الاشتراك مع الإضافات بالطريقة نفسها التي تتم بها معالجة عملية شراء اشتراك واحد، كما هو موضّح في مقالة دمج Google Play Billing Library في تطبيقك، والفرق الوحيد هو أنّ المستخدم يمكنه الحصول على امتيازات متعددة من خلال عملية شراء واحدة. عند شراء اشتراك يتضمّن حِزمًا إضافية، يتم عرض عناصر متعدّدة يمكن استردادها باستخدام Purchase.getProducts() في مكتبة الفوترة في Google Play، ثم قائمة lineItems في purchases.subscriptionsv2.get من Google Play Developer API.
تعديل الاشتراكات التي تتضمّن ميزات إضافية
يؤدي إجراء أي تغييرات على اشتراكك مع حِزم إضافية إلى ترقية أو الرجوع إلى إصدار سابق. لمزيد من المعلومات، راجِع مقالة ترقية الاشتراكات أو الرجوع إلى إصدار سابق.
لتغيير أو استعادة عملية شراء حالية لاشتراك يتضمّن إضافات في تطبيقك، عليك استدعاء واجهة برمجة التطبيقات launchBillingFlow مع مَعلمات إضافية، والتأكّد من ما يلي:
- يجب دائمًا طلب
setOldPurchaseTokenباستخدام رمز الشراء الخاص بعملية شراء الاشتراك الحالية. - لترقية منتج أو الرجوع إلى إصدار أقدم أو الترقية إلى منتج آخر، اتّصِل بالرقم
SubscriptionProductReplacementParams.setReplacementModeلتحديد كيفية التعامل مع تغيير الخطة بين المنتج القديم والمنتج الجديد. بخلاف ذلك، ليست هناك حاجة إلى ضبط السمةSubscriptionProductReplacementParams. - عندما لا يتم تغيير العنصر الأساسي، سيظل بإمكانك استدعاء
SubscriptionProductReplacementParams.setSubscriptionReplacementModeلتطبيق سلوك استبدال معيّن. للاطّلاع على القواعد السارية في هذه الحالة، يُرجى الانتقال إلى إعادة الاشتراك أو التبديل بين الخطط ضمن الاشتراك نفسه. - سيتم تطبيق الميزات الإضافية الجديدة فورًا مع تحصيل رسوم حسب الاستخدام لمطابقة تاريخ التجديد التالي مع المنتج الأساسي في الاشتراك.
- ستنتهي صلاحية الميزات الإضافية التي تمت إزالتها في نهاية مُدد الفوترة الحالية.
- عند بدء مسار الفوترة، عليك تحديد جميع العناصر النشطة في الاشتراك الذي يتضمّن ميزات إضافية باستثناء تلك التي ستتم إزالتها، بالإضافة إلى أي ميزات إضافية جديدة.
يوضّح المثال التالي كيفية استدعاء واجهة برمجة التطبيقات launchBillingFlow عند تغيير عملية شراء حالية لاشتراك يتضمّن ميزات إضافية:
Java
BillingClient billingClient = …; int replacementMode =…; // ProductDetails obtained from queryProductDetailsAsync(). ProductDetailsParams productDetails1 = ...; ProductDetailsParams productDetails2 = ...; ProductDetailsParams productDetails3 = ...; ArrayListnewProductDetailsList = new ArrayList<>(); newProductDetailsList.add(productDetails1); newProductDetailsList.add(productDetails1); newProductDetailsList.add(productDetails1); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setSubscriptionUpdateParams( SubscriptionUpdateParams.newBuilder() .setOldPurchaseToken(purchaseTokenOfExistingSubscription) // No need to set if change does not affect the base item. .setSubscriptionReplacementMode(replacementMode) .build()) .setProductDetailsParamsList(productDetailsList) .build(); billingClient.launchBillingFlow(billingFlowParams);
سيناريوهات تعديل الاشتراكات
يسرد الجدول التالي سيناريوهات التعديل المختلفة للاشتراك مع الإضافات والسلوك المقابل.
عند استخدام SubscriptionProductReplacementParams
| السلع الحالية | العناصر المعدَّلة | هل يجب ضبط وضع الاستبدال في SubscriptionProductReplacementParams؟ | السلوك |
|---|---|---|---|
| أ (السلعة الأساسية)، ب | أ (عنصر أساسي) | نعم (استخدِم KEEP_EXISTING) |
|
| A | أ (السلعة الأساسية)، ب | نعم (استخدِم KEEP_EXISTING لـ A) |
|
| أ (السلعة الأساسية)، ب | أ (السلعة الأساسية)، ج | نعم (استخدِم KEEP_EXISTING للحرف A) |
|
| أ (السلعة الأساسية)، ب | B (المنتج الأساسي) | لا | تم تحديد موعد لإزالة A بشكل مؤجّل. |
| أ (السلعة الأساسية)، ب | C (السلعة الأساسية) | نعم |
|
| أ (السلعة الأساسية)، ب | C (المنتج الأساسي)، B | نعم |
|
| أ (السلعة الأساسية)، ب | C (السلعة الأساسية)، D | نعم |
|
| أ (السلعة الأساسية)، ب | أ (السلعة الأساسية)، ج | نعم |
|
| أ (السلعة الأساسية)، ب، ج | D (السلعة الأساسية)، B، C | نعم |
|
عند استخدام SubscriptionUpdateParams
| السلع الحالية | العناصر المعدَّلة | هل تحتاج إلى ضبط المعلومات البديلة؟ | السلوك |
|---|---|---|---|
| أ (السلعة الأساسية)، ب | أ (عنصر أساسي) | لا |
|
| A | أ (السلعة الأساسية)، ب | لا |
|
| أ (السلعة الأساسية)، ب | أ (السلعة الأساسية)، ج | لا |
|
| أ (السلعة الأساسية)، ب | B (المنتج الأساسي) | لا | تم تحديد موعد لإزالة A بشكل مؤجّل. |
| أ (السلعة الأساسية)، ب | C (السلعة الأساسية) | نعم |
|
| أ (السلعة الأساسية)، ب | C (المنتج الأساسي)، B | نعم | يعتمد بديل A -> C على
setSubscriptionReplacementMode (تم إيقافه نهائيًا في الإصدار 8.1 من PBL). |
| أ (السلعة الأساسية)، ب | C (السلعة الأساسية)، D | نعم |
|
الإشعارات في الوقت الفعلي الخاصة بالمطوّرين
لم يتم توفير الحقل subscriptionId في RTDN لعمليات شراء اشتراك مع حِزم إضافية تتضمّن أذونات متعددة.
بدلاً من ذلك، يمكنك استخدام واجهات Play Developer APIs للحصول على معلومات حول عملية الشراء والاطّلاع على أذونات الوصول إلى السلع المرتبطة بها.
تغييرات الأسعار للمشتركين الحاليين
يشبه تغيير أسعار الاشتراكات للمشتركين الحاليين في اشتراك يتضمّن عمليات شراء إضافية تغيير أسعار الاشتراك الفردي كما هو موضّح في تغيير أسعار الاشتراك، ولكن هناك بعض القيود والاختلافات الوظيفية كما هو موضّح في هذا القسم.
إنهاء مجموعة نموذجية قديمة للأسعار
يؤثّر إنهاء مجموعة نموذجية قديمة أيضًا في الاشتراكات التي تتضمّن عمليات شراء إضافات. تنطبق القواعد التالية:
يجب أن يكون لجميع زيادات الأسعار المعلقة التي تتطلّب موافقة وقت التجديد نفسه مع السعر الجديد. إذا كان أحد العناصر في عملية شراء اشتراك مع حِزم إضافية يتضمّن زيادة في السعر تتطلّب موافقة ولم يؤكّدها المستخدم بعد، سيتم تجاهل أي زيادة جديدة في السعر تتطلّب موافقة لعناصر أخرى في عملية الشراء ما لم تؤدِّ إلى وقت التجديد نفسه لتطبيق السعر الجديد مثل الزيادة الحالية في السعر في الحالة معلّقة. وبعد أن يؤكّد المستخدم الزيادة في السعر، سيتم تسجيل أي تغييرات أحدث في السعر. ويمكن للمستخدمين قبول جميع زيادات الأسعار المعلقة التي تتطلّب موافقة في وقت واحد فقط.
مثال:
- لنفترض أنّ لديك اشتراكًا يتضمّن حِزمًا إضافية (العنصران A وB)، ويتم تجديده في اليوم السابع من كل شهر.
- يخضع المنتج "أ" لعملية نقل مستمرة للسعر من 7 دولار أمريكي إلى 10 دولار أمريكي، ومن المتوقّع أن يتم تطبيق الزيادة في السعر في 7 تموز (يوليو).
- يبدأ نقل السعر الجديد من 5 دولار أمريكي إلى 6 دولار أمريكي للسلعة B في 2 يونيو. وبما أنّ الزيادة الاختيارية في السعر تبدأ بعد 37 يومًا من عملية النقل، ستكون الزيادة الأولى في سعر السلعة B في 7 أغسطس.
في هذا السيناريو، لن يتم تسجيل تفاصيل تغيير السعر للمنتج B عند شراء الاشتراك إلى أن يوافق المستخدم على تغيير السعر للمنتج A (إلى أن يصبح في الحالة CONFIRMED)، ولن تعرض السمة SubscriptionPurchaseV2 تفاصيل تغيير السعر للمنتج B. بعد أن يؤكّد المستخدم تغيير سعر المنتج (أ)، يبدأ تغيير سعر المنتج (ب). لا يتلقّى المستخدم الزيادة في سعر المنتج "ب" التي تتطلّب موافقة إلا بعد الموافقة على الزيادة في سعر المنتج "أ".
تتضمّن رسالة البريد الإلكتروني من Google Play قائمة بجميع السلع التي سيتم تطبيق زيادة أو نقصان في أسعارها في اليوم نفسه.
إلغاء اشتراك يتضمّن ميزات إضافية
يمكن للمستخدمين إلغاء عملية شراء اشتراك يتضمّن ميزات إضافية بالكامل من "مركز اشتراكات Play"، ولا يمكنك إلغاء عملية شراء اشتراك يتضمّن ميزات إضافية بالكامل إلا باستخدام Google Play Developer API.
عند إلغاء عملية شراء اشتراك بدون إبطالها، لن يتم تجديد أي من السلع المضمّنة في عملية الشراء تلقائيًا، ولكن سيظل بإمكان المستخدم الوصول إلى السلع التي يحق له الحصول عليها، بما في ذلك أي فترات تجريبية مجانية، إلى أن تنتهي فترات الفوترة المقابلة.
إبطال الاشتراكات التي تتضمّن ميزات إضافية وردّ الأموال المدفوعة مقابلها
في ما يلي بعض الإرشادات المتعلّقة بإلغاء الاشتراكات وردّ الأموال المدفوعة مقابلها:
استخدِم Play Console لردّ مبلغ محدّد من الأموال المدفوعة مقابل طلب معيّن بدون إبطال إمكانية الوصول إلى الاشتراك.
اتّصِل بالرقم
orders.refundلردّ الأموال بالكامل مقابل دفعات اشتراك محدّدة أجراها المستخدم بدون إبطال إمكانية الوصول إلى الاشتراك.يمكنك إجراء مكالمة
purchases.subscriptionsv2.revokeلإلغاء إذن الوصول على الفور إلى جميع عناصر الاشتراك. باستخدام واجهة برمجة التطبيقات هذه، يمكنك إجراء ما يلي:إلغاء إذن الوصول إلى جميع العناصر وتقديم استرداد نسبي للأموال
عند إبطال اشتراك يتضمّن حِزمًا باستخدام عمليات ردّ الأموال حسب الاستخدام، سيتم ردّ الأموال الخاصة بآخر طلب لكل منتج بمبلغ نسبي استنادًا إلى الوقت المتبقي حتى التجديد التالي.
إلغاء إذن الوصول إلى جميع العناصر وتقديم ردّ كامل للأموال
إلغاء إذن الوصول إلى منتج فردي مع ردّ الأموال بالكامل مقابل المنتج
إبطال عنصر فردي في اشتراك يتضمّن ميزات إضافية
لإلغاء عناصر اشتراك فردية في اشتراك يتضمّن حِزمًا إضافية بدون إلغاء عملية الشراء بالكامل، استخدِم الدالة purchases.subscriptionsv2.revoke مع ضبط الحقل ItemBasedRefund في RevocationContext. يمكن ضبط productId السلعة التي يجب إبطالها وردّ أموالها في الحقل ItemBasedRefund.
يمكن ضبط حقل ItemBasedRefund لعمليات الشراء التي تتضمّن منتج اشتراك واحدًا أو أكثر يتجدّد تلقائيًا.
- إذا كانت هناك سلع نشطة متبقية في عملية شراء الاشتراك بعد إبطال السلعة المحدّدة في
ItemBasedRefund، سيتم إبطال السلعة فقط وردّ الأموال المدفوعة بالكامل بدون التأثير في حالة الاشتراك. - إذا لم تتبقَ أي سلع نشطة في عملية شراء الاشتراك بعد إبطال السلعة المحدّدة في
ItemBasedRefund، سيتم إبطال السلعة وردّ أموالها بالكامل وإلغاء الاشتراك.
الاعتبارات
- عند استخدام
ItemBasedRefund، يمكن إبطال عنصر واحد فقط في كل مرة، ويمكن طلب ذلك عدة مرات إذا كان يجب إبطال عناصر مختلفة. - عندما تكون حالة شراء الاشتراك هي أي من حالات رفض الدفع، أو إذا لم يكن المنتج المحدّد في
ItemBasedRefundمملوكًا أو انتهت صلاحيته، يتم حظر إيقاف المنتج. - لا تتوفّر إمكانية إيقاف المنتج في الاشتراك المدفوع مسبقًا.
تأجيل الفوترة
يمكنك تقديم تاريخ الفوترة التالي للاشتراك الذي يتضمّن إضافات باستخدام الطريقة Purchases.subscriptionsv2:defer.
عند تأجيل اشتراك يتضمّن ميزات إضافية، يتم تأجيل جميع العناصر في الاشتراك لمدة التأجيل نفسها. خلال مدة التأجيل، يحتفظ المستخدم بإمكانية الوصول الكامل إلى جميع العناصر بدون تحصيل رسوم منه. يتم تعديل تاريخ تجديد جميع العناصر ليوافق التاريخ الجديد.
يمكن أن يكون ذلك مفيدًا للعروض الترويجية أو مبادرات كسب ولاء العملاء. يمكن تأجيل الفوترة لمدة يوم واحد كحد أدنى ولمدة عام واحد كحد أقصى لكل طلب بيانات من واجهة برمجة التطبيقات. يمكنك طلب واجهة برمجة التطبيقات عدة مرات لتمديد فترة تأجيل الدفع قبل حلول تاريخ الفوترة الجديد.
يتم إرسال SUBSCRIPTION_DEFERRED إشعار في الوقت الفعلي خاص بالمطوّرين عند اتّخاذ هذا الإجراء.
انتهاء صلاحية السلعة أثناء رفض الدفعة
عند شراء اشتراك يتضمّن إضافات، قد تحتاج بعض عمليات التجديد إلى تمديد مجموعة فرعية فقط من أذونات الوصول إلى المحتوى، بدون التأثير في المحتوى الذي يتضمّن تاريخ انتهاء صلاحية مستقبلي.
بغض النظر عن المنتجات التي يتضمّنها التجديد، إذا تم رفض دفع رسوم التجديد، ستدخل عملية شراء الاشتراك بالكامل فترة السماح وسيتم تعليق الحساب كما هو موضّح في المستندات التالية.
اختيار فترة الاسترداد
بما أنّ فترة السماح تمنح المستخدم إذن الاستخدام، عند شراء اشتراك يتضمّن ميزات إضافية، يتم رفض دفعة التجديد، ويتم اختيار المنتج الذي يتضمّن الحدّ الأدنى لفترة السماح من بين جميع المنتجات النشطة، ويتم تطبيق فترة السماح وفترة تعليق الاشتراك كفترة استرداد لهذا التجديد.
تشمل العناصر النشطة العناصر التي كانت نشطة عند شراء اشتراك يتضمّن حِزمًا إضافية قبل محاولة التجديد مباشرةً، ولا تشمل أي عناصر تمت إضافتها حديثًا (ولن تكون مؤهَّلة إلا بعد الاسترداد)، كما لا تشمل أي عناصر لم تعُد نشطة بسبب إزالتها أو إيقافها.
يتم تطبيق إعداد تعليق الاشتراك الخاص بالمنتج الذي تم اختيار الحدّ الأدنى لفترة السماح له. إذا كان هناك أكثر من منتج واحد يتضمّن الحدّ الأدنى لفترة السماح، ولكن مع فترات تعليق اشتراك مختلفة، سيتم تطبيق أطول فترة تعليق اشتراك.
فترة السماح
عند رفض دفعة تجديد الاشتراك، ستنتقل عملية شراء الاشتراك إلى حالة فترة السماح. وخلال فترة السماح، سيظل بإمكان المستخدم الوصول إلى جميع العناصر النشطة من فترة التجديد السابقة. بعد انتهاء فترة السماح، إذا لم يتم حلّ مشكلة طريقة الدفع، سيتم تعليق عملية شراء الاشتراك بالكامل. إذا بلغت أي عناصر أخرى تاريخ التجديد خلال فترة السماح، سيتم بدء محاولة جديدة لتحصيل الرسوم مقابل هذه العناصر بعد استعادة الاشتراك من حالة رفض الدفع.
فترة تعليق الاشتراك
أثناء تعليق الاشتراك، يتم تعليق إمكانية الوصول إلى جميع المنتجات المضمّنة في الاشتراك إلى أن يتم استرداد الدفعة.
في حال استرداد الاشتراك المعلق، سيظل الاشتراك كما هو. أما إذا لم يتم استرداده، فستنتهي صلاحية السلع التي تم رفض دفع ثمنها، وسيتم استئناف إمكانية الوصول إلى السلع الأخرى خلال ما تبقى من مدة الفوترة.
مثال:
لدى المستخدم اشتراك في خطة أساسية تتجدّد في اليوم الأول من كل شهر، ثم في 15 آب (أغسطس)، يضيف خطة إضافية بقيمة 10 دولار أمريكي شهريًا مع فترة تجريبية مجانية لمدة سبعة أيام. لم يتم ضبط فترة سماح لأي من المنتجات، وكلاهما يتضمّن فترة تعليق للحساب لمدة 30 يومًا.
في 22 أغسطس، يتم تحصيل 2.90 دولار أمريكي من المستخدم (10*9/31) لتحديد نسبة الاشتراك حتى 31 أغسطس، ولكن تنتهي صلاحية طريقة الدفع التي يستخدمها قبل ذلك، ويتم رفض الدفع في 22 أغسطس.
عندما يتم تعليق الاشتراك بسبب رفض الدفع، لن يتمكّن المستخدم من الوصول إلى أي من العناصر المضمّنة في الاشتراك مع حِزم إضافية. وسيتم ردّ الوقت المتبقي للعناصر التي لم يتم تجديدها إلى المستخدمين عند انتهاء فترة تعليق الاشتراك، إما بسبب استرداد المبلغ المدفوع أو إلغاء الاشتراك.
في المثال السابق، يبدأ تعليق الاشتراك في 22 آب (أغسطس).
إذا تم استرداد الحساب في 25 أغسطس، أي قبل تاريخ التجديد العام في 1 سبتمبر، سيستعيد المستخدم إمكانية الوصول إلى كل من الخطة الأساسية وخطة الإضافة في اليوم نفسه، وسيتم تغيير تاريخ الفوترة التالي إلى 4 سبتمبر.
إذا لم يتم استرداد الحساب بعد 30 يومًا، سيتم إلغاء الاشتراك في 21 أيلول (سبتمبر) وسيفقد المستخدم إمكانية الوصول إلى خطة الإضافة، وسيستعيد إمكانية الوصول إلى الخطة الأساسية حتى 30 أيلول (سبتمبر).
في هذا المثال، يجب الحصول على expiryTime المعدَّل لجميع العناصر في الاشتراك مع الإضافات، لأنّه قد يتم استئناف إذن الوصول إلى بعض العناصر بعد فترة السماح وتعليق الحساب.
إعداد التقارير المالية والتسوية
استخدِم تقرير الأرباح لتسوية اشتراكاتك النشطة مع المعاملات على Play. يحتوي كل عنصر من عناصر المعاملة على معرّف طلب. عندما تمثّل عمليات الشراء عدة منتجات، ستتضمّن تقارير الأرباح والمبيعات المقدّرة صفوفًا منفصلة لكل معاملة، مثل الرسوم والضرائب والمبالغ المستردة، لكل منتج معنيّ.
بالنسبة إلى لوحات البيانات في Play Console:
يتم تقسيم إحصاءات الإيرادات المعروضة في قسم التقارير المالية ضمن وحدة التحكّم حسب السلع.
تعكس إدارة الطلبات عملية شراء اشتراك مع ميزات إضافية، وتعرض قوائم مفصّلة بالمشتريات. من خلال إدارة الطلبات، يمكنك إبطال عملية شراء أجراها أحد المستخدمين أو إلغاؤها أو ردّ أموالها بالكامل.