إرشادات الدمج داخل التطبيق للفوترة البديلة مع خيار المستخدم

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

إعداد Play Billing Library

أضِف عنصر Play Billing Library التابع إلى تطبيق Android. لاستخدام واجهات برمجة التطبيقات لنظام الفوترة البديل، يجب استخدام الإصدار 5.2 أو إصدار أحدث. إذا كنت بحاجة إلى نقل البيانات من إصدار سابق، اتّبِع التعليمات الواردة في دليل نقل البيانات قبل محاولة تنفيذ نظام الفوترة البديل.

الربط بخدمة Google Play

تتشابه الخطوات الأولى في عملية الدمج مع الخطوات الموضّحة في دليل دمج خدمة الفوترة في Google Play، مع بعض التعديلات عند إعداد BillingClient:

  • عليك استدعاء طريقة جديدة للإشارة إلى أنّك تريد أن توفّر للمستخدم خيارًا من بين خيارات الفوترة: enableUserChoiceBilling.
  • عليك تسجيل UserChoiceBillingListener للتعامل مع الحالات التي يختار فيها المستخدم طريقة فوترة بديلة.

يوضّح المثال التالي كيفية تهيئة BillingClient مع هذه التعديلات:

Kotlin

val purchasesUpdatedListener =
   PurchasesUpdatedListener { billingResult, purchases ->
       // Handle new Google Play purchase.
   }

val userChoiceBillingListener =
   UserChoiceBillingListener { userChoiceDetails ->
       // Handle alternative billing choice.
   }

val billingClient = BillingClient.newBuilder(context)
   .setListener(purchasesUpdatedListener)
   .enablePendingPurchases()
   .enableUserChoiceBilling(userChoiceBillingListener)
   .build()

Java

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
    @Override
    public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
        // Handle new Google Play purchase.
    }
};

private UserChoiceBillingListener userChoiceBillingListener = new UserChoiceBillingListener() {
    @Override
    public void userSelectedAlternativeBilling(
        UserChoiceDetails userChoiceDetails) {
        // Handle new Google Play purchase.
    }
};

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .enableUserChoiceBilling(userChoiceBillingListener)
    .build();

بعد إعداد BillingClient، عليك إنشاء اتصال بخدمة Google Play كما هو موضّح في دليل الدمج.

عرض المنتجات المتوفّرة

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

إطلاق مسار الفوترة حسب اختيار المستخدم

ابدأ تدفق ميزة "الفوترة حسب اختيار المستخدم" من خلال استدعاء launchBillingFlow(). تعمل هذه الطريقة بشكل مشابه لإطلاق عملية شراء من خلال دمج نظام الفوترة في Google Play: عليك تقديم مثيل ProductDetails وofferToken يتوافق مع المنتج والعرض الذي يريد المستخدم الحصول عليه. إذا اختار المستخدم نظام الفوترة في Google Play، سيتم استخدام هذه المعلومات لمواصلة عملية الشراء.

عندما يستدعي المطوّرون launchBillingFlow()، يجري نظام الفوترة في Google Play عملية التحقّق التالية:

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

أن يكون بلد المستخدم على Play من البلدان التي تتوفّر فيها الخدمة

بلد المستخدم على Play غير متاح

تم استدعاء enableUserChoiceBilling أثناء إعداد BillingClient

ظهور تجربة المستخدم الخاصة بخيار المستخدم

تظهر للمستخدم تجربة المستخدم العادية لنظام الفوترة في Google Play

لم يتم استدعاء enableUserChoiceBilling أثناء إعداد BillingClient

تظهر للمستخدم تجربة المستخدم العادية لنظام الفوترة في Google Play

تظهر للمستخدم تجربة المستخدم العادية لنظام الفوترة في Google Play

التعامل مع اختيار المستخدم

يختلف أسلوب التعامل مع بقية خطوات عملية الشراء حسب ما إذا اختار المستخدم نظام الفوترة في Google Play أو نظام فوترة بديلاً.

عندما يختار المستخدم نظام فوترة بديلاً

إذا اختار المستخدم نظام الفوترة البديل، يطلب Google Play من UserChoiceBillingListener إرسال إشعار إلى التطبيق بأنّه بحاجة إلى بدء مسار الشراء في نظام الفوترة البديل. وعلى وجه الخصوص، يتم استدعاء الطريقة userSelectedAlternativeBilling().

