利用地区性商品价格开拓新市场

1. 简介

在此 Codelab 中,您将重点学习如何创建一次性商品、定义其购买选项、设置特定于地区的价格,以及测试一次性商品的购买流程。

观众群

此 Codelab 适用于想要使用 Play 管理中心管理一次性商品清单的 Android 应用开发者。

学习内容…

  • 一次性商品对象模型。
  • 如何浏览和使用 Google Play 管理中心 来管理一次性商品清单。
  • 如何免费将一次性商品详情翻译成多种语言。
  • 如何为一次性商品配置地区性库存状况和价格
  • 如何使用 Play 结算库 API 查询一次性商品详情。
  • 如何使用 Play Billing Lab 测试一次性商品。

所需条件…

2. 一次性商品简介

一次性商品对象模型可让您更灵活地销售商品,并降低管理商品的复杂性。对象模型会将销售内容与销售方式分开,支持为同一项使用权设定多个价位并以不同的方式向用户营销。对象模型具有三个层次的层级结构:

  • 一次性商品:商品对象,用于定义用户购买的商品。
  • 购买选项:购买选项定义了向用户授予使用权的途径、商品价格以及供应商品的区域。单款产品可设有多个购买选项,在不同区域提供不同价格。
  • 优惠:优惠会影响所关联购买选项对应的价格,可用于构建折扣或预订模型。单个购买选项可设有多项优惠。

下图展示了一次性商品对象模型。

codelab-otp-model.png 图 1:一次性对象模型。

如需了解详情,请参阅一次性商品概览

3. 构建示例应用

此 Codelab 使用示例 Android 应用向您展示如何管理一次性商品。该示例应用旨在成为一个功能齐全的 Android 应用,其中包含完整的源代码,展示了以下方面:

  • 将应用与 PBL 集成
  • 提取一次性商品和相关购买选项
  • 运行采用地区定价的购买流程

以下演示视频展示了示例应用在部署和运行后的外观和行为。

如果您已熟悉一次性商品和 Play 结算库 (PBL),则可以下载示例应用并试用。

前提条件

在构建和部署示例应用之前,请执行以下操作:

构建

此构建步骤的目标是生成示例应用的已签名 Android App Bundle 文件。

如需生成 Android App Bundle,请执行以下步骤:

  1. 从 GitHub 下载示例应用
  2. 构建示例应用。在构建之前,请更改示例应用的软件包名称,然后进行构建。如果您的 Play 管理中心内有其他应用的软件包,请确保为示例应用提供的软件包名称是唯一的。

    注意:构建示例应用只会创建一个 APK 文件,您可以使用该文件进行本地测试。但是,运行该应用不会提取商品和价格,因为这些商品尚未在 Play 管理中心内配置。
  3. 生成已签名的 Android App Bundle。
    1. 生成上传密钥和密钥库
    2. 使用上传密钥为应用签名
    3. 配置 Play 应用签名功能

下一步是将 Android App Bundle 上传到 Google Play 管理中心。

4. 在 Play 管理中心内创建一次性商品

如需在 Google Play 管理中心内创建一次性商品,您需要在 Play 管理中心内拥有一个应用。在 Play 管理中心内创建一个应用,然后上传之前创建的已签名 App Bundle。

创建应用

如需创建应用,请执行以下操作:

  1. 使用您的开发者账号登录 Google Play 管理中心
  2. 点击创建应用 。系统随即会打开创建应用 页面。
  3. 输入应用名称、选择默认语言,以及其他与应用相关的详细信息。
  4. 点击创建应用 。系统随即会在 Google Play 管理中心内创建一个应用。

现在,您可以上传示例应用的已签名 App Bundle 了。

上传已签名的 App Bundle

  1. 将已签名的 App Bundle 上传到 Google Play 管理中心内部测试轨道。只有在上传后,您才能在 Play 管理中心内配置与创收相关的功能。
  2. 依次点击测试和发布 > 测试 > 内部版本 > 创建新版本
  3. 输入版本名称并上传已签名的 APK 文件。
  4. 点击下一步 ,然后点击保存并发布

现在,您可以创建一次性商品了。

创建一次性商品

