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

Google Play取消购买后purchaseState查询与遍历返回值不一致问题

问题原因

1. 核心问题:异步调用时序错误

queryPurchasesAsync是异步API,你调用该方法后立刻遍历purchaseQuerySkus变量时,onQueryPurchasesResponse回调还没有执行,你遍历的是上一次查询缓存的旧列表数据,并不是本次回调返回的新列表。
你看到的两个日志并非来自同一份数据:回调中打印的purchaseState=0是本次最新查询结果,而遍历打印的purchaseState=1是上一次残留的旧数据,只是两次查询的列表长度刚好都是1,导致你误以为是同一份数据取值不一致。

2. 其他可能原因

  • 旧版本Google Play Billing库存在字段映射bug,会出现JSON字段和getPurchaseState返回值不匹配的问题
  • 退款订单没有及时做消耗/确认处理,导致本地缓存长期残留旧的购买状态
修复方案

1. 修正异步逻辑时序

所有购买列表的判断、处理逻辑必须放到onQueryPurchasesResponse回调内部执行,禁止在回调外访问共享的列表变量,避免时序问题读取旧数据。
修正后代码示例:

private void queryPurchasesAsync() {
    if(mBillingClient.isReady()) {
        LogUtils.LOGI(TAG, "queryPurchasesAsync");
        billingClient.queryPurchasesAsync(BillingClient.SkuType.INAPP, new PurchasesResponseListener() {
            @Override
            public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> list) {
                LogUtils.LOGI(TAG, "queryPurchasesAsync list" + list);
                // 所有列表处理逻辑移到回调内部执行
                handlePurchaseList(list);
            }
        });
    }
}

private void handlePurchaseList(List<Purchase> purchaseList) {
    LogUtils.LOGI(TAG, "QUE_PUR_LIST_SIZE " + purchaseList.size()); 
    for (Purchase pur : purchaseList) {
        String thisSku = pur.getSkus().get(0);
        int purchaseState = pur.getPurchaseState();
        LogUtils.LOGI(TAG, "pur.getPurchase state " + purchaseState);
        // 已购买判断需要同时校验状态和确认状态
        if (purchaseState == Purchase.PurchaseState.PURCHASED && pur.isAcknowledged()) {
            // 执行已购买逻辑
        } else if (purchaseState == Purchase.PurchaseState.UNSPECIFIED_STATE) {
            // 退款订单调用消耗接口清除本地缓存
            consumePurchase(pur);
        }
    }
}

private void consumePurchase(Purchase purchase) {
    ConsumeParams consumeParams = ConsumeParams.newBuilder()
            .setPurchaseToken(purchase.getPurchaseToken())
            .build();
    mBillingClient.consumeAsync(consumeParams, (billingResult, purchaseToken) -> {
        // 消耗完成后该订单下次查询不会再返回
    });
}

2. 升级Billing库版本

将Google Play Billing依赖升级到最新稳定版,规避旧版本的底层bug。

3. 增加服务端校验

不要完全依赖客户端返回的购买状态,将purchaseToken传到自有服务端调用Google Play Developer API查询订单真实状态,避免本地缓存异常或者客户端篡改导致的误判。

4. 及时处理订单

消耗型商品购买完成后及时调用consumeAsync消耗,非消耗型商品及时调用确认接口,避免无效订单残留。


内容的提问来源于stack exchange,提问作者sejn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:45:05