diff --git a/lib/app/model/entity_from_json_util.dart b/lib/app/model/entity_from_json_util.dart index 7e8d102..196897a 100755 --- a/lib/app/model/entity_from_json_util.dart +++ b/lib/app/model/entity_from_json_util.dart @@ -43,6 +43,8 @@ abstract class EntityFromJsonUtil { return KRPurchaseOrderNo.fromJson(json) as T; case "KRPurchaseOrderUrl": return KRPurchaseOrderUrl.fromJson(json) as T; + case "KRCheckoutResponse": + return KRCheckoutResponse.fromJson(json) as T; case "KROrderStatus": return KROrderStatus.fromJson(json) as T; case "KRAlreadySubscribeList": diff --git a/lib/app/model/response/kr_purchase_order_no.dart b/lib/app/model/response/kr_purchase_order_no.dart index 50ded8c..91bc56f 100755 --- a/lib/app/model/response/kr_purchase_order_no.dart +++ b/lib/app/model/response/kr_purchase_order_no.dart @@ -18,4 +18,48 @@ class KRPurchaseOrderUrl { factory KRPurchaseOrderUrl.fromJson(Map json) { return KRPurchaseOrderUrl(url: json['checkout_url'] ?? ''); } +} + +/// Checkout 响应(参考 Tauri 项目) +class KRCheckoutResponse { + final String type; // "url" | "qr" | "stripe" + final String? checkoutUrl; + final KRStripePayment? stripe; + + KRCheckoutResponse({ + required this.type, + this.checkoutUrl, + this.stripe, + }); + + factory KRCheckoutResponse.fromJson(Map json) { + return KRCheckoutResponse( + type: json['type'] ?? 'url', + checkoutUrl: json['checkout_url'], + stripe: json['stripe'] != null + ? KRStripePayment.fromJson(json['stripe']) + : null, + ); + } +} + +/// Stripe 支付信息 +class KRStripePayment { + final String method; + final String clientSecret; + final String publishableKey; + + KRStripePayment({ + required this.method, + required this.clientSecret, + required this.publishableKey, + }); + + factory KRStripePayment.fromJson(Map json) { + return KRStripePayment( + method: json['method'] ?? '', + clientSecret: json['client_secret'] ?? '', + publishableKey: json['publishable_key'] ?? '', + ); + } } diff --git a/lib/app/modules/kr_order_status/controllers/kr_order_status_controller.dart b/lib/app/modules/kr_order_status/controllers/kr_order_status_controller.dart index ba586f2..0d0fde5 100755 --- a/lib/app/modules/kr_order_status/controllers/kr_order_status_controller.dart +++ b/lib/app/modules/kr_order_status/controllers/kr_order_status_controller.dart @@ -11,7 +11,7 @@ import '../../../utils/kr_common_util.dart'; import '../../../localization/app_translations.dart'; import '../../../utils/kr_log_util.dart'; -/// 订单状态控制器 +/// 订单状态控制器(参考 Tauri 项目实现) class KROrderStatusController extends GetxController { /// API服务 final KRSubscribeApi kr_subscribeApi = KRSubscribeApi(); @@ -23,7 +23,7 @@ class KROrderStatusController extends GetxController { final RxBool kr_isLoading = true.obs; /// 支付URL - final String kr_paymentUrl = Get.arguments['url'] as String; + final String kr_paymentUrl = Get.arguments['url'] as String? ?? ''; /// 订单信息 final String kr_order = Get.arguments['order']; @@ -31,9 +31,27 @@ class KROrderStatusController extends GetxController { /// 支付方式类型 final String kr_paymentType = Get.arguments['payment_type'] as String; + /// Checkout 类型(url, qr, stripe) + final String kr_checkoutType = Get.arguments['checkout_type'] as String? ?? 'url'; + /// 定时器 Timer? kr_timer; + /// 倒计时定时器 + Timer? kr_countdownTimer; + + /// 15分钟倒计时(毫秒) + final RxInt kr_countdown = (15 * 60 * 1000).obs; + + /// 格式化的倒计时字符串 + final RxString kr_formattedCountdown = '15:00'.obs; + + /// 订单创建时间(用于计算倒计时) + DateTime? kr_orderCreatedAt; + + /// 上次刷新时间 + int kr_lastRefreshTime = 0; + /// 订单状态常量 static const int kr_statusPending = 1; // 待支付 static const int kr_statusPaid = 2; // 已支付 @@ -53,129 +71,221 @@ class KROrderStatusController extends GetxController { @override void onInit() { super.onInit(); + print('═══════════════════════════════════════'); + print('📊 订单状态页面初始化'); + print(' 订单号: $kr_order'); + print(' 支付方式: $kr_paymentType'); + print(' Checkout类型: $kr_checkoutType'); + print('═══════════════════════════════════════'); + + // 立即查询一次订单状态,获取创建时间 + kr_checkPaymentStatus(); + // 启动轮询和倒计时 kr_startCheckingPaymentStatus(); } @override void onReady() { super.onReady(); - // 只有在非余额支付且有支付URL时才处理支付跳转 - if (kr_paymentUrl.isNotEmpty && kr_paymentType != 'balance') { - if (Platform.isAndroid || Platform.isIOS) { - // 移动端使用 WebView - Get.toNamed( - Routes.KR_WEBVIEW, - arguments: { - 'url': kr_paymentUrl, - 'order': kr_order, - }, - ); - } else { - // 桌面端使用外部浏览器 - final Uri uri = Uri.parse(kr_paymentUrl); - launchUrl(uri, mode: LaunchMode.externalApplication); - } - } + // 注意:支付链接已经在购买流程中打开了,这里不再重复打开 } @override void onClose() { + print('🔚 订单状态页面关闭,清理定时器'); kr_timer?.cancel(); + kr_countdownTimer?.cancel(); super.onClose(); } - /// 开始检查支付状态 + /// 开始检查支付状态(参考 Tauri 项目:5秒轮询一次) void kr_startCheckingPaymentStatus() { - // 根据支付方式类型设置不同的查询间隔 - final Duration interval = kr_paymentType == 'balance' - ? const Duration(seconds: 2) // 余额支付每2秒查询一次 - : const Duration(seconds: 5); // 其他支付方式每5秒查询一次 - - kr_timer = Timer.periodic(interval, (timer) { + print('🔄 启动支付状态轮询(每5秒检查一次)'); + + // 状态轮询:每5秒检查一次订单状态 + kr_timer = Timer.periodic(const Duration(seconds: 5), (timer) { kr_checkPaymentStatus(); }); + + // 倒计时更新:每1秒更新一次UI显示 + kr_countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) { + kr_updateCountdown(); + }); } - /// 检查支付状态 + /// 更新倒计时(参考 Tauri 项目) + void kr_updateCountdown() { + if (kr_orderCreatedAt == null) { + // 订单创建时间还未获取,显示默认倒计时 + kr_formattedCountdown.value = '15:00'; + print('⏱️ 倒计时更新: 等待订单创建时间...'); + return; + } + + final now = DateTime.now().millisecondsSinceEpoch; + final createdAt = kr_orderCreatedAt!.millisecondsSinceEpoch; + final targetTime = createdAt + (15 * 60 * 1000); // 15分钟后 + + final timeLeft = targetTime - now; + + print('⏱️ 倒计时调试信息:'); + print(' 当前时间(ms): $now'); + print(' 创建时间(ms): $createdAt'); + print(' 目标时间(ms): $targetTime'); + print(' 剩余时间(ms): $timeLeft'); + print(' 剩余时间(秒): ${(timeLeft / 1000).floor()}'); + + if (timeLeft > 0) { + kr_countdown.value = timeLeft; + // 格式化倒计时:MM:SS + final minutes = (timeLeft / 60000).floor(); + final seconds = ((timeLeft % 60000) / 1000).floor(); + kr_formattedCountdown.value = '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}'; + print(' 格式化倒计时: ${kr_formattedCountdown.value}'); + } else { + // 倒计时结束,订单超时 + kr_countdown.value = 0; + kr_formattedCountdown.value = '00:00'; + kr_countdownTimer?.cancel(); + kr_timer?.cancel(); + + print('⏱️ 订单支付超时(15分钟)'); + kr_statusTitle.value = AppTranslations.kr_orderStatus.closedTitle; + kr_statusDescription.value = '订单已超时,请重新下单'; + kr_isLoading.value = false; + } + } + + /// 检查支付状态(使用公开接口,参考 Tauri 项目) Future kr_checkPaymentStatus() async { + final now = DateTime.now().millisecondsSinceEpoch; + try { - final result = await kr_subscribeApi.kr_orderDetail(kr_order); + print('🔍 检查订单状态 [${kr_order}]'); + + // 使用公开接口查询订单状态 + final result = await kr_subscribeApi.kr_queryOrderStatus(kr_order); result.fold( (error) { - KRLogUtil.kr_e('检查支付状态失败: $error', tag: 'OrderStatusController'); + print('❌ 查询失败: ${error.msg}'); + KRLogUtil.kr_e('检查支付状态失败: ${error.msg}', tag: 'OrderStatusController'); kr_isLoading.value = false; kr_statusTitle.value = AppTranslations.kr_orderStatus.checkFailedTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.checkFailedDescription; - kr_statusIcon.value = 'payment_success'; }, (kr_orderStatus) { - KRLogUtil.kr_i('检查支付状态: ${kr_orderStatus.toJson()}', tag: 'OrderStatusController'); + // 保存订单创建时间(用于倒计时) + if (kr_orderCreatedAt == null && kr_orderStatus.kr_createdAt > 0) { + // 判断是秒级还是毫秒级时间戳 + // 如果时间戳大于10位数字,说明是毫秒级 + final timestamp = kr_orderStatus.kr_createdAt; + final isMilliseconds = timestamp > 10000000000; // 大于10位数说明是毫秒级 + + kr_orderCreatedAt = DateTime.fromMillisecondsSinceEpoch( + isMilliseconds ? timestamp : timestamp * 1000 + ); + + print('📅 订单创建时间: ${kr_orderCreatedAt}'); + print('📅 原始时间戳: $timestamp'); + print('📅 时间戳类型: ${isMilliseconds ? "毫秒级" : "秒级"}'); + print('📅 转换后时间戳(ms): ${kr_orderCreatedAt!.millisecondsSinceEpoch}'); + } + + print('📊 订单状态: ${kr_orderStatus.kr_status} (${_getStatusName(kr_orderStatus.kr_status)})'); + switch (kr_orderStatus.kr_status) { case kr_statusPending: // 待支付状态,继续轮询 kr_statusTitle.value = AppTranslations.kr_orderStatus.pendingTitle; - kr_statusDescription.value = AppTranslations.kr_orderStatus.pendingDescription; + kr_statusDescription.value = '${AppTranslations.kr_orderStatus.pendingDescription}\n剩余时间: ${kr_formattedCountdown.value}'; kr_statusIcon.value = 'payment_success'; break; + case kr_statusPaid: // 已支付状态,继续轮询直到完成 + print('✅ 订单已支付,等待确认...'); kr_statusTitle.value = AppTranslations.kr_orderStatus.paidTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.paidDescription; kr_statusIcon.value = 'payment_success'; break; + case kr_statusFinished: // 订单完成 + print('🎉 订单完成!停止轮询'); kr_isPaymentSuccess.value = true; kr_isLoading.value = false; kr_timer?.cancel(); + kr_countdownTimer?.cancel(); kr_statusTitle.value = AppTranslations.kr_orderStatus.successTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.successDescription; kr_statusIcon.value = 'payment_success'; + // 发送支付成功事件 KREventBus().kr_sendMessage(KRMessageType.kr_payment); break; + case kr_statusClose: // 订单已关闭 + print('❌ 订单已关闭'); kr_isLoading.value = false; kr_timer?.cancel(); + kr_countdownTimer?.cancel(); kr_statusTitle.value = AppTranslations.kr_orderStatus.closedTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.closedDescription; kr_statusIcon.value = 'payment_success'; break; + case kr_statusFailed: // 支付失败 + print('❌ 支付失败'); kr_isLoading.value = false; kr_timer?.cancel(); + kr_countdownTimer?.cancel(); kr_statusTitle.value = AppTranslations.kr_orderStatus.failedTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.failedDescription; kr_statusIcon.value = 'payment_success'; break; + default: // 未知状态 + print('⚠️ 未知状态: ${kr_orderStatus.kr_status}'); kr_isLoading.value = false; kr_timer?.cancel(); + kr_countdownTimer?.cancel(); kr_statusTitle.value = AppTranslations.kr_orderStatus.unknownTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.unknownDescription; kr_statusIcon.value = 'payment_success'; break; } + + kr_lastRefreshTime = now; }, ); } catch (error) { + print('❌ 异常: $error'); KRLogUtil.kr_e('检查支付状态失败: $error', tag: 'OrderStatusController'); kr_isLoading.value = false; kr_statusTitle.value = AppTranslations.kr_orderStatus.checkFailedTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.checkFailedDescription; - kr_statusIcon.value = 'payment_success'; } } - /// 检查支付状态 - Future kr_checkPaymentStatusWithRetry() async { - try { - // ... 其他代码 ... - } catch (err) { - KRLogUtil.kr_e('检查支付状态失败: $err', tag: 'OrderStatusController'); + /// 获取状态名称(用于日志) + String _getStatusName(int status) { + switch (status) { + case kr_statusPending: + return '待支付'; + case kr_statusPaid: + return '已支付'; + case kr_statusClose: + return '已关闭'; + case kr_statusFailed: + return '支付失败'; + case kr_statusFinished: + return '已完成'; + default: + return '未知'; } } + } 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 dd87e35..073eb6f 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 @@ -4,6 +4,7 @@ import 'package:kaer_with_panels/app/model/response/kr_package_list.dart'; import 'package:kaer_with_panels/app/utils/kr_common_util.dart'; import 'package:kaer_with_panels/app/localization/app_translations.dart'; import 'package:kaer_with_panels/app/utils/kr_log_util.dart'; +import 'package:url_launcher/url_launcher.dart'; import '../../../common/app_run_data.dart'; import '../../../common/app_config.dart'; @@ -399,22 +400,31 @@ class KRPurchaseMembershipController extends GetxController { '', ); + // 打印下单请求和响应 + print('═══════════════════════════════════════'); + print('🔗 下单接口: /v1/public/order/purchase'); + print('📤 请求参数:'); + print(' subscribe_id: ${selectedPlan.kr_id}'); + print(' quantity: $quantity'); + print(' payment: $paymentMethodId'); + print(' coupon: ""'); + print(''); + purchaseEither.fold( - (error) => KRCommonUtil.kr_showToast(error.msg), + (error) { + print('❌ 请求失败:'); + print(' 错误码: ${error.code}'); + print(' 错误信息: ${error.msg}'); + print('═══════════════════════════════════════'); + KRCommonUtil.kr_showToast(error.msg); + }, (order) async { - // 所有支付方式都需要调用 checkout 接口 - final checkoutEither = await _kr_subscribeApi.kr_checkout(order); - checkoutEither.fold( - (error) => KRCommonUtil.kr_showToast(error.msg), - (uri) => Get.toNamed( - Routes.KR_ORDER_STATUS, - arguments: { - 'url': uri, - 'order': order, - 'payment_type': paymentPlatform, - }, - ), - ); + print('✅ 请求成功:'); + print(' 订单号: $order'); + print('═══════════════════════════════════════'); + + // 调用 checkout 接口获取支付链接 + await _kr_handleCheckout(order, paymentPlatform); }, ); } @@ -597,4 +607,102 @@ class KRPurchaseMembershipController extends GetxController { return AppTranslations.kr_purchaseMembership .devices(plan.kr_deviceLimit.toString()); } + + /// 处理 checkout 并打开支付链接(参考 Tauri 项目) + Future _kr_handleCheckout(String orderNo, String paymentPlatform) async { + print(''); + print('═══════════════════════════════════════'); + print('🔗 调用 Checkout 接口'); + print('📤 请求参数:'); + print(' orderNo: $orderNo'); + print(' returnUrl: ${AppConfig.getInstance().baseUrl}'); + print(''); + + final checkoutEither = await _kr_subscribeApi.kr_checkout(orderNo); + + checkoutEither.fold( + (error) { + print('❌ Checkout 失败:'); + print(' 错误码: ${error.code}'); + print(' 错误信息: ${error.msg}'); + print('═══════════════════════════════════════'); + KRCommonUtil.kr_showToast(error.msg); + }, + (checkoutResponse) async { + print('✅ Checkout 成功:'); + print(' 支付类型: ${checkoutResponse.type}'); + + if (checkoutResponse.type == 'url') { + // URL 类型:在浏览器中打开支付链接,同时跳转到订单状态页面 + if (checkoutResponse.checkoutUrl != null && checkoutResponse.checkoutUrl!.isNotEmpty) { + print(' 支付链接: ${checkoutResponse.checkoutUrl}'); + print('🌐 正在用外部浏览器打开支付链接...'); + print('═══════════════════════════════════════'); + + final url = Uri.parse(checkoutResponse.checkoutUrl!); + if (await canLaunchUrl(url)) { + // 在外部浏览器打开支付链接 + await launchUrl( + url, + mode: LaunchMode.externalApplication, + ); + + // 跳转到订单状态页面进行轮询检查 + Get.toNamed( + Routes.KR_ORDER_STATUS, + arguments: { + 'url': checkoutResponse.checkoutUrl, + 'order': orderNo, + 'payment_type': paymentPlatform, + 'checkout_type': 'url', + }, + ); + } else { + print('❌ 无法打开URL: ${checkoutResponse.checkoutUrl}'); + KRCommonUtil.kr_showToast('无法打开支付链接'); + } + } else { + print('⚠️ 支付链接为空'); + print('═══════════════════════════════════════'); + KRCommonUtil.kr_showToast('支付链接为空'); + } + } else if (checkoutResponse.type == 'qr') { + // QR 类型:显示二维码(跳转到订单状态页面) + print(' 二维码内容: ${checkoutResponse.checkoutUrl}'); + print('📱 显示二维码支付...'); + print('═══════════════════════════════════════'); + + Get.toNamed( + Routes.KR_ORDER_STATUS, + arguments: { + 'url': checkoutResponse.checkoutUrl, + 'order': orderNo, + 'payment_type': paymentPlatform, + 'checkout_type': 'qr', + }, + ); + } else if (checkoutResponse.type == 'stripe') { + // Stripe 类型:显示 Stripe 支付表单 + print(' Stripe Method: ${checkoutResponse.stripe?.method}'); + print(' Stripe Client Secret: ${checkoutResponse.stripe?.clientSecret}'); + print('💳 显示 Stripe 支付表单...'); + print('═══════════════════════════════════════'); + + Get.toNamed( + Routes.KR_ORDER_STATUS, + arguments: { + 'order': orderNo, + 'payment_type': paymentPlatform, + 'checkout_type': 'stripe', + 'stripe': checkoutResponse.stripe, + }, + ); + } else { + print('⚠️ 未知的支付类型: ${checkoutResponse.type}'); + print('═══════════════════════════════════════'); + KRCommonUtil.kr_showToast('不支持的支付类型: ${checkoutResponse.type}'); + } + }, + ); + } } diff --git a/lib/app/network/base_response.dart b/lib/app/network/base_response.dart index 94907e1..44c5fbd 100755 --- a/lib/app/network/base_response.dart +++ b/lib/app/network/base_response.dart @@ -30,16 +30,28 @@ class BaseResponse { if (shouldDecrypt && cipherText.isNotEmpty && nonce.isNotEmpty) { try { - KRLogUtil.kr_i('🔓 开始解密响应数据', tag: 'BaseResponse'); + print('═══════════════════════════════════════'); + print('🔐 检测到加密响应,开始解密...'); + print('📥 加密数据长度: ${cipherText.length} 字符'); + print('⏰ 时间戳: $nonce'); + final decrypted = KRAesUtil.decryptData(cipherText, nonce, AppConfig.kr_encryptionKey); body = jsonDecode(decrypted); - KRLogUtil.kr_i('✅ 解密成功', tag: 'BaseResponse'); - // 打印完整的解密后数据,方便调试 - final bodyStr = jsonEncode(body); - KRLogUtil.kr_i('📦 解密后数据(完整): $bodyStr', tag: 'BaseResponse'); + print('✅ 解密成功'); + print(''); + print('📦 解密后的完整数据:'); + // 格式化打印 JSON,方便调试 + final bodyStr = JsonEncoder.withIndent(' ').convert(body); + print(bodyStr); + print('═══════════════════════════════════════'); + + KRLogUtil.kr_i('🔓 解密成功', tag: 'BaseResponse'); } catch (e) { - KRLogUtil.kr_e('❌ 解密失败: $e,使用原始数据', tag: 'BaseResponse'); + print('❌ 解密失败: $e'); + print('⚠️ 将使用原始数据'); + print('═══════════════════════════════════════'); + KRLogUtil.kr_e('❌ 解密失败: $e', tag: 'BaseResponse'); body = dataMap; } } diff --git a/lib/app/network/http_util.dart b/lib/app/network/http_util.dart index 9b3eea2..921b87c 100755 --- a/lib/app/network/http_util.dart +++ b/lib/app/network/http_util.dart @@ -282,6 +282,36 @@ class _KRSimpleHttpInterceptor extends Interceptor { print('>>> Request │ ${options.method} │ ${options.uri}'); if (options.data != null) { print('Body: ${options.data}'); + + // 检查是否是加密数据(包含 data 和 time 字段) + if (options.data is Map) { + final data = options.data as Map; + if (data.containsKey('data') && data.containsKey('time')) { + try { + print(''); + print('🔐 检测到加密请求,正在解密...'); + // 尝试解密并打印原始数据 + final encryptedData = data['data'] as String; + final nonce = data['time'] as String; + final decrypted = KRAesUtil.decryptData( + encryptedData, + nonce, + AppConfig.kr_encryptionKey, + ); + print('🔓 解密后的原始请求数据:'); + // 尝试格式化 JSON + try { + final jsonData = jsonDecode(decrypted); + final prettyJson = JsonEncoder.withIndent(' ').convert(jsonData); + print(prettyJson); + } catch (_) { + print(decrypted); + } + } catch (e) { + print('⚠️ 请求解密失败: $e'); + } + } + } } handler.next(options); } @@ -291,6 +321,41 @@ class _KRSimpleHttpInterceptor extends Interceptor { print('<<< Response │ ${response.requestOptions.method} │ ${response.statusCode} ${response.statusMessage} │ ${response.requestOptions.uri}'); if (response.data != null) { print('Body: ${response.data}'); + + // 检查响应是否是加密数据(包含 data 和 time 字段) + if (response.data is Map) { + final dataMap = response.data as Map; + + // 检查是否包含嵌套的 data 字段(加密数据格式) + final nestedData = dataMap['data']; + if (nestedData is Map && + nestedData.containsKey('data') && + nestedData.containsKey('time')) { + try { + print(''); + print('🔐 检测到加密响应,正在解密...'); + // 尝试解密并打印原始响应数据 + final encryptedData = nestedData['data'] as String; + final nonce = nestedData['time'] as String; + final decrypted = KRAesUtil.decryptData( + encryptedData, + nonce, + AppConfig.kr_encryptionKey, + ); + print('🔓 解密后的原始响应数据:'); + // 尝试格式化 JSON + try { + final jsonData = jsonDecode(decrypted); + final prettyJson = JsonEncoder.withIndent(' ').convert(jsonData); + print(prettyJson); + } catch (_) { + print(decrypted); + } + } catch (e) { + print('⚠️ 响应解密失败: $e'); + } + } + } } handler.next(response); } diff --git a/lib/app/services/api_service/api.dart b/lib/app/services/api_service/api.dart index 86f5760..aaaefc4 100755 --- a/lib/app/services/api_service/api.dart +++ b/lib/app/services/api_service/api.dart @@ -38,10 +38,10 @@ abstract class Api { static const String kr_getPaymentMethods = "/v1/app/payment/methods"; /// 进行下单 - static const String kr_purchase = "/v1/app/order/purchase"; + static const String kr_purchase = "/v1/public/order/purchase"; - /// 获取支付地址,跳转到付款地址 - static const String kr_checkout = "/v1/app/order/checkout"; + /// 获取支付地址,跳转到付款地址(参考 Tauri 项目) + static const String kr_checkout = "/v1/public/portal/order/checkout"; /// 获取可购买套餐 static const String kr_getPackageList = "/v1/public/subscribe/list"; @@ -61,6 +61,9 @@ abstract class Api { /// 通过该接口判断订单状态 static const String kr_orderDetail = "/v1/app/order/detail"; + /// 查询订单状态(公开接口,参考 Tauri 项目) + static const String kr_queryOrderStatus = "/v1/public/order/detail"; + /// 获取消息列表 static const String kr_getMessageList = "/v1/public/announcement/list"; diff --git a/lib/app/services/api_service/kr_subscribe_api.dart b/lib/app/services/api_service/kr_subscribe_api.dart index 43ab976..9c28a91 100755 --- a/lib/app/services/api_service/kr_subscribe_api.dart +++ b/lib/app/services/api_service/kr_subscribe_api.dart @@ -120,6 +120,27 @@ class KRSubscribeApi { return right(baseResponse.model); } + /// 查询订单状态(公开接口,用于支付轮询) + Future> kr_queryOrderStatus( + String orderNo) async { + final Map data = {}; + data['order_no'] = orderNo; + + BaseResponse baseResponse = + await HttpUtil.getInstance().request( + Api.kr_queryOrderStatus, + data, + method: HttpMethod.GET, + isShowLoading: false, + ); + if (!baseResponse.isSuccess) { + return left( + HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode)); + } + + return right(baseResponse.model); + } + /// 获取支付方式 Future>> kr_getPaymentMethods() async { @@ -231,14 +252,14 @@ class KRSubscribeApi { return right(baseResponse.model.orderNo); } - /// 获取支付地址,跳转到付款地址 - Future> kr_checkout(String orderId) async { + /// 获取支付地址,跳转到付款地址(新版本:支持多种支付类型) + Future> kr_checkout(String orderId) async { final Map data = {}; data['orderNo'] = orderId; data['returnUrl'] = AppConfig.getInstance().baseUrl; - BaseResponse baseResponse = - await HttpUtil.getInstance().request( + BaseResponse baseResponse = + await HttpUtil.getInstance().request( Api.kr_checkout, data, method: HttpMethod.POST, @@ -249,7 +270,7 @@ class KRSubscribeApi { HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode)); } - return right(baseResponse.model.url); + return right(baseResponse.model); } /// 重置订阅周期