خيارات وعروض متعددة للشراء للمنتجات التي يتم تحصيل سعرها مرة واحدة

يوضّح هذا المستند تفاصيل عملية دمج المنتجات التي يتم تحصيل سعرها مرة واحدة مع واجهة Play Billing Library. وتوضّح أيضًا كيفية دمج خيارات الشراء والعروض الترويجية المختلفة المرتبطة بمنتجاتك التي يتم تحصيل سعرها مرة واحدة.

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

المتطلّبات الأساسية

لإعداد عروض متعددة للمنتجات التي يتم تحصيل سعرها مرة واحدة، يجب استخدام واجهة برمجة التطبيقات queryProductDetailsAsync(). واجهة برمجة التطبيقات querySkuDetailsAsync() المتوقّفة نهائيًا غير متوافقة. للحصول على معلومات حول كيفية استخدام queryProductDetailsAsync() وإصدار launchBillingFlow() الذي يقبل ProductDetailsParams كمدخل، يُرجى الاطّلاع على خطوات نقل البيانات.

طلب تفاصيل المنتج

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

بدء عملية الفوترة

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

يوضّح المثال التالي كيفية بدء عملية شراء منتج يتم تحصيل سعره مرة واحدة ويتضمّن عروضًا متعددة:

Java

    
// An activity reference from which the billing flow will launch.
Activity activity = ...;
ImmutableList<ProductDetailsParams> productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
             // retrieve a value for productDetails by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // to get an offer token, call
            // ProductDetails.getOneTimePurchaseOfferDetailsList() 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);
    
    

يمكن العثور على offerToken كجزء من OneTimePurchaseOfferDetails. عند عرض العرض الترويجي للمستخدم، احرص على ضبط مَعلمات مسار الفوترة باستخدام الرمز المميز الصحيح للعرض الترويجي الذي يمكنك الحصول عليه من طريقة oneTimePurchaseOfferDetails.getOfferToken().

خيارات الشراء والعروض

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

يتيح Google Play خيارات الشراء التالية للمنتجات التي يتم تحصيل سعرها مرة واحدة:

  • خيار الشراء "شراء"
  • خيار الشراء "استئجار"

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

يتيح Google Play عروض الشراء التالية للمنتجات التي يتم تحصيل سعرها مرة واحدة:

  • عرض الطلب المُسبَق (يتوفّر لخيار الشراء "شراء" فقط)
  • عرض خصم (يتوفّر لكل من خيارَي الشراء والاستئجار)

خيار الشراء "شراء"

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

تتشابه خطوات دمج خيارَي الشراء والاستئجار مع واجهة Google Play Billing Library. للتعرّف على كيفية دمج خيار الشراء "شراء" مع واجهة Google Play Billing Library، اطّلِع على دمج خيار الشراء "استئجار" مع واجهة Google Play Billing Library.

خيار الشراء "استئجار"

يتيح خيار الشراء "استئجار" للمستخدمين الوصول إلى المنتجات التي يتم تحصيل سعرها مرة واحدة لمدة زمنية محدّدة. يمكنك تحديد مدة الاستئجار وتاريخ انتهاء صلاحيتها. يوضّح هذا المستند الخطوات اللازمة لدمج خيار الشراء أو الاستئجار مع واجهة برمجة التطبيقات Play Billing Library (PBL).

دمج خيار الشراء "استئجار" مع مكتبة الفوترة في Google Play

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

لضبط المنتجات المتاحة للاستئجار، عليك استخدام خدمة monetization.onetimeproducts الجديدة في Play Developer API أو واجهة مستخدم Play Developer Console. لاستخدام الخدمة، يمكنك طلب REST API مباشرةً أو استخدام مكتبة برامج Java.

إطلاق مسار شراء لخيار الاستئجار

