应用内购买结算参考

本文档提供了使用 In-app Billing API 的技术参考信息。

服务器响应代码

下表列出了从 Google Play 发送到您应用的所有服务器响应代码。Google Play 将在响应 Bundle 中以映射到 RESPONSE_CODE 键的整数形式同步发送响应代码。您的应用必须处理所有这些响应代码。

表 1. In-app Billing API 调用的响应代码汇总。

响应代码 说明
BILLING_RESPONSE_RESULT_OK 0 成功
BILLING_RESPONSE_RESULT_USER_CANCELED 1 用户按上一步或取消对话框
BILLING_RESPONSE_RESULT_SERVICE_UNAVAILABLE 2 网络连接断开
BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE 3 所请求的类型不支持 Billing API 版本
BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE 4 请求的商品已不再出售。
BILLING_RESPONSE_RESULT_DEVELOPER_ERROR 5 提供给 API 的参数无效。此错误也可能说明未在 Google Play 中针对应用内购买结算正确签署或设置应用,或者应用在其清单中不具备所需的权限。
BILLING_RESPONSE_RESULT_ERROR 6 API 操作期间出现严重错误
BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED 7 未能购买,因为已经拥有此商品
BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED 8 未能消费,因为尚未拥有此商品

Billing Support API 参考

本节介绍了几种方法,这些方法可用于获取适用于您应用的应用内购买结算支持类型的信息。

isBillingSupported() 方法

该方法可指示:

  • 您的应用是否支持给定的 API 版本。
  • Google Play 是否支持在用户所在国家/地区进行结算。
  • 您的应用软件包中是否已启用结算功能。
  • 您的应用是否可以使用给定类型的商品进行结算。

表 2. isBillingSupported() 参数。

类型 说明
apiVersion int 您的应用正在使用的 In-app Billing API 的版本号。
packageName String 调用此方法的应用软件包名称。
type String 对于应用内商品,该值必须为 inapp,对于订阅,该值必须为 subs

此方法在版本 3 及更高版本的 In-app Billing API 中可用。

isBillingSupportedExtraParams() 方法

此方法类似于 isBillingSupported(),不同之处在于您可以传入第四个参数 Bundle(可包含额外的参数)。

表 3. isBillingSupportedExtraParams() 参数。

类型 说明
apiVersion int 您的应用正在使用的 In-app Billing API 的版本号。
packageName String 调用此方法的应用软件包名称。
type String 对于应用内商品,该值必须为 inapp,对于订阅,该值必须为 subs
extraParams Bundle

一组额外的参数,进一步指定应用支持的应用内购买结算类型。

本 Bundle 可以包含一个名为 vr 的可选键,此键具有布尔值。此标志指定此应用是否支持虚拟现实 (VR) 购买流程。

此方法在版本 7 及更高版本的 In-app Billing API 中可用。

Billing Details API 参考

In-app Billing API 在 IInAppBillingService.aidl 文件中定义,该文件包含在版本 3 示例应用中。

getSkuDetails() 方法

使用 getSkuDetails() 方法获取产品 ID 的相应列表的产品详细信息。

表 4. GetSkuDetails() 参数。

类型 说明
apiVersion int 您的应用正在使用的 In-app Billing API 的版本号。
packageName String 调用此方法的应用软件包名称。
type String 应用内商品的类型(“inapp”用于一次性购买,“subs”用于订阅)。
skusBundle Bundle Bundle,其中包含具有 ITEM_ID_LIST 键的 SKU 的 StringArrayList

如果 getSkuDetails() 方法成功,Google Play 会发送一个响应 Bundle。查询结果存储在映射到 DETAILS_LIST 键的字符串 ArrayList 中的 Bundle 中。详情列表中的每个字符串都以 JSON 格式包含一种商品的商品详情。表 5 汇总了含有商品详情的 JSON 字符串中的字段。

表 5. getSkuDetails() 请求返回的包含产品项详细信息的 JSON 字段说明。

