本主题介绍了如何从 Google Play Billing Library 4 或 5 迁移到 Google Play Billing Library 6,以及如何使用新的订阅功能。
有关 6.0.0 版中的所有更改,请参阅版本说明。
概览
Google Play Billing Library 6 以版本 5 中引入的新订阅功能为基础,并增加了一些改进。这些功能允许你以更多方式销售订阅,从而减少运营成本,无需创建和管理不断增加的 SKU 数量。
如需详细了解 Play Billing Library 5 中引入的新功能,请参阅 Play 管理中心近期订阅变动。
向后兼容的 Play Billing Library 升级
作为 Play Billing Library 5 和新订阅平台于 2022 年 5 月发布的一部分,所有现有订阅产品已自动转换为这种新范例。这意味着你无需进行任何订阅产品配置更改即可拥有与新版 Play Billing Library 兼容的产品目录。如需详细了解订阅 SKU 如何转换为向后兼容的订阅,请参阅 Play 管理中心帮助文章中的“使用旧版订阅”部分。
旧版应用仍可正常运行
如果你拥有向后兼容的订阅目录,你的应用所有现有版本都应仍能正常运行,以支持这些产品。一次性产品购买在旧版本中也应继续正常运行。
使用已废弃方法(例如 querySkuDetailsAsync()
)的应用版本将无法销售任何不向后兼容的基本方案或优惠。你可以在相关的 Play 管理中心帮助文章中阅读有关向后兼容优惠的信息。
升级到 Play Billing Library 5 或 6
Play Billing Library 5 和 6 包含已废弃方法 querySkuDetailsAsync
和 BillingFlowParams.Builder.setSkuDetails
,后者将 SkuDetails
作为结算流程参数。这意味着你可以通过规划不同的迁移阶段逐步迁移到 Play Billing Library 6。
作为迁移的第一步,你可以仅 更新库版本,保持你的产品目录和后端不变,并在应用仍使用已废弃方法的情况下测试应用。如果你不使用 queryPurchases
、launchPriceChangeFlow
或 setVrPurchaseFlow
,它应该仍能正常运行。之后,你可以迭代以完全采用 2022 年 5 月发布的新订阅功能。
如果你之前已通过 Google Play Billing Library 5 迁移采用了这些功能,则可以直接跳到标有 更新 Google Play Billing Library 和 更改用户的订阅购买交易 的部分。如果你从较早的版本开始或尚未完全采用新功能,则可以阅读以下完整迁移步骤,了解如何采用这些功能。
完整迁移步骤
在后端产品目录中创建新的订阅
使用 Play 管理中心或 Play Developer API,你现在可以配置具有多个基本方案的单个订阅,每个基本方案又具有多个优惠。订阅优惠具有灵活的定价模式和资格选项。你可以使用各种自动续订和预付费方案,在整个订阅生命周期中创建优惠。
我们建议你在迁移应用之前,先按照新订阅平台中的实体结构为 Play Billing Library 6 集成创建新产品。你可以将旧目录中表示相同授权权益的重复产品合并到单个订阅下,并使用基本方案和优惠配置来表示你希望提供的所有选项。有关此建议的更多信息,请参阅 Play 管理中心帮助文章中的“使用旧版订阅”部分。
我们建议你在 2022 年 5 月发布后不要修改已转换的订阅产品;你应该保持它们原样,以与使用已废弃方法(例如 querySkuDetailsAsync()
)的应用版本一起销售,而无需引入可能影响这些旧版本构建的更改。
转换过程将 2022 年 5 月之前你的产品目录中的订阅产品设为只读,以避免意外更改可能导致现有集成出现问题。可以对这些订阅进行更改,但这可能会影响你的前端和后端集成。
在前端,使用
querySkuDetailsAsync()
获取订阅产品详细信息的应用版本只能销售向后兼容的基本方案和优惠,并且只能有一种向后兼容的基本方案和优惠组合,因此如果你向已转换的订阅添加新的方案或优惠,这些新增的基本方案或优惠将无法在这些旧版本的应用上销售。在后端,如果你在 Play 管理中心界面中编辑已转换的订阅,将无法使用
inappproducts
端点对其进行管理,即使你之前调用该端点用于此目的。你还应迁移到新的订阅购买状态端点 (purchases.subscriptionsv2.get
) 来管理这些订阅的购买交易,因为旧的购买状态端点 (purchases.subscriptions.get
) 仅返回处理向后兼容的基本方案和优惠购买所需的数据。如需了解详细信息,请阅读 管理订阅购买状态部分。
使用新 API 管理后端订阅目录
如果你使用 Google Play Developer API 自动管理订阅产品目录,则需要使用新的订阅产品定义端点来创建和管理订阅、基本方案和优惠。阅读2022 年 5 月订阅功能指南,了解有关此版本产品目录 API 更改的更多信息。
要迁移用于 Google Play 结算订阅的自动化产品目录管理模块,请将 inappproducts
API 替换为新的 Subscription Publishing API 来管理和发布你的订阅目录。有三个新端点:
Monetization.subscriptions
:用于管理订阅产品。Monetization.basePlans
:用于管理订阅的基本方案。Monetization.offers
:用于管理基本方案的优惠。
这些新端点具备利用目录中所有新功能的必要功能:基本方案和优惠标记、区域定位、预付费方案等等。
你仍应使用 inappproducts
API 来管理一次性购买产品的应用内产品目录。
使用已废弃方法(例如 querySkuDetailsAsync()
)的应用版本将无法销售任何不向后兼容的基本方案或优惠。你可以在此处阅读有关向后兼容优惠的信息。
更新 Google Play Billing Library
创建新的订阅产品目录后,你可以将应用迁移到 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 的概念被认为是已废弃的,但为了使应用移植过程更简单、更循序渐进,它仍然存在。
初始化 Billing Client 并建立与 Google Play 的连接
从 Android 应用发起购买请求的第一步保持不变:
显示可购买的产品
获取用户有资格购买的所有优惠:
- 将
SkuDetailsParams
替换为QueryProductDetailsParams
- 将
BillingClient.querySkuDetailsAsync()
调用切换为使用BillingClient.queryProductDetailsAsync()
请注意,查询结果现在是 ProductDetails
而不是 SkuDetails
。每个 ProductDetails
项包含有关产品的信息(ID、标题、类型等)。对于订阅产品,ProductDetails
包含一个 List<ProductDetails.SubscriptionOfferDetails>
,即订阅优惠详细信息的列表。对于一次性购买产品,ProductDetails
包含一个 ProductDetails.OneTimePurchaseOfferDetails
。这些信息可用于决定向用户显示哪些优惠。
以下示例展示了进行这些更改前后你的应用可能的样子:
之前
Kotlin
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 }
Java
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. } } );
之后
Kotlin
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 }
Java
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
项包含有关产品的信息(ID、标题、类型等)。主要区别在于,订阅产品现在还包含一个 List<ProductDetails.SubscriptionOfferDetails>
,其中包含用户可用的所有优惠。
由于旧版本的 Play Billing Library 不支持新对象(订阅、基本方案、优惠等),新系统会将每个订阅 SKU 转换为单个向后兼容的基本方案和优惠。可用的一次性购买产品也会移植到 ProductDetails
对象。可以使用 getOneTimePurchaseOfferDetails()
方法访问一次性购买产品的优惠详细信息。
极少数情况下,某些设备可能无法支持 ProductDetails
和 queryProductDetailsAsync()
,这通常是由于 Google Play 服务版本过旧所致。为确保对此情景的良好支持,请在调用 queryProductDetailsAsync
之前,针对 PRODUCT_DETAILS
功能调用 isFeatureSupported()
。如果响应为 OK
,则表示设备支持该功能,你可以继续调用 queryProductDetailsAsync()
。如果响应为 FEATURE_NOT_SUPPORTED
,则可以转而使用 querySkuDetailsAsync()
请求可用的向后兼容产品列表。要详细了解如何使用向后兼容功能,请参阅2022 年 5 月订阅功能指南。
启动优惠购买流程
启动优惠购买流程与启动 SKU 购买流程非常相似。要使用版本 6 发起购买请求,请执行以下操作:
- 对于
BillingFlowParams
,使用ProductDetailsParams
代替SkuDetails
。 - 优惠详细信息(例如优惠 ID、基本方案 ID 等)可以使用
SubscriptionOfferDetails
对象获取。
要购买用户选择的优惠所对应的产品,请获取所选优惠的 offerToken
并将其传入 ProductDetailsParams
对象。
创建 BillingFlowParams
对象后,使用 BillingClient
启动结算流程的方式保持不变。
以下示例展示了进行这些更改前后你的应用可能的样子:
之前
Kotlin
// 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)
Java
// 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)
之后
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) // 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)
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) // 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 处理购买交易与旧版本类似。
要拉取用户拥有的所有有效购买交易并查询新购买交易,请执行以下操作:
- 调用
queryPurchasesAsync()
时,传递包含BillingClient.ProductType
值的QueryPurchasesParams
对象,而不是传递BillingClient.SkuType
值。
以下示例展示了进行这些更改前后你的应用可能的样子:
之前
Kotlin
billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS) { billingResult, purchaseList -> { // Process the result } }
Java
billingClient.queryPurchasesAsync( BillingClient.SkuType.SUBS, new PurchasesResponseListener() { public void onQueryPurchasesResponse( BillingResult billingResult, List<Purchase> purchases) { // process the result } } );
之后
Kotlin
billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder() .setProductType(BillingClient.ProductType.SUBS) .build() ) { billingResult, purchaseList -> // Process the result }
Java
billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder().setProductType(ProductType.SUBS).build(), new PurchasesResponseListener() { public void onQueryPurchasesResponse( BillingResult billingResult, List<Purchase> purchases) { // Process the result } } );
使用后端的新 API 管理订阅购买状态
你应迁移后端中的订阅购买状态管理组件,以便能够处理之前步骤中创建的新产品的购买交易。对于你在 2022 年 5 月发布之前定义的已转换订阅产品,你当前的订阅购买状态管理组件应能正常运行,并且足以管理向后兼容优惠的购买交易,但它不支持任何新功能。
你需要为你的订阅购买状态管理模块实现新的 Subscription Purchases API,该 API 用于检查购买状态并在后端管理 Play 结算订阅授权。该 API 的旧版本不返回在新平台中管理购买交易所需的所有详细信息。有关与旧版本相比的更改的详细信息,请参阅2022 年 5 月新订阅功能指南。
通常,你会在每次收到 SubscriptionNotification
实时开发者通知时调用 Subscription Purchases API,以获取订阅状态的最新信息。你需要将对 purchases.subscriptions.get
的调用替换为新版 Subscription Purchases API,即 purchases.subscriptionsv2.get
。有一个名为 SubscriptionPurchaseV2
的新资源,它提供了足够的信息来管理新模型中订阅的购买授权。
这个新端点会返回所有订阅产品和所有购买交易的状态,无论销售它们的 App 版本以及产品定义的时间(在 2022 年 5 月发布之前或之后),因此迁移后,你只需要此版本的订阅购买状态管理模块。
更改用户的订阅购买交易
在 Play Billing Library 5 及更早版本中,ProrationMode
用于应用对用户订阅购买交易的更改,例如升级或降级。这已在版本 6 中废弃,并由 ReplacementMode
取代。
处理订阅价格变动
之前已废弃的 launchPriceConfirmationFlow
API 已在 Play Billing Library 6 中移除。有关替代方案,请参阅价格变动指南。
处理 Play Billing Library 错误
在 Play Billing Library 6 中,添加了一个新的 NETWORK_ERROR
代码,以指示用户设备与 Google Play 系统之间的网络连接问题。代码 SERVICE_TIMEOUT
和 SERVICE_UNAVAILABLE
也有更改。有关更多信息,请参阅处理 BillingResult 响应代码。
处理待处理交易
从版本 6.0.0 开始,Play Billing Library 不会为待处理购买交易创建订单 ID。对于这些购买交易,订单 ID 在购买进入 PURCHASED
状态后才会填充。请确保你的集成只在交易完全完成后才期望订单 ID。你仍然可以使用购买令牌进行记录。有关处理待处理购买交易的更多信息,请参阅 Play Billing Library 集成指南和购买生命周期管理指南。