Files

109 lines
3.6 KiB
Dart

import 'dart:async';
import 'package:fluwx/fluwx.dart' as fluwx;
import 'package:tobias/tobias.dart' as tobias;
import '../config/app_config.dart';
import 'models.dart';
import 'order_api.dart';
/// 支付服务抽象:创建订单 + 拉起渠道支付 + 返回支付结果
abstract class PaymentService {
/// 支付完成后会通知服务端落授权;成功与否以 [PayResult.success] 为准
Future<PayResult> pay(Plan plan, PayChannel channel);
}
/// 微信支付(fluwx 实现)
class WechatPayService implements PaymentService {
WechatPayService({required this.orderApi});
final OrderApi orderApi;
@override
Future<PayResult> pay(Plan plan, PayChannel channel) async {
assert(channel == PayChannel.wechat);
final order =
await orderApi.createOrder(planId: plan.id, channel: channel);
final p = order.wechatParams;
final launched = await fluwx.Fluwx().pay(
which: fluwx.Payment(
appId: AppConfig.wechatAppId,
partnerId: p['partnerId'] as String? ?? '',
prepayId: p['prepayId'] as String? ?? '',
packageValue: p['packageValue'] as String? ?? 'Sign=WXPay',
nonceStr: p['nonceStr'] as String? ?? '',
timestamp: int.tryParse('${p['timeStamp'] ?? p['timestamp']}') ?? 0,
sign: p['sign'] as String? ?? '',
),
);
if (!launched) {
return const PayResult(
success: false, message: '未安装微信或拉起支付失败,请稍后再试');
}
// 等待微信回调(errCode == 0 为成功),10s 超时
final completer = Completer<PayResult>();
final cancel = fluwx.Fluwx().addSubscriber((response) {
if (response is! fluwx.WeChatPaymentResponse) return;
completer.complete(PayResult(
success: response.isSuccessful,
message: response.isSuccessful ? null : (response.errStr ?? '微信支付未完成'),
orderId: order.orderId,
));
});
try {
final result =
await completer.future.timeout(const Duration(seconds: 10));
if (result.success) await orderApi.confirmOrder(order.orderId);
return result;
} on TimeoutException {
return PayResult(
success: false,
message: '等待微信支付结果超时,请确认支付状态',
orderId: order.orderId);
} finally {
cancel.cancel();
}
}
}
/// 支付宝支付(tobias 实现,resultStatus 9000 为成功)
class AlipayService implements PaymentService {
AlipayService({required this.orderApi});
final OrderApi orderApi;
@override
Future<PayResult> pay(Plan plan, PayChannel channel) async {
assert(channel == PayChannel.alipay);
final order =
await orderApi.createOrder(planId: plan.id, channel: channel);
final orderStr = order.alipayOrderStr;
if (orderStr == null) {
return const PayResult(success: false, message: '订单缺少支付参数');
}
final map = await tobias.Tobias().pay(
orderStr,
universalLink: AppConfig.alipayUniversalLink,
);
final status = map['resultStatus']?.toString() ?? '';
final ok = status == '9000';
if (ok) await orderApi.confirmOrder(order.orderId);
return PayResult(
success: ok,
message: ok ? null : _alipayMessage(status),
orderId: order.orderId,
);
}
static String _alipayMessage(String status) => switch (status) {
'8000' => '支付结果确认中,请稍后查看',
'6001' => '用户取消支付',
'6002' => '网络异常,支付未完成',
'6004' => '支付结果未知,请查询订单状态',
_ => '支付宝支付未完成',
};
}