如需创建一次性商品,请执行以下操作:

  1. Google Play 管理中心内,从左侧导航菜单中依次前往 借助 Play 变现 > 商品 > 一次性商品
  2. 点击创建一次性商品
  3. 输入以下商品详情:
    • 商品 ID :输入唯一 ID。例如,trending_movie_1
    • (可选)标签 :添加相关标签。
    • 名称 :输入商品名称。例如,Product Movie
    • 说明 :输入商品说明。例如,Product Description
    手动翻译商品名称和说明
    默认情况下,商品名称和说明采用英语(美国)- en-US 。您还可以手动输入其他语言的名称和说明。如需输入详细信息,请点击管理翻译,选择您要输入译文的语言,然后点击应用。下图展示了管理翻译 选项:manage-translations.png图 2:管理翻译。

    您选择的语言将显示在语言下拉列表中。选择每种语言,然后输入所选语言对应的名称和说明。您还可以免费自动翻译商品名称和说明。如需了解详情,请参阅此 Codelab 中的翻译一次性商品部分。

    注意:出于此 Codelab 的目的,您可以跳过配置图标字段和税务、合规性和计划部分。
  4. 点击下一步
  5. 添加购买选项并配置其地区供应情况。一次性商品需要至少一个购买选项,该选项定义了授予使用权的途径、价格和地区供应情况。 在此 Codelab 中,我们将为产品添加标准的 购买 选项。

    购买选项 部分中,输入以下详细信息:
    • 购买选项 ID :输入唯一 ID。例如,buy-movie
    • 购买类型 :选择购买
    • (可选)标签 :添加特定于此购买选项的标签。
    • (可选)点击高级选项 可配置高级选项。出于此 Codelab 的目的,您可以跳过高级选项配置。
  6. 接下来,您必须为购买选项配置地区供应情况和价格。在地区供应情况中,您将指定商品的供应地区,包括尚未发布应用的地区。默认情况下,购买选项在所有地区均供应。

    供应情况和定价 部分中,依次点击修改供应情况和访问权限 > 设为不供应。请注意,默认情况下,所有地区都设置为供应
    1. 选择除 FranceSpainUnited States 之外的所有国家/地区,然后点击设为不供应
    2. 所有地区 下拉列表中,选择可供应的国家/地区 。系统随即只会显示您在上一步中选择的国家/地区。
    3. 对于每个可供应的国家/地区,点击价格 列中的“修改”图标。系统随即会显示一个对话框,供您修改价格。输入并保存以下价格:
      • 对于 France,输入 10 欧元
      • 对于 Spain,输入 8 欧元
      • 对于 United States,输入 13 美元
  7. 点击 Activate (激活)。这样,您的一次性商品便会通过购买 购买选项提供。

注意:地区价格币种会根据用户的 Google Play 国家/地区设置显示。例如,如果用户的 Play 国家/地区设置为法国,则一次性商品价格以欧元显示。

一次性商品创建视频

以下视频展示了之前介绍的一次性商品创建步骤。

添加租借购买选项

现在,为之前创建的一次性商品添加租借购买选项。

  1. Google Play 管理中心内,从左侧导航菜单中依次前往 借助 Play 变现 > 商品 > 一次性商品
  2. 点击您在上一步中创建的商品 ID 为 trending_movie_1 的商品对应的向右箭头。
  3. 点击添加购买选项
  4. 购买选项 部分中,输入以下详细信息:
    • 购买选项 ID :输入 rent-movie
    • 购买类型 :选择租借
    • 租期 :选择 48 小时。
    • 租借启用时限 :选择 24 小时。
    • (可选)标签 :添加特定于此购买选项的标签。
    • (可选)点击高级选项 可配置高级选项。出于此 Codelab 的目的,您可以跳过高级选项配置。
  5. 接下来,与购买购买选项类似,为租借购买选项配置地区供应情况。请参阅上一部分中的第 6 步和第 7 步。设置地区价格时,请为租借设置不同的价格。例如:
    • France - 5 欧元
    • Spain - 4 欧元
    • United States - 7 美元。

5. 翻译一次性商品详情

您可以使用 Google Play 管理中心内提供的机器翻译功能,免费翻译商品名称和说明。

如需翻译标题和说明,请执行以下操作:

  1. Google Play 管理中心内,从左侧导航菜单中依次前往 吸引用户 > 翻译 > 商品详情和应用内商品
  2. 点击创建订单
  3. 选择免费机器翻译 选项,然后点击下一步
  4. 翻译成 语言中,选择法语 - fr-FR西班牙语 - es-ES ,然后点击下一步
  5. 选择一次性商品和订阅,然后点击翻译并查看译文。系统随即会显示免责声明横幅。确认免责声明。
  6. 您现在将看到翻译后的语言列表。点击某种语言对应的查看并应用 。查看文本,然后点击应用所有翻译 。针对您选择翻译的所有语言重复此步骤。

翻译后,您可以在 Play 管理中心内修改译文。如需修改译文,请执行以下操作:

  1. 打开一次性商品 > [您的一次性商品] > 修改一次性商品 > 修改一次性商品详情 页面。
  2. 从语言下拉列表中选择所需语言。系统随即会显示所选语言的文本。下图展示了如何选择语言来修改译文:

    edit-translations.png 图 3:修改译文。
  3. 根据需要修改文本,然后点击保存更改

