Flutter中如何检查Play Store订阅续订及处理多购买记录?
Flutter in_app_purchase订阅续订失效与状态检查解决方案
一、获取并筛选最新订阅记录
Play Store会为每次续订生成新的购买记录,必须从历史记录中筛选出最新的有效订阅,这是解决续订失效的核心。
实现步骤:
- 调用
InAppPurchase.instance.queryPastPurchases()获取所有历史购买记录; - 过滤出订阅类型且状态为已购买/已恢复的记录;
- 按到期日期(优先)或购买日期排序,取最新的一条。
代码示例:
Future<PurchaseDetails?> getLatestActiveSubscription() async { final response = await InAppPurchase.instance.queryPastPurchases(); if (response.error != null) { // 处理查询错误(如网络问题) return null; } // 筛选目标订阅的有效记录 final activeSubs = response.pastPurchases.where((purchase) { return purchase.productID == "你的订阅商品ID" // 替换为实际商品ID && purchase.purchaseType == PurchaseType.subscription && (purchase.status == PurchaseStatus.purchased || purchase.status == PurchaseStatus.restored); }).toList(); if (activeSubs.isEmpty) return null; // 按到期日期倒序,取最晚到期的订阅 activeSubs.sort((a, b) { final aExpiry = a.subscriptionPurchaseDetails?.expiryDate ?? a.purchaseDate!; final bExpiry = b.subscriptionPurchaseDetails?.expiryDate ?? b.purchaseDate!; return bExpiry.compareTo(aExpiry); }); return activeSubs.first; }
二、检查订阅状态与过期日期
拿到最新订阅记录后,通过subscriptionPurchaseDetails字段获取订阅的核心信息:
关键字段说明:
autoRenewing:是否开启自动续订;expiryDate:订阅到期时间;purchaseDate:购买/续订时间(兜底用)。
状态检查代码:
Future<bool> isSubscriptionActive() async { final latestSub = await getLatestActiveSubscription(); if (latestSub == null) return false; final expiryDate = latestSub.subscriptionPurchaseDetails?.expiryDate; if (expiryDate != null) { // 直接用到期日期判断是否活跃 return expiryDate.isAfter(DateTime.now()); } // 极端情况(如无到期日期),用购买日期加套餐天数兜底 final purchaseDate = latestSub.purchaseDate!; return purchaseDate.add(const Duration(days: 30)).isAfter(DateTime.now()); // 替换为你的套餐天数 }
三、修复续订失效问题
之前只依赖首次购买的purchaseDate计算有效期,忽略了续订后的新记录和到期日期,调整逻辑如下:
1. 监听所有购买状态更新
通过purchaseStream监听包括续订在内的所有购买事件,触发有效期更新:
StreamSubscription<List<PurchaseDetails>>? _purchaseStreamSub; void initPurchaseListener() { _purchaseStreamSub = InAppPurchase.instance.purchaseStream.listen( (purchaseList) => _handlePurchaseUpdates(purchaseList), onError: (err) => print("购买流错误: $err"), onDone: () => _purchaseStreamSub?.cancel(), ); } void _handlePurchaseUpdates(List<PurchaseDetails> purchaseList) { for (final purchase in purchaseList) { if (purchase.status == PurchaseStatus.purchased || purchase.status == PurchaseStatus.restored) { // 无论首次购买还是续订,都重新同步最新订阅状态 _updateUserSubscriptionValidity(); } } } Future<void> _updateUserSubscriptionValidity() async { final latestSub = await getLatestActiveSubscription(); if (latestSub == null) { // 无活跃订阅,重置本地有效期记录 final prefs = await SharedPreferences.getInstance(); await prefs.remove("subscription_expiry"); return; } // 将最新到期日期保存到本地,方便快速判断 final expiryDate = latestSub.subscriptionPurchaseDetails?.expiryDate; if (expiryDate != null) { final prefs = await SharedPreferences.getInstance(); await prefs.setString("subscription_expiry", expiryDate.toIso8601String()); } }
2. 应用启动时同步状态
每次启动应用都调用_updateUserSubscriptionValidity(),避免应用关闭期间续订导致状态不一致。
新手注意事项
- 确保Play Console中订阅商品已开启自动续订;
- 不要仅依赖本地保存的到期日期,定期调用
queryPastPurchases()同步最新状态; - 处理用户取消订阅的情况:
autoRenewing变为false时,到期后订阅失效。
内容的提问来源于stack exchange,提问作者K_Chandio
相关产品推荐
相关产品推荐

