购买iap_lifetime内购包后VIP身份无法验证,请求排查代码问题
问题分析:内购“iap_lifetime”购买后未被识别为VIP
用户集成了以下检查VIP状态的代码,用户购买永久内购包“iap_lifetime”后,系统未识别其VIP身份。已在购买回调中调用acknowledgePurchase方法,不确定是否为代码问题。
确认购买的代码实现
val acknowledgeParams = AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.purchaseToken) .build() client.acknowledgePurchase(acknowledgeParams) { billingResult: BillingResult -> runOnUiThread { processingPurchaseTokens.remove(purchase.purchaseToken) if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) { val productId = purchase.products.firstOrNull() ?: "" AdAnalyticsHelper.trackIapRevenue(purchase, productDetailsMap[productId]) } else { showToast("Acknowledge failed: ${billingResult.debugMessage}") } finalizeVipActivation(grant) } }
检查VIP状态的代码实现
fun checkSubscription() { try { val billingClient = BillingClient.newBuilder(this) .enablePendingPurchases() .setListener { _, _ -> } .build() billingClient.startConnection(object : BillingClientStateListener { override fun onBillingServiceDisconnected() { } override fun onBillingSetupFinished(billingResult: BillingResult) { if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) { VipManager.setVip(false) return } // Check SUBS billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder() .setProductType(BillingClient.ProductType.SUBS) .build() ) { subsResult, subsList -> var isVip = false if (subsResult.responseCode == BillingClient.BillingResponseCode.OK) { isVip = subsList.any { purchase -> purchase.purchaseState == Purchase.PurchaseState.PURCHASED && purchase.products.isNotEmpty() } } if (!isVip) { billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder() .setProductType(BillingClient.ProductType.INAPP) .build() ) { inAppResult, inAppList -> if (inAppResult.responseCode == BillingClient.BillingResponseCode.OK) { isVip = inAppList.any { purchase -> purchase.purchaseState == Purchase.PurchaseState.PURCHASED && purchase.products.contains("iap_lifetime") } } VipManager.setVip(isVip) } } else { VipManager.setVip(true) } } } }) } catch (_: Exception) { } }
可能的问题点及修复建议
1. 确认购买后的VIP状态更新逻辑缺失
当前代码在确认购买成功后调用了finalizeVipActivation(grant),但未明确该方法是否会直接将用户标记为VIP。建议:
- 在
acknowledgePurchase成功回调中,当productId为“iap_lifetime”时,直接调用VipManager.setVip(true),无需依赖后续的checkSubscription查询,避免查询延迟或失败导致的状态不更新。 - 检查
grant参数是否正确传递了VIP激活的标识,确保finalizeVipActivation方法逻辑正确。
2. checkSubscription方法的异常处理不合理
方法中捕获所有异常但未做任何处理,若BillingClient连接、查询过程中出现异常,会导致VipManager.setVip无法执行,VIP状态停留在之前的错误值。建议:
- 在catch块中添加默认处理,比如
VipManager.setVip(false),同时可添加日志记录异常信息,方便排查问题。
3. 内购查询未处理未确认的购买
Google Play中,购买成功但未确认的订单,purchaseState仍为Purchase.PurchaseState.PURCHASED,但长期未确认会被自动退款。当前查询逻辑未检查购买是否已确认,可能导致状态判断混乱。建议:
- 在INAPP购买的判断条件中,增加
purchase.isAcknowledged检查,确保只将已确认的“iap_lifetime”购买标记为VIP:isVip = inAppList.any { purchase -> purchase.purchaseState == Purchase.PurchaseState.PURCHASED && purchase.isAcknowledged && purchase.products.contains("iap_lifetime") }
4. 检查ProductId的匹配准确性
确认代码中使用的“iap_lifetime”与Google Play Console中配置的内购商品ID完全一致,注意大小写、拼写错误,这是常见的排查点。
5. BillingClient实例管理优化
每次调用checkSubscription都新建BillingClient实例,虽然功能正常,但可能增加连接开销。建议复用全局的BillingClient实例,避免重复创建和连接。
内容的提问来源于stack exchange,提问作者Hải Đào Ngọc
相关产品推荐
相关产品推荐

