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 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 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(); 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 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, }; } }