|
|
|
@ -1,4 +1,5 @@ |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'dart:convert'; |
|
|
|
import 'package:voitrans/data/services/network/api.dart'; |
|
|
|
import 'package:tobias/tobias.dart'; |
|
|
|
import 'package:url_launcher/url_launcher.dart'; |
|
|
|
@ -361,7 +362,7 @@ class PayService extends GetxService { |
|
|
|
required String productName, |
|
|
|
String? productDesc, |
|
|
|
required int amount, |
|
|
|
int paymentMethod = 2, // 2表示支付宝 |
|
|
|
int paymentMethod = 3, // 2表示支付宝 |
|
|
|
String? clientIp, |
|
|
|
String? notifyUrl, |
|
|
|
String? extraData, |
|
|
|
@ -445,9 +446,73 @@ class PayService extends GetxService { |
|
|
|
'extra_data': extraData ?? '', |
|
|
|
}); |
|
|
|
|
|
|
|
// 兼容不同字段命名,尽量从返回中提取可用的支付URL |
|
|
|
if (response != null) { |
|
|
|
final candidates = [ |
|
|
|
// 1) 提取并缓存平台订单号(用于回查) |
|
|
|
String? appOrderId; |
|
|
|
const candidates = [ |
|
|
|
'order_id', |
|
|
|
'orderId', |
|
|
|
'out_trade_no', |
|
|
|
'outTradeNo', |
|
|
|
]; |
|
|
|
for (final key in candidates) { |
|
|
|
final v = response[key]; |
|
|
|
if (v is String && v.isNotEmpty) { |
|
|
|
appOrderId = v; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
final data = response['data']; |
|
|
|
if (appOrderId == null && data is Map<String, dynamic>) { |
|
|
|
for (final key in candidates) { |
|
|
|
final v = data[key]; |
|
|
|
if (v is String && v.isNotEmpty) { |
|
|
|
appOrderId = v; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
_lastOrderId = appOrderId; // 记录APP侧订单号(如 APP2025...),用于 pay_askorder |
|
|
|
|
|
|
|
// 2) 优先解析 paypal_pay_params 字段(后端返回JSON字符串,含 links) |
|
|
|
String? rawParams; |
|
|
|
final topParams = response['paypal_pay_params']; |
|
|
|
final dataParams = |
|
|
|
(data is Map<String, dynamic>) ? data['paypal_pay_params'] : null; |
|
|
|
if (topParams is String && topParams.isNotEmpty) { |
|
|
|
rawParams = topParams; |
|
|
|
} else if (dataParams is String && dataParams.isNotEmpty) { |
|
|
|
rawParams = dataParams; |
|
|
|
} |
|
|
|
|
|
|
|
if (rawParams != null) { |
|
|
|
try { |
|
|
|
final parsed = jsonDecode(rawParams); |
|
|
|
if (parsed is Map<String, dynamic>) { |
|
|
|
final links = parsed['links']; |
|
|
|
if (links is List) { |
|
|
|
for (final item in links) { |
|
|
|
if (item is Map) { |
|
|
|
final rel = item['rel']?.toString(); |
|
|
|
final hrefRaw = item['href']?.toString(); |
|
|
|
if (rel == 'approve' && |
|
|
|
hrefRaw != null && |
|
|
|
hrefRaw.isNotEmpty) { |
|
|
|
// 清理日志中可能出现的反引号等噪音字符 |
|
|
|
final href = hrefRaw.replaceAll('`', '').trim(); |
|
|
|
return href; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
print('解析 paypal_pay_params 失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 3) 回退:尝试从常见字段直接取URL |
|
|
|
final urlKeys = [ |
|
|
|
'paypal_pay_url', |
|
|
|
'approval_url', |
|
|
|
'paypalApprovalUrl', |
|
|
|
@ -455,16 +520,14 @@ class PayService extends GetxService { |
|
|
|
'payment_url', |
|
|
|
'url', |
|
|
|
]; |
|
|
|
for (final key in candidates) { |
|
|
|
for (final key in urlKeys) { |
|
|
|
final url = response[key]; |
|
|
|
if (url is String && url.isNotEmpty) { |
|
|
|
return url; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
final data = response['data']; |
|
|
|
if (data is Map<String, dynamic>) { |
|
|
|
for (final key in candidates) { |
|
|
|
for (final key in urlKeys) { |
|
|
|
final url = data[key]; |
|
|
|
if (url is String && url.isNotEmpty) { |
|
|
|
return url; |
|
|
|
@ -472,6 +535,7 @@ class PayService extends GetxService { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
print('创建 PayPal 订单失败或未返回有效URL: $response'); |
|
|
|
return null; |
|
|
|
} catch (e) { |
|
|
|
|