member_pay_helper.dart 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. import 'dart:io';
  2. import 'package:agile_pay/flutter_pay.dart';
  3. import 'package:apple_pay/apple_pay.dart';
  4. import 'package:flutter/cupertino.dart';
  5. import 'package:flutter_screenutil/flutter_screenutil.dart';
  6. import 'package:get/get.dart';
  7. import 'package:get/get_core/src/get_main.dart';
  8. import 'package:injectable/injectable.dart';
  9. import 'package:location/data/bean/goods_bean.dart';
  10. import 'package:location/data/bean/pay_item_bean.dart';
  11. import 'package:location/data/repositories/member_repository.dart';
  12. import 'package:location/utils/common_expand.dart';
  13. import '../data/api/response/request_pay_response.dart';
  14. import '../data/bean/wechat_payment_sign_bean.dart';
  15. import '../data/consts/channel_id.dart';
  16. import '../data/consts/error_code.dart';
  17. import '../data/consts/payment_type.dart';
  18. import '../data/repositories/account_repository.dart';
  19. import '../device/atmob_platform_info.dart';
  20. import '../dialog/alipay_qr_code_dialog.dart';
  21. import '../dialog/common_confirm_dialog.dart';
  22. import '../dialog/loading_dialog.dart';
  23. import '../dialog/wechat_qr_code_dialog.dart';
  24. import '../module/login/login_page.dart';
  25. import '../resource/string.gen.dart';
  26. import '../utils/http_handler.dart';
  27. import '../utils/payment_status_manager.dart';
  28. import '../utils/toast_util.dart';
  29. @lazySingleton
  30. class MemberPayHelper implements PaymentStatusCallback {
  31. final PaymentStatusManager paymentStatusManager;
  32. final MemberRepository memberRepository;
  33. MemberPayHelper(this.paymentStatusManager, this.memberRepository);
  34. Future<void> launchPay(GoodsBean? bean, PayItemBean? payWay) async {
  35. if (bean == null) {
  36. ToastUtil.show(StringName.memberPleaseChoiceGoods);
  37. return;
  38. }
  39. if (payWay == null && !Platform.isIOS) {
  40. ToastUtil.show(StringName.memberPleaseChoicePayment);
  41. return;
  42. }
  43. //增加渠道登录判断
  44. if (atmobPlatformInfo.tgPlatform == ChannelId.sd) {
  45. if (!AccountRepository.getInstance().isLogin.value) {
  46. ToastUtil.show(StringName.accountNoLogin);
  47. final isLogin = await LoginPage.start();
  48. if (!isLogin) {
  49. return;
  50. }
  51. }
  52. }
  53. int goodsId = bean.id;
  54. int payPlatform = payWay!.payPlatform;
  55. int payMethod = payWay.payMethod;
  56. LoadingDialog.show(StringName.payLoading,
  57. backDismiss: true, clickMaskDismiss: true);
  58. memberRepository.setLastSelectedMember(bean, payWay);
  59. try {
  60. final RequestPayResponse response = await MemberRepository.getInstance()
  61. .submitAndRequestPay(
  62. goodsId: goodsId, payPlatform: payPlatform, payMethod: payMethod);
  63. int payWayType =
  64. getPayWayType(payMethod: payMethod, payPlatform: payPlatform);
  65. if (payWayType == PayWayType.paymentWayWechat) {
  66. _onWeChatPay(response.outTradeNo, response.wechatPayPrepayJson!,
  67. payMethod, bean, payWay);
  68. } else if (payWayType == PayWayType.paymentWayWechatScan) {
  69. _onWechatScanPay(
  70. response.outTradeNo, response.wechatPayQrcodeUrl!, payWay, bean);
  71. } else if (payWayType == PayWayType.paymentWayAlipay) {
  72. _onAliPay(response.outTradeNo, response.alipayOrderString!, payMethod,
  73. bean, payWay);
  74. } else if (payWayType == PayWayType.paymentWayAlipayScan) {
  75. _onAliScanPay(
  76. response.outTradeNo, response.alipayQrcodeHtml!, payWay, bean);
  77. } else if (payWayType == PayWayType.paymentWayApple) {
  78. _onApplePay(
  79. response.outTradeNo, response.appAccountToken ?? "", payWay, bean);
  80. } else {
  81. LoadingDialog.hide();
  82. ToastUtil.show(StringName.payNotSupport);
  83. }
  84. } catch (error) {
  85. LoadingDialog.hide();
  86. if (error is ServerErrorException) {
  87. if (error.code == ErrorCode.payOrderError) {
  88. ToastUtil.show(error.message);
  89. } else if (error.code == ErrorCode.noLoginError) {
  90. ToastUtil.show(StringName.accountNoLogin);
  91. LoginPage.start();
  92. } else {
  93. ToastUtil.show(error.message);
  94. }
  95. } else {
  96. ToastUtil.show(StringName.memberPaymentFailed);
  97. }
  98. rethrow;
  99. }
  100. }
  101. Future<void> _onApplePay(
  102. String outTradeNo,
  103. String appAccountToken,
  104. PayItemBean payWayInfo,
  105. GoodsBean goodsInfo,
  106. ) async {
  107. final result = await ApplePay().purchase(
  108. productId: goodsInfo.appleGoodsId ?? "",
  109. appAccountToken: appAccountToken,
  110. );
  111. if (result["success"] == true) {
  112. var receipt = result['receipt'];
  113. print('购买成功: ${result['receipt']}');
  114. checkPaymentStatus(
  115. outTradeNo,
  116. payWayInfo,
  117. goodsInfo,
  118. receiptData: receipt,
  119. );
  120. } else {
  121. LoadingDialog.hide();
  122. ToastUtil.show("支付失败,请稍后重试");
  123. print('购买失败: ${result['error']}');
  124. }
  125. }
  126. void _onAliScanPay(String outTradeNo, String qrHtml, PayItemBean paymentWay,
  127. GoodsBean goodsBean) {
  128. LoadingDialog.hide();
  129. AlipayQrCodeDialog.show(
  130. qrCodeHtml: qrHtml,
  131. loadSuccessCallback: () {
  132. checkPaymentStatus(outTradeNo, paymentWay, goodsBean);
  133. },
  134. onCloseCallback: () async {
  135. //关闭后再持续查询几秒
  136. CustomLoadingDialog.show();
  137. await Future.delayed(Duration(seconds: 4));
  138. paymentStatusManager.removePollingSubscription(outTradeNo);
  139. CustomLoadingDialog.hide();
  140. });
  141. }
  142. void _onAliPay(String outTradeNo, String payJson, int payMethod,
  143. GoodsBean buyGoods, PayItemBean buyPayWay) {
  144. final payInfo = AliPayInfo(payJson);
  145. requestSdkPay(payInfo, outTradeNo, payMethod, buyGoods, buyPayWay);
  146. }
  147. void _onWeChatPay(String outTradeNo, String payJson, int payMethod,
  148. GoodsBean buyGoods, PayItemBean buyPayWay) {
  149. final bean = WechatPaymentSignBean.stringToBean(payJson);
  150. final payInfo = WechatPayInfo(
  151. appId: bean.appId,
  152. partnerId: bean.partnerId,
  153. prepayId: bean.prepayId,
  154. package: bean.package,
  155. noncestr: bean.nonceStr,
  156. timestamp: bean.timeStamp,
  157. sign: bean.sign);
  158. requestSdkPay(payInfo, outTradeNo, payMethod, buyGoods, buyPayWay);
  159. }
  160. void _onWechatScanPay(String outTradeNo, String qrCodeUrl,
  161. PayItemBean paymentWay, GoodsBean goodsBean) {
  162. LoadingDialog.hide();
  163. WechatQrCodeDialog.show(
  164. qrCodeUrl: qrCodeUrl,
  165. loadSuccessCallback: () {
  166. checkPaymentStatus(outTradeNo, paymentWay, goodsBean);
  167. },
  168. onCloseCallback: () async {
  169. //关闭后再持续查询几秒
  170. CustomLoadingDialog.show();
  171. await Future.delayed(Duration(seconds: 4));
  172. paymentStatusManager.removePollingSubscription(outTradeNo);
  173. CustomLoadingDialog.hide();
  174. });
  175. }
  176. void requestSdkPay(dynamic payInfo, String outTradeNo, int payMethod,
  177. GoodsBean buyGoods, PayItemBean buyPayWay) {
  178. AgilePay.startPay(payInfo, success: (String? result) {
  179. checkPaymentStatus(outTradeNo, buyPayWay, buyGoods, receiptData: result);
  180. }, payError: (int errno, String? errorMessage) {
  181. LoadingDialog.hide();
  182. debugPrint('MemberPayHelper---payError: $errno, $errorMessage');
  183. errorPayToast(errno);
  184. }, error: (int errno, String? error) {
  185. LoadingDialog.hide();
  186. debugPrint('MemberPayHelper---error: $errno, $error');
  187. errorPayToast(errno);
  188. });
  189. }
  190. void checkPaymentStatus(
  191. String orderNo, PayItemBean paymentWay, GoodsBean goodsBean,
  192. {String? receiptData}) {
  193. LoadingDialog.show(StringName.payQuerypayState);
  194. paymentStatusManager.registerPaymentSuccessCallback(orderNo, this);
  195. paymentStatusManager.checkPaymentStatus(orderNo, paymentWay, goodsBean,
  196. receiptData: receiptData);
  197. }
  198. void errorPayToast(int errno) {
  199. if (errno == AgilePayCode.payCodeNotSupport) {
  200. ToastUtil.show(StringName.payNotSupport);
  201. } else if (errno == AgilePayCode.payCodeCancelError) {
  202. ToastUtil.show(StringName.payUserCancel);
  203. } else if (errno == AgilePayCode.payCodeWxEnvError) {
  204. ToastUtil.show(StringName.payWxEvnError);
  205. } else if (errno == AgilePayCode.payCodeNotConnectStore) {
  206. ToastUtil.show(StringName.payNotConnectStore);
  207. } else {
  208. ToastUtil.show(StringName.payError);
  209. }
  210. }
  211. @override
  212. void onPaymentFail() {
  213. LoadingDialog.hide();
  214. }
  215. @override
  216. void onPaymentSuccess(
  217. String orderNo, PayItemBean paymentWay, GoodsBean storeItemBean) {
  218. ///购买成功消失
  219. LoadingDialog.hide();
  220. memberRepository.clearLastSelectedMember();
  221. ///购买成功之后弹出
  222. onPaySucessShow();
  223. }
  224. void onPaySucessShow() {
  225. try {
  226. WechatQrCodeDialog.dismiss();
  227. AlipayQrCodeDialog.dismiss();
  228. CustomLoadingDialog.hide();
  229. LoadingDialog.hide();
  230. } catch (e) {
  231. debugPrint('zk---onPaymentSuccess error: $e');
  232. }
  233. showPaymentSuccessDialog(onConfirm: () {
  234. if (Get.key.currentState?.canPop() ?? false) {
  235. Get.back();
  236. }
  237. }, onCancel: () {
  238. if (Get.key.currentState?.canPop() ?? false) {
  239. Get.back();
  240. }
  241. });
  242. }
  243. void showPaymentSuccessDialog(
  244. {required VoidCallback onConfirm, required VoidCallback onCancel}) {
  245. CommonConfirmDialog.show(
  246. backDismiss: false,
  247. clickMaskDismiss: false,
  248. titleWidget: Text(StringName.paySuccessTitle,
  249. style: TextStyle(
  250. fontSize: 17.sp,
  251. color: '#333333'.color,
  252. fontWeight: FontWeight.bold)),
  253. descWidget: Text(
  254. StringName.paySuccessDesc,
  255. style: TextStyle(fontSize: 14.sp, color: '#404040'.color),
  256. ),
  257. confirmText: StringName.dialogSure,
  258. cancelOnTap: onCancel,
  259. confirmOnTap: onConfirm);
  260. }
  261. }