说明
productId 产品 ID。
type 对于应用内商品,该值必须为 inapp;对于订阅,该值必须为 subs
price 商品的格式化价格,包括货币符号。该价格不含税。
price_amount_micros 以微单位显示的价格,其中 1,000,000 个微单位等于 1 个单位的货币。例如,如果 price"€7.99",则 price_amount_micros"7990000"。此值表示特定币种已经过四舍五入的当地价格。
price_currency_code priceISO 4217 货币代码。例如,如果 price 采用英制英镑单位,则 price_currency_code"GBP"
title 商品的标题。
description 商品的简介。
subscriptionPeriod 订阅期限,采用 ISO 8601 格式指定。例如,P1W 相当于一周,P1M 相当于一个月,P3M 相当于三个月,P6M 相当于六个月,P1Y 相当于一年。

注意:仅针对订阅返回。

freeTrialPeriod Google Play 管理中心中配置的试用期,采用 ISO 8601 格式指定。例如,P7D 相当于七天。要详细了解免费试用资格,请参阅应用内订阅

注意:仅针对配置了试用期的订阅返回。

introductoryPrice 订阅的格式化体验价格,包括货币符号,例如 €3.99。该价格不含税。

注意:仅针对配置了体验期的订阅返回。

introductoryPriceAmountMicros 以微单位显示的体验价格。币种与 price_currency_code 相同。

注意:仅针对配置了体验期的订阅返回。

introductoryPricePeriod 体验价格的结算周期,采用 ISO 8601 格式指定。

注意:仅针对配置了体验期的订阅返回。

introductoryPriceCycles 用户将享受体验价格的订阅结算周期数,例如 3。

注意:仅针对配置了体验期的订阅返回。

getBuyIntent() 方法

此方法会返回一个映射到 RESPONSE_CODE 键的响应代码整数,以及一个 PendingIntent 来启动映射到 BUY_INTENT 键的应用内商品的购买流程(如实现应用内购买结算中所述)。Google Play 在收到 PendingIntent 后,会发送一个包含该采购订单的数据的响应 Intent。表 6 汇总了响应 Intent 中返回的数据。

注意:我们建议您不要使用此方法,而应使用 getBuyIntentExtraParams(),因为它提供了额外的功能。

表 6. 来自应用内结算购买请求的响应数据。

说明
RESPONSE_CODE 如果购买成功,则值为 0;若不是,则表示出现了错误。
INAPP_PURCHASE_DATA JSON 格式的字符串,其中包含有关采购订单的详细信息。有关 JSON 字段的说明,请参阅表 7。
INAPP_DATA_SIGNATURE 包含使用开发者私钥签署的购买数据签名的字符串。该数据签名使用 RSASSA-PKCS1-v1_5 模式。

表 7 说明了采购订单响应数据中返回的 JSON 字段。

表 7. INAPP_PURCHASE_DATA 的 JSON 字段说明。

字段 说明
autoRenewing 表明是否自动续订订阅。如果为 true,则表示订阅处于活动状态,并将在下一个结算日期自动续订。如果为 false,则表示用户已取消订阅。用户可以在下一个结算日期之前访问订阅内容,并且在该日期后将无法访问,除非他们重新启用自动续订(或者手动续订,如手动续订中所述)。如果您提供宽限期,只要宽限期尚未结束,对于所有订阅而言,此值都将保持为 true。下一次结算日期每天都会自动推延,直至宽限期结束或用户更改他们的付款方式。
orderId 交易的唯一订单标识符。此标识符对应于 Google 付款订单 ID。
packageName 发起购买的应用软件包。
productId 商品的产品标识符。每件商品都有一个产品 ID,您必须在 Google Play 管理中心的应用产品列表中指定产品 ID。
purchaseTime 购买产品的时间,以从 Epoch 纪元日(1970 年 1 月 1 日)开始计算的毫秒数表示。
purchaseState 订单的购买状态。始终返回 0(已购买)。
developerPayload 开发者指定的字符串,其中包含关于订单的补充信息。当您发出 getBuyIntent 请求时,您可以为此字段指定一个值。
purchaseToken 用于唯一标识给定商品和用户对的购买令牌。

