1. 简介
在此 Codelab 中,您将重点学习如何创建一次性商品、定义其购买选项、设置特定于地区的价格,以及测试一次性商品的购买流程。
观众群
此 Codelab 适用于想要使用 Play 管理中心管理一次性商品清单的 Android 应用开发者。
学习内容…
- 一次性商品对象模型。
- 如何浏览和使用 Google Play 管理中心 来管理一次性商品清单。
- 如何免费将一次性商品详情翻译成多种语言。
- 如何为一次性商品配置地区性库存状况和价格 。
- 如何使用 Play 结算库 API 查询一次性商品详情。
- 如何使用 Play Billing Lab 测试一次性商品。
所需条件…
- 拥有开发者账号,并且能够访问 Google Play 管理中心。如果您没有开发者账号,则需要创建一个账号。
- 此 Codelab 的示例应用,您可以从 GitHub 下载。
- Android Studio。
2. 一次性商品简介
一次性商品对象模型可让您更灵活地销售商品,并降低管理商品的复杂性。对象模型会将销售内容与销售方式分开,支持为同一项使用权设定多个价位并以不同的方式向用户营销。对象模型具有三个层次的层级结构:
- 一次性商品:商品对象,用于定义用户购买的商品。
- 购买选项:购买选项定义了向用户授予使用权的途径、商品价格以及供应商品的区域。单款产品可设有多个购买选项,在不同区域提供不同价格。
- 优惠:优惠会影响所关联购买选项对应的价格,可用于构建折扣或预订模型。单个购买选项可设有多项优惠。
下图展示了一次性商品对象模型。
图 1:一次性对象模型。
如需了解详情,请参阅一次性商品概览。
3. 构建示例应用
此 Codelab 使用示例 Android 应用向您展示如何管理一次性商品。该示例应用旨在成为一个功能齐全的 Android 应用,其中包含完整的源代码,展示了以下方面:
- 将应用与 PBL 集成
- 提取一次性商品和相关购买选项
- 运行采用地区定价的购买流程
以下演示视频展示了示例应用在部署和运行后的外观和行为。
如果您已熟悉一次性商品和 Play 结算库 (PBL),则可以下载示例应用并试用。
前提条件
在构建和部署示例应用之前,请执行以下操作:
- 创建 Google Play 管理中心开发者账号。如果您已有开发者账号,请跳过此步骤。
- 在 Play 管理中心内创建新应用。创建应用时,您可以为示例应用指定任何应用名称。
- 安装 Android Studio。
构建
此构建步骤的目标是生成示例应用的已签名 Android App Bundle 文件。
如需生成 Android App Bundle,请执行以下步骤:
- 从 GitHub 下载示例应用。
- 构建示例应用。在构建之前,请更改示例应用的软件包名称,然后进行构建。如果您的 Play 管理中心内有其他应用的软件包,请确保为示例应用提供的软件包名称是唯一的。
注意:构建示例应用只会创建一个 APK 文件,您可以使用该文件进行本地测试。但是,运行该应用不会提取商品和价格,因为这些商品尚未在 Play 管理中心内配置。 - 生成已签名的 Android App Bundle。
下一步是将 Android App Bundle 上传到 Google Play 管理中心。
4. 在 Play 管理中心内创建一次性商品
如需在 Google Play 管理中心内创建一次性商品,您需要在 Play 管理中心内拥有一个应用。在 Play 管理中心内创建一个应用,然后上传之前创建的已签名 App Bundle。
创建应用
如需创建应用,请执行以下操作:
- 使用您的开发者账号登录 Google Play 管理中心。
- 点击创建应用 。系统随即会打开创建应用 页面。
- 输入应用名称、选择默认语言,以及其他与应用相关的详细信息。
- 点击创建应用 。系统随即会在 Google Play 管理中心内创建一个应用。
现在,您可以上传示例应用的已签名 App Bundle 了。
上传已签名的 App Bundle
- 将已签名的 App Bundle 上传到 Google Play 管理中心内部测试轨道。只有在上传后,您才能在 Play 管理中心内配置与创收相关的功能。
- 依次点击测试和发布 > 测试 > 内部版本 > 创建新版本 。
- 输入版本名称并上传已签名的 APK 文件。
- 点击下一步 ,然后点击保存并发布 。
现在,您可以创建一次性商品了。
创建一次性商品
如需创建一次性商品,请执行以下操作:
- 在 Google Play 管理中心内,从左侧导航菜单中依次前往 借助 Play 变现 > 商品 > 一次性商品。
- 点击创建一次性商品 。
- 输入以下商品详情:
- 商品 ID :输入唯一 ID。例如,
trending_movie_1。 - (可选)标签 :添加相关标签。
- 名称 :输入商品名称。例如,
Product Movie。 - 说明 :输入商品说明。例如,
Product Description。
默认情况下,商品名称和说明采用英语(美国)- en-US 。您还可以手动输入其他语言的名称和说明。如需输入详细信息,请点击管理翻译,选择您要输入译文的语言,然后点击应用。下图展示了管理翻译 选项:
图 2:管理翻译。
您选择的语言将显示在语言下拉列表中。选择每种语言,然后输入所选语言对应的名称和说明。您还可以免费自动翻译商品名称和说明。如需了解详情,请参阅此 Codelab 中的翻译一次性商品部分。
注意:出于此 Codelab 的目的,您可以跳过配置图标字段和税务、合规性和计划部分。 - 商品 ID :输入唯一 ID。例如,
- 点击下一步 。
- 添加购买选项并配置其地区供应情况。一次性商品需要至少一个购买选项,该选项定义了授予使用权的途径、价格和地区供应情况。 在此 Codelab 中,我们将为产品添加标准的 购买 选项。
在 购买选项 部分中,输入以下详细信息:- 购买选项 ID :输入唯一 ID。例如,
buy-movie。 - 购买类型 :选择购买 。
- (可选)标签 :添加特定于此购买选项的标签。
- (可选)点击高级选项 可配置高级选项。出于此 Codelab 的目的,您可以跳过高级选项配置。
- 购买选项 ID :输入唯一 ID。例如,
- 接下来,您必须为购买选项配置地区供应情况和价格。在地区供应情况中,您将指定商品的供应地区,包括尚未发布应用的地区。默认情况下,购买选项在所有地区均供应。
在供应情况和定价 部分中,依次点击修改供应情况和访问权限 > 设为不供应。请注意,默认情况下,所有地区都设置为供应 。- 选择除
France、Spain和United States之外的所有国家/地区,然后点击设为不供应 。 - 从所有地区 下拉列表中,选择可供应的国家/地区 。系统随即只会显示您在上一步中选择的国家/地区。
- 对于每个可供应的国家/地区,点击价格 列中的“修改”图标。系统随即会显示一个对话框,供您修改价格。输入并保存以下价格:
- 对于
France,输入 10 欧元 - 对于
Spain,输入 8 欧元 - 对于
United States,输入 13 美元
- 对于
- 选择除
- 点击 Activate (激活)。这样,您的一次性商品便会通过购买 购买选项提供。
注意:地区价格币种会根据用户的 Google Play 国家/地区设置显示。例如,如果用户的 Play 国家/地区设置为法国,则一次性商品价格以欧元显示。
一次性商品创建视频
以下视频展示了之前介绍的一次性商品创建步骤。
添加租借购买选项
现在,为之前创建的一次性商品添加租借购买选项。
- 在 Google Play 管理中心内,从左侧导航菜单中依次前往 借助 Play 变现 > 商品 > 一次性商品。
- 点击您在上一步中创建的商品 ID 为
trending_movie_1的商品对应的向右箭头。 - 点击添加购买选项 。
- 在购买选项 部分中,输入以下详细信息:
- 购买选项 ID :输入
rent-movie。 - 购买类型 :选择租借 。
- 租期 :选择 48 小时。
- 租借启用时限 :选择 24 小时。
- (可选)标签 :添加特定于此购买选项的标签。
- (可选)点击高级选项 可配置高级选项。出于此 Codelab 的目的,您可以跳过高级选项配置。
- 购买选项 ID :输入
- 接下来,与购买购买选项类似,为租借购买选项配置地区供应情况。请参阅上一部分中的第 6 步和第 7 步。设置地区价格时,请为租借设置不同的价格。例如:
France- 5 欧元Spain- 4 欧元United States- 7 美元。
5. 翻译一次性商品详情
您可以使用 Google Play 管理中心内提供的机器翻译功能,免费翻译商品名称和说明。
如需翻译标题和说明,请执行以下操作:
- 在 Google Play 管理中心内,从左侧导航菜单中依次前往 吸引用户 > 翻译 > 商品详情和应用内商品。
- 点击创建订单 。
- 选择免费机器翻译 选项,然后点击下一步。
- 从翻译成 语言中,选择法语 - fr-FR 和西班牙语 - es-ES ,然后点击下一步 。
- 选择一次性商品和订阅,然后点击翻译并查看译文。系统随即会显示免责声明横幅。确认免责声明。
- 您现在将看到翻译后的语言列表。点击某种语言对应的查看并应用 。查看文本,然后点击应用所有翻译 。针对您选择翻译的所有语言重复此步骤。
翻译后,您可以在 Play 管理中心内修改译文。如需修改译文,请执行以下操作:
- 打开一次性商品 > [您的一次性商品] > 修改一次性商品 > 修改一次性商品详情 页面。
- 从语言下拉列表中选择所需语言。系统随即会显示所选语言的文本。下图展示了如何选择语言来修改译文:
图 3:修改译文。 - 根据需要修改文本,然后点击保存更改 。
用户看到的译文取决于用户手机的语言偏好设置。例如,如果用户手机的语言设置为法语,则一次性商品标题和说明以法语显示。以下示例图片展示了译文在不同语言中的显示方式和显示位置。
图 4:应用中的译文。
翻译配置视频
以下视频展示了之前介绍的翻译配置步骤。
6. 与 PBL 集成
如需将应用与 Play 结算库 (PBL) 集成,请执行以下步骤:
- 将 Play 结算库依赖项添加到示例应用。
dependencies { val billing_version = "8.0.0" implementation("com.android.billingclient:billing-ktx:$billing_version") } - 初始化 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(); } - 连接到 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"); } }); } - 提取一次性商品详情。将应用与 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 来唯一标识该选项。 - 提取租借和购买优惠的优惠令牌。您需要优惠令牌才能在第 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); } } - 启动结算流程。
/** * 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 集成。
您将学习如何测试价格本地化和供应情况,其中应用仅在某些区域提供,并且每个区域的价格不同。
前提条件
- 在 Google Play 管理中心内添加许可测试人员,然后为内部测试启用许可测试人员。
- 在手机或模拟器上下载并安装 Play Billing Lab 应用。
- 在手机或模拟器上运行之前创建的示例应用。
测试购买选项的地区定价
如需测试购买选项的地区定价,请执行以下操作:
- 打开 Play Billing Lab 应用,然后以许可测试人员身份登录。
- 在配置设置 中,点击修改 ,选择国家/地区
France,然后点击应用 。在这里,我们选择 Play 国家/地区,该国家/地区决定了应用中显示的币种。 - 关闭并重新打开示例应用。现在,它应该以欧元显示
France的购买和租借币种。
如需针对其他国家/地区进行测试,请在第 2 步中选择 Spain,然后执行第 3 步。
Play Billing Lab 测试视频
以下视频展示了使用示例应用进行地区价格测试的步骤。
8. 后续步骤
- 了解如何最大限度提高 Play 结算集成效果。
- 了解如何分析商品购买流失情况。
- 请务必遵循最佳实践,在用户开始购买这些商品后,在安全后端验证和处理购买交易。
参考文档
9. 恭喜!
恭喜!您已成功浏览 Google Play 管理中心,创建了新的一次性商品,配置了购买选项,并使用 Play Billing Lab 测试了购买流程。现在,您对 Google Play 灵活的一次性购买商品清单有了更深入的了解。
调查问卷
我们非常重视您对此 Codelab 的反馈。请考虑抽出几分钟时间填写我们的调查问卷。