feat: integrate unified payment and wallet refunds
This commit is contained in:
2
apps/user_app/lib/data/services/payment_jsapi.dart
Normal file
2
apps/user_app/lib/data/services/payment_jsapi.dart
Normal file
@@ -0,0 +1,2 @@
|
||||
export 'payment_jsapi_stub.dart'
|
||||
if (dart.library.js_interop) 'payment_jsapi_web.dart';
|
||||
2
apps/user_app/lib/data/services/payment_jsapi_stub.dart
Normal file
2
apps/user_app/lib/data/services/payment_jsapi_stub.dart
Normal file
@@ -0,0 +1,2 @@
|
||||
Future<void> invokeWechatJsapi(String clientArgs) =>
|
||||
throw UnsupportedError('微信 JSAPI 仅支持 Web');
|
||||
25
apps/user_app/lib/data/services/payment_jsapi_web.dart
Normal file
25
apps/user_app/lib/data/services/payment_jsapi_web.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:js_interop';
|
||||
|
||||
@JS('WeixinJSBridge.invoke')
|
||||
external void _invoke(String name, JSAny? arguments, JSFunction callback);
|
||||
|
||||
Future<void> invokeWechatJsapi(String clientArgs) {
|
||||
final completer = Completer<void>();
|
||||
final arguments = jsonDecode(clientArgs).jsify();
|
||||
_invoke(
|
||||
'getBrandWCPayRequest',
|
||||
arguments,
|
||||
(JSAny? rawResult) {
|
||||
final result = rawResult.dartify();
|
||||
final message = result is Map ? result['err_msg']?.toString() ?? '' : '';
|
||||
if (message == 'get_brand_wcpay_request:ok') {
|
||||
completer.complete();
|
||||
} else {
|
||||
completer.completeError(StateError('微信支付未完成:$message'));
|
||||
}
|
||||
}.toJS,
|
||||
);
|
||||
return completer.future;
|
||||
}
|
||||
56
apps/user_app/lib/data/services/payment_launcher.dart
Normal file
56
apps/user_app/lib/data/services/payment_launcher.dart
Normal file
@@ -0,0 +1,56 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:fluwx/fluwx.dart';
|
||||
import 'package:tobias/tobias.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import 'payment_jsapi.dart';
|
||||
|
||||
/// 只负责调起支付渠道;支付结果必须重新向服务端查询确认。
|
||||
class PaymentLauncher {
|
||||
PaymentLauncher({Fluwx? wechat, Tobias? alipay})
|
||||
: _wechat = wechat ?? Fluwx(),
|
||||
_alipay = alipay ?? Tobias();
|
||||
|
||||
final Fluwx _wechat;
|
||||
final Tobias _alipay;
|
||||
|
||||
Future<void> launch(Map<String, Object?> payment) async {
|
||||
final channel = payment['channel'];
|
||||
final payType = payment['pay_type'];
|
||||
final argsText = payment['client_args'] as String? ?? '';
|
||||
|
||||
// 支付宝手机网站支付返回可直接打开的收银台 URL。
|
||||
if (payType == 'wap') {
|
||||
final uri = Uri.tryParse(argsText);
|
||||
if (uri == null ||
|
||||
!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
|
||||
throw StateError('无法打开支付页面');
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (kIsWeb && payType == 'jsapi') {
|
||||
await invokeWechatJsapi(argsText);
|
||||
return;
|
||||
}
|
||||
if (channel == 'alipay') {
|
||||
await _alipay.pay(argsText);
|
||||
return;
|
||||
}
|
||||
|
||||
final args = (jsonDecode(argsText) as Map).cast<String, dynamic>();
|
||||
final accepted = await _wechat.pay(
|
||||
which: Payment(
|
||||
appId: payment['app_id'] as String? ?? '',
|
||||
partnerId: args['partnerId'] as String,
|
||||
prepayId: args['prepayId'] as String,
|
||||
packageValue: args['package'] as String,
|
||||
nonceStr: args['nonceStr'] as String,
|
||||
timestamp: int.parse(args['timeStamp'] as String),
|
||||
sign: args['sign'] as String,
|
||||
),
|
||||
);
|
||||
if (!accepted) throw StateError('微信未接受支付请求');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user