xe_create_order_handler.dart
8.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
import 'dart:async';
import 'dart:convert';
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/locator.dart';
import 'package:appframe/data/repositories/user_auth_repository.dart';
import 'package:appframe/services/dispatcher.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_localization/flutter_localization.dart';
import 'package:appframe/services/subscription_service_ios.dart';
import 'package:fluwx/fluwx.dart';
class XeCreateOrderHandler extends MessageHandler {
late final Fluwx _fluwx;
late final UserAuthRepository _userAuthRepository;
late FluwxCancelable _fluwxCancelable;
// 支付结果 Completer,用于将异步回调转为 await
Completer<WeChatPaymentResponse>? _payCompleter;
// 超时定时器
Timer? _timeoutTimer;
final SubscriptionService _subService = SubscriptionService();
XeCreateOrderHandler() {
_fluwx = getIt.get<Fluwx>();
_userAuthRepository = getIt.get<UserAuthRepository>();
}
@override
Future<dynamic> handleMessage(params) async {
print("handleMessage "+params);
// 从 params 中提取支付参数
final String chargeCode = params['chargeCode'] as String? ?? '';
final int durationType = params['durationType'] as int? ?? 0;
final int duration = params['duration'] as int? ?? 0;
final int totalFee = params['totalFee'] as int? ?? 0;
final bool renew = params['renew'] as bool? ?? false;
final String phone = params['phone'] as String? ?? '';
final String userCode = params['userCode'] as String? ?? '';
final String tbxStuId = params['tbxStuId'] as String? ?? '';
final String stuId = params['stuId'] as String? ?? '';
// ext 为 JSON 格式字符串
final String ext = params['ext'] as String? ?? '{}';
// 解析 ext
final Map<String, dynamic> extMap = jsonDecode(ext);
final useCoin = extMap['useCoin'] as bool? ?? false;
debugPrint('PayHandler params: chargeCode=$chargeCode, durationType=$durationType, '
'duration=$duration, totalFee=$totalFee, renew=$renew, '
'phone=$phone, userCode=$userCode, tbxStuId=$tbxStuId, stuId=$stuId, '
'ext=$ext');
// 1. 请求后端获取预支付订单信息
final deviceType = 'ios';
print("[debug]. handleMessage 1 ");
if (deviceType == 'andorid'){
await _wx_pay_proc_(userCode, tbxStuId, chargeCode, deviceType, phone, stuId, ext, duration, durationType, totalFee, renew, useCoin);
}else if (deviceType == 'ios'){
// 暂时不支持使用学币扣减
await _ios_pay_proc_(userCode, tbxStuId, chargeCode, deviceType, phone, stuId, ext, duration, durationType, totalFee, renew, 0);
}
}
// 执行微信支付
Future<dynamic> _wx_pay_proc_ (String userCode, tbxStuId, chargeCode,deviceType,phone,stuId,ext,int duration, durationType, totalFee,bool renew, useCoin) async{
// 2. 检查微信是否安装
if (!await _fluwx.isWeChatInstalled) {
throw Exception('设备上未安装微信App,不支持微信支付');
}
var result = await _userAuthRepository.createOrder(userCode, tbxStuId, chargeCode, duration, durationType, totalFee,
renew, phone, stuId, ext, useCoin ? 1 : 0, deviceType);
if (result == null) {
throw Exception('获取支付信息失败');
}
var data = result['data'] as Map<String, dynamic>?;
if (data == null) {
throw Exception('支付参数获取失败');
}
// 3. 从后端响应中提取预支付ID
final prepayId = data['prepayId'] as String?;
if (prepayId == null || prepayId.isEmpty) {
throw Exception('预支付订单ID获取失败');
}
// 4. 从后端响应中提取支付参数(nonceStr、timestamp、paySign 由后端生成)
final appId = Constant.wxAppId;
final partnerId = Constant.wxPartnerId;
final packageValue = 'Sign=WXPay';
final nonceStr = data['nonceStr'] as String;
final timestamp = data['timeStamp'] as int;
final paySign = data['paySign'] as String;
final wxTradeNo = data['wxTradeNo'] as String;
debugPrint('_wx_pay_proc_ => prepayId: $prepayId');
debugPrint('_wx_pay_proc_ => nonceStr: $nonceStr');
debugPrint('_wx_pay_proc_ => timestamp: $timestamp');
debugPrint('_wx_pay_proc_ => paySign: $paySign');
debugPrint('_wx_pay_proc_ => appId: $appId');
debugPrint('_wx_pay_proc_ => partnerId: $partnerId');
debugPrint('_wx_pay_proc_ => packageValue: $packageValue');
debugPrint('_wx_pay_proc_ => wxTradeNo: $wxTradeNo');
if (nonceStr.isEmpty || paySign.isEmpty || wxTradeNo.isEmpty) {
throw Exception('支付参数获取失败');
}
// 5. 注册支付结果监听器
_payCompleter = Completer<WeChatPaymentResponse>();
_fluwxCancelable = _fluwx.addSubscriber(_responseListener);
// 6. 启动超时兜底(60秒 * 10)
_timeoutTimer = Timer(const Duration(seconds: 600), () {
if (_payCompleter != null && !_payCompleter!.isCompleted) {
_payCompleter!.completeError(TimeoutException('支付超时'));
}
});
// 7. 调用 fluwx.pay() 拉起微信支付
final payResult = await _fluwx.pay(
which: Payment(
// 微信开放平台 AppID
appId: appId,
// 商户号(固定)
partnerId: partnerId,
// 预支付ID(后端返回)
prepayId: prepayId,
// 固定值 Sign=WXPay
packageValue: packageValue,
// 随机字符串(后端返回)
nonceStr: nonceStr,
// 时间戳(后端返回,秒级)
timestamp: timestamp,
// 签名(后端生成)
sign: paySign,
),
);
if (!payResult) {
_cleanup();
throw Exception('拉起微信支付失败');
}
// 8. 等待支付结果回调
try {
final response = await _payCompleter!.future;
if (response.isSuccessful) {
debugPrint('wechat pay success: ${response.errStr}');
return {"orderUnique": wxTradeNo, "orderState": 1};
} else if (response.errCode == -2) {
debugPrint('wechat pay cancel: ${response.errStr}');
// 用户取消支付
// throw Exception('已取消支付');
return {"orderUnique": wxTradeNo, "orderState": 0};
} else {
debugPrint('wechat pay failed: ${response.errStr}');
// 支付失败
throw Exception('支付失败');
}
} catch (e) {
debugPrint('wechat pay error: $e');
throw Exception('支付异常:$e');
} finally {
_cleanup();
}
}
/// Fluwx 响应监听器
void _responseListener(WeChatResponse response) {
if (response is WeChatPaymentResponse) {
_timeoutTimer?.cancel();
if (_payCompleter != null && !_payCompleter!.isCompleted) {
_payCompleter!.complete(response);
}
}
}
/// 清理资源
void _cleanup() {
_fluwxCancelable.cancel();
_timeoutTimer?.cancel();
_timeoutTimer = null;
_payCompleter = null;
}
// 执行ios的微信支付
Future<dynamic> _ios_pay_proc_ (String userCode, tbxStuId, chargeCode,deviceType,phone,stuId,ext,int duration, durationType, totalFee,bool renew, useCoin) async{
var result = await _userAuthRepository.createOrder(userCode, tbxStuId, chargeCode, duration, durationType, totalFee,
renew, phone, stuId, ext, useCoin ? 1 : 0, deviceType);
print("[debug]. _ios_pay_proc_ 1 ");
var data = result['data'] as Map<String, dynamic>?;
if (data == null) {
throw Exception('支付参数获取失败');
}
print("[debug]. _ios_pay_proc_ 2 ");
// 3. 从后端响应中提取预支付ID
final prepayId = data['prepayId'] as String?;
if (prepayId == null || prepayId.isEmpty) {
throw Exception('预支付订单ID获取失败');
}
// 4. 从后端响应中提取支付参数(nonceStr、timestamp、paySign 由后端生成)
final timestamp = data['timeStamp'] as int;
final wxTradeNo = data['wxTradeNo'] as String;
print("[debug]. _ios_pay_proc_ 3 ");
debugPrint('_ios_pay_proc_ => prepayId: $prepayId');
debugPrint('_ios_pay_proc_ => timestamp: $timestamp');
debugPrint('_ios_pay_proc_ => wxTradeNo: $wxTradeNo');
if (wxTradeNo.isEmpty) {
throw Exception('支付参数获取失败');
}
// 执行ios支付
await _subService.initialize();
// 为了调试,先模拟
final product = _subService.products[0];
_subService.buySubscription(product, userCode, tbxStuId,wxTradeNo);
}
}