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

يوضّح هذا المستند تفاصيل دمج المنتجات التي يتم تحصيل سعرها مرة واحدة مع 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 &quot;productDetails&quot; 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" (الإصدار 7 أو الإصدارات الأقدم) التي لا تتوافق مع النموذج الجديد. للتوافق مع الأنظمة القديمة، يجب وضع علامة على خيار شراء واحد على الأقل للإشارة إلى أنّه متوافق مع الإصدارات القديمة.

تتشابه خطوات دمج خيارَي الشراء والاستئجار مع ميزة "الدفع حسب المنتج". لمعرفة كيفية دمج خيار الشراء مع ميزة "الدفع حسب الاستخدام"، يُرجى الاطّلاع على دمج خيار الشراء مع ميزة "الدفع حسب الاستخدام".

خيار الشراء عند الاستئجار

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

دمج خيار شراء الاستئجار مع PBL

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

لضبط المنتجات المتاحة للاستئجار، عليك استخدام خدمة 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().

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

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

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

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

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

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

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

  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.