You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 02:42:03