دمج "مكتبة الفوترة في Google Play" في تطبيقك

يوضّح هذا المستند كيفية دمج Google Play Billing Library في تطبيقك لبدء بيع المنتجات.

مراحل معالجة عملية الشراء

في ما يلي مسار شراء نموذجي لعملية شراء لمرة واحدة أو اشتراك.

  1. اعرض للمستخدم ما يمكنه شراؤه.
  2. ابدأ مسار الشراء ليقبل المستخدم عملية الشراء.
  3. تحقَّق من عملية الشراء على الخادم.
  4. قدِّم المحتوى للمستخدم.
  5. تأكيد تسليم المحتوى بالنسبة إلى المنتجات الاستهلاكية، يجب استهلاك عملية الشراء حتى يتمكّن المستخدم من شراء المنتج مرة أخرى.

يتم تجديد الاشتراكات تلقائيًا إلى أن يتم إلغاؤها. يمكن أن يمر الاشتراك بالحالات التالية:

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

إعداد اتصال بـ Google Play

الخطوة الأولى لدمج تطبيقك مع نظام الفوترة في Google Play هي إضافة مكتبة Google Play Billing Library إلى تطبيقك وبدء الاتصال.

إضافة اعتمادية Google Play Billing Library

أضِف تبعية Google Play Billing Library إلى ملف build.gradle في تطبيقك كما هو موضّح:

أنيق

dependencies {
    def billing_version = "9.1.0"

    implementation "com.android.billingclient:billing:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "9.1.0"

    implementation("com.android.billingclient:billing:$billing_version")
}

إذا كنت تستخدم لغة Kotlin، فإنّ وحدة KTX في Google Play Billing Library تحتوي على إضافات Kotlin ودعم لبرامج الكوروتين التي تتيح لك كتابة لغة Kotlin الاصطلاحية عند استخدام Google Play Billing Library. لتضمين هذه الإضافات في مشروعك، أضِف التبعية التالية إلى ملف build.gradle في تطبيقك كما هو موضّح:

أنيق

dependencies {
    def billing_version = "9.1.0"

    implementation "com.android.billingclient:billing-ktx:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "9.1.0"

    implementation("com.android.billingclient:billing-ktx:$billing_version")
}

إعداد BillingClient

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

  • ننصحك بفتح اتصال واحد نشط في BillingClient في المرة الواحدة لتجنُّب عمليات معاودة الاتصال المتعددة في PurchasesUpdatedListener لحدث واحد.
  • يُنصح ببدء اتصال لـ BillingClient عند تشغيل تطبيقك أو ظهوره في المقدّمة لضمان معالجة تطبيقك لعمليات الشراء في الوقت المناسب. يمكن تحقيق ذلك باستخدام ActivityLifecycleCallbacks المسجَّل من قِبل registerActivityLifecycleCallbacks والاستماع إلى onActivityResumed لبدء الاتصال عند رصد استئناف نشاط لأول مرة. يُرجى الرجوع إلى القسم المتعلّق بمعالجة عمليات الشراء لمزيد من التفاصيل حول سبب اتّباع أفضل الممارسات هذه. تذكَّر أيضًا إنهاء الاتصال عند إغلاق تطبيقك.

لإنشاء BillingClient، استخدِم newBuilder. يمكنك تمرير أي سياق إلى newBuilder()، ويستخدمه BillingClient للحصول على سياق التطبيق. هذا يعني أنّه لا داعي للقلق بشأن تسرّب الذاكرة. لتلقّي آخر الأخبار حول عمليات الشراء، عليك أيضًا استدعاء setListener، مع تمرير مرجع إلى PurchasesUpdatedListener. يتلقّى هذا المستمع تحديثات لجميع عمليات الشراء في تطبيقك.

Kotlin

private val purchasesUpdatedListener =
    PurchasesUpdatedListener { billingResult, purchases ->
        // To be implemented in a later section.
    }

private var billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    // Configure other settings.
    .build()

Java

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
  @Override
  public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
      // To be implemented in a later section.
  }
};

private BillingClient billingClient = BillingClient.newBuilder(context)
  .setListener(purchasesUpdatedListener)
  // Configure other settings.
  .build();

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

بعد إنشاء BillingClient، عليك إنشاء اتصال بـ Google Play.