لإطلاق مسار شراء لعرض استئجار، اتّبِع الخطوات التالية:

  1. استرجِع البيانات الوصفية لخيار الشراء "استئجار" باستخدام الطريقة ProductDetails.oneTimePurchaseOfferDetails.getRentalDetails().

    يوضّح المثال التالي كيفية الحصول على البيانات الوصفية الخاصة بشراء المحتوى أو استئجاره:

    Java

    billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
      public void onProductDetailsResponse(
          BillingResult billingResult, QueryProductDetailsResult productDetailsResult) {
        // check billingResult
        // …
        // process productDetailsList returned by QueryProductDetailsResult
        for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) {
          for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails :
              productDetails.getOneTimePurchaseOfferDetailsList()) {
            // Checks if the offer is a rent purchase option.
            if (oneTimePurchaseOfferDetails.getRentalDetails() != null) {
              // process the returned RentalDetails
              OneTimePurchaseOfferDetails.RentalDetails rentalDetails =
                  oneTimePurchaseOfferDetails.getRentalDetails();
              // Get rental period in ISO 8601 format.
              String rentalPeriod = rentalDetails.getRentalPeriod();
              // Get rental expiration period in ISO 8601 format, if present.
              if (rentalDetails.getRentalExpirationPeriod() != null) {
                String rentalExpirationPeriod = rentalDetails.getRentalExpirationPeriod();
              }
              // Get offer token
                String offerToken = oneTimePurchaseOfferDetails.getOfferToken();
              // Get the associated purchase option ID
              if (oneTimePurchaseOfferDetails.getPurchaseOptionId() != null) {
                String purchaseOptionId = oneTimePurchaseOfferDetails.getPurchaseOptionId();
              }
            }
          }
        }
      }
    });
  2. تشغيل مسار الفوترة

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

    يوضّح المثال التالي كيفية بدء عملية الفوترة:

    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.subscriptionOfferDetails()
            // 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<ProductDetailsParams> productDetailsParamsList =
        ImmutableList.of(
            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.subscriptionOfferDetails()
                // 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);

    يمكن العثور على offerToken كجزء من OneTimePurchaseOfferDetails. عند عرض العرض الترويجي للمستخدم، احرص على ضبط مَعلمات عملية الفوترة باستخدام الرمز المميز الصحيح للعرض الترويجي الذي يمكنك الحصول عليه من الطريقة oneTimePurchaseOfferDetails.getOfferToken().

عرض طلب مُسبَق

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

يوضّح هذا المستند خطوات دمج عرض الشراء المسبَق مع مكتبة Play Billing Library (PBL).

دمج عرض الطلب المُسبَق مع ميزة "الدفع حسب الاستخدام"

يوضّح هذا القسم كيفية دمج عرض الطلب المُسبَق مع مكتبة الفوترة في Play‏ (PBL). ويفترض هذا الدليل أنّك على دراية بخطوات الدمج الأولية لمكتبة الفوترة في Google Play، مثل إضافة عنصر تابع لمكتبة الفوترة في Google Play إلى تطبيقك وإعداد BillingClient والربط بخدمة Google Play. يركّز هذا القسم على جوانب دمج PBL الخاصة بعرض الطلب المُسبَق.

إطلاق مسار شراء لعرض طلب مُسبَق

لإطلاق مسار شراء لعرض طلب مُسبَق، اتّبِع الخطوات التالية:

  1. يمكنك جلب البيانات الوصفية الخاصة بعرض الطلب المُسبَق باستخدام طريقة ProductDetails.oneTimePurchaseOfferDetails.getPreorderDetails(). تعرض العيّنة التالية كيفية الحصول على البيانات الوصفية لعرض الطلب المُسبَق:

    Java

    billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
      public void onProductDetailsResponse(
          BillingResult billingResult, QueryProductDetailsResult productDetailsResult) {
        // check billingResult
        // …
        // process productDetailsList returned by QueryProductDetailsResult
        for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) {
          for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails :
              productDetails.getOneTimePurchaseOfferDetailsList()) {
            // Checks if the offer is a preorder offer.
            if (oneTimePurchaseOfferDetails.getPreorderDetails() != null) {
              // process the returned PreorderDetails
              OneTimePurchaseOfferDetails.PreorderDetails preorderDetails =
                  oneTimePurchaseOfferDetails.getPreorderDetails();
              // Get preorder release time in millis.
              long preorderReleaseTimeMillis = preorderDetails.getPreorderReleaseTimeMillis();
              // Get preorder presale end time in millis.
              long preorderPresaleEndTimeMillis = preorderDetails.getPreorderPresaleEndTimeMillis();
              // Get offer ID
                String offerId = oneTimePurchaseOfferDetails.getOfferId();
              // Get the associated purchase option ID
              if (oneTimePurchaseOfferDetails.getPurchaseOptionId() != null) {
                String purchaseOptionId = oneTimePurchaseOfferDetails.getPurchaseOptionId();
              }
            }
          }
        }
      }
    });

  2. تشغيل مسار الفوترة

    لبدء طلب شراء من تطبيقك، استدعِ طريقة launchBillingFlow() من سلسلة التعليمات البرمجية الرئيسية في تطبيقك. يستقبل هذا الإجراء مرجعًا إلى عنصر BillingFlowParams الذي يحتوي على عنصر ProductDetails ذي الصلة الذي تم الحصول عليه من خلال استدعاء queryProductDetailsAsync(). لإنشاء عنصر BillingFlowParams، استخدِم BillingFlowParams.Builder class. يُرجى العِلم أنّه يجب ضبط رمز العرض الترويجي الذي يطابق العرض الترويجي الذي اختاره المستخدم عند إنشاء العنصر BillingFlowParams. إذا كان المستخدم مؤهلاً للاستفادة من عرض الطلب المُسبَق، سيتلقّى عرضًا يتضمّن PreorderDetails وofferId في طريقة queryProductDetailsAsync().

    يوضّح المثال التالي كيفية بدء عملية الفوترة:

    Java

    // An activity reference from which the billing flow will launch.
    Activity activity = ...;
    ImmutableList productDetailsParamsList =
        ImmutableList.of(
        ProductDetailsParams.newBuilder()
             // retrieve a value for productDetails by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // to get an offer token, call
            // ProductDetails.getOneTimePurchaseOfferDetailsList() 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);

    يمكن العثور على offerToken كجزء من OneTimePurchaseOfferDetails. عند عرض العرض الترويجي للمستخدم، احرص على ضبط مَعلمات عملية الفوترة باستخدام الرمز المميز الصحيح للعرض الترويجي الذي يمكنك الحصول عليه من الطريقة oneTimePurchaseOfferDetails.getOfferToken().

عرض خصم

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

هناك أربع معلَمات مختلفة يمكنك ضبطها في عرض خصم على منتج يتم تحصيل سعره مرة واحدة:

  • سعر العرض المخفَّض: يحدّد تفاصيل حول النسبة المئوية المخفَّضة أو السعر المطلق المخفَّض من السعر الأصلي.

  • بلدان أو مناطق الأهلية: تحدّد مدى توفّر عروض المنتجات التي يتم تحصيل سعرها مرة واحدة في بلد أو منطقة.

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

  • المدة المحدودة (اختيارية): تحدّد هذه السمة الفترة الزمنية التي يتوفّر فيها العرض. وخارج هذه الفترة الزمنية، لا يكون العرض مؤهلاً للشراء.

استرداد معلومات سعر العرض الترويجي المخفَّض

بالنسبة إلى العرض المخفَّض، يمكنك استرداد النسبة المئوية للخصم أو الخصم المطلق المقدَّم.

المثال 1: استرداد النسبة المئوية للخصم على العرض المخفَّض

يوضّح المثال التالي كيفية الحصول على السعر الكامل الأصلي للعرض المخفَّض ونسبة الخصم. يُرجى العِلم أنّ معلومات الخصم بالنسبة المئوية لا يتم عرضها إلا للعروض المخفَّضة.

Java

billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
      public void onProductDetailsResponse(
          BillingResult billingResult, QueryProductDetailsResult productDetailsResult){
        // check billingResult
        // …
        // process productDetailsList returned by QueryProductDetailsResult
        for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) {
          for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails :
              productDetails.getOneTimePurchaseOfferDetailsList()) {
            long discountedOfferPriceMicros =
                oneTimePurchaseOfferDetails.getPriceAmountMicros();
            // process the returned fullPriceMicros and percentageDiscount.
            if (oneTimePurchaseOfferDetails.getFullPriceMicros() != null) {
              long fullPriceMicros = oneTimePurchaseOfferDetails.getFullPriceMicros();
            }
            if (oneTimePurchaseOfferDetails.getDiscountDisplayInfo() != null) {
              long percentageDiscount =
                  oneTimePurchaseOfferDetails
                      .getDiscountDisplayInfo()
                      .getPercentageDiscount();
            }
            // …
          }
        }
      }
    });
    
