В этом документе подробно описана интеграция ваших разовых продуктов (OTP) с библиотекой Play Billing. Также объясняется, как интегрировать различные варианты покупки и предложения, связанные с вашими разовыми продуктами.
Для разовых товаров можно настроить несколько вариантов покупки и предложений. Например, для одного и того же разового товара можно настроить вариант покупки и предложение предварительного заказа.
Предварительные требования
Для настройки нескольких предложений для разовых товаров необходимо использовать API queryProductDetailsAsync() . Устаревший API querySkuDetailsAsync() не поддерживается. Информацию об использовании queryProductDetailsAsync() и версии launchBillingFlow() , принимающей ProductDetailsParams в качестве входных данных, см. в разделе «Шаги миграции» .
Запросите подробную информацию о товаре.
If you have configured multiple offers or purchase options for your one-time product, the ProductDetails object returned by the queryProductDetailsAsync() method can have more than one available buy and (or) rent purchase option per one-time product. To get the list of all the eligible offers for each ProductDetails object, use the getOneTimePurchaseOfferDetailsList() method. Only offers and purchase options for which the user is eligible will be returned as part of this list. Your code in the onProductDetailsResponse() method should handle the returned offers.
Запустите процесс выставления счетов.
To start a purchase request from your app, call the launchBillingFlow() method from your app's main thread. This method takes a reference to a BillingFlowParams object that contains the relevant ProductDetails object obtained from calling queryProductDetailsAsync() . To create a BillingFlowParams object, use the BillingFlowParams.Builder class. Note that you must set the offer token corresponding to the offer selected by the user when creating the BillingFlowParams object.
В следующем примере показано, как запустить процесс покупки разового товара с несколькими предложениями:
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 или старше), которые не поддерживают новую модель. Для обеспечения обратной совместимости как минимум один вариант покупки должен быть помечен как совместимый с устаревшими версиями.
Пошаговая инструкция по интеграции вариантов покупки и аренды с PBL одинакова. Чтобы понять, как интегрировать вариант покупки с PBL, см. раздел «Интеграция варианта аренды с PBL» .
Вариант аренды с правом выкупа
Опция «аренда с правом выкупа» позволяет пользователям получать доступ к разовым продуктам на определенный период времени. Вы можете указать период аренды и дату его окончания. В этом документе описаны шаги по интеграции опции «аренда с правом выкупа» с Play Billing Library (PBL).
Интегрировать опцию аренды с правом выкупа с PBL
This section describes how to integrate the rent purchase option with the Play Billing Library (PBL). It assumes that you are familiar with the initial PBL integration steps such as, adding the PBL dependency to your app , initializing the BillingClient , and connecting to Google Play . This section focuses on the PBL integration aspects that are specific to the rent purchase option.
Для настройки продуктов, доступных для аренды, вам потребуется использовать новый сервис monetization.onetimeproducts из Play Developer API или пользовательский интерфейс Play Developer Console. Для использования сервиса вы можете напрямую вызвать REST API или использовать клиентскую библиотеку Java .
Запустите процесс покупки варианта аренды.
Для запуска процесса покупки арендного предложения выполните следующие шаги:
Получите метаданные варианта аренды с правом выкупа, используя метод
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(); } } } } } });
Запустите процесс выставления счетов.
To start a purchase request from your app, call the
launchBillingFlow()method from your app's main thread. This method takes a reference to aBillingFlowParamsobject that contains the relevantProductDetailsobject obtained from callingqueryProductDetailsAsync(). To create aBillingFlowParamsobject, use theBillingFlowParams.Builderclass. Note that you must set the offer token corresponding to the offer selected by the user when creating theBillingFlowParamsobject. If a user is eligible for the rent purchase option, they will receive an offer with RentalDetails and offerId inqueryProductDetailsAsync().В следующем примере показано, как запустить процесс выставления счетов:
Котлин
// 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);
offerTokenможно найти в объектеOneTimePurchaseOfferDetails. При показе предложения пользователю убедитесь, что вы настроили параметры процесса выставления счетов с правильным токеном предложения, который можно получить из методаoneTimePurchaseOfferDetails.getOfferToken().
Предложение предварительного заказа
Предзаказ позволяет настроить разовую покупку товаров до их официального выпуска. При оформлении предзаказа пользователь соглашается оплатить товар после его выпуска, если только он не отменит предзаказ до даты релиза. В день релиза с покупателя списывается сумма, и Play уведомит его по электронной почте о выпуске товара.
В этом документе описаны шаги по интеграции предложения предварительного заказа с библиотекой Play Billing Library (PBL).
Интегрируйте предложение предварительного заказа с PBL.
В этом разделе описывается, как интегрировать предложение предварительного заказа с Play Billing Library (PBL). Предполагается, что вы знакомы с начальными шагами интеграции PBL, такими как добавление зависимости PBL в ваше приложение , инициализация BillingClient и подключение к Google Play . Этот раздел посвящен аспектам интеграции PBL, специфичным для предложения предварительного заказа.
Запустите процесс оформления покупки по предложению предварительного заказа.
Для запуска процесса покупки по предварительному заказу выполните следующие шаги:
Получите метаданные предварительного заказа, используя метод
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(); } } } } } });
Запустите процесс выставления счетов.
To start a purchase request from your app, call the
launchBillingFlow()method from your app's main thread. This method takes a reference to aBillingFlowParamsobject that contains the relevantProductDetailsobject obtained from calling queryProductDetailsAsync(). To create aBillingFlowParamsobject, use theBillingFlowParams.Builder class. Note that you must set the offer token corresponding to the offer selected by the user when creating theBillingFlowParamsobject. If a user is eligible for the pre-order offer, they will receive an offer with PreorderDetails and offerId in thequeryProductDetailsAsync()method.В следующем примере показано, как запустить процесс выставления счетов:
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(); // … } } } } });
Количество товаров по сниженной цене ограничено.
Максимальное количество товара можно указать на уровне предложения скидки, и оно применяется только на уровне самого предложения. Вот пример для иллюстрации:
- На сайте Super Screensavers действуют 2 предложения по продукту «Заставка»: вариант покупки заставки и заставка со скидкой.
- В опции покупки в качестве заставки нет ограничений по количеству.
- Для этой заставки со скидкой максимальное допустимое количество товаров в рамках акции установлено на уровне 3.
- Для данного продукта-заставки не установлено максимально допустимое количество, поэтому пользователи могут приобрести неограниченное количество этого продукта.
- У пользователя уже есть одна заставка со скидкой, и он планирует купить ещё одну, используя ту же заставку.
- При получении доступных предложений значение параметра LimitedQuantityInfo для варианта покупки в качестве заставки имеет значение null, а значение оставшегося количества для заставки со скидкой равно 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 учитывает использованные покупки или ожидающие покупки. Покупки, которые были отменены, возвращены или аннулированы платежом, не учитываются в количестве товаров, находящихся в собственности пользователя. Например:
Супер-заставки предлагают скидку, при этом максимальное количество товаров ограничено одной заставкой, поэтому пользователи могут приобрести до одной заставки со скидкой.
Пользователь покупает одну из заставок со скидкой. Если пользователь затем попытается купить вторую заставку со скидкой, возникнет ошибка, и
PurchasesUpdatedListenerполучит код ответа ITEM_UNAVAILABLE.Пользователь запрашивает возврат средств за первоначально приобретенную заставку со скидкой и успешно получает возврат. Пользователь пытается купить одну из заставок со скидкой, и покупка проходит успешно.
Критерии отбора по стране и региону
You can choose the countries or regions where purchase option offer or discount offer will be available to users. Google Play will evaluate user eligibility based on Play country. When you configure regional availability for an offer, it will only be returned as part of getOneTimePurchaseOfferDetailsList() if the user is in a targeted country or region, otherwise it won't be part of the list of offers returned when you call 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 есть два предложения на продукт «Заставка»: заставка с возможностью покупки и заставка со скидкой.
- У заставки Super Screensaver есть товарный тег
SSProductTag. - Заставка с вариантами покупки имеет тег предложения
SSPurchaseOptionTag. - У этой заставки со скидкой есть тег предложения
SSDiscountOfferTag.
В этом примере метод oneTimePurchaseOfferDetails.getOfferTagsList() для предложения с возможностью покупки возвращает SSProductTag и SSPurchaseOptionTag . Для предложения со скидкой метод возвращает SSProductTag , SSPurchaseOptionTag и SSDiscountOfferTag .