Мигрируйте в Google Play Библиотеку Биллинг 6 из версий 4 или 5

В этом разделе описывается, как перейти с библиотеки Google Play Billing 4 или 5 на библиотеку Google Play Billing 6 и как использовать новые возможности подписки.

Полный список изменений в версии 6.0.0 можно найти в примечаниях к выпуску .

Обзор

Библиотека выставления счетов Google Play 6 основана на новых функциях подписки, представленных в версии 5, и содержит еще несколько улучшений. Эти функции позволяют вам продавать подписки разными способами, сокращая эксплуатационные расходы за счет устранения необходимости создавать и управлять постоянно растущим количеством SKU.

Дополнительную информацию о новых функциях, представленных в Play Billing Library 5, см. в разделе Последние изменения в подписках в Play Console .

Обновление библиотеки Play Billing Library с обратной совместимостью

Все существующие продукты по подписке были автоматически преобразованы в эту новую парадигму в рамках выпуска Play Billing Library 5 и новой платформы подписок в мае 2022 года. Это означает, что вам не нужно вносить какие-либо изменения в конфигурацию продукта по подписке, чтобы иметь каталог, совместимый с новыми версиями библиотеки платежей Play. Дополнительную информацию о том, как SKU подписок были преобразованы в подписки с обратной совместимостью, можно найти в разделе «Работа со старыми подписками» в справочной статье Play Console .

Старые версии вашего приложения по-прежнему работают.

Если у вас есть каталог подписок с обратной совместимостью, все существующие версии вашего приложения должны по-прежнему работать так, как предназначено для этих продуктов. Единовременные покупки продуктов также должны продолжать работать без проблем в более старых версиях.

Версии вашего приложения, использующие устаревшие методы (например, querySkuDetailsAsync() ), не смогут продавать базовые планы или предложения, которые не имеют обратной совместимости. О предложениях обратной совместимости можно прочитать в соответствующей статье Справочного центра Play Console .

Обновите библиотеку Play Billing Library 5 или 6.

Библиотека выставления счетов Play 5 и 6 включает устаревшие методы querySkuDetailsAsync и BillingFlowParams.Builder.setSkuDetails , которые принимают SkuDetails в качестве параметра потока выставления счетов. Это означает, что вы можете постепенно переходить на Play Billing Library 6, планируя различные этапы перехода.

В качестве первого шага к миграции вы можете просто обновить версию библиотеки , оставить каталог и серверную часть без изменений и протестировать свое приложение, пока оно все еще использует устаревшие методы. Если вы не используете queryPurchases , launchPriceChangeFlow или setVrPurchaseFlow , он все равно должен работать должным образом. После этого вы можете выполнить итерацию, чтобы полностью внедрить новые функции подписки, выпущенные в мае 2022 года .

Если вы ранее использовали эти функции при переходе на Google Play Billing Library 5, вы можете перейти непосредственно к разделам « Обновить Google Play Billing Library» и «Изменить покупки подписки» . Если вы начинаете с более ранней версии или еще не полностью внедрили новые функции, вы можете прочитать подробные инструкции по переходу , которые приведены ниже, чтобы узнать, как их применить.

Полные шаги миграции

Создавайте новые подписки в своем внутреннем каталоге продуктов.

Используя консоль разработчика Play или API разработчика Play, вы теперь можете настроить одну подписку с несколькими базовыми планами, каждый из которых имеет несколько предложений. Предложения по подписке имеют гибкие модели ценообразования и варианты соответствия. Вы можете создавать предложения на протяжении всего жизненного цикла подписки, используя различные планы с автоматическим продлением и предоплаченными планами.

Перед переносом приложения мы рекомендуем создавать новые продукты в соответствии со структурой объектов на новой платформе подписки для интеграции вашей библиотеки Play Billing Library 6. Вы можете объединить дублирующиеся продукты в своем старом каталоге, представляющие одни и те же преимущества в рамках одной подписки, и использовать базовый план и конфигурации предложений, чтобы представить все варианты, которые вы хотите предложить. Дополнительную информацию об этой рекомендации можно найти в разделе «Работа со старыми подписками» статьи справки Play Console .

Мы рекомендуем не изменять преобразованные продукты по подписке после выпуска в мае 2022 г.; вам следует оставить их, поскольку они будут продаваться вместе с версиями вашего приложения, использующими устаревшие методы (например, querySkuDetailsAsync() ), без внесения изменений, которые могут повлиять на эти старые сборки.

