Android Google Play订阅支付makePurchase方法无响应,无法唤起支付窗口求助
遇到这种没日志、没报错但代码突然卡住的情况确实挺闹心的,我结合你贴的代码,梳理几个大概率的问题点,你可以逐一排查:
1. 订阅支付必须指定Offer Token(最可能的原因)
你之前做一次性内购的时候,创建ProductDetailsParams只需要传入商品详情就行,但**订阅是必须指定具体的优惠/计划令牌(Offer Token)**的!你的代码里只调用了setProductDetails(productDetails),完全没处理订阅的offer信息,这会直接导致launchBillingFlow无法正常触发支付窗口。
解决办法:
从productDetails里获取订阅的offer详情,取出对应的token传入。比如取第一个默认的基础计划:
private void makePurchase(ProductDetails productDetails) { Print.e("makePurchase: " + productDetails.getName()); // 先获取订阅的offer详情,订阅必须指定offer token List<ProductDetails.SubscriptionOfferDetails> offerDetailsList = productDetails.getSubscriptionOfferDetails(); if (offerDetailsList == null || offerDetailsList.isEmpty()) { Print.e("makePurchase: 没有可用的订阅计划"); return; } // 取第一个默认的offer(可根据业务需求选择特定优惠计划) ProductDetails.SubscriptionOfferDetails offerDetails = offerDetailsList.get(0); List<BillingFlowParams.ProductDetailsParams> productDetailsParamsList = ImmutableList.of( BillingFlowParams.ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(offerDetails.getOfferToken()) // 必须添加这一行! .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); try { BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams); Print.e("billingResult: " + billingResult.getResponseCode() + " getDebugMessage: " + billingResult.getDebugMessage() + " toString: " + billingResult.toString()); } catch (Exception e) { Print.e("makePurchase 抛出异常: " + e.getMessage(), e); } }
2. ImmutableList创建方式有误
你用ImmutableList.from()来创建列表,但from()方法需要传入Iterable类型的参数(比如List),而你直接传了单个ProductDetailsParams对象,这会触发运行时异常!只是因为代码在异步回调里,没有被捕获,所以没打日志。
应该换成支持直接传入单个元素的ImmutableList.of():
// 错误写法 ImmutableList.from(BillingFlowParams.ProductDetailsParams.newBuilder().build()); // 正确写法 ImmutableList.of(BillingFlowParams.ProductDetailsParams.newBuilder().build());
3. 检查BillingClient的连接状态
在调用launchBillingFlow之前,一定要确保billingClient处于已连接状态。虽然你在onBillingSetupFinished里调用了queryProduct,但如果中间连接意外断开,后续调用就会无响应。建议在makePurchase开头加个判断:
if (!billingClient.isReady()) { Print.e("makePurchase: BillingClient未连接,尝试重新连接"); // 这里可以重新调用startConnection,或者通知用户稍后重试 return; }
4. 添加异常捕获排查问题
因为queryProductDetailsAsync的回调是在异步线程里,如果这里抛出异常,默认不会打印到日志里(除非你有全局异常处理器)。给makePurchase方法加个try-catch,把异常信息打出来,就能明确知道到底哪里出问题了。
你可以先优先排查前两个点,这两个是最可能导致你当前问题的原因,应该能解决无法唤起支付窗口的问题。
备注:内容来源于stack exchange,提问作者stavros.3p

