This commit is contained in:
macbook_max
2026-10-15 20:36:59 +08:00
commit 6bf949949c
7923 changed files with 1369582 additions and 0 deletions
+139
View File
@@ -0,0 +1,139 @@
import 'dart:async';
import 'package:fluwx/fluwx.dart';
import 'package:tobias/tobias.dart';
import '../core/config/app_config.dart';
import 'payment_service.dart';
/// 支付宝/微信原生 SDK 调起封装(《03-接口文档》8.2 pay_params)
///
/// 服务端配置了商户密钥时 pay_params 为真实调起参数,此处调起原生 SDK;
/// 未配置(dev)时服务端返回 dev_mock 占位,调用方应以轮询兜底代替调起。
enum PayLaunchResult {
/// 渠道回调成功(仍需以服务端查单为准,避免客户端伪造)
success,
/// 用户主动取消
canceled,
/// 调起失败(未安装 App / 参数缺失 / SDK 报错)
failed,
/// pay_params 无有效调起参数(服务端未配置商户密钥)
unsupported,
}
class PayLauncher {
PayLauncher._();
static final _fluwx = Fluwx();
/// 微信调起等待回调的最长时间
static const _wechatTimeout = Duration(minutes: 5);
/// 支付宝调起:order_string 直接交给 SDK
static Future<PayLaunchResult> launchAlipay(RechargeOrderInfo order) async {
final orderString = order.payParams['order_string'] as String?;
if (orderString == null || orderString.isEmpty) {
return PayLaunchResult.unsupported;
}
try {
final result = await Tobias().pay(orderString);
return _mapAlipayStatus(result['resultStatus'] as String?);
} catch (_) {
return PayLaunchResult.failed;
}
}
/// 微信调起:registerApi → pay → 等待 SDK 回调
static Future<PayLaunchResult> launchWechat(RechargeOrderInfo order) async {
final params = order.payParams;
final appId = params['appid'] as String?;
final partnerId = params['partnerid'] as String?;
final prepayId = params['prepayid'] as String?;
final packageValue = params['package'] as String?;
final nonceStr = params['noncestr'] as String?;
final sign = params['sign'] as String?;
final timestamp = int.tryParse('${params['timestamp']}');
if (appId == null ||
appId.isEmpty ||
partnerId == null ||
partnerId.isEmpty ||
prepayId == null ||
prepayId.isEmpty ||
packageValue == null ||
packageValue.isEmpty ||
nonceStr == null ||
nonceStr.isEmpty ||
sign == null ||
sign.isEmpty ||
timestamp == null) {
return PayLaunchResult.unsupported;
}
final completer = Completer<PayLaunchResult>();
final cancelable = _fluwx.addSubscriber((response) {
if (response is WeChatPaymentResponse && !completer.isCompleted) {
completer.complete(_mapWechatErrCode(response.errCode));
}
});
try {
await _fluwx.registerApi(
appId: appId,
universalLink: AppConfig.wechatUniversalLink.isEmpty
? null
: AppConfig.wechatUniversalLink,
);
final sent = await _fluwx.pay(
which: Payment(
appId: appId,
partnerId: partnerId,
prepayId: prepayId,
packageValue: packageValue,
nonceStr: nonceStr,
timestamp: timestamp,
sign: sign,
),
);
if (!sent) return PayLaunchResult.failed;
return await completer.future.timeout(
_wechatTimeout,
onTimeout: () => PayLaunchResult.failed,
);
} catch (_) {
return PayLaunchResult.failed;
} finally {
cancelable.cancel();
}
}
/// 按支付方式分发(1支付宝 2微信)
static Future<PayLaunchResult> launch(RechargeOrderInfo order) {
return switch (order.payMethod) {
1 => launchAlipay(order),
2 => launchWechat(order),
_ => Future.value(PayLaunchResult.unsupported),
};
}
/// 支付宝 resultStatus:9000成功 6001用户取消 8000/8001处理中 其余失败
static PayLaunchResult _mapAlipayStatus(String? status) {
return switch (status) {
'9000' => PayLaunchResult.success,
'6001' => PayLaunchResult.canceled,
'8000' || '8001' => PayLaunchResult.success, // 处理中,交由服务端查单确认
_ => PayLaunchResult.failed,
};
}
/// 微信 errCode:0成功 -2用户取消 其余失败
static PayLaunchResult _mapWechatErrCode(int? errCode) {
return switch (errCode) {
0 => PayLaunchResult.success,
-2 => PayLaunchResult.canceled,
_ => PayLaunchResult.failed,
};
}
}