لربط حسابك بـ Google Play، يُرجى الاتصال بالرقم startConnection. عملية الربط غير متزامنة، وعليك تنفيذ BillingClientStateListener لتلقّي معاودة الاتصال بعد اكتمال إعداد العميل واستعداده لتقديم طلبات أخرى.

إذا لم تفعّل إعادة الاتصال التلقائي بالخدمة، عليك أيضًا تنفيذ منطق إعادة المحاولة للتعامل مع الاتصالات المفقودة بـ Google Play. لتنفيذ منطق إعادة المحاولة، عليك إلغاء طريقة رد الاتصال onBillingServiceDisconnected() والتأكّد من أنّ BillingClient تستدعي الطريقة startConnection() لإعادة الاتصال بـ Google Play قبل تقديم طلبات أخرى. إذا فعّلت ميزة إعادة الاتصال التلقائي بالخدمة، يمكنك تنفيذ هذه الطريقة كعملية فارغة.

يوضّح المثال التالي كيفية بدء اتصال واختبار جاهزيته للاستخدام:

Kotlin

billingClient.startConnection(object : BillingClientStateListener {
    override fun onBillingSetupFinished(billingResult: BillingResult) {
        if (billingResult.responseCode == BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    override fun onBillingServiceDisconnected() {
        // If automatic service reconnection is enabled, this can be left empty (no-op)
        // because the library handles retries. You can still use this for non-retry
        // tasks like logging or updating the UI to reflect a disconnected state.
        // Otherwise, try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
})

Java

billingClient.startConnection(
        new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(BillingResult billingResult) {
                if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                    // The BillingClient is ready. You can query purchases here.
                    // It's a good practice to query products after the connection is established.
                    queryProductDetails();
                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
                // This is automatically handled by the library when you call a method that requires a connection.
            }
        });

إعادة إنشاء اتصال تلقائيًا

من خلال تقديم طريقة enableAutoServiceReconnection() في BillingClient.Builder في الإصدار 8.0.0، يمكن لمكتبة Google Play Billing Library الآن إعادة إنشاء اتصال الخدمة تلقائيًا في حال إجراء طلب بيانات من واجهة برمجة التطبيقات أثناء انقطاع اتصال الخدمة. يمكن أن يؤدي ذلك إلى تقليل عدد الردود SERVICE_DISCONNECTED لأنّه تتم معالجة إعادة الاتصال داخليًا قبل إجراء طلب البيانات من واجهة برمجة التطبيقات.

كيفية تفعيل إعادة الاتصال التلقائي

عند إنشاء مثيل BillingClient، استخدِم الإجراء enableAutoServiceReconnection() في BillingClient.Builder لتفعيل إعادة الاتصال التلقائي.

Kotlin

val billingClient = BillingClient.newBuilder(context)
    .setListener(listener)
    .enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build())
    .enableAutoServiceReconnection() // Add this line to enable reconnection
    .build()

Java

BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(listener)
    .enablePendingPurchases()
    .enableAutoServiceReconnection() // Add this line to enable reconnection
    .build();

عرض المنتجات المتاحة للشراء

بعد إنشاء اتصال بـ Google Play، ستكون جاهزًا للاستعلام عن منتجاتك المتاحة وعرضها للمستخدمين.

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

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

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

Kotlin

val queryProductDetailsParams =
    QueryProductDetailsParams.newBuilder()
        .setProductList(
            listOf(
                Product.newBuilder()
                    .setProductId("product_id_example")
                    .setProductType(ProductType.SUBS)
                    .build()
            )
        )
        .build()

billingClient.queryProductDetailsAsync(queryProductDetailsParams) {
        billingResult,
        queryProductDetailsResult ->
    if (billingResult.responseCode == BillingResponseCode.OK) {
        for (productDetails in queryProductDetailsResult.productDetailsList) {
            // Process successfully retrieved product details here.
        }

        for (unfetchedProduct in queryProductDetailsResult.unfetchedProductList) {
            // Handle any unfetched products as appropriate.
        }
    }
}

Java

QueryProductDetailsParams queryProductDetailsParams =
QueryProductDetailsParams.newBuilder()
    .setProductList(
        ImmutableList.of(
            Product.newBuilder()
                .setProductId("product_id_example")
                .setProductType(ProductType.SUBS)
                .build()))
    .build();

billingClient.queryProductDetailsAsync(
queryProductDetailsParams,
new ProductDetailsResponseListener() {
    public void onProductDetailsResponse(BillingResult billingResult,
            QueryProductDetailsResult queryProductDetailsResult) {
        if (billingResult.getResponseCode() == BillingResponseCode.OK) {
           for (ProductDetails productDetails : queryProductDetailsResult.getProductDetailsList()) {
             // Process successfully retrieved product details here.
           }

           for (UnfetchedProduct unfetchedProduct : queryProductDetailsResult.getUnfetchedProductList()) {
             // Handle any unfetched products as appropriate.
           }
        }
    }
}
)

عند الاستعلام عن تفاصيل المنتج، يجب تمرير مثيل من QueryProductDetailsParams يحدّد قائمة بسلاسل معرّفات المنتجات التي تم إنشاؤها في Google Play Console مع ProductType. يمكن أن تكون قيمة ProductType إما ProductType.INAPP للمنتجات المدفوعة لمرة واحدة أو ProductType.SUBS للاشتراكات.

الاستعلام باستخدام إضافات Kotlin

إذا كنت تستخدم إضافات Kotlin، يمكنك الاستعلام عن تفاصيل المنتجات المدفوعة لمرة واحدة من خلال استدعاء دالة الإضافة queryProductDetails().

تستفيد queryProductDetails() من الكوروتينات في Kotlin لكي لا تحتاج إلى تحديد مستمع منفصل. بدلاً من ذلك، يتم تعليق الدالة إلى أن تكتمل عملية الاستعلام، وبعد ذلك يمكنك معالجة النتيجة:

suspend fun processPurchases() {
    val productList = listOf(
        QueryProductDetailsParams.Product.newBuilder()
            .setProductId("product_id_example")
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
    )
    val params = QueryProductDetailsParams.newBuilder()
    params.setProductList(productList)

    // leverage queryProductDetails Kotlin extension function
    val productDetailsResult = withContext(Dispatchers.IO) {
        billingClient.queryProductDetails(params.build())
    }

    // Process the result.
}

في حالات نادرة، لا تتوافق بعض الأجهزة مع ProductDetails وqueryProductDetailsAsync()، ويرجع ذلك عادةً إلى استخدام إصدارات قديمة من خدمات Google Play. لتقديم الدعم المناسب لهذا السيناريو، تعرَّف على كيفية استخدام ميزات التوافق مع الأنظمة القديمة في دليل نقل البيانات إلى الإصدار 7 من Play Billing Library.

معالجة النتيجة

تخزِّن Google Play Billing Library نتائج طلب البحث في عنصر QueryProductDetailsResult. يحتوي QueryProductDetailsResult على List من عناصر ProductDetails. يمكنك بعد ذلك استدعاء مجموعة متنوعة من الإجراءات لكل عنصر ProductDetails في القائمة لعرض المعلومات ذات الصلة بمنتج مدفوع لمرة واحدة تم استرجاعه بنجاح، مثل سعره أو وصفه. للاطّلاع على تفاصيل المنتج المتاحة، يُرجى مراجعة قائمة الطرق في فئة ProductDetails.

يحتوي QueryProductDetailsResult أيضًا على List من عناصر UnfetchedProduct. يمكنك بعد ذلك الاستعلام عن كل UnfetchedProduct للحصول على رمز حالة يتوافق مع سبب تعذُّر الجلب. للاطّلاع على معلومات المنتج المتاحة التي لم يتم جلبها، يُرجى مراجعة قائمة الطرق في فئة UnfetchedProduct.

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

قبل تقديم اشتراك، تأكَّد من أنّ المستخدم غير مشترك حاليًا. يُرجى أيضًا مراعاة ما يلي:

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

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

بدء مسار الشراء

لبدء طلب الموافقة على الشراء من تطبيقك، يمكنك استدعاء الطريقة launchBillingFlow() من سلسلة التعليمات الرئيسية لتطبيقك. يستخدم هذا الإجراء مرجعًا لعنصر BillingFlowParams يحتوي على عنصر ProductDetails ذي الصلة الذي تم الحصول عليه من خلال استدعاء queryProductDetailsAsync. لإنشاء عنصر BillingFlowParams، استخدِم فئة BillingFlowParams.Builder.

Kotlin

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...

val productDetailsParamsList = listOf(
    BillingFlowParams.ProductDetailsParams.newBuilder()
        // retrieve a value for productDetails by calling queryProductDetailsAsync()
        .setProductDetails(productDetails)
        // Get the offer token:
        // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList()
        // for a list of offers that are available to the user.
        // b. For subscriptions, call ProductDetails.getSubscriptionOfferDetails()
        // for a list of offers that are available to the user.
        .setOfferToken(selectedOfferToken)
        .build()
)

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build()

// Launch the billing flow
val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

Java

// An activity reference from which the billing flow will be launched.
Activity activity = ...;

ImmutableList<BillingFlowParams.ProductDetailsParams> productDetailsParamsList =
    ImmutableList.of(
        BillingFlowParams.ProductDetailsParams.newBuilder()
             // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // Get the offer token:
            // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList()
            // for a list of offers that are available to the user.
            // b. For subscriptions, call ProductDetails.getSubscriptionOfferDetails()
            // for a list of offers that are available to the user.
            .setOfferToken(selectedOfferToken)
            .build()
    );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

تُنتج الطريقة launchBillingFlow() أحد رموز الاستجابة المتعدّدة المدرَجة في BillingClient.BillingResponseCode. احرص على التحقّق من هذه النتيجة للتأكّد من عدم حدوث أخطاء أثناء بدء مسار الشراء. تشير قيمة BillingResponseCode لـ "OK" إلى نجاح عملية الإطلاق.

عند نجاح طلب البيانات من launchBillingFlow()، يعرض النظام شاشة الشراء على Google Play. يوضّح الشكل 1 شاشة شراء اشتراك:

تعرض شاشة الشراء في Google Play اشتراكًا متاحًا للشراء
الشكل 1. تعرض شاشة الشراء على Google Play اشتراكًا متاحًا للشراء.

يستدعي Google Play واجهة برمجة التطبيقات onPurchasesUpdated() لإرسال نتيجة عملية الشراء إلى مستمع ينفّذ واجهة PurchasesUpdatedListener. يتم تحديد المستمع باستخدام طريقة setListener() عند إعداد العميل.

يجب تنفيذ onPurchasesUpdated() لمعالجة رموز الاستجابة المحتملة. يوضّح المثال التالي كيفية إلغاء onPurchasesUpdated():

Kotlin

override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
    if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) {
        for (purchase in purchases) {
            // Process the purchase as described in the next section.
        }
    } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) {
        // Handle an error caused by a user canceling the purchase flow.
    } else {
        // Handle any other error codes.
    }
}

