使用Unity IAP实现安卓应用订阅升降级遇到空引用错误如何解决
报错根本原因
你代码里触发空引用异常的核心问题出在遍历商品的逻辑顺序:
- 你在未判断
p.hasReceipt是否为真的前提下,直接调用new GooglePurchaseData(p.receipt)构造收据对象。当遍历到没有购买记录的商品时,p.receipt为null,直接传入构造函数就会触发空引用异常,和你logcat输出的报错完全吻合。 - 另外还存在两个潜在风险:
- 遍历到第一个有收据的商品就直接中断,没有校验该订阅是否仍在生效周期内,可能传入过期订阅的商品对象触发后续升级接口报错
- 拿到
data.json.productId重新查找oldProduct后,没有校验oldProduct.receipt是否存在就直接构造第二个GooglePurchaseData,极端场景下也会触发空引用
修复方案
调整遍历逻辑的执行顺序,增加必要的空校验,修改后的代码如下:
public void Buy1YearSubscription() { print("trying to buy 12 months of subscription"); bool alreadyHaveSomeSubscription = false; Product oldProduct = null; // 先遍历所有商品,找有效订阅 foreach (Product p in m_StoreController.products.all) { // 先判断有没有收据,再处理后续逻辑 if (p.hasReceipt && !string.IsNullOrEmpty(p.receipt)) { GooglePurchaseData data = new GooglePurchaseData(p.receipt); // 可选:加订阅有效性校验,比如判断过期时间大于当前时间,避免拿过期订阅升级 // if(data.json.purchaseTime + 订阅时长 > 现在时间) 再往下走 alreadyHaveSomeSubscription = true; oldProduct = p; // 直接用当前遍历到的有效商品,不用再重新查一次,减少空引用风险 print("Has the receipt of-----" + data.json.productId); break; } } if (!alreadyHaveSomeSubscription || oldProduct == null) { print("no previous valid subscription"); BuyProductID(_1YearSubscription); } else { print("upgrading to 1year"); Product newProduct = m_StoreController.products.WithID(_1YearSubscription); // 额外校验新商品是否存在,避免空引用 if(newProduct == null) { Debug.LogError("New subscription product not found"); return; } SubscriptionManager.UpdateSubscriptionInGooglePlayStore(oldProduct, newProduct, (string msg1, string msg2) => { IgoogleplayStoreExtention.UpdateSubscription(oldProduct, newProduct, GooglePlayStoreProrationMode.ImmediateWithoutProration); }); } }
额外排查点
如果修改后仍有报错,可以检查以下两点:
- 确保Google Play控制台里三个订阅档位都属于同一个订阅组,否则无法跨组升级
- 内部测试阶段请用配置的测试账号购买订阅,不要用正式账号,避免缓存的收据数据异常
内容的提问来源于stack exchange,提问作者Ashish Rana
相关产品推荐
相关产品推荐

