diff --git a/lib/app/modules/kr_home/controllers/kr_home_controller.dart b/lib/app/modules/kr_home/controllers/kr_home_controller.dart index 35d99d1..e34152a 100755 --- a/lib/app/modules/kr_home/controllers/kr_home_controller.dart +++ b/lib/app/modules/kr_home/controllers/kr_home_controller.dart @@ -37,6 +37,8 @@ import 'package:flutter/foundation.dart'; import 'package:kaer_with_panels/app/utils/kr_init_log_collector.dart'; // 🔧 新增:导入日志收集器 import 'package:kaer_with_panels/app/utils/kr_latency_tester.dart'; // 🔧 新增:导入真实延迟测试工具 import 'package:kaer_with_panels/app/utils/account_guard.dart'; +import 'package:kaer_with_panels/app/services/iap/iap_service.dart'; + class KRHomeController extends GetxController with WidgetsBindingObserver { // 🔧 新增:日志收集器实例 diff --git a/lib/app/modules/kr_purchase_membership/controllers/kr_purchase_membership_controller.dart b/lib/app/modules/kr_purchase_membership/controllers/kr_purchase_membership_controller.dart index b3e60fc..38bd9ce 100755 --- a/lib/app/modules/kr_purchase_membership/controllers/kr_purchase_membership_controller.dart +++ b/lib/app/modules/kr_purchase_membership/controllers/kr_purchase_membership_controller.dart @@ -23,6 +23,7 @@ import 'dart:async'; import 'package:kaer_with_panels/app/model/response/kr_purchase_order_no.dart'; import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart'; import 'package:kaer_with_panels/app/services/iap/iap_pending_order_service.dart'; +import 'package:kaer_with_panels/app/services/iap/iap_service.dart'; /// 会员购买控制器 /// 负责处理会员套餐选择、支付方式选择和订阅流程 @@ -55,9 +56,6 @@ class KRPurchaseMembershipController extends GetxController { /// 当前余额 RxInt _kr_balance = 0.obs; - // -------------------- IAP 全局监听 -------------------- - late StreamSubscription> _iapSubscription; - @override void onInit() async { super.onInit(); @@ -85,22 +83,11 @@ class KRPurchaseMembershipController extends GetxController { print('💳 [PurchaseMembership] ❌ 写入调试日志失败: $e'); } - // 初始化 IAP 全局监听 - if (Platform.isIOS) { - _iapSubscription = InAppPurchase.instance.purchaseStream.listen( - _handleIapUpdates, - onError: (error) { - print('IAP Stream Error: $error'); - }, - ); - } - kr_initializeData(); } @override void onClose() { - _iapSubscription.cancel(); _kr_eventWorker?.dispose(); super.onClose(); } @@ -461,21 +448,26 @@ class KRPurchaseMembershipController extends GetxController { print('开始订阅流程,选定支付'); kr_errorMessage.value = ''; - // ✅ 仅在 iOS 检查未完成订单 + // ✅ 1. iOS 核心拦截:检测本地是否有“挂起”的订单号 if (Platform.isIOS) { - final existing = await IAPPendingOrderService.getPendingOrderNo(); - if (existing != null && existing.isNotEmpty) { + final existingOrderNo = await IAPPendingOrderService.getPendingOrderNo(); + + if (existingOrderNo != null && existingOrderNo.isNotEmpty) { + print('🛑 [IAP] 拦截成功:发现未结单 $existingOrderNo'); + await HIDialog.show( - title: '存在未完成订单', - message: '检测到未完成订单,需要恢复购买以完成订阅。', - confirmText: '恢复购买', + title: '检测到待激活订单', + message: '您有一笔订单已支付成功,但尚未同步会员权益。请点击“立即激活”完成同步。', + confirmText: '立即激活', + cancelText: '取消', barrierDismissible: false, - preventBackDismiss: true, onConfirm: () { - kr_restorePurchases(); // 恢复未完成订单 + // 🚀 调用全局 Service 的重试逻辑 + // 这会触发苹果重新推送 PurchaseStream,进而走验证流程 + KRIAPService.instance.retryUnfinishedTransactions(); }, ); - return; // 等待恢复完成,不再继续发起新订阅 + return; // 🛑 关键:必须 return,阻止创建重复的新订单 } } @@ -1008,9 +1000,10 @@ class KRPurchaseMembershipController extends GetxController { // ---------------------------------------------------------------------- // ProductDetails 已成功获取,并已构造 purchaseParam。 // ---------------------------------------------------------------------- - await IAPPendingOrderService.setPendingOrderNo(orderNo); - KRCommonUtil.kr_showLoading(); + try { + await IAPPendingOrderService.setPendingOrderNo(orderNo); + KRCommonUtil.kr_showLoading(); final result = await iap.buyNonConsumable(purchaseParam: purchaseParam); if (!result) { @@ -1030,67 +1023,6 @@ class KRPurchaseMembershipController extends GetxController { ); } - // -------------------- IAP 统一处理 -------------------- - void _handleIapUpdates(List purchases) async { - final iap = InAppPurchase.instance; - final pendingOrderNo = await IAPPendingOrderService.getPendingOrderNo(); - print('p.pendingOrderNo ${pendingOrderNo}'); - if (pendingOrderNo == null || pendingOrderNo.isEmpty) return; - - for (final p in purchases) { - print('p.status ${p.status}'); - if (p.status == PurchaseStatus.pending) continue; - - if (p.status == PurchaseStatus.error) { - if (p.pendingCompletePurchase) await iap.completePurchase(p); - KRCommonUtil.kr_showToast('购买失败'); - continue; - } - - if (p.status == PurchaseStatus.purchased || p.status == PurchaseStatus.restored) { - KRCommonUtil.kr_showLoading(); - bool ok = false; - final either = await _kr_subscribeApi.kr_attachAppleIapTransaction(p.purchaseID!, pendingOrderNo); - either.fold((e) {}, (v) => ok = true); - // if (p.status == PurchaseStatus.purchased) { - // - // either.fold((e) {}, (v) => ok = true); - // } else if (p.status == PurchaseStatus.restored) { - // final either = await _kr_subscribeApi.kr_restoreAppleIapTransaction(p.purchaseID!, pendingOrderNo); - // either.fold((e) {}, (v) => ok = true); - // } - - // ❌ 服务端失败,必须给用户反馈 - if (!ok) { - KRCommonUtil.kr_hideLoading(); - HIDialog.show( - title: '激活失败,请稍后重试', - message: '检测到未完成订单,需要恢复购买以完成订阅。', - confirmText: '恢复购买', - cancelText: '关闭', - barrierDismissible: false, - preventBackDismiss: true, - onConfirm: () { - kr_restorePurchases(); // 恢复未完成订单 - }, - ); - return; - } - - if (p.pendingCompletePurchase) await iap.completePurchase(p); - await IAPPendingOrderService.clearPendingOrderNo(); - KRCommonUtil.kr_hideLoading(); - Get.toNamed( - Routes.KR_ORDER_STATUS, - arguments: { - 'order': pendingOrderNo, - 'payment_type': 'apple_iap', - 'checkout_type': 'ipa', - }, - ); - } - } - } Future kr_restorePurchases({bool isShowLoading = true}) async { print('重试'); diff --git a/lib/app/modules/kr_purchase_membership/views/kr_purchase_membership_view.dart b/lib/app/modules/kr_purchase_membership/views/kr_purchase_membership_view.dart index 43c3b1c..2e5b1a6 100755 --- a/lib/app/modules/kr_purchase_membership/views/kr_purchase_membership_view.dart +++ b/lib/app/modules/kr_purchase_membership/views/kr_purchase_membership_view.dart @@ -19,6 +19,8 @@ import 'package:kaer_with_panels/app/widgets/swipe/swipe_config.dart'; import 'dart:convert'; import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart'; import '../../../routes/app_pages.dart'; +import 'package:kaer_with_panels/app/services/iap/iap_service.dart'; + /// 购买会员页面视图 @@ -201,9 +203,9 @@ class KRPurchaseMembershipView extends GetView } return Center( child: GestureDetector( - onTap: () { + onTap: () async{ // 异步处理补单 - controller.kr_restorePurchases(isShowLoading: false); // 恢复未完成订单 + await KRIAPService.instance.retryUnfinishedTransactions(); HIDialog.show( title: '温馨提示', message: '购买订单已确认,请耐心等待。若时长未到账,请联系在线客服处理。', diff --git a/lib/app/services/api_service/api.dart b/lib/app/services/api_service/api.dart index 91d9588..8124405 100755 --- a/lib/app/services/api_service/api.dart +++ b/lib/app/services/api_service/api.dart @@ -112,7 +112,7 @@ abstract class Api { static const String kr_getPublicPaymentMethods = "/v1/public/payment/methods"; static const String kr_attachAppleIapTransaction = - "/v1/public/iap/apple/transactions/attach_by_id"; + "/v1/public/iap/apple/transactions/attach"; static const String kr_restoreAppleIap = "/v1/public/iap/apple/restore"; /// 获取用户信息(用于获取邀请码等) diff --git a/lib/app/services/api_service/kr_subscribe_api.dart b/lib/app/services/api_service/kr_subscribe_api.dart index 528c59c..ea3085b 100755 --- a/lib/app/services/api_service/kr_subscribe_api.dart +++ b/lib/app/services/api_service/kr_subscribe_api.dart @@ -332,9 +332,9 @@ class KRSubscribeApi { } Future> kr_attachAppleIapTransaction( - String transactionId, String orderNo) async { + String jwsData, String orderNo) async { final Map data = {}; - data['transaction_id'] = transactionId; + data['signed_transaction_jws'] = jwsData; data['order_no'] = orderNo; BaseResponse baseResponse = diff --git a/lib/app/services/iap/iap_pending_order_service.dart b/lib/app/services/iap/iap_pending_order_service.dart new file mode 100644 index 0000000..be20964 --- /dev/null +++ b/lib/app/services/iap/iap_pending_order_service.dart @@ -0,0 +1,17 @@ +import 'package:flutter_keychain/flutter_keychain.dart'; + +class IAPPendingOrderService { + static const _key = 'hi_iap_pending_order_no'; + + static Future setPendingOrderNo(String orderNo) async { + await FlutterKeychain.put(key: _key, value: orderNo); + } + + static Future getPendingOrderNo() async { + return await FlutterKeychain.get(key: _key); + } + + static Future clearPendingOrderNo() async { + await FlutterKeychain.remove(key: _key); + } +} diff --git a/lib/app/services/iap/iap_service.dart b/lib/app/services/iap/iap_service.dart new file mode 100644 index 0000000..e13f44a --- /dev/null +++ b/lib/app/services/iap/iap_service.dart @@ -0,0 +1,175 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:get/get.dart'; +import 'package:in_app_purchase/in_app_purchase.dart'; +import 'package:kaer_with_panels/app/services/iap/iap_pending_order_service.dart'; +import 'package:kaer_with_panels/app/utils/kr_common_util.dart'; +import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart'; +import 'package:kaer_with_panels/app/services/api_service/kr_subscribe_api.dart'; +import 'package:kaer_with_panels/app/routes/app_pages.dart'; + +class KRIAPService extends GetxService { + static KRIAPService get instance => Get.find(); + + final KRSubscribeApi _kr_subscribeApi = KRSubscribeApi(); + final InAppPurchase _iap = InAppPurchase.instance; + StreamSubscription>? _subscription; +// 增加标志位,防止多次初始化 + bool _hasStarted = false; + + @override + void onInit() { + super.onInit(); + // 不再这里自动启动,等待 Home 页面手动开启 + } + + /// 【外部调用】在 Home 页面加载完成后调用此方法 + void setup() { + if (!Platform.isIOS) return; + if (_hasStarted) return; + _hasStarted = true; + _startGlobalListening(); + } + + void _startGlobalListening() { + print('💳 [IAPService] ========== 🚀 全局监听流已就绪 =========='); + + // 确保不会重复监听 + _subscription?.cancel(); + + _subscription = _iap.purchaseStream.listen( + _handleIapUpdates, + onDone: () => _subscription?.cancel(), + onError: (error) { + print('💳 [IAPService] ❌ Stream Error: $error'); + // 如果发生错误,可以尝试重启流 + }, + ); + } + + // 1. 监听回调:只负责状态分流 + void _handleIapUpdates(List purchases) async { + final pendingOrderNo = await IAPPendingOrderService.getPendingOrderNo(); + + // 如果没有本地挂起的订单号,说明不是通过 App 正常发起的支付(或是已处理完的补单) + if (pendingOrderNo == null || pendingOrderNo.isEmpty) return; + + for (final p in purchases) { + print('🔄 [IAPService] 处理状态: ${p.status} | ID: ${p.purchaseID}'); + + if (p.status == PurchaseStatus.pending) continue; + + if (p.status == PurchaseStatus.error) { + if (p.pendingCompletePurchase) await _iap.completePurchase(p); + KRCommonUtil.kr_showToast('购买失败'); + KRCommonUtil.kr_hideLoading(); + continue; + } + + if (p.status == PurchaseStatus.purchased || p.status == PurchaseStatus.restored) { + // 核心:跳转到统一验证逻辑 + _verifyWithServer(p, pendingOrderNo); + } + } + } + + // 2. 统一验证逻辑:负责与后端交互、补单、UI 引导 + Future _verifyWithServer(PurchaseDetails p, String orderNo) async { + final String jwsData = p.verificationData.serverVerificationData; + + if (jwsData.isEmpty) { + print('❌ [IAPService] JWS 数据为空,跳过验证'); + if (p.pendingCompletePurchase) { + await InAppPurchase.instance.completePurchase(p); + } + KRCommonUtil.kr_hideLoading(); + return; + } + + KRCommonUtil.kr_showLoading(message: '正在激活会员权益...'); + bool ok = false; + + try { + // 根据状态选择对应的后端接口 + if (p.status == PurchaseStatus.purchased || p.status == PurchaseStatus.restored) { + final either = await _kr_subscribeApi.kr_attachAppleIapTransaction(jwsData, orderNo); + either.fold((e) => print('❌ [IAPService] 支付激活失败: ${e.msg}'), (v) => ok = true); + } else { + // 注意:restore 接口如果后端要求传 JWS,这里保持一致 + // final either = await _kr_subscribeApi.kr_restoreAppleIapTransaction(jwsData, orderNo); + // either.fold((e) => print('❌ [IAPService] 恢复激活失败: ${e.msg}'), (v) => ok = true); + } + } catch (e) { + print('🌐 [IAPService] 网络请求异常'); + } + + if (ok) { + await _finalizeTransaction(p, orderNo); + } else { + _handleVerificationFailure(p, orderNo); + } + } + + // 3. 验证成功后的收尾工作 + Future _finalizeTransaction(PurchaseDetails p, String orderNo) async { + print('✅ [IAPService] 验证成功,清理流程'); + + // I. 结束苹果事务(关键:防止重复推送) + if (p.pendingCompletePurchase) { + await _iap.completePurchase(p); + } + + // II. 清理本地拦截订单号 + await IAPPendingOrderService.clearPendingOrderNo(); + KRCommonUtil.kr_hideLoading(); + + // III. 跳转结果页 + // 如果已经在结果页了就不跳,或者根据路由判断 + if (!Get.currentRoute.contains(Routes.KR_ORDER_STATUS)) { + Get.offNamed( + Routes.KR_ORDER_STATUS, + arguments: { + 'order': orderNo, + 'payment_type': 'apple_iap', + 'checkout_type': 'ipa', + }, + ); + } + } + + // 4. 验证失败后的重试引导 + void _handleVerificationFailure(PurchaseDetails p, String orderNo) { + KRCommonUtil.kr_hideLoading(); + HIDialog.show( + title: '激活失败', + message: '您的支付已成功,但由于网络原因未能开启权益。', + confirmText: '重试激活', + cancelText: '关闭', + barrierDismissible: false, + preventBackDismiss: true, + onConfirm: () { + // 💡 重点:直接重新调用验证逻辑,不重复触发监听流 + _verifyWithServer(p, orderNo); + }, + ); + } + + // 5. 手动触发(用于 UI 上的恢复购买按钮) + Future retryUnfinishedTransactions() async { + try { + KRCommonUtil.kr_showLoading(message: '正在查找未完成订单...'); + await _iap.restorePurchases(); + // 如果 5 秒后没触发流,隐藏 loading + Future.delayed(const Duration(seconds: 5), () => KRCommonUtil.kr_hideLoading()); + } catch (e) { + KRCommonUtil.kr_hideLoading(); + KRCommonUtil.kr_showToast("请求失败,请稍后重试"); + } + } + + @override + void onClose() { + _subscription?.cancel(); + super.onClose(); + } +} \ No newline at end of file diff --git a/lib/app/utils/account_guard.dart b/lib/app/utils/account_guard.dart index 145ec85..b2d350c 100644 --- a/lib/app/utils/account_guard.dart +++ b/lib/app/utils/account_guard.dart @@ -5,6 +5,7 @@ import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart'; import 'package:kaer_with_panels/app/routes/app_pages.dart'; import 'package:kaer_with_panels/app/utils/kr_common_util.dart'; import 'package:kaer_with_panels/app/services/kr_site_config_service.dart'; +import 'package:kaer_with_panels/app/services/iap/iap_service.dart'; Future ensureAccountExists() async { final app = KRAppRunData.getInstance(); @@ -27,6 +28,7 @@ Future ensureAccountExists() async { return false; } + KRIAPService.instance.setup(); var crispId = config.kr_website_id; var deviceLimitText = config.device_limit; var deviceLimit = int.tryParse(deviceLimitText) ?? 0; diff --git a/pubspec.lock b/pubspec.lock index 45b36cb..fbc5fbc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,23 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" url: "https://pub.dev" source: hosted - version: "72.0.0" - _macros: - dependency: transitive - description: dart - source: sdk - version: "0.3.2" + version: "67.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" url: "https://pub.dev" source: hosted - version: "6.7.0" + version: "6.4.1" analyzer_plugin: dependency: transitive description: @@ -194,10 +189,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" color: dependency: transitive description: @@ -298,18 +293,10 @@ packages: dependency: transitive description: name: custom_lint_core - sha256: "02450c3e45e2a6e8b26c4d16687596ab3c4644dd5792e3313aa9ceba5a49b7f5" + sha256: a85e8f78f4c52f6c63cdaf8c872eb573db0231dcdf3c3a5906d493c1f8bc20e6 url: "https://pub.dev" source: hosted - version: "0.7.0" - custom_lint_visitor: - dependency: transitive - description: - name: custom_lint_visitor - sha256: "8aeb3b6ae2bb765e7716b93d1d10e8356d04e0ff6d7592de6ee04e0dd7d6587d" - url: "https://pub.dev" - source: hosted - version: "1.0.0+6.7.0" + version: "0.6.3" dart_earcut: dependency: transitive description: @@ -338,10 +325,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" url: "https://pub.dev" source: hosted - version: "2.3.7" + version: "2.3.6" dartx: dependency: "direct main" description: @@ -402,18 +389,18 @@ packages: dependency: transitive description: name: drift - sha256: af3941e4d544727b2eb80590eb64e9cb8d77cd68c7690265502ea6a2427aa621 + sha256: df027d168a2985a2e9da900adeba2ab0136f0d84436592cf3cd5135f82c8579c url: "https://pub.dev" source: hosted - version: "2.23.1" + version: "2.21.0" drift_dev: dependency: "direct dev" description: name: drift_dev - sha256: fa98fdbb7303a1b5b2dc110cb516eda2253a5d291680f8cbc72b1af24099f7f9 + sha256: "623649abe932fc17bd32e578e7e05f7ac5e7dd0b33e6c8669a0634105d1389bf" url: "https://pub.dev" source: hosted - version: "2.23.1" + version: "2.21.2" easy_refresh: dependency: "direct main" description: @@ -511,18 +498,18 @@ packages: dependency: transitive description: name: flutter_gen_core - sha256: "3eaa2d3d8be58267ac4cd5e215ac965dd23cae0410dc073de2e82e227be32bfc" + sha256: "53890b653738f34363d9f0d40f82104c261716bd551d3ba65f648770b6764c21" url: "https://pub.dev" source: hosted - version: "5.10.0" + version: "5.9.0" flutter_gen_runner: dependency: "direct dev" description: name: flutter_gen_runner - sha256: e74b4ead01df3e8f02e73a26ca856759dbbe8cb3fd60941ba9f4005cd0cd19c9 + sha256: de70b42eb5329f712c8b041069d081ad5fb5109f32d6d1ea9c1b39596786215d url: "https://pub.dev" source: hosted - version: "5.10.0" + version: "5.9.0" flutter_hooks: dependency: transitive description: @@ -705,10 +692,10 @@ packages: dependency: "direct dev" description: name: freezed - sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e" + sha256: a434911f643466d78462625df76fd9eb13e57348ff43fe1f77bbe909522c67a1 url: "https://pub.dev" source: hosted - version: "2.5.7" + version: "2.5.2" freezed_annotation: dependency: "direct main" description: @@ -873,10 +860,10 @@ packages: dependency: "direct main" description: name: in_app_purchase - sha256: "11a40f148eeb4f681a0572003e2b33432e110c90c1bbb4f9ef83b81ec0c4f737" + sha256: "5cddd7f463f3bddb1d37a72b95066e840d5822d66291331d7f8f05ce32c24b6c" url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.3" in_app_purchase_android: dependency: transitive description: @@ -894,13 +881,13 @@ packages: source: hosted version: "1.4.0" in_app_purchase_storekit: - dependency: transitive + dependency: "direct main" description: name: in_app_purchase_storekit - sha256: "6ce1361278cacc0481508989ba419b2c9f46a2b0dc54b3fe54f5ee63c2718fef" + sha256: aedbeea5beae10af3e5c380b65049842715b2bb014983e2a48b9006473f33cd9 url: "https://pub.dev" source: hosted - version: "0.3.22+1" + version: "0.4.4" intl: dependency: transitive description: @@ -961,10 +948,10 @@ packages: dependency: "direct dev" description: name: json_serializable - sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c + sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b url: "https://pub.dev" source: hosted - version: "6.9.0" + version: "6.8.0" latlong2: dependency: "direct main" description: @@ -977,18 +964,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" url: "https://pub.dev" source: hosted - version: "10.0.5" + version: "10.0.7" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.8" leak_tracker_testing: dependency: transitive description: @@ -1045,14 +1032,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" - macros: - dependency: transitive - description: - name: macros - sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" - url: "https://pub.dev" - source: hosted - version: "0.1.2-main.4" markdown: dependency: transitive description: @@ -1401,10 +1380,10 @@ packages: dependency: transitive description: name: riverpod_analyzer_utils - sha256: c6b8222b2b483cb87ae77ad147d6408f400c64f060df7a225b127f4afef4f8c8 + sha256: "8b71f03fc47ae27d13769496a1746332df4cec43918aeba9aff1e232783a780f" url: "https://pub.dev" source: hosted - version: "0.5.8" + version: "0.5.1" riverpod_annotation: dependency: "direct main" description: @@ -1417,10 +1396,10 @@ packages: dependency: "direct dev" description: name: riverpod_generator - sha256: "63546d70952015f0981361636bf8f356d9cfd9d7f6f0815e3c07789a41233188" + sha256: d451608bf17a372025fc36058863737636625dfdb7e3cbf6142e0dfeb366ab22 url: "https://pub.dev" source: hosted - version: "2.6.3" + version: "2.4.0" rxdart: dependency: "direct main" description: @@ -1513,7 +1492,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" slang: dependency: "direct main" description: @@ -1582,18 +1561,18 @@ packages: dependency: transitive description: name: sqlparser - sha256: "4cad4b2c5f63dc9ea1a8dcffb58cf762322bea5dd8836870164a65e913bdae41" + sha256: d77749237609784e337ec36c979d41f6f38a7b279df98622ae23929c8eb954a4 url: "https://pub.dev" source: hosted - version: "0.40.0" + version: "0.39.2" stack_trace: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.0" state_notifier: dependency: transitive description: @@ -1622,10 +1601,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" stripe_android: dependency: transitive description: @@ -1662,10 +1641,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.3" time: dependency: transitive description: @@ -1830,10 +1809,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b url: "https://pub.dev" source: hosted - version: "14.2.5" + version: "14.3.0" watcher: dependency: transitive description: @@ -1963,5 +1942,5 @@ packages: source: hosted version: "2.2.2" sdks: - dart: ">=3.5.0 <4.0.0" - flutter: ">=3.24.0" + dart: ">=3.6.0 <4.0.0" + flutter: ">=3.27.0" diff --git a/pubspec.yaml b/pubspec.yaml index dbb9439..f6778cc 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -114,7 +114,8 @@ dependencies: tray_manager: ^0.2.0 device_info_plus: ^11.3.0 flutter_stripe: ^10.1.0 - in_app_purchase: 3.2.1 + in_app_purchase: ^3.2.3 + in_app_purchase_storekit: ^0.4.2 dev_dependencies: flutter_test: sdk: flutter