Java

@Override
void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
  if (billingResult.getResponseCode() == BillingResponseCode.OK
      && purchases != null) {
      for (Purchase purchase : purchases) {
          // Process the purchase as described in the next section.
      }
  } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
      // Handle an error caused by a user canceling the purchase flow.
  } else {
      // Handle any other error codes.
  }
}

تؤدي عملية الشراء الناجحة إلى إنشاء شاشة نجاح عملية الشراء على Google Play مشابهة للشكل 2.

عرض تأكيد عملية الشراء على Google Play
الشكل 2. شاشة نجاح عملية الشراء في Google Play

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

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

الإشارة إلى سعر مخصّص

إذا كان من الممكن توزيع تطبيقك على المستخدمين في الاتحاد الأوروبي، استخدِم طريقة setIsOfferPersonalized() عند طلب launchBillingFlow للإفصاح للمستخدمين عن أنّه تم تخصيص سعر المنتج باستخدام عملية اتخاذ القرار المبرمَجة.

شاشة الشراء على Google Play التي تشير إلى أنّه تم تخصيص السعر للمستخدم
الشكل 3. شاشة الشراء على Google Play التي تشير إلى أنّ السعر تم تخصيصه للمستخدم

يجب الرجوع إلى المادة يُرجى الاطّلاع على المادة رقم 6 (1) (ea) من "توجيه حقوق المستهلك" ‎2011/83/EU لمعرفة ما إذا كان السعر الذي يُعرض للمستخدمين مُخصّصًا أو لا.