يمثّل رمز المعاملة الخارجية المقدَّم في العنصر UserChoiceDetails توقيعًا على اختيار المستخدم اتّباع مسار نظام الفوترة البديل. استخدِم هذا الرمز المميّز لتسجيل أي معاملة ناتجة عن هذا الخيار كما هو موضّح في دليل الدمج في الخلفية.

يجب أن ينفّذ UserChoiceBillingListener الإجراءات التالية:

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

إذا أكمل المستخدم عملية الشراء باستخدام نظام الفوترة البديل، عليك إبلاغ Google Play بالمعاملة من خلال استدعاء Google Play Developer API من الخلفية خلال 24 ساعة، مع تقديم externalTransactionToken وتفاصيل المعاملة الإضافية. يمكنك الاطّلاع على دليل الدمج في الخلفية لمزيد من التفاصيل.

يوضّح المثال التالي كيفية تنفيذ UserChoiceBillingListener:

Kotlin

private val userChoiceBillingListener =
    UserChoiceBillingListener { userChoiceDetails ->
        // Get the products being purchased by the user.
        val products = userChoiceDetails.products

        // Send external transaction token to developer backend server
        // this devBackend object is for demonstration purposes,
        // developers can implement this step however best fits their
        // app to backend communication.
        devBackend.sendExternalTransactionStarted(
            userChoiceDetails.externalTransactionToken,
            user
        )

        // Launch alternative billing
        // ...
        // The developer backend handles reporting the transaction
        // to Google Play's backend once the alternative billing
        // purchase is completed.
    }

Java

private userChoiceBillingListener userChoiceBillingListener = new UserChoiceBillingListener() {
    @Override
    public void userSelectedAlternativeBilling(
           UserChoiceDetails userChoiceDetails) {
       // Get the products being purchased by the user.
       List<Product> products =
              userChoiceDetails.getProducts();

       // Send external transaction token to developer backend server
       // this devBackend object is for demonstration purposes,
       // developers can implement this step however best fits their
       // app to backend communication.
       devBackend.sendExternalTransactionStarted(
              userChoiceDetails.getExternalTransactionToken(),
              user
       );

       // Launch alternative billing
       // ...
       // The developer backend handles reporting the transaction
       // to Google Play's backend once the alternative billing
       // purchase is completed.
    }
};

عندما يختار المستخدم نظام الفوترة في Google Play

إذا اختار المستخدم نظام الفوترة في Google Play، سيواصل عملية الشراء من خلال Google Play.

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

التعامل مع التغييرات في الاشتراك

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

يوضّح هذا القسم كيفية التعامل مع بعض السيناريوهات الشائعة لتغيير الاشتراك.

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

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

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

الاشتراكات التي تم شراؤها من خلال نظام فوترة بديل

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

لإجراء ذلك، استدعِ الدالة launchBillingFlow() عندما يطلب المستخدم ترقية أو الرجوع إلى إصدار سابق. بدلاً من تحديد عنصر SubscriptionUpdateParams في المَعلمات، استخدِم setOriginalExternalTransactionId، مع توفير رقم تعريف المعاملة الخارجية لعملية الشراء الأصلية. لا تعرض هذه السياسة شاشة اختيار المستخدم، لأنّ اختيار المستخدم للشراء الأصلي يتم الاحتفاظ به عند الترقية أو الرجوع إلى إصدار أقدم. يؤدي طلب launchBillingFlow() في هذه الحالة إلى إنشاء رمز مميز جديد لمعاملة خارجية للمعاملة، ويمكنك استرداده من دالة الرجوع.

Kotlin

// The external transaction ID from the current
// alternative billing subscription.
val externalTransactionId = //... ;

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        listOf(
            BillingFlowParams.ProductDetailsParams.newBuilder()
                // Fetched using queryProductDetailsAsync.
                .setProductDetails(productDetailsNewPlan)
                // offerIdToken can be found in
                // ProductDetails=>SubscriptionOfferDetails.
                .setOfferToken(offerTokenNewPlan)
                .build()
        )
    )
    .setSubscriptionUpdateParams(
        BillingFlowParams.SubscriptionUpdateParams.newBuilder()
            .setOriginalExternalTransactionId(externalTransactionId)
            .build()
        )
    .build()