المثال 2: استرداد الخصم المطلق للعرض المخفَّض

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

Java

billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
      public void onProductDetailsResponse(
          BillingResult billingResult, QueryProductDetailsResult productDetailsResult) {
        // check billingResult
        // …
        // process productDetailsList returned by QueryProductDetailsResult
        for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) {
          for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails :
              productDetails.getOneTimePurchaseOfferDetailsList()) {
            long discountedOfferPriceMicros =
                oneTimePurchaseOfferDetails.getPriceAmountMicros();
            // process the returned fullPriceMicros and absolute DiscountAmountMicros.
            if (oneTimePurchaseOfferDetails.getFullPriceMicros() != null) {
              long fullPriceMicros = oneTimePurchaseOfferDetails.getFullPriceMicros();
            }
            if (oneTimePurchaseOfferDetails.getDiscountDisplayInfo() != null) {
              long discountAmountMicros =
                  oneTimePurchaseOfferDetails
                      .getDiscountDisplayInfo()
                      .getDiscountAmount()
                      .getDiscountAmountMicros();
            }
            // …
          }
        }
      }
    });
    

الحصول على فترة العرض الترويجي الصالحة

يمكنك استخدام طريقة OneTimePurchaseOfferDetails.getValidTimeWindow() للحصول على الفترة الزمنية الصالحة لعرض ترويجي. يحتوي هذا العنصر على وقت بدء الفترة الزمنية ووقت انتهائها بالمللي ثانية.