تتطلّب السمة setIsOfferPersonalized() قيمة منطقية. عندما تكون قيمة السمة true، تتضمّن واجهة مستخدم Google Play بيان الإفصاح. عندما تكون قيمة السمة false، لا تعرض واجهة المستخدم الإفصاح. القيمة التلقائية هي false.

لمزيد من المعلومات، يُرجى الانتقال إلى مركز مساعدة المستهلكين.

إرفاق معرّفات المستخدمين

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

رصد عمليات الشراء ومعالجتها

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

يرصد تطبيقك عمليات الشراء الجديدة وعمليات الشراء المُعلّقة المكتملة بإحدى الطرق التالية:

  1. عند استدعاء onPurchasesUpdated نتيجة استدعاء تطبيقك لـ launchBillingFlow (كما هو موضّح في القسم السابق) أو إذا كان تطبيقك يعمل باتصال نشط بواجهة برمجة التطبيقات Billing Library عند إجراء عملية شراء خارج تطبيقك أو عند اكتمال عملية شراء مُعلّقة. على سبيل المثال، يوافق أحد أفراد العائلة على عملية شراء مُعلّقة على جهاز آخر.
  2. عندما يستدعي تطبيقك واجهة برمجة التطبيقات queryPurchasesAsync للاستعلام عن عمليات الشراء التي أجراها المستخدم

