});
注意:强烈建议您实施自己的连接重试策略并覆盖该 onBillingServiceDisconnected() 方法。BillingClient执行任何方法时,请确保维护连接。
4、查询应用内商品详细信息
您在配置应用内商品时创建的唯一商品ID用于异步查询Google Play的应用内商品详细信息。要在Google Play中查询应用内商品详情,请致电 querySkuDetailsAsync()。调用此方法时,传递一个实例,SkuDetailsParams 该实例 指定产品ID字符串列表和一个SkuType。该SkuType可以是SkuType.INAPP一次性产品或SkuType.SUBS订阅费。
注意:要查询产品详细信息,您的应用将使用您在Google Play控制台中配置产品时定义的产品ID。
要处理异步操作的结果,还必须指定一个实现该SkuDetailsResponseListener 接口的侦听 器。然后onSkuDetailsResponse() ,您可以重写 以在查询结束时通知侦听器,如以下示例代码所示:
List skuList = new ArrayList<> ();
skuList.add(“premium_upgrade”);
skuList.add(“gas”);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(SkuType.INAPP);
billingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(BillingResult billingResult,
List skuDetailsList) {
// Process the result.
}
});
注意:有些 Android 设备安装的可能是旧版 Google Play 商店应用,不支持订阅等某些商品类型。在您的应用进入结算流程之前,您可以调用 isFeatureSupported() 以确定设备是否支持您要销售的商品。
5、启动购买流程
如需从应用发起购买请求,请从应用的主线程调用 launchBillingFlow() 方法。此方法接受对 BillingFlowParams 对象的引用,该对象包含通过调用 querySkuDetailsAsync() 获取的相关 SkuDetails 对象。如需创建 BillingFlowParams 对象,请使用 BillingFlowParams.Builder 类。BillingFlowParams ,请使用 BillingFlowParams.Builder 类:
// An activity reference from which the billing flow will be launched.
Activity activity = …;
// Retrieve a value for “skuDetails” by calling querySkuDetailsAsync().
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.build();
int responseCode = billingClient.launchBillingFlow(activity, billingFlowParams).getResponseCode();
// Handle the result.
launchBillingFlow() 方法会返回 BillingClient.BillingResponseCode 中列出的几个响应代码之一。请务必检查此结果,以确保在启动购买流程时没有错误。BillingResponseCode 为 OK 表示成功启动。
成功调用 launchBillingFlow() 后,系统会显示 Google Play 购买屏幕。如下图:
Google Play 会调用 onPurchasesUpdated(),以将购买操作的结果传送给实现 PurchasesUpdatedListener接口的监听器。您可以在初始化客户端时使用 setListener() 方法指定监听器。
你必须实现 onPurchasesUpdated() 来处理可能的响应代码。以下示例展示了如何替换 onPurchasesUpdated():
@Override
void onPurchasesUpdated(BillingResult billingResult, List purchases) {
if (billingResult.getResponseCode() == BillingResponseCode.OK
&& purchases != null) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
}
} else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
// Handle an error caused by a user cancelling the purchase flow.
} else {
// Handle any other error codes.
}
}
如果成功购买商品,系统会产生一个Google Play成功屏幕。如下图:
如果成功购买商品,系统还会生成购买令牌,它是一个唯一标识符,表示用户及其所购应用内商品的商品 ID。您的应用可以在本地存储购买令牌,不过我们建议您将令牌传递到安全的后端服务器,您随后可以在该服务器上验证购买交易及防范欺诈行为。下一部分对此过程进行了详细说明。
用户还会收到包含交易收据的电子邮件,其中包含订单 ID 或交易的唯一 ID。用户每次购买一次性商品时,都会收到包含唯一订单 ID 的电子邮件。此外,用户最初购买订阅时以及后续定期自动续订时,也会收到这样的电子邮件。您可以在 Google Play 管理中心内使用订单 ID 来管理退款。
6、确认购买交易(消费掉才算真正的完结该订单)
如果你使用的是Google Play结算库2.0版或更高版本,则必须在三天内确认所有购买。未正确确认购买会导致这些购买被退款。
用户完成购买交易后,您的应用需要处理该购买交易。在大多数情况下,您的应用会通过 PurchasesUpdatedListener 收到购买交易的通知。但在某些情况下,您的应用通过调用 BillingClient.queryPurchasesAsync() 得知购买交易,如提取购买交易中所述。
您的应用应按以下方式处理购买交易:
1、验证购买交易。
2、向用户提供内容,并确认内容已传送给用户。还可以选择性地将商品标记为已消费,以便用户可以再次购买商品。
如需验证购买交易,请先检查购买交易的状态是否为 PURCHASED。如果购买交易的状态为 PENDING,则您应按照处理待处理的交易中的说明处理购买交易。对于通过 onPurchasesUpdated() 或 queryPurchasesAsync 接收的购买交易,您应在应用授予权利之前进一步验证购买交易以确保其合法性。如需了解如何正确验证购买交易,请参阅在授予权利前验证购买交易。
一旦您验证了购买交易,您的应用就可以向用户授予权利了。授予权利后,您的应用必须确认购买交易。此确认会告知 Google Play 您已授予购买权。
注意:如果您在三天内未确认购买交易,用户会自动收到退款,并且 Google Play 会撤消该购买交易。
注意:使用 2.0 之前的 Google Play 结算库版本时,不需要确认。
授予权利并确认购买交易的流程取决于购买的是非消耗型商品、消耗型商品,还是订阅。
对于消耗型商品,consumeAsync() 方法满足确认要求,并且表明您的应用已授予用户权利。此外,通过此方法,您的应用可让一次性商品可供再次购买。
如需表明某件一次性商品已被消耗,请调用 consumeAsync() 并添加 Google Play 应在用户重新购买时提供的购买令牌。您还必须传递一个实现 ConsumeResponseListener 接口的对象。该对象用于处理消耗操作的结果。您可以替换 onConsumeResponse() 方法,Google Play 结算库会在消耗操作完成时调用该方法。
以下示例展示了如何使用关联的购买令牌来消耗商品:
void handlePurchase(Purchase purchase) {
// Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
Purchase purchase = …;
// Verify the purchase.
// Ensure entitlement was not already granted for this purchaseToken.
// Grant entitlement to the user.
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
ConsumeResponseListener listener = new ConsumeResponseListener() {
@Override
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
// Handle the success of the consume operation.
}
}
};
billingClient.consumeAsync(consumeParams, listener);
}
注意:由于消耗请求偶尔会失败,因此您必须检查安全的后端服务器,确保所有购买令牌都未被使用过,这样您的应用就不会针对同一购买交易多次授予权利。或者,您的应用也可以等到您收到 Google Play 发来的成功消耗响应后再授予权利。如果您选择在 Google Play 发来成功消耗响应之前不让用户消耗所购商品,那么您必须非常小心,在消耗请求发出后时刻跟踪相应商品。
如需确认非消耗型商品的购买交易,请使用结算库中的 BillingClient.acknowledgePurchase() 或 Google Play Developer API 中的 Product.Purchases.Acknowledge。在确认购买交易之前,您的应用应使用 Google Play 结算库中的 isAcknowledged() 方法或 Google Play Developer API 中的 acknowledgementState 字段检查该购买交易是否已经过确认。
以下示例展示了如何使用 Google Play 结算库来确认购买交易:
BillingClient client = …
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = …
void handlePurchase(Purchase purchase) {
if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()) {
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
}
}
}
订阅的处理方式与非消耗型商品类似。您可以使用 Google Play 结算库中的 BillingClient.acknowledgePurchase() 或 Google Play Developer API 中的 Purchases.Subscriptions.Acknowledge 确认订阅。所有初始订阅购买交易都需要确认。订阅续订不需要确认。
7、提取交易信息
使用 PurchasesUpdatedListener 监听购买交易更新不足以确保您的应用会处理所有购买交易。有时您的应用可能不知道用户进行的部分购买交易。在下面这几种情况下,您的应用可能会跟踪不到或不知道购买交易:
在购买过程中出现网络问题:用户成功购买了商品并收到了 Google 的确认消息,但他们的设备在通过 PurchasesUpdatedListener
收到购买交易的通知之前失去了网络连接。
多台设备:用户在一台设备上购买了一件商品,然后在切换设备时期望看到该商品。
处理在您的应用外进行的购买交易:某些购买交易(如促销活动兑换)可能会在您的应用外进行。
为了处理这些情况,请确保您的应用在 onResume() 和 onCreate() 方法中调用 BillingClient.queryPurchasesAsync(),以确保所有购买交易都得到成功处理,如处理购买交易中所述。
8、处理在您的应用外进行的购买交易(我未集成)
某些购买交易(如促销活动兑换)可能发生在您的应用外。当用户在您的应用外进行购买交易时,他们希望您的应用显示应用内消息,或使用某种通知机制告知用户应用已正确接收并处理该购买交易。下面是一些可接受的机制:
显示应用内弹出式消息。
将消息传送到应用内消息箱,并清楚地指出应用内消息箱中有新消息。
使用操作系统通知消息。
请注意,当您的应用识别出购买交易时,它有可能处于任何状态。甚至有可能在用户进行购买交易时根本没有安装您的应用。无论应用处于什么状态,用户都希望在继续使用应用时收到其所购商品。
无论用户进行购买交易时应用处于什么状态,您都必须检测购买交易。不过,在一些例外情况下,不立即通知用户已收到商品或许是可以接受的。例如:
当用户在玩游戏时,显示消息可能会让用户分心。在这种情况下,必须待游戏结束后再通知用户。
在出现过场动画时,显示消息可能会让用户分心。在这种情况下,必须待过场动画结束后再通知用户。
当用户在游戏中学习初始教程和进行用户设置时。我们建议您在新用户打开游戏后立即将奖励通知用户,或在用户进行初始设置期间通知他们。不过,您也可以等到用户正式进入游戏环节时再通知用户。
在斟酌何时以及如何通知用户在您的应用外进行的购买交易时,一定要把用户放在心上。如果用户没有立即收到通知,他们可能会感到困惑,并且可能会停止使用您的应用,与用户支持团队联系,或在社交媒体上抱怨。
9、处理待处理的交易
注意:只有 Google Play 结算库 2.0 及更高版本支持待处理的交易。
注意:其他付款方式不可用于订阅购买交易。
Google Play 支持待处理的交易,即从用户发起购买交易到购买交易的付款方式得到处理期间需要执行一个或多个额外步骤的交易。在 Google 通知您已通过用户的付款方式成功扣款之前,您的应用不得授予对这些类型的购买交易的权利。
例如,用户可以选择现金作为付款方式来创建应用内商品的 PENDING 购买交易。然后,用户可以选择在一家实体店完成交易,并通过通知和电子邮件收到一个代码。当用户到达实体店时,他们可以在收银员处兑换该代码并用现金支付。Google 随后会通知您和用户已收到现金。您的应用随后就可以授予用户权利了。
如要启用“待处理的购买交易”功能,请在初始化应用期间调用 enablePendingPurchases()。
当您的应用通过 PurchasesUpdatedListener 或由于调用 queryPurchasesAsync() 而收到新的购买交易时,使用 getPurchaseState() 方法确定购买交易的状态是 PURCHASED 还是 PENDING。请注意,只有在状态为 PURCHASED 时,您才能授予权利。如果您的应用在用户完成购买交易时正在运行,系统会再次调用 PurchasesUpdatedListener,并且 PurchaseState 现在为 PURCHASED。此时,您的应用可以使用处理一次性购买的标准方法处理购买交易。此外,您的应用还应在其 onResume() 和 onCreate() 方法中调用 queryPurchasesAsync(),以处理您的应用未在运行时过渡到 PURCHASED 状态的购买交易。
注意:只有在状态为 PURCHASED 时,您才能确认购买交易。当购买交易处于 PENDING 状态时,您不能确认。当购买状态从“PENDING”转换为“PURCHASED”时,3 天的确认期限才会开始。