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

Android使用BillingClient库如何查询用户已购买的内购商品

Google Play Billing 3.0.1 购买记录查询为空问题解决

问题核心原因

你现有代码的核心问题是未等待BillingClient连接完成就直接发起查询请求,同时没有对返回的BillingResult状态做校验,直接操作可能为null的列表。

正确实现逻辑

首先明确场景适配:你需要检测用户是否已购买有效内购商品,优先使用queryPurchases()方法,该方法读取本地缓存,无需联网,返回当前用户名下所有未消费的有效内购/订阅记录,更适合启动时的校验场景。queryPurchaseHistoryAsync多用于拉取历史购买记录(含已消费/已过期的记录),需要联网,可用作后续对账补充。

完整实现步骤

  • 第一步:初始化BillingClient并建立连接
  • 第二步:连接成功后先查询本地有效购买记录
  • 第三步:对返回结果做状态校验,避免空指针
// 1. 初始化BillingClient
mBillingClient = BillingClient.newBuilder(getApplicationContext())
        .enablePendingPurchases()
        .setListener(this)
        .build();

// 2. 先建立连接,连接成功后再执行查询
mBillingClient.startConnection(new BillingClientStateListener() {
    @Override
    public void onBillingSetupFinished(@NonNull BillingResult billingResult) {
        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
            // 连接成功,先查询本地缓存的有效购买记录
            Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);
            if (purchasesResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                List<Purchase> purchaseList = purchasesResult.getPurchasesList();
                if (purchaseList != null && !purchaseList.isEmpty()) {
                    // 遍历purchaseList,匹配你要校验的商品SKU,确认购买状态
                    for (Purchase purchase : purchaseList) {
                        if (purchase.getSku().equals("你的商品SKU") 
                            && purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED
                            && !purchase.isAcknowledged()) {
                            // 注意未确认的购买需要先调用acknowledgePurchase确认,再判定为已购买
                            // 用户已购买该商品,做对应逻辑处理
                        }
                    }
                }
            }

            // 如果需要拉取完整历史购买记录,再调用queryPurchaseHistoryAsync
            mBillingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP, new PurchaseHistoryResponseListener() {
                @Override
                public void onPurchaseHistoryResponse(@NonNull BillingResult billingResult, @Nullable List<PurchaseHistoryRecord> list) {
                    // 先校验响应状态,再操作列表
                    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) {
                        // 处理历史记录逻辑
                        list.size();
                    }
                }
            });
        }
    }

    @Override
    public void onBillingServiceDisconnected() {
        // 连接断开可触发重连逻辑
    }
});

其他可能导致返回null的排查点

  • 设备已登录正常的谷歌Play账号,测试场景下账号已加入应用的测试白名单
  • 应用签名、包名与谷歌Play后台提交的版本完全一致
  • 谷歌Play服务版本已更新到支持BillingClient 3.0.1的最新版本
  • SKU类型传参正确:内购商品传BillingClient.SkuType.INAPP,订阅商品传BillingClient.SkuType.SUBS

内容的提问来源于stack exchange,提问作者Serkan Şeker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 17:09:02