بالنسبة إلى رقم 1، سيتم استدعاء onPurchasesUpdated تلقائيًا لعمليات الشراء الجديدة أو المكتملة طالما أنّ تطبيقك قيد التشغيل ولديه اتصال نشط بـ Google Play Billing Library. إذا لم يكن تطبيقك قيد التشغيل أو لم يكن لديه اتصال نشط بـ Google Play Billing Library، فلن يتم استدعاء onPurchasesUpdated. يُرجى تذكُّر أنّه من المستحسن أن يحاول تطبيقك الحفاظ على اتصال نشط طالما أنّ تطبيقك في المقدّمة حتى يحصل على تحديثات الشراء في الوقت المناسب.

بالنسبة إلى الحالة الثانية، يجب طلب البيانات من واجهة BillingClient.queryPurchasesAsync()‎ للتأكّد من أنّ تطبيقك يعالج جميع عمليات الشراء. ننصحك بإجراء ذلك عندما ينشئ تطبيقك اتصالاً بنجاح مع Google Play Billing Library (وهو ما يُنصح به عند تشغيل تطبيقك أو ظهوره في المقدّمة كما هو موضّح في إعداد BillingClient). ويمكن تحقيق ذلك من خلال استدعاء queryPurchasesAsync عند تلقّي نتيجة ناجحة من onServiceConnected. يعد اتباع هذه التوصية أمرًا بالغ الأهمية للتعامل مع الأحداث والمواقف مثل:

  • مشاكل في الشبكة أثناء عملية الشراء: يمكن للمستخدم إجراء عملية شراء ناجحة وتلقّي تأكيد من Google، ولكن يفقد جهازه الاتصال بالشبكة قبل أن يتلقّى جهازه وتطبيقك إشعارًا بعملية الشراء من خلال PurchasesUpdatedListener.
  • أجهزة متعددة: قد يشتري المستخدم منتجًا على جهاز واحد ثم يتوقع رؤية المنتج عند تبديل الأجهزة.
  • التعامل مع عمليات الشراء التي تتم خارج تطبيقك: يمكن إجراء بعض عمليات الشراء خارج تطبيقك، مثل تحصيل قيمة العروض الترويجية.
  • التعامل مع عمليات الانتقال بين حالات الشراء: قد يُكمل المستخدم عملية الدفع مقابل عملية شراء مُعلّقة أثناء عدم تشغيل تطبيقك، ويتوقّع تلقّي تأكيد على إكمال عملية الشراء عند فتح تطبيقك.
  • الاشتراكات المعلّقة: قد يتم تعليق الاشتراك خلال دورة حياة الاشتراك. ستعرض واجهة برمجة التطبيقات BillingClient.queryPurchasesAsync()‎ الاشتراكات المعلّقة فقط في حال ضبط المَعلمة includeSuspendedSubscriptions على QueryPurchasesParams.Builder. لا يتم عرض الاشتراكات المعلّقة في PurchasesUpdatedListener.