val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

// When the user selects the alternative billing flow,
// the UserChoiceBillingListener is triggered.

Java

// The external transaction ID from the current
// alternative billing subscription.
String externalTransactionId = //... ;

BillingFlowParams billingFlowParams =
    BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(
            ImmutableList.of(
                ProductDetailsParams.newBuilder()
                    // Fetched using queryProductDetailsAsync.
                    .setProductDetails(productDetailsNewPlan)
                    // offerIdToken can be found in
                    // ProductDetails=>SubscriptionOfferDetails
                    .setOfferToken(offerTokenNewPlan)
                    .build()
                )
            )
        .setSubscriptionUpdateParams(
            SubscriptionUpdateParams.newBuilder()
                .setOriginalExternalTransactionId(externalTransactionId)
                .build()
            )
        .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

// When the user selects the alternative billing flow,
// the UserChoiceBillingListener is triggered.

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

الاشتراكات التي يتم شراؤها من خلال نظام الفوترة في Google Play

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

  1. حدِّد offerToken العرض الترويجي المحدّد للخطة الجديدة:

    Kotlin

    val offerTokenNewPlan = productDetailsNewPlan
         .getSubscriptionOfferDetails(selectedOfferIndex)
         .getOfferToken()
    

    Java

    String offerTokenNewPlan = productDetailsNewPlan
            .getSubscriptionOfferDetails(selectedOfferIndex)
            .getOfferToken();
    
  2. أرسِل المعلومات الصحيحة إلى نظام الفوترة في Google Play لمعالجة عملية الشراء الجديدة، بما في ذلك رمز الشراء للاشتراك الحالي:

    Kotlin

    val billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(
                listOf(
                    BillingFlowParams.ProductDetailsParams.newBuilder()
                        // Fetched using queryProductDetailsAsync
                        .setProductDetails(productDetailsNewPlan)
                        // offerIdToken can be found in
                        // ProductDetails=>SubscriptionOfferDetails.
                        .setOfferToken(offerTokenNewPlan)
                        .build()
                    )
            )
            .setSubscriptionUpdateParams(
                BillingFlowParams.SubscriptionUpdateParams.newBuilder()
                    // purchaseToken can be found in
                    // Purchase#getPurchaseToken
                    .setOldPurchaseToken(oldToken)
                    .setReplaceProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE)
                    .build()
            )
            .build()
    
    val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
    

    Java

    BillingFlowParams billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(
                ImmutableList.of(
                    ProductDetailsParams.newBuilder()
                        // Fetched using queryProductDetailsAsync
                        .setProductDetails(productDetailsNewPlan)
                        // offerIdToken can be found in
                        // ProductDetails=>SubscriptionOfferDetails.
                        .setOfferToken(offerTokenNewPlan)
                        .build()
                )
            )
            .setSubscriptionUpdateParams(
                SubscriptionUpdateParams.newBuilder()
                    // purchaseToken can be found in
                    // Purchase#getPurchaseToken
                    .setOldPurchaseToken(oldToken)
                    .setReplaceProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE)
                    .build()
            )
            .build();
    
    BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
    

تتم عملية الشراء هذه في نظام الفوترة في Google Play، ويتلقّى تطبيقك طلب PurchasesUpdatedListener.onPurchaseUpdated مع نتيجة عملية الشراء. إذا تمت عملية الشراء بنجاح، تتلقّى الطريقة onPurchaseUpdated() أيضًا معلومات عملية الشراء الجديدة، ويتلقّى الخلفية SUBSCRIPTION_PURCHASED إشعارًا في الوقت الفعلي خاصًا بالمطوّرين. عند استرداد حالة عملية الشراء الجديدة، ترتبط السمة linkedPurchaseToken بعملية شراء الاشتراك القديم حتى تتمكّن من إيقافها على النحو الموصى به.

عمليات إلغاء الاشتراكات واستعادتها

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

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

الاشتراكات التي تم شراؤها من خلال نظام فوترة بديل

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

الاشتراكات التي يتم شراؤها من خلال نظام الفوترة في Google Play

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

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

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

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

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

اختبار نظام الفوترة البديل

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

الخطوات التالية

بعد الانتهاء من عملية الدمج داخل التطبيق، يمكنك دمج الخلفية.