警告:AIDL 现已弃用,并且将在未来的版本中移除。如需实现结算相关功能,请使用 Google Play 结算库。
您可以使用 Android 接口定义语言 (AIDL) 接口实现 Google Play 结算系统的一些功能。
购买商品

图 1. 购买请求的基本顺序。
Google Play 结算服务 AIDL API 中的典型购买流程如下:
- 您的应用向 Google Play 发送
isBillingSupported
请求,确定您目前使用的 Google Play 结算服务 AIDL API 的目标版本是否受支持。该请求还会验证 Google Play 是否支持在用户所在的国家/地区进行结算。 - 当您的应用启动或用户登录时,最好向 Google Play 进行查询,确定该用户拥有哪些商品。如需查询用户购买的商品,请发送
getPurchases
请求。如果该请求成功,Google Play 会返回一个Bundle
,其中包含所购商品的商品 ID 列表、各项购买详情的列表以及购买签名的列表。 - 通常情况下,您需要将可供购买的商品通知用户。如需查询您在 Google Play 中定义的应用内商品的详细信息,应用可以发送
getSkuDetails
请求。您必须在查询请求中指定商品 ID 列表。如果该请求成功,Google Play 会返回一个包含商品详情(包括商品的价格、商品名、说明和购买类型)的Bundle
。 - 如果该用户还未拥有某种应用内商品,您可以提示购买。为了发起购买请求,您的应用会发送
getBuyIntent
请求,指定要购买商品的商品 ID 以及其他参数。当您在 Google Play 管理中心内创建新的应用内商品时,应记录其商品 ID。- Google Play 返回的
Bundle
中包含PendingIntent
,您的应用可用它启动购买结算界面。 - 您的应用通过调用
startIntentSenderForResult
方法启动待定 intent。 - 当结算流程结束后(即用户成功购买商品或取消购买),Google Play 会向您的
onActivityResult
方法发送响应Intent
。onActivityResult
的结果代码中有一个代码将用于表明用户是完成还是取消了购买。响应Intent
中包含所购商品的相关信息,包括 Google Play 为了对此次购买交易进行唯一标识而生成的purchaseToken
字符串。Intent
中还包含使用您的开发者私钥签署的购买签名。
- Google Play 返回的
如需详细了解 Google Play 结算服务 AIDL API 的调用和服务器响应,请参阅 Google Play 结算服务 AIDL API 参考。
消耗应用内商品
您可以使用消耗机制跟踪用户对受管理商品的所有权。
所有受管理商品都在 Google Play 结算服务 AIDL API 中进行管理。也就是说,用户对所有所购受管理商品的所有权均由 Google Play 维护,您的应用可以在需要时查询用户的购买信息。当用户成功购买受管理商品后,此次购买就会记录在 Google Play 中。受管理商品一经购买,就会被视为“被拥有”。处于“被拥有”状态的受管理商品无法再通过 Google Play 购买。您必须对“被拥有”的受管理商品发送消耗请求,然后 Google Play 才能再次将其设成可购买状态。消耗受管理商品会将其切换回“未被拥有”状态,并舍弃之前的购买数据。