بعد أن يرصد تطبيقك عملية شراء جديدة أو مكتملة، يجب أن ينفّذ ما يلي:

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

تتم مناقشة هذه الخطوات بالتفصيل في الأقسام التالية متبوعة بقسم لتلخيص جميع الخطوات.

التحقّق من عملية الشراء

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

منح الإذن للمستخدم

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

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

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

إرسال إشعار إلى المستخدم

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

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

عند إرسال إشعار إلى المستخدم بشأن عملية شراء، ينصح Google Play باستخدام الآليات التالية:

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

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

إشعار Google بأنّه تمت معالجة عملية الشراء

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

المنتجات الاستهلاكية

بالنسبة إلى المنتجات الاستهلاكية، إذا كان تطبيقك يتضمّن خلفية آمنة، ننصحك باستخدام Purchases.products:consume لاستهلاك عمليات الشراء بشكل موثوق. تأكَّد من أنّ عملية الشراء لم يتم استهلاكها من خلال التحقّق من consumptionState من نتيجة طلب Purchases.products:get. إذا كان تطبيقك مخصّصًا للعملاء فقط بدون خلفية، استخدِم consumeAsync() من Google Play Billing Library. تستوفي كلتا الطريقتين متطلبات الإقرار وتشيران إلى أنّ تطبيقك قد منح المستخدم الإذن بالوصول إلى المحتوى. تتيح هذه الطرق أيضًا لتطبيقك إتاحة المنتج المدفوع لمرة واحدة المتوافق مع رمز الشراء المميّز المُدخل لإعادة الشراء. باستخدام consumeAsync()، عليك أيضًا تمرير عنصر ينفّذ واجهة ConsumeResponseListener. يعالج هذا العنصر نتيجة عملية الاستهلاك. يمكنك إلغاء طريقة onConsumeResponse() التي تستدعيها Google Play Billing Library عند اكتمال العملية.

يوضّح المثال التالي استهلاك منتج باستخدام Google Play Billing Library ورمز الشراء المميّز المرتبط به:

Kotlin

val consumeParams =
    ConsumeParams.newBuilder()
        .setPurchaseToken(purchase.getPurchaseToken())
        .build()
val consumeResult = withContext(Dispatchers.IO) {
    client.consumePurchase(consumeParams)
}

Java

ConsumeParams consumeParams =
        ConsumeParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();

ConsumeResponseListener listener =
        (billingResult, purchaseToken) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                // Handle the success of the consume operation.
            }
        };

billingClient.consumeAsync(consumeParams, listener);

المنتجات غير الاستهلاكية

للإقرار بعمليات الشراء غير الاستهلاكية، إذا كان تطبيقك يتضمّن واجهة خلفية آمنة، ننصحك باستخدام Purchases.products:acknowledge للإقرار بعمليات الشراء بشكل موثوق. تأكَّد من أنّه لم يسبق الإقرار بعملية الشراء من خلال التحقّق من acknowledgementState من نتيجة طلب Purchases.products:get.

إذا كان تطبيقك مخصّصًا للعملاء فقط، استخدِم BillingClient.acknowledgePurchase() من Google Play Billing Library في تطبيقك. قبل تأكيد عملية الشراء، يجب أن يتحقّق تطبيقك مما إذا كان قد تم تأكيدها من قبل باستخدام طريقة isAcknowledged() في Google Play Billing Library.

يوضّح المثال التالي كيفية تأكيد عملية شراء باستخدام Google Play Billing Library:

Kotlin

val client: BillingClient = billingClient
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
    .setPurchaseToken(purchase.purchaseToken)
val ackPurchaseResult = withContext(Dispatchers.IO) {
    client.acknowledgePurchase(acknowledgePurchaseParams.build())
}

Java

if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
    if (!purchase.isAcknowledged()) {
        AcknowledgePurchaseParams acknowledgePurchaseParams =
                AcknowledgePurchaseParams.newBuilder()
                        .setPurchaseToken(purchase.getPurchaseToken())
                        .build();
        billingClient.acknowledgePurchase(acknowledgePurchaseParams, (billingResult) -> {
            // Acknowledgment handled.
        });
    }
}

الاشتراكات

