如果您的应用通过 Google Play 分发,并且您想销售数字商品或提供订阅服务,则必须使用 Google Play 结算服务。Google Play 结算服务提供用于管理目录、价格和订阅的工具、实用报告,以及由用户熟悉的 Play 商店提供支持的结账流程。
对于使用可信 Web 活动构建并通过 Google Play 商店分发的应用,您现在可以使用 Payment Request API 和 Digital Goods API 与 Google Play 结算系统集成。此功能适用于 Android 版和 ChromeOS 版 Chrome 101 及更高版本。
在本指南中,您将了解如何为 PWA 添加 Google Play 结算支持,并将其打包以在 ChromeOS 和 Play 商店的 Google Play 商店中分发。
您将使用两个 Web 平台 API 为 PWA 添加 Play 结算支持。Digital Goods API 用于收集 SKU 信息,并检查 Play 商店中的购买交易和使用权。Payment Request API 用于将 Google Play 商店配置为付款方式,并完成购买流程。
如何在 Play 商店中通过应用创收
您的应用可以通过以下两种方式在 Play 商店中使用 Google Play 结算服务创收:
要求
若要设置 Google Play 结算服务,您需要满足以下条件:
- Google Play 开发者账号和Google Payments 商家账号已相互关联。
- Play 商店商品详情,其中有版本在公开测试轨道、封闭式测试轨道或内部测试轨道上发布。
- 如需在 Play 商店中创建和配置应用的商品和订阅,
- Bubblewrap 生成的项目,其中包含有效的数字资产关联配置。
更新 Bubblewrap 项目
如果您尚未安装 Bubblewrap,则需要先安装。如需详细了解如何开始使用此版本,请参阅快速入门指南。如果您已安装 Bubblewrap,请务必更新到 1.8.2 或更高版本。
Bubblewrap 也提供了此功能,但需要通过标志启用。如需启用该功能,您需要修改位于项目根目录下的 twa-manifest.json
中的项目配置,并同时启用 alphaDependencies
和 playBilling
功能:
..., "enableNotifications": true, "features": { "playBilling": { "enabled": true } }, "alphaDependencies": { "enabled": true }, ...
更新配置文件后,运行 bubblewrap update
将配置应用于项目,然后运行 bubblewrap build
以生成新的 Android 软件包并将此软件包上传到 Play 商店。
检测 Digital Goods API 和 Google Play 结算服务可用性的功能
目前,只有在可信 Web 活动内执行 PWA 时,Chrome 才支持 Digital Goods API。您可以通过检查 window
对象上的 getDigitalGoodsService
来检测其是否可用:
if ('getDigitalGoodsService' in window) { // Digital Goods API is supported! }
Digital Goods API 可能适用于任何浏览器,并支持不同的商店。如需检查是否支持特定的商店后端,您需要调用 getDigitalGoodsService()
,并将商店 ID 作为参数传递。Google Play 商店由字符串 https://play.google.com/billing
标识:
if ('getDigitalGoodsService' in window) { // Digital Goods API is supported! try { const service = await window.getDigitalGoodsService('https://play.google.com/billing'); // Google Play Billing is supported! } catch (error) { // Google Play Billing is not available. Use another payment flow. return; } }
检索 SKU 的详细信息
Digital Goods API 提供 getDetails()
,可从付款后端检索商品名、说明以及最重要的价格等信息。
然后,您可以在界面中使用这些信息,并向用户提供更多详细信息:
const skuDetails = await service.getDetails(['shiny_sword', 'gem']); for (item of skuDetails) { // Format the price according to the user locale. const localizedPrice = new Intl.NumberFormat( navigator.language, {style: 'currency', currency: item.price.currency} ).format(item.price.value); // Render the price to the UI. renderProductDetails( item.itemId, item.title, localizedPrice, item.description); }
构建购买流程
PaymentRequest 的构造函数接受两个参数:付款方式列表和付款详情列表。
在可信 Web activity 中,您必须使用 Google Play 结算服务付款方式,方法是将 https://play.google.com/billing
设置为标识符,并将商品 SKU 添加为数据成员:
async function makePurchase(service, sku) { // Define the preferred payment method and item ID const paymentMethods = [{ supportedMethods: "https://play.google.com/billing", data: { sku: sku, } }]; ... }
虽然付款详情是必需的,但 Play 结算系统会忽略这些值,并使用在 Play 管理中心内创建 SKU 时设置的值,因此可以填充虚假值:
const paymentDetails = { total: { label: `Total`, amount: {currency: `USD`, value: `0`} } }; const request = new PaymentRequest(paymentMethods, paymentDetails);
对付款请求对象调用 show()
以启动付款流程。如果 Promise 成功,则表示付款可能已成功。如果失败,则表示用户可能已中止付款。
如果 promise 成功执行,您需要验证并确认购买交易。为防范欺诈,此步骤必须使用您的后端实现。请参阅 Play 结算文档,了解如何在后端实现验证。 如果您未确认购买交易,三天后,用户会收到退款,并且 Google Play 会撤消该购买交易。
... const request = new PaymentRequest(paymentMethods, paymentDetails); try { const paymentResponse = await request.show(); const {purchaseToken} = paymentResponse.details; // Call backend to validate and acknowledge the purchase. if (await acknowledgePurchaseOnBackend(purchaseToken, sku)) { // Optional: tell the PaymentRequest API the validation was // successful. The user-agent may show a "payment successful" // message to the user. const paymentComplete = await paymentResponse.complete('success'); } else { // Optional: tell the PaymentRequest API the validation failed. The // user agent may show a message to the user. const paymentComplete = await paymentResponse.complete('fail'); } } catch(e) { // The purchase failed, and we can handle the failure here. AbortError // usually means a user cancellation } ...
您还可以选择对 purchaseToken 调用 consume()
,以将购买交易标记为已用尽,并允许再次购买。
将所有内容整合起来,购买方法应如下所示:
async function makePurchase(service, sku) { // Define the preferred payment method and item ID const paymentMethods = [{ supportedMethods: "https://play.google.com/billing", data: { sku: sku, } }]; // The "total" member of the paymentDetails is required by the Payment // Request API, but is not used when using Google Play Billing. We can // set it up with bogus details. const paymentDetails = { total: { label: `Total`, amount: {currency: `USD`, value: `0`} } }; const request = new PaymentRequest(paymentMethods, paymentDetails); try { const paymentResponse = await request.show(); const {purchaseToken} = paymentResponse.details; // Call backend to validate and acknowledge the purchase. if (await acknowledgePurchaseOnBackend(purchaseToken, sku)) { // Optional: consume the purchase, allowing the user to purchase // the same item again. service.consume(purchaseToken); // Optional: tell the PaymentRequest API the validation was // successful. The user-agent may show a "payment successful" // message to the user. const paymentComplete = await paymentResponse.complete('success'); } else { // Optional: tell the PaymentRequest API the validation failed. // The user agent may show a message to the user. const paymentComplete = await paymentResponse.complete('fail'); } } catch(e) { // The purchase failed, and we can handle the failure here. // AbortError usually means a user cancellation } }
查看现有购买交易的状态
借助 Digital Goods API,您可以检查用户是否拥有之前购买的任何现有使用权(尚未消耗的应用内购买交易或正在进行的订阅),无论是通过其他设备、之前的安装、通过促销代码兑换,还是在最近一次打开应用时购买的。
const service = await window.getDigitalGoodsService('https://play.google.com/billing'); ... const existingPurchases = await service.listPurchases(); for (const p of existingPurchases) { // Update the UI with items the user is already entitled to. console.log(`Users has entitlement for ${p.itemId}`); }
这也是检查之前进行但未确认的购买交易的好时机。建议您尽快确认购买交易,以确保用户的权限在您的应用中正确反映。
const service = await window.getDigitalGoodsService("https://play.google.com/billing"); ... const existingPurchases = await service.listPurchases(); for (const p of existingPurchases) { await verifyOrAcknowledgePurchaseOnBackend(p.purchaseToken, p.itemId); // Update the UI with items the user is already entitled to. console.log(`Users has entitlement for ${p.itemId}`); }
测试您的集成
在开发 Android 设备上
您可以在开发 Android 设备上启用 Digital Goods API 以进行测试:
- 确保您使用的是 Android 9 或更高版本,且已启用开发者模式。
- 安装 Chrome 101 或更高版本。
- 在 Chrome 中,前往
chrome://flags
并按名称搜索 flag,以启用以下 flag:#enable-debug-for-store-billing
- 确保网站是使用 https 协议托管的。使用 http 会导致 API
undefined
在 ChromeOS 设备上
从 ChromeOS 89 开始,Digital Goods API 将在稳定版 ChromeOS 上提供。与此同时,您可以测试 Digital Goods API:
- 在设备上从 Play 商店安装您的应用。
- 确保网站是使用 https 协议托管的。使用 http 会导致 API
undefined
与测试用户和质量检查团队合作
Play 商店提供了用于测试的功能,包括用户测试账号和测试 SKU。如需了解详情,请参阅 Google Play 结算服务测试文档。
接下来该怎么做?
如本文档所述,Play 结算服务 API 包含客户端组件(由 Digital Goods API 管理)和服务器端组件。
- 请参阅 Peter Conn 的示例:https://github.com/PEConn/beer
- 请参阅有关购物验证的 Play 文档。
- 不妨考虑使用 Google Play Developer API 客户端库之一,这些库提供多种语言版本。
- 如果要在应用中实现订阅模型,请参阅 Play 结算服务订阅文档。
- 实现实时开发者通知 (RTDN) 并订阅通知,以便在订阅状态发生变化时通知您的后端,而不是轮询 Play 上的状态。
- 实现
linkedPurchaseToken
以防止重复订阅。如需了解如何正确实现它,请参阅这篇博文。