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
相关产品推荐
相关产品推荐

