提醒:从 2022 年 8 月 2 日起,所有新应用都必须使用结算库版本 4 或更高版本。自 2022 年 11 月 1 日起,现有应用的所有新版本都必须使用结算库版本 4 或更高版本。了解详情

Google Play 结算库从版本 4 迁移到版本 5 的迁移指南

本主题将介绍如何从 Google Play 结算库版本 4 迁移到 Google Play 结算库版本 5,以及如何使用新的订阅功能。

概览

Google Play 结算库版本 5 引入了订阅基础方案和订阅优惠。与以前的版本相比,这些功能拓展了订阅销售方式,并降低了集成复杂性。

使用 Play 管理中心或 Play Developer API,您可以配置包含多个基础方案的单个订阅,每个基础方案可提供多项优惠。您可以为订阅优惠设置灵活的定价模式和资格条件。您可以使用各种各样的自动续订服务和预付费方案,在整个订阅生命周期中创建优惠。如需了解详情,请参阅集成指南

迁移步骤

更新 Google Play 结算库

使用应用 build.gradle 文件更新后的版本替换现有的 Play 结算库依赖项。

dependencies {
    def billingVersion = "5.0.0"

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

即使您没有修改任何方法调用,您的项目应该也会立即构建,因为我们已在 Play 结算库版本 5 中实现了向后兼容性。不过,SKU 的概念被视为已废弃。

初始化结算客户端并与 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)

billingClient.querySkuDetailsAsync(params.build()) {
    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);

billingClient.querySkuDetailsAsync(params.build(),
    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)

billingClient.queryProductDetailsAsync(params.build()) {
    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 结算库版本不支持新对象(订阅、基础方案、优惠等),因此新系统将每个订阅 SKU 转换为单个向后兼容的基础方案和优惠。可用的一次性购买商品也改为使用 ProductDetails 对象。您可以使用 getOneTimePurchaseOfferDetails() 方法访问一次性购买商品的优惠详情。

启动优惠购买流程

启动优惠的购买流程与启动 SKU 的流程非常相似。如需使用版本 5 发起购买请求,请执行以下操作:

  • 不要将 SkuDetails 用于 BillingFlowParams,请改为使用 ProductDetailsParams
  • 您可以使用 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 = ...;
// Retrieve a value for "productDetails" by calling queryProductDetailsAsync()
// Get the offerToken of the selected offer
val offerToken = productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken

val productDetailsParamsList =
    listOf(
        BillingFlowParams.ProductDetailsParams.newBuilder()
            .setProductDetails(productDetails)
            .setOfferToken(offerToken)
            .build()
    )
val billingFlowParams =
    BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        .build()

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

Java

// Retrieve a value for "productDetails" by calling queryProductDetailsAsync()
// Get the offerToken of the selected offer
String offerToken = productDetails
                     .getSubscriptionOfferDetails()
                     .get(selectedOfferIndex)
                     .getOfferToken();
// Set the parameters for the offer that will be presented
// in the billing flow creating separate productDetailsParamsList variable
ImmutableList<ProductDetailsParams> productDetailsParamsList =
        ImmutableList.of(
                 ProductDetailsParams.newBuilder()
                     .setProductDetails(productDetails)
                     .setOfferToken(offerToken)
                     .build()
        );

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

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

处理购买交易

使用 Google Play 结算库版本 5 处理购买交易的操作与以前的版本类似。

如需拉取用户拥有的所有有效购买交易并查询新购买交易,请执行以下操作:

  • 请传递一个包含 BillingClient.ProductType 值的 QueryPurchasesParams 对象,而不要向 queryPurchasesAsync() 传递 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&lt;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
        }
    }
);

用于管理应用外购买待处理交易的步骤没有变化。

管理订阅状态

如果您的后端中具有用于检查状态和管理订阅购买交易的订阅状态管理组件,那么您需要使用 Subscription Purchases API。如需详细了解与先前版本相比的变化,请参阅 2022 年 5 月新订阅功能指南