consumePurchase() 方法

消费与给定购买令牌相对应的购买。这将导致此商品从 getPurchases() 的所有后续响应中移除,并允许重新购买相同 SKU 的商品。

表 8. consumePurchase() 参数。

类型 说明
apiVersion int 您的应用正在使用的 In-app Billing API 的版本号。
packageName String 调用此方法的应用软件包名称。
purchaseToken String 购买信息 JSON 中的令牌,用于标识要消费的购买。

此方法在消费成功时返回 RESULT_OK(0),并在失败时返回适当的响应代码。

getBuyIntentToReplaceSkus() 方法

可以使用此方法升级或降级订阅购买。该方法类似于 getBuyIntent(),不同之处在于它会获取一个列表,其中只包含一个已购买的 SKU,该 SKU 将被替换为正在购买的 SKU。当用户完成购买后,Google Play 将换掉旧的 SKU,并按比例向用户返还未使用的订阅时间所对应的余额。Google Play 会将此余额结转到新订阅中,并且在此余额用完之前不会向用户收取新订阅的费用。

注意:我们建议您不要使用此方法,而应使用 getBuyIntentExtraParams(),因为它提供了额外的功能。

此方法已添加到版本 5 的 In-app Billing API 中。要验证该方法是否已报告,请发送 isBillingSupported AIDL 请求。

注意:您只能针对订阅购买使用此方法。如果传递的 type 参数不是 "subs",则该方法会返回 BILLING_RESPONSE_RESULT_DEVELOPER_ERROR。此外,传递的 SKU 可能不包含季度订阅的 SKU。

此方法会返回一个映射到 RESPONSE_CODE 键的响应代码整数,以及一个 PendingIntent 来启动映射到 BUY_INTENT 键的应用内订阅的购买流程(如实现应用内购买结算中所述)。Google Play 在收到 PendingIntent 后,会发送一个包含该采购订单的数据的响应 Intent。表 9 汇总了响应 Intent 中返回的数据。

表 9. 来自应用内购买结算版本 5 购买请求的响应数据。

说明
RESPONSE_CODE 如果购买成功,值为 0。如果购买失败,则包含错误代码。
INAPP_PURCHASE_DATA JSON 格式的字符串,其中包含有关采购订单的详细信息。有关 JSON 字段的说明,请参阅表 6
INAPP_DATA_SIGNATURE 包含使用开发者私钥签署的购买数据签名的字符串。该数据签名使用 RSASSA-PKCS1-v1_5 模式。

getBuyIntentExtraParams() 方法

此方法会开启一个购买请求。该方法是 getBuyIntent() 方法的变体,并采用额外的 extraParams 参数。此参数是影响该方法操作的可选键和值的 Bundle(如表 10 所示)。

表 10. getBuyIntentExtraParams() 的额外参数。

类型 说明
skusToReplace List<String> 仅包含用户正在升级或降级的一个 SKU 的可选列表。如果购买是对现有订阅的升级或降级,则传递此字段。指定的 SKU 将被替换为用户正在购买的 SKU。Google Play 将在下一个结算周期开始时替换指定的 SKU。
replaceSkusProration boolean

指定用户是否应该就升级或降级的 SKU 获得任何未使用的订阅时间的余额返还。如果将此字段设置为 true,Google Play 将换掉旧的 SKU 并按比例向用户返还未使用的订阅时间所对应的余额。Google Play 会将此余额结转到新订阅中,并且在此余额用完之前不会向用户收取新订阅的费用。

如果将此字段设置为 false,则用户不会因未使用的订阅时间获得余额返还,并且下个订阅周期的开始日期不会改变。

默认值为 true。如果您不传递 skusToReplace,则忽略。

accountId String

可选的混淆字符串,与您应用中的用户帐号唯一关联。如果您传递此值,Google Play 可以使用它来检测不正常的活动,例如大量设备在短时间内使用同一帐号进行购买。

