feat: 全局监听iap,在home初始化。避免过早处理,升级dart和flutter,支持storekit插件,强制指定storekit2版本

This commit is contained in:
2025-12-17 20:34:59 -08:00
parent 05d2c71cd0
commit 801a77f942
6 changed files with 113 additions and 37 deletions
@@ -1,17 +1,29 @@
import 'package:flutter_keychain/flutter_keychain.dart';
class IAPPendingOrderService {
static const _key = 'hi_iap_pending_order_no';
static const _keyOrderNo = 'hi_iap_pending_order_no';
static const _keyJwsData = 'hi_iap_pending_jws_data'; // 新增 Key
static Future<void> setPendingOrderNo(String orderNo) async {
await FlutterKeychain.put(key: _key, value: orderNo);
await FlutterKeychain.put(key: _keyOrderNo, value: orderNo);
}
static Future<String?> getPendingOrderNo() async {
return await FlutterKeychain.get(key: _key);
return await FlutterKeychain.get(key: _keyOrderNo);
}
/// 存储 JWS 凭证数据
static Future<void> setPendingJwsData(String jwsData) async {
await FlutterKeychain.put(key: _keyJwsData, value: jwsData);
}
/// 获取存储的 JWS 凭证数据
static Future<String?> getPendingJwsData() async {
return await FlutterKeychain.get(key: _keyJwsData);
}
static Future<void> clearPendingOrderNo() async {
await FlutterKeychain.remove(key: _key);
await FlutterKeychain.remove(key: _keyOrderNo);
await FlutterKeychain.remove(key: _keyJwsData);
}
}
+60 -19
View File
@@ -50,7 +50,7 @@ class KRIAPService extends GetxService {
// 1. 监听回调:只负责状态分流
void _handleIapUpdates(List<PurchaseDetails> purchases) async {
final pendingOrderNo = await IAPPendingOrderService.getPendingOrderNo();
print('🔄 [IAPService] 处理状态222: ${pendingOrderNo}');
// 如果没有本地挂起的订单号,说明不是通过 App 正常发起的支付(或是已处理完的补单)
if (pendingOrderNo == null || pendingOrderNo.isEmpty) return;
@@ -92,13 +92,15 @@ class KRIAPService extends GetxService {
try {
// 根据状态选择对应的后端接口
if (p.status == PurchaseStatus.purchased || p.status == PurchaseStatus.restored) {
await IAPPendingOrderService.setPendingJwsData(jwsData);
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);
}
// 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] 网络请求异常');
}
@@ -110,31 +112,70 @@ class KRIAPService extends GetxService {
}
}
String? findCurrentRoute() {
String? routeName;
try {
// 强制通过 Navigator 的 context 获取栈信息
Get.key.currentState?.popUntil((route) {
routeName = route.settings.name;
// 打印每一层,看看栈里到底有什么
print('层级检查: $routeName');
// 如果拿到的是有效名且不是 null,就锁定它
if (routeName != null && routeName != '/') return true;
return false;
});
} catch (e) {
print('路由查找异常: $e');
}
return routeName;
}
// 3. 验证成功后的收尾工作
Future<void> _finalizeTransaction(PurchaseDetails p, String orderNo) async {
print('✅ [IAPService] 验证成功,清理流程');
print('✅ [IAPService] 验证成功,清理流程${p.pendingCompletePurchase}');
// I. 结束苹果事务(关键:防止重复推送)
if (p.pendingCompletePurchase) {
await _iap.completePurchase(p);
}
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',
},
);
}
String? realRoute = findCurrentRoute();
print('🔍 [IAP Fix] Final Found Route: "$realRoute"');
// if (Get.currentRoute.contains(Routes.KR_ORDER_STATUS)) return;
//
// // 2. 判断是否需要自动跳转
// // 如果当前在“会员购买页”,说明是用户刚刚点的,直接跳
// if (Get.currentRoute.contains(Routes.KR_PURCHASE_MEMBERSHIP)) {
// _navigateToStatusPage(orderNo);
// } else {
// // 3. ⚠️ 如果在 Home 或其他地方(说明是后台自动补单成功)
// // 弹窗提示,由用户决定是否查看详情
// HIDialog.show(
// title: '订单处理成功',
// message: '检测到您有一笔未完成的订单已激活成功,会员权益已到账。',
// confirmText: '查看订单',
// cancelText: '我知道了',
// onConfirm: () => _navigateToStatusPage(orderNo),
// );
// }
// 拿不到真实的值,不知道为什么路由栈找不到,
_navigateToStatusPage(orderNo);
}
void _navigateToStatusPage(String orderNo) {
Get.offNamed(
Routes.KR_ORDER_STATUS,
arguments: {
'order': orderNo,
'payment_type': 'apple_iap',
'checkout_type': 'ipa',
},
);
}
// 4. 验证失败后的重试引导