用户看到的译文取决于用户手机的语言偏好设置。例如,如果用户手机的语言设置为法语,则一次性商品标题和说明以法语显示。以下示例图片展示了译文在不同语言中的显示方式和显示位置。

post-translation.png图 4:应用中的译文。

翻译配置视频

以下视频展示了之前介绍的翻译配置步骤。

6. 与 PBL 集成

如需将应用与 Play 结算库 (PBL) 集成,请执行以下步骤:

  1. 将 Play 结算库依赖项添加到示例应用。
    dependencies {
    val billing_version = "8.0.0"
    
    implementation("com.android.billingclient:billing-ktx:$billing_version")
    }
    
  2. 初始化 BillingClient。BillingClient 是驻留在应用中并与 Play 结算库通信的客户端 SDK。以下代码段展示了如何初始化结算客户端。
    private BillingClient createBillingClient() {
    return BillingClient.newBuilder(activity)
        .enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build())
        // For one-time products, add a listener to process and acknowledge the purchases. This will notify
        // Google the purchase was processed.
        // For client-only apps, use billingClient.acknowledgePurchase().
        // If you have a secure backend, you must acknowledge purchases on your server using the
        // server-side API.
        // See https://developer.android.com/google/play/billing/security#acknowledge
        // In this sample snippet purchases aren't processed. You must
        // implement your business logic to process and acknowledge the purchases.
        .setListener((billingResult, purchases) -> {})
        .enableAutoServiceReconnection()
        .build();
     }
    
  3. 连接到 Google Play。以下代码段展示了如何连接到 Google Play。
    /**
    * Starts the billing connection with Google Play. This method should be called exactly once
    * before any other methods in this class.
    *
    * @param productList The list of products to query for after the connection is established.
    */
    public void startBillingConnection(List<Product> productList) {
        billingClient.startConnection(
            new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(BillingResult billingResult) {
                if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                Log.d(TAG, "Billing Client Connection Successful");
                queryProductDetails(productList);
                } else {
                Log.e(TAG, "Billing Client Connection Failed: " + billingResult.getDebugMessage());
                listener.onBillingSetupFailed(billingResult); // Propagate the error to the listener to show a message to the user.
                }
            }
    
            @Override
            public void onBillingServiceDisconnected() {
                Log.e(TAG, "Billing Client Connection Lost");
                listener.onBillingError("Billing Connection Lost");
            }
            });
    }
    
  4. 提取一次性商品详情。将应用与 PBL 集成后,您必须将一次性商品详情提取到应用中。以下代码段展示了如何在应用中提取一次性商品详情。
    private void queryProductDetails(List<Product> productList) {
        QueryProductDetailsParams queryProductDetailsParams =
            QueryProductDetailsParams.newBuilder().setProductList(productList).build();
    
        billingClient.queryProductDetailsAsync(
            queryProductDetailsParams,
            new ProductDetailsResponseListener() {
            @Override
            public void onProductDetailsResponse(
                BillingResult billingResult, QueryProductDetailsResult productDetailsResponse) {
                if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                List<ProductDetails> productDetailsList =
                    productDetailsResponse.getProductDetailsList();
                    listener.onProductDetailsResponse(productDetailsList);
                } else {
                Log.e(TAG, "QueryProductDetailsAsync Failed: " + billingResult.getDebugMessage());
                listener.onBillingError("Query Products Failed: " + billingResult.getResponseCode());
                }
            }
            });
    }
    
    ProductDetails 中提取一次性商品(在此示例中为 trending_movie_1)后,您会收到类似于以下内容的响应:
    {
        "productId": "trending_movie_1",
        "type": "inapp",
        "title": "Purrfect Mayhem: The Rewind Protocol (Movies All Day | Play Samples)",
        "name": "Purrfect Mayhem: The Rewind Protocol",
        "description": "Dr. Arid Thorne and a smart tiger named Yolo find a mysterious tape. It's a \"Rewind Protocol\" to fix time. A shadowy group, the Clockinator, hunts them to seize the tape's power.",
        "skuDetailsToken": "<---skuDetailsToken--->",
        "oneTimePurchaseOfferDetails": {},
        "oneTimePurchaseOfferDetailsList": [
            {
                "priceAmountMicros": 13000000,
                "priceCurrencyCode": "USD",
                "formattedPrice": "$13.00",
                "offerIdToken": "<---buy offerIdToken --->",
                "purchaseOptionId": "buy-option",
                "offerTags": [
                    "adventure",
                    "mystery"
                ]
            },
            {
                "priceAmountMicros": 7000000,
                "priceCurrencyCode": "USD",
                "formattedPrice": "$7.00",
                "offerIdToken": "<---rent offerIdToken--->",
                "purchaseOptionId": "rent-option",
                "offerTags": [
                    "adventure",
                    "mystery"
                ],
                "rentalDetails": {
                    "rentalPeriod": "P30D",
                    "rentalExpirationPeriod": "PT24H"
                }
            }
        ]
    }
    
    请注意,购买和租借购买选项在 oneTimePurchaseOfferDetailsList 中提供。此列表包含在 Play 管理中心内配置的 2 个购买选项(购买选项租借选项)。您可以通过每个购买选项的 offerIdToken 来唯一标识该选项。
  5. 提取租借和购买优惠的优惠令牌。您需要优惠令牌才能在第 6 步中启动结算流程。
    @Override
    public void onProductDetailsResponse(List<ProductDetails> productDetailsList) {
    
        if (productDetailsList != null && !productDetailsList.isEmpty()) {
    
            // Iterate over all details of the queried product in step 4.
            for (ProductDetails productDetails : productDetailsList) {
    
                // Get the list of all the offers associated with the product.
                List<ProductDetails.OneTimePurchaseOfferDetails> offerDetailsList =
                        productDetails.getOneTimePurchaseOfferDetailsList();
    
                // Iterate over the offer details
                for (ProductDetails.OneTimePurchaseOfferDetails offerDetails : offerDetailsList) {
    
                    // For a Rent purchase option, the
                    // offerDetails.getRentalDetails() method returns
                    // the rent information. If this information is present,
                    // the offer corresponds to a Rent purchsae option.
                    if (offerDetails.getRentalDetails() != null) {
                        rentFormattedPrice = offerDetails.getFormattedPrice();
    
                        // Get the offerIdToken for the Rent purchase option
                        rentOfferToken = offerDetails.getOfferToken();
                        rentMovieTags = offerDetails.getOfferTags();
                    }
                    // If the offerDetails.getRentalDetails() returns
                    // null, the offer corresponds to a Buy purchsae option.
                    else {
                        buyFormattedPrice = offerDetails.getFormattedPrice();
    
                        // Get the offerIdToken for the Buy purchase option
                        buyOfferToken = offerDetails.getOfferToken();
                        buyMovieTags = offerDetails.getOfferTags();
                    }
                }
                updateUIButtons();
                return;
    
            }
        } else {
            Log.e(TAG, "No product details found for " + productId);
        }
    }
    
  6. 启动结算流程。
    /**
     * Launches the billing flow for the product with the given offer token.
    *
    * @param activity The activity instance from which the billing flow will be launched.
    * @param productDetails The product details of the product to purchase.
    * @param offerToken The offer token of the product to purchase.
    * @return The result of the billing flow.
    */
    public void launchPurchase(Activity activity, ProductDetails productDetails, String offerToken) {
        ImmutableList<BillingFlowParams.ProductDetailsParams> productDetailsParamsList =
            ImmutableList.of(
                BillingFlowParams.ProductDetailsParams.newBuilder()
                    .setProductDetails(productDetails)
                    .setOfferToken(offerToken)
                    .build());
        BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(productDetailsParamsList)
            .build();
        billingClient.launchBillingFlow(activity, billingFlowParams);
    }
    

