fix: 增加iap的跳转
This commit is contained in:
parent
b96008d6dc
commit
57a47874be
@ -762,9 +762,11 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = PacketTunnel/HiddifyPacketTunnel.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = NJRRF427XB;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NJRRF427XB;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
EXCLUDED_ARCHS = armv7;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
@ -790,6 +792,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).PacketTunnel";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "HiFastVPN-iOS-Pord-PacketTunnel";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
@ -815,9 +818,11 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = PacketTunnel/PacketTunnelRelease.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = NJRRF427XB;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NJRRF427XB;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
EXCLUDED_ARCHS = armv7;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
@ -843,6 +848,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).PacketTunnel";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "HiFastVPN-iOS-Pord-PacketTunnel";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
@ -866,9 +872,11 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = PacketTunnel/HiddifyPacketTunnel.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = NJRRF427XB;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NJRRF427XB;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
EXCLUDED_ARCHS = armv7;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
@ -894,6 +902,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).PacketTunnel";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "HiFastVPN-iOS-Pord-PacketTunnel";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
@ -971,9 +980,11 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = NJRRF427XB;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NJRRF427XB;
|
||||
ENABLE_BITCODE = NO;
|
||||
"EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@ -1005,6 +1016,7 @@
|
||||
"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = com.taw.hifastvpn;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "HiFastVPN-iOS-Pord";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
@ -1200,9 +1212,11 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = NJRRF427XB;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NJRRF427XB;
|
||||
ENABLE_BITCODE = NO;
|
||||
"EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
|
||||
@ -1234,6 +1248,7 @@
|
||||
"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = com.taw.hifastvpn;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "HiFastVPN-iOS-Pord";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
@ -1255,9 +1270,11 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerRelease.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = NJRRF427XB;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NJRRF427XB;
|
||||
ENABLE_BITCODE = NO;
|
||||
"EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@ -1289,6 +1306,7 @@
|
||||
"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = com.taw.hifastvpn;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "HiFastVPN-iOS-Pord";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
|
||||
@ -176,6 +176,7 @@ class KRInviteView extends GetView<KRInviteController> {
|
||||
maxLength: 10,
|
||||
style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
|
||||
decoration: InputDecoration(
|
||||
counterText: '',
|
||||
hintText: '填码领免费时长...',
|
||||
hintStyle: const TextStyle(color: Color(0xFFA6A6A6)),
|
||||
filled: true,
|
||||
|
||||
@ -7,6 +7,7 @@ import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'dart:io';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
import '../../../common/app_run_data.dart';
|
||||
import '../../../common/app_config.dart';
|
||||
@ -19,12 +20,14 @@ import '../../../network/http_util.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
// import 'package:flutter_stripe/flutter_stripe.dart';
|
||||
import 'package:in_app_purchase/in_app_purchase.dart';
|
||||
import 'package:in_app_purchase_storekit/store_kit_2_wrappers.dart';
|
||||
import 'dart:async';
|
||||
import 'package:flutter/services.dart';
|
||||
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';
|
||||
import '../../../services/kr_site_config_service.dart';
|
||||
|
||||
/// 会员购买控制器
|
||||
/// 负责处理会员套餐选择、支付方式选择和订阅流程
|
||||
@ -86,6 +89,12 @@ class KRPurchaseMembershipController extends GetxController {
|
||||
print('💳 [PurchaseMembership] ❌ 写入调试日志失败: $e');
|
||||
}
|
||||
|
||||
// 判断是否有 curversion,如果没有先请求下 site/config 接口让配置初始化下
|
||||
final siteConfigService = KRSiteConfigService();
|
||||
if (siteConfigService.getCurVersion().isEmpty) {
|
||||
siteConfigService.fetchSiteConfig();
|
||||
}
|
||||
|
||||
kr_initializeData();
|
||||
}
|
||||
|
||||
@ -1006,6 +1015,60 @@ class KRPurchaseMembershipController extends GetxController {
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔧 版本和地区检查逻辑
|
||||
try {
|
||||
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
final String currentVersion = packageInfo.version;
|
||||
final String curVersion = KRSiteConfigService().getCurVersion();
|
||||
|
||||
print('💳 [IAP] 支付检查: App版本=$currentVersion, 服务端参考版本=$curVersion');
|
||||
|
||||
if (curVersion.isNotEmpty) {
|
||||
// 如果代码中的version版本小于等于 curversion 时
|
||||
if (_kr_compareVersion(currentVersion, curVersion) <= 0) {
|
||||
// 判断 apple id 账号地区是否在香港(HK)、台湾(TW)
|
||||
// 使用 StoreKit 的地区代码(SKStorefront),它是根据当前登录的 App Store 账户决定的
|
||||
// 使用 StoreKit 2 的地区代码,它是根据当前登录的 App Store 账户决定的
|
||||
String storefrontCountryCode = '';
|
||||
try {
|
||||
// StoreKit 2 API
|
||||
final Storefront storefront = Storefront();
|
||||
final String storefrontCountryCode = await storefront.countryCode();
|
||||
print('💳 [IAP] Storefront 2 地区检查: countryCode=$storefrontCountryCode');
|
||||
} catch (e) {
|
||||
print('💳 [IAP] 获取 Storefront 2 信息失败, 尝试使用系统地区作为后备: $e');
|
||||
storefrontCountryCode = Get.deviceLocale?.countryCode ?? '';
|
||||
}
|
||||
|
||||
// 定义 H5 支付白名单 (包含 2 位和 3 位国家代码)
|
||||
const h5WhiteList = [
|
||||
'HKG', // 香港
|
||||
'TWN', // 台湾
|
||||
'MAC', // 澳门
|
||||
'SGP', // 新加坡
|
||||
'MYS', // 马来西亚
|
||||
'THA', // 泰国
|
||||
'VNM', // 越南
|
||||
'PHL', // 菲律宾
|
||||
];
|
||||
|
||||
if (h5WhiteList.contains(storefrontCountryCode.toUpperCase())) {
|
||||
final String token = KRAppRunData.getInstance().kr_token ?? '';
|
||||
final String url = 'https://hifastvpn.com/login/$token';
|
||||
print('💳 [IAP] 符合跳转条件 (Storefront: $storefrontCountryCode),跳转至网页支付: $url');
|
||||
|
||||
final Uri uri = Uri.parse(url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
return; // 终止后续苹果内购流程
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('💳 [IAP] 版本或地区检查时发生异常: $e');
|
||||
}
|
||||
|
||||
final KRIpaPayment iapParams = (checkoutResponse.ipa == null ||
|
||||
(checkoutResponse.ipa?.productId.isEmpty ?? true))
|
||||
? KRIpaPayment(
|
||||
@ -1115,4 +1178,27 @@ class KRPurchaseMembershipController extends GetxController {
|
||||
return; // 终止后续操作
|
||||
}
|
||||
}
|
||||
|
||||
/// 比较版本号
|
||||
/// 返回值:
|
||||
/// -1: v1 < v2
|
||||
/// 0: v1 == v2
|
||||
/// 1: v1 > v2
|
||||
int _kr_compareVersion(String v1, String v2) {
|
||||
if (v1.isEmpty || v2.isEmpty) return 0;
|
||||
try {
|
||||
List<String> list1 = v1.split('.');
|
||||
List<String> list2 = v2.split('.');
|
||||
int len = list1.length > list2.length ? list1.length : list2.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
int n1 = i < list1.length ? int.tryParse(list1[i]) ?? 0 : 0;
|
||||
int n2 = i < list2.length ? int.tryParse(list2[i]) ?? 0 : 0;
|
||||
if (n1 > n2) return 1;
|
||||
if (n1 < n2) return -1;
|
||||
}
|
||||
} catch (e) {
|
||||
print('版本比较失败: $e');
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,6 +299,42 @@ class KRSiteConfigService extends ChangeNotifier {
|
||||
return _siteConfig?.site.deviceLimit ?? '0';
|
||||
}
|
||||
|
||||
/// 获取当前版本号
|
||||
///
|
||||
/// 功能:从站点配置的 customData 中解析并返回 curVersion
|
||||
/// 参数:无
|
||||
/// 返回:String 当前版本号,如未配置返回空字符串
|
||||
String getCurVersion() {
|
||||
try {
|
||||
final customData = _siteConfig?.site.customData ?? '';
|
||||
if (customData.isEmpty) return '';
|
||||
final Map<String, dynamic> jsonMap =
|
||||
jsonDecode(customData) as Map<String, dynamic>;
|
||||
final value = jsonMap['curVersion'];
|
||||
return value == null ? '' : value.toString();
|
||||
} catch (_) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取分享地址
|
||||
///
|
||||
/// 功能:从站点配置的 customData 中解析并返回 shareUrl
|
||||
/// 参数:无
|
||||
/// 返回:String 分享地址,如未配置返回空字符串
|
||||
String getShareUrl() {
|
||||
try {
|
||||
final customData = _siteConfig?.site.customData ?? '';
|
||||
if (customData.isEmpty) return '';
|
||||
final Map<String, dynamic> jsonMap =
|
||||
jsonDecode(customData) as Map<String, dynamic>;
|
||||
final value = jsonMap['shareUrl'];
|
||||
return value == null ? '' : value.toString();
|
||||
} catch (_) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/// 重置配置
|
||||
void reset() {
|
||||
_siteConfig = null;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user