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

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

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

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

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

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

خيار شراء المحتوى المستأجَر

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

دمج خيار شراء المحتوى المستأجَر مع ميزة "الاستئجار مقابل اشتراك"

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

لضبط المنتجات المتاحة للإيجار، عليك استخدام واجهة برمجة التطبيقات الجديدة monetization.onetimeproducts في Play Developer API أو واجهة مستخدم Play 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 Billing Library (PBL).

دمج عرض الطلب المُسبَق مع ميزة "الإعلانات التي تظهر قبل التشغيل"

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

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

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

  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.