В процессе преобразования продукты по подписке, которые были в вашем каталоге до мая 2022 г., стали доступны только для чтения, чтобы избежать случайных изменений, которые могли бы привести к проблемам с существующей интеграцией. Внесение изменений в эти подписки возможно, но это может повлиять на интеграцию внешнего и внутреннего интерфейса:

  • На внешнем интерфейсе версии приложения, использующие querySkuDetailsAsync() для получения сведений о продукте по подписке, могут продавать только обратно совместимые базовые планы и предложения, и может быть только один обратно совместимый базовый план и комбинация предложений, поэтому, если вы добавите новые планы или предложения в преобразованные подписки, новые дополнительные базовые планы или предложения нельзя будет продавать в этих старых версиях вашего приложения.

  • На серверной стороне, если вы редактируете преобразованные подписки в пользовательском интерфейсе Play Console, вы не сможете управлять ими с помощью конечной точки inappproducts , если вы вызывали конечную точку для этой цели. Вам также следует перейти на новую конечную точку статуса покупки подписки ( purchases.subscriptionsv2.get ), чтобы управлять покупками для этих подписок, поскольку старая конечная точка статуса покупки ( purchases.subscriptions.get ) возвращает только данные, необходимые для обработки обратно совместимых базовых планов. и предлагает покупки. Дополнительные сведения см. в разделе «Управление статусом покупки подписки» .

Управляйте своим серверным каталогом подписок с помощью нового API

Если вы управляете каталогом продуктов по подписке автоматически с помощью API разработчика Google Play, вам необходимо использовать новые конечные точки определения продуктов по подписке для создания подписок, базовых планов и предложений и управления ими. Прочтите руководство по функциям подписки за май 2022 года, чтобы узнать больше об изменениях API каталога продуктов в этом выпуске.

Чтобы перенести модуль автоматического управления каталогом продуктов для подписок Google Play Billing, замените API inappproducts новым API публикации подписки, чтобы управлять каталогом подписок и публиковать его. Появилось три новые конечные точки:

Эти новые конечные точки обладают всеми необходимыми функциями для использования всех новых возможностей вашего каталога: базового плана и тегов предложений, регионального таргетинга, планов с предоплатой и т. д.

Вам по-прежнему следует использовать API inappproducts для управления каталогом продуктов в приложении для продуктов, приобретаемых единоразово.

Версии вашего приложения, использующие устаревшие методы (например, querySkuDetailsAsync() ), не смогут продавать базовые планы или предложения, которые не имеют обратной совместимости. Про обратно совместимые предложения можно прочитать здесь .

Обновите библиотеку платежей Google Play

После создания нового каталога продуктов по подписке вы можете перенести свое приложение в Google Billing Library 5. Замените существующую зависимость Play Billing Library обновленной версией в файле build.gradle вашего приложения.

dependencies {
    def billingVersion = "6.0.0"

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

Ваш проект должен быть собран сразу же, даже если вы не изменили никаких вызовов методов — Play Billing Library 6 обратно совместима. Концепция SKU считается устаревшей, но все еще присутствует, чтобы сделать перенос приложений более простым и поэтапным процессом.

Инициализируйте Биллинговый клиент и установите соединение с Google Play.

Первые шаги для запуска покупок из приложения Android остаются прежними:

Показать продукты, доступные для покупки

Чтобы получить все предложения, которые пользователь имеет право приобрести:

  • Замените SkuDetailsParams на QueryProductDetailsParams
  • Переключите вызов BillingClient.querySkuDetailsAsync() на использование BillingClient.queryProductDetailsAsync()

Обратите внимание, что результатами запроса теперь являются ProductDetails вместо SkuDetails . Каждый элемент ProductDetails содержит информацию о продукте (идентификатор, название, тип и т. д.). Для продуктов по подписке ProductDetails содержит List<ProductDetails.SubscriptionOfferDetails> , который представляет собой список сведений о предложении по подписке. Для продуктов, приобретаемых единоразово, ProductDetails содержит ProductDetails.OneTimePurchaseOfferDetails . Их можно использовать, чтобы решить, какие предложения показывать пользователям.

В следующем примере показано, как ваше приложение может выглядеть до и после внесения этих изменений:

До

Котлин

val skuList = ArrayList<String>()

skuList.add("up_basic_sub")

val params = SkuDetailsParams.newBuilder()

params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS).build()

billingClient.querySkuDetailsAsync(params) {
    billingResult,
    skuDetailsList ->
    // Process the result
}