提示:您还可以设置实时开发者通知 (RTDN),以实施赢回营销活动和其他购买生命周期管理策略。如需了解如何设置 RTDN 以及如何通过准确的跟踪和使用权处理通知,建议您阅读最大限度提高 Play 结算服务集成效果 Codelab

7. 测试购买选项

在正式版应用中提供一次性商品之前,您可以使用许可测试人员和 Play Billing Lab 测试 PBL 集成。

您将学习如何测试价格本地化和供应情况,其中应用仅在某些区域提供,并且每个区域的价格不同。

前提条件

测试购买选项的地区定价

如需测试购买选项的地区定价,请执行以下操作:

  1. 打开 Play Billing Lab 应用,然后以许可测试人员身份登录。
  2. 配置设置 中,点击修改 ,选择国家/地区 France,然后点击应用 。在这里,我们选择 Play 国家/地区,该国家/地区决定了应用中显示的币种。
  3. 关闭并重新打开示例应用。现在,它应该以欧元显示 France 的购买和租借币种。

如需针对其他国家/地区进行测试,请在第 2 步中选择 Spain,然后执行第 3 步。

Play Billing Lab 测试视频

以下视频展示了使用示例应用进行地区价格测试的步骤。

8. 后续步骤

参考文档

9. 恭喜!

恭喜!您已成功浏览 Google Play 管理中心,创建了新的一次性商品,配置了购买选项,并使用 Play Billing Lab 测试了购买流程。现在,您对 Google Play 灵活的一次性购买商品清单有了更深入的了解。

调查问卷

我们非常重视您对此 Codelab 的反馈。请考虑抽出几分钟时间填写我们的调查问卷。