109 lines
3.6 KiB
Dart
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' => '支付结果未知,请查询订单状态',
|
|
_ => '支付宝支付未完成',
|
|
};
|
|
}
|