Ява

List<String> skuList = new ArrayList<>();

skuList.add("up_basic_sub");

SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();

params.setSkusList(skuList).setType(SkuType.SUBS).build();

billingClient.querySkuDetailsAsync(params,
    new SkuDetailsResponseListener() {
        @Override
        public void onSkuDetailsResponse(BillingResult billingResult,
                List<SkuDetails> skuDetailsList) {
            // Process the result.
        }
    }
);

После

Котлин

val productList =
    listOf(
        QueryProductDetailsParams.Product.newBuilder()
            .setProductId("up_basic_sub")
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
    )

val params = QueryProductDetailsParams.newBuilder().setProductList(productList).build()

billingClient.queryProductDetailsAsync(params) {
    billingResult,
    productDetailsList ->
    // Process the result
}

Ява

ImmutableList<Product> productList = ImmutableList.of(Product.newBuilder()
                                            .setProductId("up_basic_sub")
                                            .setProductType(ProductType.SUBS)
                                            .build());

QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
    .setProductList(productList)
    .build();

billingClient.queryProductDetailsAsync(
        params,
        new ProductDetailsResponseListener() {
                public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) {
                    // Process the result
                }
        }
);

Обратный вызов для queryProductDetailsAsync возвращает List<ProductDetails> . Каждый элемент ProductDetails содержит информацию о продукте (идентификатор, название, тип и т. д.). Основное отличие состоит в том, что продукты по подписке теперь также содержат List<ProductDetails.SubscriptionOfferDetails> , содержащий все предложения, доступные пользователю.

Поскольку предыдущие версии библиотеки платежей Play не поддерживают новые объекты (подписки, базовые планы, предложения и т. д.), новая система преобразует каждый номер SKU подписки в один обратно совместимый базовый план и предложение. Доступные для единоразовой покупки продукты также переносятся в объект ProductDetails . Доступ к сведениям о предложении продукта, приобретаемого единоразово, можно получить с помощью метода getOneTimePurchaseOfferDetails() .

В редких случаях некоторые устройства не поддерживают ProductDetails и queryProductDetailsAsync() , обычно из-за устаревших версий Google Play Services . Чтобы обеспечить правильную поддержку этого сценария, вызовите isFeatureSupported() для функции PRODUCT_DETAILS перед вызовом queryProductDetailsAsync . Если ответ OK , устройство поддерживает эту функцию, и вы можете продолжить вызов queryProductDetailsAsync() . Если ответ FEATURE_NOT_SUPPORTED , вы можете вместо этого запросить список доступных обратно совместимых продуктов с помощью querySkuDetailsAsync() . Дополнительные сведения об использовании функций обратной совместимости см. в руководстве по функциям подписки за май 2022 г.

Запустите процесс покупки предложений

Запуск потока покупки оффера очень похож на запуск потока SKU. Чтобы запустить заявку на покупку с использованием версии 6, выполните следующие действия:

  • Вместо использования SkuDetails для BillingFlowParams используйте ProductDetailsParams .
  • Сведения о предложениях, такие как идентификатор предложения, идентификатор базового плана и т. д., можно получить с помощью объекта SubscriptionOfferDetails .

Чтобы приобрести продукт с выбранным пользователем предложением, получите offerToken выбранного предложения и передайте его в объект ProductDetailsParams .

После создания объекта BillingFlowParams запуск процесса выставления счетов с помощью BillingClient остается прежним.

В следующем примере показано, как ваше приложение может выглядеть до и после внесения этих изменений:

До

Котлин

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
val billingFlowParams = BillingFlowParams.newBuilder()
                            .setSkuDetails(skuDetails)
                            .build()

val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

Ява

// An activity reference from which the billing flow will be launched.
Activity activity = ...;
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(skuDetails)
        .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

После

Котлин

// 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)
        // For One-time product, "setOfferToken" method shouldn't be called.
        // For subscriptions, to get the offer token corresponding to the selected
        // offer call productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken
        .setOfferToken(selectedOfferToken)
        .build()
)

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

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

Ява

// 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)
            // For one-time products, "setOfferToken" method shouldn't be called.
            // For subscriptions, to get the offer token corresponding to the selected
            // offer call productDetails.getSubscriptionOfferDetails().get(selectedOfferIndex).getOfferToken()
            .setOfferToken(selectedOfferToken)
            .build()
    );

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

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

Обработка покупок

