Android Billing 4.0.0如何实现已购内购商品的恢复功能
问题修复方案
你当前的代码缺少必要的状态校验,同时存在多个可能触发返回空结果的场景,对应解决方法如下:
- 先校验Billing返回结果:你当前未对
billingResult的响应码做判断,当Google Play服务连接异常、用户未登录Google账号、权限不足时,即使list不为空也不会返回有效数据,必须先判断响应码为BillingClient.BillingResponseCode.OK后再处理购买记录。 - 匹配正确的商品类型:你当前传入的查询类型是
BillingClient.SkuType.INAPP,仅对应一次性非订阅商品,如果你的在售商品包含订阅类,需要额外调用一次queryPurchasesAsync传入BillingClient.SkuType.SUBS单独查询订阅类购买记录。 - 确认账号与购买状态匹配:
- 检查当前设备登录的Google Play账号,和之前完成购买的账号必须为同一个,多账号设备可切换到购买用的账号后重试
- 确认你购买的是非消耗型商品:如果代码逻辑中曾对该商品调用
consumeAsync方法做消耗处理,消耗后的商品不会再被queryPurchasesAsync返回 - 确认购买已完成确认:如果购买后未调用
acknowledgePurchase方法确认购买,3天后Google会自动退款,该笔购买记录也不会被返回
- 处理同步延迟问题:真实购买后Google Play的购买记录同步存在15-30分钟的延迟,可等待一段时间后再触发恢复购买操作,测试环境下的沙盒购买有效期更短,过期后也无法查询到记录。
修正后的参考代码如下:
private void restorePreviousPurchases () { // 查询一次性非订阅商品 billingClient.queryPurchasesAsync(BillingClient.SkuType.INAPP, new PurchasesResponseListener() { @Override public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> list) { // 先判断响应码正常再处理数据 if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) { for (Purchase purchase : list) { // 额外校验购买状态有效 if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED && !purchase.isAcknowledged()) { // 先确认购买,再处理商品交付 acknowledgePurchase(purchase); } ArrayList<String> skus = purchase.getSkus(); if (skus != null) { for (String sku : skus) { setPurchasedItem(sku); } } } } else { Log.d("DEBUGGING...", "查询一次性商品失败,响应码:" + billingResult.getResponseCode() + " 错误信息:" + billingResult.getDebugMessage()); } } }); // 如果有订阅类商品,新增订阅查询逻辑 billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS, new PurchasesResponseListener() { @Override public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> list) { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) { for (Purchase purchase : list) { if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED && !purchase.isAcknowledged()) { acknowledgePurchase(purchase); } ArrayList<String> skus = purchase.getSkus(); if (skus != null) { for (String sku : skus) { setPurchasedItem(sku); } } } } else { Log.d("DEBUGGING...", "查询订阅商品失败,响应码:" + billingResult.getResponseCode() + " 错误信息:" + billingResult.getDebugMessage()); } } }); } // 补充购买确认逻辑 private void acknowledgePurchase(Purchase purchase) { AcknowledgePurchaseParams params = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); billingClient.acknowledgePurchase(params, billingResult -> { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { // 确认成功处理后续逻辑 } }); }
内容的提问来源于stack exchange,提问作者neowinston
相关产品推荐
相关产品推荐