يتم التعامل مع الاشتراكات بشكل مشابه للمنتجات غير الاستهلاكية. إذا أمكن، استخدِم Purchases.subscriptions.acknowledge من Google Play Developer API للإقرار بعملية الشراء بشكل موثوق من الخلفية الآمنة. تأكَّد من أنّه لم يسبق الإقرار بعملية الشراء من خلال التحقّق من acknowledgementState في مورد الشراء من Purchases.subscriptions:get. يمكنك بدلاً من ذلك تأكيد الاشتراك باستخدام BillingClient.acknowledgePurchase() من Google Play Billing Library بعد التحقّق من isAcknowledged(). يجب تأكيد جميع عمليات شراء الاشتراكات الأولية. لا يلزم الإقرار بتجديد الاشتراكات. لمزيد من المعلومات حول الحالات التي يجب فيها إرسال إشعار باستلام الاشتراكات، يُرجى الاطّلاع على موضوع بيع الاشتراكات.

التعامل مع عمليات الشراء المرفوضة أو غير المكتملة

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

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

بدلاً من ذلك، يمكنك إلغاء عمليات الشراء المرفوضة وردّ الأموال على الفور من الواجهة الخلفية باستخدام Google Play Developer API:

  • الاشتراكات: يمكنك طلب purchases.subscriptionsv2.revoke باستخدام "fullRefund": {} في revocationContext. يؤدي هذا الإجراء إلى إنهاء الاشتراك على الفور وإلغاء إمكانية الوصول إلى المحتوى وبدء عملية ردّ الأموال بالكامل.
  • المنتجات المدفوعة لمرة واحدة: يمكنك استدعاء orders.refund مع ضبط المَعلمة revoke على true لردّ أموال الطلب على الفور وإلغاء حق الوصول إليه. عند استدعاء هذه الطريقة، يجب تمرير معرّف طلب الشراء الذي يمكنك استرداده باستخدام Purchase.getOrderId() أو purchases.productsv2.getproductpurchasev2. لا تطلب أبدًا consumeAsync() أو acknowledgePurchase() أو Purchases.products:consume أو Purchases.products:acknowledge في عمليات الشراء المرفوضة.
  • سلوك الإشعارات في الوقت الفعلي الخاصة بالمطوّرين (RTDN) وعمليات الشراء المُلغاة: تؤدي عمليات الإبطال وردّ الأموال التي يبدأها المطوّر (purchases.subscriptionsv2.revoke وorders.refund مع ضبط revoke على true) إلى تفعيل الإشعارات في الوقت الفعلي الخاصة بالمطوّرين ويتم تسجيلها في Voided Purchases API (purchases.voidedpurchases.list مع ضبط حقل الاستجابة voidedSource على 1 للمطوّر):
    • الاشتراكات: يرسل هذا الخيار إشعارًا من SUBSCRIPTION_REVOKED وVoidedPurchaseNotification.
    • المنتجات المدفوعة لمرة واحدة: يتم إرسال إشعار VoidedPurchaseNotification (وإشعار ONE_TIME_PRODUCT_CANCELED إذا تم ضبط تطبيقك في Play Console لتلقّي جميع إشعارات المنتجات المدفوعة لمرة واحدة).
    • يؤدي استدعاء orders.refund بدون ضبط revoke على true إلى ردّ أموال الطلب بدون إبطال الاستحقاق ولا يؤدي إلى إرسال إشعار بإبطال أو إلغاء عملية الشراء. لمزيد من التفاصيل، يُرجى الاطّلاع على مقالة إدارة الاشتراكات وعمليات الشراء لمرة واحدة.

ملخّص

في ما يلي ملخّص لهذه الخطوات.

  1. أرسِل عملية الشراء إلى الخلفية الآمنة للتحقّق من عمليات الشراء قبل منح الأذونات.

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

  3. أرسِل إشعارًا إلى المستخدم باستخدام الرسائل المناسبة (مع تأخير الإشعار إذا لزم الأمر كما هو موضّح سابقًا).

  4. أبلِغ Google بأنّه تمت معالجة عملية الشراء باتّباع الخطوات الموضّحة في قسم معالجة عمليات الشراء.

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

التعامل مع المعاملات في انتظار المعالجة

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

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

