如何在已集成Google Pay的Flutter应用中实现内购订阅功能
Flutter 订阅类应用内购实现方案(Google Play 已集成)
假设你已经完成Google Play开发者账号配置与基础支付集成,下面直接上三种订阅模式的实战落地步骤:
一、先在Google Play Console完成产品配置
在后台创建三个对应模式的订阅产品,每个分配唯一productId:
- 试用期自动续订:
com.yourapp.premium_trial(设置7天免费试用,到期自动扣月度费用,用户不主动取消则持续续订) - 直接月度自动续订:
com.yourapp.premium_monthly_auto(无试用期,按月自动扣费) - 非自动续订月度:
com.yourapp.premium_monthly_one_time(选择「预付费订阅」类型,设置30天有效期,到期不自动续订,需用户再次购买)
注意配置好各地区定价、货币规则,确保产品状态为可发布。
二、用in_app_purchase插件实现客户端逻辑
使用Flutter官方推荐的in_app_purchase插件,先添加依赖:
dependencies: in_app_purchase: ^3.1.10
初始化与购买流监听
在应用根组件或启动页初始化插件,监听购买状态变化:
final InAppPurchase _inAppPurchase = InAppPurchase.instance; StreamSubscription<List<PurchaseDetails>>? _purchaseSubscription; @override void initState() { super.initState(); final purchaseStream = _inAppPurchase.purchaseStream; _purchaseSubscription = purchaseStream.listen(_handlePurchaseUpdates, onError: (err) { // 处理网络中断、支付异常等情况 }); } @override void dispose() { _purchaseSubscription?.cancel(); super.dispose(); }
加载订阅产品信息
拉取Google Play后台配置的产品详情(价格、试用期、描述等),用于UI展示:
const _subscriptionIds = [ 'com.yourapp.premium_trial', 'com.yourapp.premium_monthly_auto', 'com.yourapp.premium_monthly_one_time', ]; List<ProductDetails> _availableProducts = []; Future<void> loadSubscriptionProducts() async { final response = await _inAppPurchase.queryProductDetails(_subscriptionIds.toSet()); if (response.notFoundIDs.isNotEmpty) { print('未找到的产品ID:${response.notFoundIDs}'); // 检查后台是否配置正确 return; } _availableProducts = response.productDetails; // 更新UI展示产品列表 }
三、三种订阅模式的购买实现
1. 试用期后自动续订
找到对应产品发起购买,Google Play会自动处理试用期与后续续订逻辑:
void buyTrialSubscription() { final trialProduct = _availableProducts.firstWhere((p) => p.id == 'com.yourapp.premium_trial'); final purchaseParam = PurchaseParam(productDetails: trialProduct); _inAppPurchase.buySubscriptions(purchaseParam: purchaseParam); }
2. 直接月度自动续订
逻辑与试用期订阅一致,更换产品ID即可:
void buyMonthlyAutoSubscription() { final autoProduct = _availableProducts.firstWhere((p) => p.id == 'com.yourapp.premium_monthly_auto'); final purchaseParam = PurchaseParam(productDetails: autoProduct); _inAppPurchase.buySubscriptions(purchaseParam: purchaseParam); }
3. 非自动续订预付费订阅
Google将预付费订阅归为订阅类型,同样使用buySubscriptions方法:
void buyOneTimeMonthlySubscription() { final oneTimeProduct = _availableProducts.firstWhere((p) => p.id == 'com.yourapp.premium_monthly_one_time'); final purchaseParam = PurchaseParam(productDetails: oneTimeProduct); _inAppPurchase.buySubscriptions(purchaseParam: purchaseParam); }
四、购买结果处理与验证
核心处理函数_handlePurchaseUpdates,覆盖所有购买状态:
void _handlePurchaseUpdates(List<PurchaseDetails> purchases) { for (final purchase in purchases) { switch (purchase.status) { case PurchaseStatus.pending: // 显示加载弹窗,告知用户正在处理支付 break; case PurchaseStatus.error: // 支付失败,提示用户(如网络问题、主动取消) _showError(purchase.error!.message); break; case PurchaseStatus.purchased: case PurchaseStatus.restored: // 必须做服务器端验证,禁止仅依赖客户端判断 final isValid = await _verifyPurchaseOnServer(purchase); if (isValid) { // 验证通过,开通高级权限(更新本地状态或后端用户数据) _unlockPremiumFeatures(purchase); // 告知Google Play订单处理完成 if (purchase.pendingCompletePurchase) { await _inAppPurchase.completePurchase(purchase); } } else { _showError('订阅验证失败,请联系客服'); } break; } } }
服务器端验证(关键)
将客户端获取的purchase.verificationData.serverVerificationData(订单令牌)传到后端,调用Google Play Developer API验证:
- 请求地址:
https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{你的包名}/purchases/subscriptions/{productId}/tokens/{订单令牌} - 验证返回的
expiryTimeMillis、autoRenewing等字段,确认订阅有效性 - 将验证结果返回给客户端,再决定是否开通权限
五、订阅状态同步与权限管理
- 恢复购买:用户换设备/重装应用时,调用
_inAppPurchase.restorePurchases()恢复历史订阅,走上述验证流程 - 定期同步:自动续订订阅可能被用户在Google Play取消或到期,需:
- 后端每日定时批量调用Google Play API,更新用户订阅状态到数据库
- 客户端启动/切换到会员页时,从后端拉取最新状态,同步UI与权限
六、测试注意事项
- 使用Google Play内部测试账号,或设置0元测试订阅
- 测试取消订阅:在Google Play「订阅管理」手动取消,验证客户端状态同步
- 测试退款:在后台给测试订单退款,确认后端能收到通知并更新用户权限
内容的提问来源于stack exchange,提问作者coder lover
相关产品推荐
相关产品推荐