图 2. 消耗请求的基本顺序。
为了检索用户所拥有商品的列表,您的应用会向 Google Play 发送 getPurchases
调用。应用可以通过发送 consumePurchase
调用提出消耗请求。在请求参数中,您必须指定受管理商品的唯一 purchaseToken
字符串,此字符串是在商品售出时由 Google Play 指定的。Google Play 会返回一个状态代码,指明此次消耗是否已成功记录。
非消耗型和消耗型受管理商品
您需要决定受管理商品是作为非消耗型商品还是消耗型商品处理。
- 非消耗型商品
- 通常情况下,对于在应用内购买一次就能永久使用的受管理商品,您无需实现消耗机制。这些商品在购买后将永久与用户的 Google 帐号相关联。高级版升级和关卡包就属于非消耗型受管理商品。
- 消耗型商品
- 相反,对于可多次购买的商品,您可以实现消耗功能。通常情况下,这类商品可提供一些临时效果。例如,用户在游戏中的角色可以从自己的库存中获得生命值或额外的金币。在您的应用中分配所购商品的收益或效果,称为“配置”受管理商品。您负责控制和跟踪如何向用户配置受管理商品。
重要提示:您必须先向 Google Play 发送消耗请求,在收到表明此次消耗已成功记录的响应之后,您才能在应用中配置消耗型受管理商品。
在应用中管理消耗型商品购买
下面是购买消耗型受管理商品的基本流程:
- 调用
getBuyIntent
方法以启动购买流程。 - 检查从 Google Play 返回的
Bundle
,以确定购买是否成功完成。 - 如果购买成功,请调用
consumePurchase
方法以消耗购买。 - 检查从 Google Play 接收的响应代码,确定消耗是否成功完成。
- 如果消耗成功,请在您的应用中配置商品。
之后,当用户启动或登录到您的应用时,您应检查该用户是否拥有任何尚未消耗的消耗型应用内商品。如果有,请务必消耗并配置这些商品。如果您在应用中实现消耗型应用内商品,则可以采用以下推荐的应用启动流程:
- 发送
getPurchases
请求,查询该用户拥有的应用内商品。 - 如果有任何消耗型应用内商品,请调用
consumePurchase
消耗这些商品。此操作不可省略,因为应用虽可能已完成该消耗型商品的采购订单,但在其发送消耗请求之前仍有可能已停止运行或断开连接。 - 检查从 Google Play 接收的响应代码,确定消耗是否成功完成。
- 如果消耗成功,请在您的应用中配置商品。
配置奖励购买
警告:奖励商品不再受支持。如需了解详情,请参阅创建奖励商品。
使用 AIDL 处理奖励商品时,您应该在用户需要收取奖励之前缓存购买“Intent”。您可以在后台线程上调用购买 Intent 并保存成功的响应“Intent”,直到用户采取行动收取奖励。
列出并加载 SKU
在向用户提供奖励商品之前,请通过调用 getSkuDetails()
获取商品详情。为 SKU 列表中的每个奖励商品填充一个新的 JSON 字段“rewardToken”。
getBuyIntentExtraParams()
。收到 BILLING_RESPONSE_RESULT_OK
的响应后,为用户启用奖励商品并保存返回的 PendingIntent
对象以供日后使用。以下代码段演示了加载与奖励商品相关联的广告的流程:
Kotlin
val rewardToken = skuDetailsJson.optString("rewardToken") val extraParams = Bundle().putString("rewardToken", rewardToken) // This call blocks the current thread, so do this in the background. val buyIntentBundle : Bundle = mService.getBuyIntentExtraParams(9, packageName, sku, "inapp", "", extraParams) val response = buyIntentBundle.getInt("RESPONSE_CODE") if (response == BILLING_RESPONSE_RESULT_OK) { // Enable rewarded product. // Save this object for use later. val pendingIntentToSave = bundle.getParcelable(RESPONSE_BUY_INTENT) } else { // Don't offer rewarded product. }
Java
String rewardToken = skuDetailsJson.optString("rewardToken"); Bundle extraParams = new Bundle(); extraParams.putString("rewardToken", rewardToken); // This call blocks the current thread, so do this in the background. Bundle buyIntentBundle = mService.getBuyIntentExtraParams(9, getPackageName(), sku, "inapp", "", extraParams); int response = buyIntentBundle.getInt("RESPONSE_CODE"); if (response == BILLING_RESPONSE_RESULT_OK) { // Enable rewarded product. // Save this object for use later. PendingIntent pendingIntentToSave = bundle.getParcelable(RESPONSE_BUY_INTENT); } else { // Don't offer rewarded product. }
声明适合相应年龄段的广告
为了协助履行与儿童和未成年用户相关的法律义务(包括《儿童在线隐私保护法》[COPPA] 和《一般数据保护条例》[GDPR]),您应该在应用中声明哪些广告在美国应视为面向儿童的内容,以及哪些广告面向的是未满所在国家/地区规定的同意年龄的用户。AdMob 帮助中心的文章阐明了在哪些情况下应将广告请求标记为面向儿童的内容,以及在哪些情况下应将其标记为适合未达到同意年龄的用户的内容,并说明了这样做的影响。
如需指明奖励请求是针对儿童或未满规定年龄的用户,请添加 childDirected
和 underAgeOfConsent
这两个额外的参数,如以下代码段中所示:
Kotlin
val rewardToken = skuDetailsJson.optString("rewardToken") val extraParams = Bundle().putString("rewardToken", rewardToken) .putInt("childDirected", ChildDirected.CHILD_DIRECTED) .putInt("underAgeOfConsent", UnderAgeOfConsent.UNDER_AGE_OF_CONSENT) // This call blocks the current thread, so do this in the background. val buyIntentBundle : Bundle = mService.getBuyIntentExtraParams(9, packageName, sku, "inapp", "", extraParams)
Java
Bundle extraParams = new Bundle(); extraParams.putString("rewardToken", rewardToken); extraParams.putInt("childDirected", ChildDirected.CHILD_DIRECTED); extraParams.putInt("underAgeOfConsent", UnderAgeOfConsent.UNDER_AGE_OF_CONSENT); // This call blocks the current thread, so do this in the background. Bundle buyIntentBundle = mService.getBuyIntentExtraParams( 9, getPackageName(), sku, "inapp", "", extraParams);
在奖励用户之前播放广告
在用户点击相应按钮开始观看广告后,您的应用可使用已保存的PendingIntent
对象开始播放广告。为此,请调用 startIntentSenderForResult()
。Kotlin
startIntentSenderForResult( pendingIntentToSave, RC_BUY, Intent(), 0, 0, 0 )
Java
startIntentSenderForResult(pendingIntentToSave, RC_BUY, new Intent(), 0, 0, 0);
然后,在 onActivityResult()
中处理结算工作流的结果,如以下代码段中所示。处理广告播放流程时,Google Play 会使用与处理其他结算流程时相同的一组服务器响应代码。
Kotlin
fun onActivityResult(requestCode : Int, resultCode : Int, data : Intent) { if (requestCode == RC_BUY) { int responseCode = data.getIntExtra(RESPONSE_CODE) String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA) String signature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE) // Handle reward purchase. } }
Java
public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RC_BUY) { int responseCode = data.getIntExtra(RESPONSE_CODE); String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA); String signature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE); // Handle reward purchase. } }
本地缓存
由于 Google Play 客户端现在在设备本地缓存结算信息,因此您可以使用 Google Play 结算服务 AIDL API 更频繁地查询此信息。以下 Google Play 结算服务 AIDL API 调用是在缓存中进行查找,而不需要网络连接,这样显著加快了 API 的响应速度:
getBuyIntent
getPurchases
isBillingSupported