请勿在此字段中使用开发者 ID 或用户的 Google ID。另外,该字段不应以明文形式包含用户 ID。我们建议您使用单向哈希技术来根据用户 ID 生成一个字符串,并将此哈希字符串存储在该字段中。

vr boolean

指定所提供的 intent 是否代表虚拟实境 (VR) 购买流程的开始。

注意:为了使该额外的参数对您的应用产生影响,您必须使用版本 7 或更高版本的 In-app Billing API。

此方法在版本 6 及更高版本的 In-app Billing API 中可用。

getPurchases() 方法

此方法将返回当前归用户所有但未消费的商品,包括购买的商品和通过兑换促销代码获得的商品。表 11 列出了 Bundle 中返回的响应数据。

表 11. 来自 getPurchases 请求的响应数据。

说明
RESPONSE_CODE 如果请求成功,则值为 0;若不是 0,则表示出现了错误。
INAPP_PURCHASE_ITEM_LIST StringArrayList,包含从此应用购买的产品 Id 列表。
INAPP_PURCHASE_DATA_LIST StringArrayList,包含从此应用进行的购买的详细信息。请参阅表 6 以获取列表中每个 INAPP_PURCHASE_DATA 商品中存储的详细信息的列表。
INAPP_DATA_SIGNATURE_LIST StringArrayList,包含从此应用进行的购买的签名。
INAPP_CONTINUATION_TOKEN 一个字符串,其中包含用于检索用户拥有的下一组应用内商品的继续令牌。如果用户拥有的商品的数量非常庞大,则此字符串只能通过 Google Play 服务设置。当响应中存在继续令牌时,您必须对 getPurchases 发起另一个调用,并传入您接收到的继续令牌。随后的 getPurchases 调用会返回更多购买并可能会返回另一个继续令牌。

getPurchaseHistory() 方法

此方法返回用户对每个 SKU 所做的最近一次购买,即使该购买已过期、取消或消费。表 12 列出了 Bundle 中返回的响应数据:

表 12. 来自 getPurchaseHistory 请求的响应数据。

说明
RESPONSE_CODE 如果请求成功,则值为 0;若不是,则表示出现了错误。
INAPP_PURCHASE_ITEM_LIST StringArrayList,包含从此应用购买的产品 Id 列表。
INAPP_PURCHASE_DATA_LIST StringArrayList,包含最近从此应用进行的购买的详细信息。请参阅表 6 以获取列表中每个 INAPP_PURCHASE_DATA 商品中存储的详细信息的列表。
INAPP_DATA_SIGNATURE_LIST StringArrayList,包含从此应用进行的购买的签名。
INAPP_CONTINUATION_TOKEN 一个字符串,其中包含用于检索用户拥有的下一组应用内商品的继续令牌。如果用户拥有的商品的数量非常庞大,则此字符串只能通过 Google Play 服务设置。当响应中存在继续令牌时,您必须对 getPurchases 发起另一个调用,并传入您接收到的继续令牌。随后的 getPurchases 调用会返回更多购买并可能会返回另一个继续令牌。

表 13. getPurchaseHistory() 返回的购买历史记录的 JSON 字段的说明。

字段 说明
productId 商品的产品标识符。每件商品都有一个产品 ID,您必须在 Google Play 管理中心的应用产品列表中指定产品 ID。
purchaseTime 购买产品的时间,以从 Epoch 纪元日(1970 年 1 月 1 日)开始计算的毫秒数表示。
developerPayload 开发者指定的字符串,其中包含关于订单的补充信息。当您发出 getBuyIntent 请求时,您可以为此字段指定一个值。
purchaseToken 用于唯一标识给定商品和用户对的购买令牌。

注意getPurchaseHistory() 方法的开销比 getPurchases() 高,因为它需要调用 Google Play 服务器。如果您确实不需要用户的购买历史记录,则应该使用 getPurchases()

此方法在版本 6 及更高版本的 In-app Billing API 中可用。