يوضّح المثال التالي كيفية الحصول على الفترة الزمنية الصالحة لعرض:

Java

billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
      public void onProductDetailsResponse(
          BillingResult billingResult, QueryProductDetailsResult productDetailsResult) {
        // check billingResult
        // …
        // process productDetailsList returned by QueryProductDetailsResult
        for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) {
          for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails :
              productDetails.getOneTimePurchaseOfferDetailsList()) {
            if (oneTimePurchaseOfferDetails.getValidTimeWindow() != null) {
              // process the returned startTimeMillis and endTimeMillis.
              ValidTimeWindow validTimeWindow =
                  oneTimePurchaseOfferDetails.getValidTimeWindow();
              long startTimeMillis = validTimeWindow.getStartTimeMillis();
              long endTimeMillis = validTimeWindow.getEndTimeMillis();
              // …
            }
          }
        }
      }
    });
    

كمية محدودة على مستوى عرض الخصم

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

  1. تقدّم Super screensavers عرضَين لمنتج شاشة التوقف: شاشة توقف يمكن شراؤها وشاشة توقف مخفَّضة السعر.
    1. لا يتضمّن تطبيق شاشة الاستراحة لخيار الشراء إعدادًا لعدد محدود.
    2. تم ضبط الحد الأقصى المسموح به لعدد المنتجات على مستوى العرض في شاشة توقّف الخصم على 3.
  2. لا يفرض منتج شاشة التوقف حدًا أقصى على الكمية المسموح بها على مستوى المنتج، وبالتالي يمكن للمستخدمين شراء كميات غير محدودة من هذا المنتج.
  3. يمتلك المستخدم صورة شاشة استراحة مخفَّضة السعر، ويخطّط لشراء صورة أخرى باستخدام صورة شاشة الاستراحة المخفَّضة السعر.
  4. عند استرداد العروض الترويجية المتاحة، تكون قيمة LimitedQuantityInfo الخاصة بشاشة توقف خيار الشراء فارغة، وتكون قيمة الكمية المتبقية لشاشة توقف الخصم هي 2.

