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

Android In-app Billing 5.0.0:如何判断调用consumeAsync还是acknowledgePurchase?

解决Billing 5.0.0中Purchase无ProductType时的方法区分问题

我之前在集成Billing 5.0.0的时候也踩过这个坑——确实,onPurchasesUpdated返回的Purchase列表里没有直接携带ProductType标识,但其实有几个靠谱的方案来区分该调用consumeAsync还是acknowledgePurchase:

  • 提前维护产品ID与类型的映射表
    这是最直接且高效的方案。因为你界面上展示的所有订阅和内购产品都是你自己在Google Play Console配置的,完全可以在本地提前创建一个映射关系,比如用Map<String, String>来存储:

    Map<String, String> productTypeMap = new HashMap<>();
    // 消耗型内购产品
    productTypeMap.put("your_consumable_product_id", BillingClient.ProductType.INAPP);
    // 订阅产品
    productTypeMap.put("your_subscription_product_id", BillingClient.ProductType.SUBS);
    

    当onPurchasesUpdated回调触发时,只需要取出每个Purchase的getProductIds()(注意多产品购买的情况),去映射表里查对应的类型:

    • 如果是INAPP且为消耗型,调用consumeAsync;
    • 如果是INAPP非消耗型或者SUBS,调用acknowledgePurchase。
  • 通过查询SkuDetails补全产品类型
    如果因为某些原因没法提前维护映射表,可以拿到Purchase的产品ID后,调用querySkuDetailsAsync接口去获取完整的产品信息:

    SkuDetailsParams params = SkuDetailsParams.newBuilder()
        .setSkusList(Collections.singletonList(purchase.getProducts().get(0)))
        .setType(BillingClient.SkuType.INAPP) // 先查内购,没查到再查订阅
        .build();
    
    billingClient.querySkuDetailsAsync(params, new SkuDetailsResponseListener() {
        @Override
        public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {
            if (skuDetailsList != null && !skuDetailsList.isEmpty()) {
                String productType = skuDetailsList.get(0).getType();
                // 根据类型调用对应的方法
                if (BillingClient.ProductType.INAPP.equals(productType)) {
                    // 判断是否为消耗型,然后调用consumeAsync或acknowledgePurchase
                } else {
                    // 订阅产品调用acknowledgePurchase
                }
            } else {
                // 查订阅类型
                SkuDetailsParams subParams = SkuDetailsParams.newBuilder()
                    .setSkusList(Collections.singletonList(purchase.getProducts().get(0)))
                    .setType(BillingClient.SkuType.SUBS)
                    .build();
                billingClient.querySkuDetailsAsync(subParams, ...);
            }
        }
    });
    

    不过这个方案需要额外的网络请求,会有一定延迟,所以优先推荐第一个方案。

  • 关键注意点

    • 消耗型产品必须调用consumeAsync,否则用户无法再次购买该产品;
    • 非消耗型内购和订阅产品必须调用acknowledgePurchase,否则Google Play会在3天后自动退款给用户;
    • 如果是多产品购买的情况,要遍历每个产品ID分别判断类型,再做对应的处理。

内容的提问来源于stack exchange,提问作者Om Infowave Developers

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 13:07:32