Обработка покупок с помощью библиотеки Google Play Billing Library 6 остается такой же, как и в предыдущих версиях.

Чтобы получить все активные покупки, принадлежащие пользователю, и запросить новые покупки, выполните следующие действия:

  • Вместо передачи значения BillingClient.SkuType в queryPurchasesAsync() передайте объект QueryPurchasesParams , содержащий значение BillingClient.ProductType .

В следующем примере показано, как ваше приложение может выглядеть до и после внесения этих изменений:

До

Котлин

billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS) {
    billingResult,
    purchaseList -> {
        // Process the result
    }
}

Ява

billingClient.queryPurchasesAsync(
    BillingClient.SkuType.SUBS,
    new PurchasesResponseListener() {
        public void onQueryPurchasesResponse(
                BillingResult billingResult,
                List<Purchase> purchases) {
            // process the result
        }
    }
);

После

Котлин

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder()
        .setProductType(BillingClient.ProductType.SUBS)
        .build()
) { billingResult, purchaseList ->
    // Process the result
}

Ява

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder().setProductType(ProductType.SUBS).build(),
    new PurchasesResponseListener() {
        public void onQueryPurchasesResponse(
                BillingResult billingResult,
                List<Purchase> purchases) {
            // Process the result
        }
    }
);

Действия по управлению покупками в приложении и ожидающими транзакциями не изменились.

Управляйте статусом покупки подписки с помощью нового API в вашем серверном интерфейсе.

Вам следует перенести компонент управления статусом покупки подписок в свою серверную часть, чтобы быть готовым обрабатывать покупки новых продуктов, созданных на предыдущих шагах. Ваш текущий компонент управления статусом покупки подписок должен работать как обычно для преобразованных продуктов подписки, которые вы определили до запуска в мае 2022 года, и его должно быть достаточно для управления покупками обратно совместимых предложений, но он не поддерживает ни одну из новых функций.

Вам необходимо внедрить новый API покупок подписок для модуля управления статусом покупки подписок, который проверяет статус покупки и управляет правами на подписку Play Billing в вашем серверном интерфейсе. Старая версия API не возвращает всю необходимую информацию для управления покупками на новой платформе. Подробную информацию об изменениях по сравнению с предыдущими версиями см. в руководстве по новым функциям подписки за май 2022 г.

Обычно вы вызываете API покупок подписки каждый раз, когда получаете уведомление разработчика SubscriptionNotification в режиме реального времени , чтобы получить самую свежую информацию о статусе подписки. Вам необходимо заменить вызовы purchases.subscriptions.get новой версией API покупок подписок, purchases.subscriptionsv2.get . Появился новый ресурс под названием SubscriptionPurchaseV2 , который предоставляет достаточно информации для управления правами на покупку подписок в новой модели.

Эта новая конечная точка возвращает статус всех ваших продуктов по подписке и всех ваших покупок, независимо от версии приложения, в котором они были проданы, и от того, когда продукт был определен (до или после выпуска в мае 2022 г.), поэтому после миграции вам потребуется только эту версию модуля управления статусом покупки подписки.

Изменение покупок подписки пользователя

В Библиотеке выставления счетов Play 5 и более ранних версиях ProrationMode использовался для применения изменений к покупкам подписки пользователя, таких как повышение или понижение версии. Это устарело и заменено на ReplacementMode в версии 6.

Обрабатывать изменения цен на подписку

Ранее устаревший API launchPriceConfirmationFlow был удален из Play Billing Library 6. Альтернативы можно найти в руководстве по изменению цен .

Обработка ошибок библиотеки выставления счетов Play

В Play Billing Library 6 добавлен новый код NETWORK_ERROR , указывающий на проблемы с сетевым подключением между устройством пользователя и системой Google Play. Также произошли изменения в кодах SERVICE_TIMEOUT и SERVICE_UNAVAILABLE . Дополнительные сведения см. в разделе Обработка кодов ответов BillingResult .

Обработка ожидающих транзакций

Начиная с версии 6.0.0, библиотека платежей Play не создает идентификатор заказа для ожидающих покупок. Для этих покупок идентификатор заказа заполняется после перевода покупки в состояние PURCHASED . Убедитесь, что ваша интеграция ожидает идентификатор заказа только после полного завершения транзакции. Вы по-прежнему можете использовать токен покупки для своих записей. Дополнительную информацию об обработке ожидающих покупок см. в руководстве по интеграции Play Billing Library и в руководстве по управлению жизненным циклом покупок .