يمكنك استدعاء enablePendingPurchases() كجزء من عملية إعداد BillingClient لتفعيل المعاملات التي في انتظار المعالجة في تطبيقك. يجب أن يفعّل تطبيقك المعاملات التي في انتظار المعالجة ويتيحها للمنتجات المدفوعة لمرة واحدة. قبل إضافة الدعم، تأكَّد من فهم دورة حياة الشراء للمعاملات في انتظار المراجعة.

عندما يتلقّى تطبيقك عملية شراء جديدة، إما من خلال PurchasesUpdatedListener أو نتيجة طلب queryPurchasesAsync، استخدِم طريقة getPurchaseState() لتحديد ما إذا كانت حالة الشراء هي PURCHASED أو PENDING. يجب منح الإذن فقط عندما تكون الحالة PURCHASED.

إذا كان تطبيقك قيد التشغيل وكان لديك اتصال نشط بواجهة Play Billing Library عندما يكمل المستخدم عملية الشراء، يتم استدعاء PurchasesUpdatedListener مرة أخرى، ويصبح PurchaseState الآن PURCHASED. في هذه المرحلة، يمكن لتطبيقك معالجة عملية الشراء باستخدام الطريقة العادية لرصد عمليات الشراء ومعالجتها. يجب أن يستدعي تطبيقك أيضًا queryPurchasesAsync() في طريقة onResume() الخاصة بتطبيقك للتعامل مع عمليات الشراء التي انتقلت إلى حالة PURCHASED أثناء عدم تشغيل تطبيقك.

عندما تنتقل عملية الشراء من PENDING إلى PURCHASED، يتلقّى عميل real_time_developer_notifications إشعارًا من النوع ONE_TIME_PRODUCT_PURCHASED أو SUBSCRIPTION_PURCHASED. في حال إلغاء عملية الشراء، ستتلقّى إشعارًا من ONE_TIME_PRODUCT_CANCELED أو SUBSCRIPTION_PENDING_PURCHASE_CANCELED. يمكن أن يحدث ذلك إذا لم يكمل العميل عملية الدفع في الإطار الزمني المطلوب. يُرجى العلم أنّه يمكنك دائمًا استخدام Google Play Developer API للتحقّق من الحالة الحالية لعملية الشراء.

التعامل مع عمليات الشراء المتعدّدة الكميات

يتيح Google Play للعملاء شراء أكثر من منتج واحد من المنتجات المدفوعة لمرة واحدة في معاملة واحدة من خلال تحديد الكمية من سلة المشتريات، وذلك في الإصدارات 4.0 والإصدارات الأحدث من Google Play Billing Library. ومن المتوقّع أن يتعامل تطبيقك مع عمليات الشراء المتعدّدة الكمية وأن يمنح الإذن بالوصول إلى المحتوى استنادًا إلى كمية الشراء المحدّدة.

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

بعد إضافة منطق للتعامل مع عمليات الشراء المتعدّدة الكمية، عليك تفعيل ميزة الكميات المتعدّدة للمنتج المعنيّ في صفحة إدارة المنتجات المدفوعة لمرة واحدة في Google Play Console.

الاستعلام عن إعدادات الفوترة الخاصة بالمستخدم

يوفّر getBillingConfigAsync() البلد الذي يستخدمه المستخدم في Google Play.

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

إذا لم يتضمّن الردّ BillingResult أي أخطاء، يمكنك التحقّق من حقل countryCode في عنصر BillingConfig للحصول على بلد المستخدم على Google Play.

Kotlin

// Use the default GetBillingConfigParams.
val getBillingConfigParams = GetBillingConfigParams.newBuilder().build()
billingClient.getBillingConfigAsync(
    getBillingConfigParams,
    object : BillingConfigResponseListener {
        override fun onBillingConfigResponse(
            billingResult: BillingResult,
            billingConfig: BillingConfig?
        ) {
            if (billingResult.responseCode == BillingResponseCode.OK &&
                billingConfig != null
            ) {
                val countryCode = billingConfig.countryCode
                // ...
            } else {
                // Handle errors
            }
        }
    }
)

Java

GetBillingConfigParams getBillingConfigParams = GetBillingConfigParams.newBuilder().build();
billingClient.getBillingConfigAsync(
        getBillingConfigParams,
        (billingResult, billingConfig) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK && billingConfig != null) {
                String countryCode = billingConfig.getCountryCode();
            } else {
                // TODO: Handle errors
            }
        });