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

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

إعداد 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.
   }

var 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 ليس بلدًا متاحًا.

تفعيل "خيارات الفوترة" التي تم استدعاءها أثناء إعداد BillingClient

يرى المستخدم تجربة المستخدم لاختيار المستخدم

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

عدم تفعيل خيار "الفوترة" ضمن ميزة "اختيار المستخدم" أثناء إعداد حساب 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 via queryProductDetailsAsync.
                .setProductDetails(productDetailsNewPlan)
                // offerIdToken can be found in
                // ProductDetails=>SubscriptionOfferDetails.
                .setOfferToken(offerTokenNewPlan)
                .build()
        )
    )
    .setSubscriptionUpdateParams(
        BillingFlowParams.SubscriptionUpdateParams.newBuilder()
            .setOriginalExternalTransactionId(externalTransactionId)
            .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 via 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 للعرض المحدد للخطة الجديدة:

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

String offerTokenNewPlan = productDetailsNewPlan
                     .getSubscriptionOfferDetails(selectedOfferIndex)
                     .getOfferToken();

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

val billingFlowParams =
    BillingFlowParams.newBuilder().setProductDetailsParamsList(
        listOf(
            BillingFlowParams.ProductDetailsParams.newBuilder()
                .setProductDetails(productDetailsNewPlan)
                .setOfferToken(offerTokenNewPlan)
                .build()
        )
    )
    .setSubscriptionUpdateParams(
        BillingFlowParams.SubscriptionUpdateParams.newBuilder()
            .setOldPurchaseToken(oldToken)
            .setReplaceProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE)
            .build()
        )
        .build()

BillingClient.launchBillingFlow(activity, billingFlowParams)

BillingFlowParams billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(
                ImmutableList.of(
                    ProductDetailsParams.newBuilder()
                        // Fetched via queryProductDetailsAsync
                        .setProductDetails(productDetailsNewPlan)
                        // offerIdToken can be found in
                        // ProductDetails=>SubscriptionOfferDetails.
                        .setOfferToken(offerTokenNewPlan)
                        .build()
                )
            )
            .setSubscriptionUpdateParams(
                SubscriptionUpdateParams.newBuilder()
                    // purchaseToken can be found in
                    // Purchase#getPurchaseToken
                    .setOldPurchaseToken("old_purchase_token")
                    .setReplaceProrationMode(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()" في هذه الحالة، كما هو موضّح في إطلاق مسار الفوترة حسب اختيار المستخدم.

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

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

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

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