تعرض العيّنة التالية كيفية الحصول على الكمية المحدودة على مستوى العرض الترويجي المخفَّض:

Java

billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
      public void onProductDetailsResponse(
          BillingResult billingResult, QueryProductDetailsResult productDetailsResult) {
        // check billingResult
        // …
        // process productDetailsList returned by QueryProductDetailsResult
        for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) {
          for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails :
              productDetails.getOneTimePurchaseOfferDetailsList()) {
            if (oneTimePurchaseOfferDetails.getLimitedQuantityInfo() != null) {
              // process the returned maximumQuantity and remainingQuantity.
              LimitedQuantityInfo limitedQuantityInfo =
                  oneTimePurchaseOfferDetails.getLimitedQuantityInfo();
              int maximumQuantity = limitedQuantityInfo.getMaximumQuantity();
              int remainingQuantity = limitedQuantityInfo.getRemainingQuantity();
              // …
            }
          }
        }
      }
    });
    

عندما يستنفد المستخدمون الحد الأقصى لعدد عمليات تحصيل القيمة لعرض ما، لا تعرض الطريقة getOneTimePurchaseOfferDetailsList() هذا العرض.

حساب حد الاسترداد

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

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

  1. تتيح شاشات الاستراحة الفائقة إعداد عرض خصم مع الحد الأقصى المسموح به وهو شاشة استراحة واحدة، ما يتيح للمستخدمين شراء شاشة استراحة واحدة مخفَّضة السعر.

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

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

البلدان والمناطق المؤهّلة

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

علامات العروض

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

Java

    
billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
      public void onProductDetailsResponse(
          BillingResult billingResult, QueryProductDetailsResult productDetailsResult) {
        // check billingResult
        // …
        // process productDetailsList returned by QueryProductDetailsResult
        for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) {
          for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails :
              productDetails.getOneTimePurchaseOfferDetailsList()) {
            // process the returned offer tags.
            ImmutableList<String> offerTags =
                oneTimePurchaseOfferDetails.getOfferTagsList();
            // …
          }
        }
      }
    });
    
    

اكتساب علامات العروض

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

على سبيل المثال، تقدّم شركة Super screensavers عرضَين لمنتج شاشة الاستراحة، وهما شاشة استراحة يمكن شراؤها وشاشة استراحة مخفَّضة السعر.

  • تحتوي شاشة الاستراحة "الرائعة" على علامة عرض المنتج SSProductTag.
  • تحتوي شاشة الاستراحة الخاصة بخيار الشراء على علامة العرض SSPurchaseOptionTag.
  • تحتوي شاشة الاستراحة التي تتضمّن خصمًا على العلامة SSDiscountOfferTag.

في هذا المثال، تعرض الطريقة oneTimePurchaseOfferDetails.getOfferTagsList() لعرض خيار الشراء SSProductTag وSSPurchaseOptionTag. بالنسبة إلى عرض الخصم، تعرض الطريقة SSProductTag وSSPurchaseOptionTag وSSDiscountOfferTag.