member_pay_helper.dart 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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. memberRepository.setLastSelectedMember(bean, payWay);
  58. try {
  59. final RequestPayResponse response = await MemberRepository.getInstance()
  60. .submitAndRequestPay(
  61. goodsId: goodsId, payPlatform: payPlatform, payMethod: payMethod);
  62. int payWayType =
  63. getPayWayType(payMethod: payMethod, payPlatform: payPlatform);
  64. if (payWayType == PayWayType.paymentWayWechat) {
  65. _onWeChatPay(response.outTradeNo, response.wechatPayPrepayJson!,
  66. payMethod, bean, payWay);
  67. } else if (payWayType == PayWayType.paymentWayWechatScan) {
  68. _onWechatScanPay(
  69. response.outTradeNo, response.wechatPayQrcodeUrl!, payWay, bean);
  70. } else if (payWayType == PayWayType.paymentWayAlipay) {
  71. _onAliPay(response.outTradeNo, response.alipayOrderString!, payMethod,
  72. bean, payWay);
  73. } else if (payWayType == PayWayType.paymentWayAlipayScan) {
  74. _onAliScanPay(
  75. response.outTradeNo, response.alipayQrcodeHtml!, payWay, bean);
  76. } else if (payWayType == PayWayType.paymentWayApple) {
  77. _onApplePay(
  78. response.outTradeNo, response.appAccountToken ?? "", payWay, bean);
  79. } else {
  80. LoadingDialog.hide();
  81. ToastUtil.show(StringName.payNotSupport);
  82. }
  83. } catch (error) {
  84. LoadingDialog.hide();
  85. if (error is ServerErrorException) {
  86. if (error.code == ErrorCode.payOrderError) {
  87. ToastUtil.show(error.message);
  88. } else if (error.code == ErrorCode.noLoginError) {
  89. ToastUtil.show(StringName.accountNoLogin);
  90. LoginPage.start();
  91. } else {
  92. ToastUtil.show(error.message);
  93. }
  94. } else {
  95. ToastUtil.show(StringName.memberPaymentFailed);
  96. }
  97. rethrow;
  98. }
  99. }
  100. Future<void> _onApplePay(
  101. String outTradeNo,
  102. String appAccountToken,
  103. PayItemBean payWayInfo,
  104. GoodsBean goodsInfo,
  105. ) async {
  106. final result = await ApplePay().purchase(
  107. productId: goodsInfo.appleGoodsId ?? "",
  108. appAccountToken: appAccountToken,
  109. );
  110. if (result["success"] == true) {
  111. var receipt = result['receipt'];
  112. print('购买成功: ${result['receipt']}');
  113. checkPaymentStatus(
  114. outTradeNo,
  115. payWayInfo,
  116. goodsInfo,
  117. receiptData: receipt,
  118. );
  119. } else {
  120. LoadingDialog.hide();
  121. ToastUtil.show("支付失败,请稍后重试");
  122. print('购买失败: ${result['error']}');
  123. }
  124. }
  125. void _onAliScanPay(String outTradeNo, String qrHtml, PayItemBean paymentWay,
  126. GoodsBean goodsBean) {
  127. LoadingDialog.hide();
  128. AlipayQrCodeDialog.show(
  129. qrCodeHtml: qrHtml,
  130. loadSuccessCallback: () {
  131. checkPaymentStatus(outTradeNo, paymentWay, goodsBean);
  132. },
  133. onCloseCallback: () async {
  134. //关闭后再持续查询几秒
  135. CustomLoadingDialog.show();
  136. await Future.delayed(Duration(seconds: 4));
  137. paymentStatusManager.removePollingSubscription(outTradeNo);
  138. CustomLoadingDialog.hide();
  139. });
  140. }
  141. void _onAliPay(String outTradeNo, String payJson, int payMethod,
  142. GoodsBean buyGoods, PayItemBean buyPayWay) {
  143. final payInfo = AliPayInfo(payJson);
  144. requestSdkPay(payInfo, outTradeNo, payMethod, buyGoods, buyPayWay);
  145. }
  146. void _onWeChatPay(String outTradeNo, String payJson, int payMethod,
  147. GoodsBean buyGoods, PayItemBean buyPayWay) {
  148. final bean = WechatPaymentSignBean.stringToBean(payJson);
  149. final payInfo = WechatPayInfo(
  150. appId: bean.appId,
  151. partnerId: bean.partnerId,
  152. prepayId: bean.prepayId,
  153. package: bean.package,
  154. noncestr: bean.nonceStr,
  155. timestamp: bean.timeStamp,
  156. sign: bean.sign);
  157. requestSdkPay(payInfo, outTradeNo, payMethod, buyGoods, buyPayWay);
  158. }
  159. void _onWechatScanPay(String outTradeNo, String qrCodeUrl,
  160. PayItemBean paymentWay, GoodsBean goodsBean) {
  161. LoadingDialog.hide();
  162. WechatQrCodeDialog.show(
  163. qrCodeUrl: qrCodeUrl,
  164. loadSuccessCallback: () {
  165. checkPaymentStatus(outTradeNo, paymentWay, goodsBean);
  166. },
  167. onCloseCallback: () async {
  168. //关闭后再持续查询几秒
  169. CustomLoadingDialog.show();
  170. await Future.delayed(Duration(seconds: 4));
  171. paymentStatusManager.removePollingSubscription(outTradeNo);
  172. CustomLoadingDialog.hide();
  173. });
  174. }
  175. void requestSdkPay(dynamic payInfo, String outTradeNo, int payMethod,
  176. GoodsBean buyGoods, PayItemBean buyPayWay) {
  177. AgilePay.startPay(payInfo, success: (String? result) {
  178. checkPaymentStatus(outTradeNo, buyPayWay, buyGoods, receiptData: result);
  179. }, payError: (int errno, String? errorMessage) {
  180. LoadingDialog.hide();
  181. debugPrint('MemberPayHelper---payError: $errno, $errorMessage');
  182. errorPayToast(errno);
  183. }, error: (int errno, String? error) {
  184. LoadingDialog.hide();
  185. debugPrint('MemberPayHelper---error: $errno, $error');
  186. errorPayToast(errno);
  187. });
  188. }
  189. void checkPaymentStatus(
  190. String orderNo, PayItemBean paymentWay, GoodsBean goodsBean,
  191. {String? receiptData}) {
  192. LoadingDialog.show(StringName.payQuerypayState);
  193. paymentStatusManager.registerPaymentSuccessCallback(orderNo, this);
  194. paymentStatusManager.checkPaymentStatus(orderNo, paymentWay, goodsBean,
  195. receiptData: receiptData);
  196. }
  197. void errorPayToast(int errno) {
  198. if (errno == AgilePayCode.payCodeNotSupport) {
  199. ToastUtil.show(StringName.payNotSupport);
  200. } else if (errno == AgilePayCode.payCodeCancelError) {
  201. ToastUtil.show(StringName.payUserCancel);
  202. } else if (errno == AgilePayCode.payCodeWxEnvError) {
  203. ToastUtil.show(StringName.payWxEvnError);
  204. } else if (errno == AgilePayCode.payCodeNotConnectStore) {
  205. ToastUtil.show(StringName.payNotConnectStore);
  206. } else {
  207. ToastUtil.show(StringName.payError);
  208. }
  209. }
  210. @override
  211. void onPaymentFail() {
  212. LoadingDialog.hide();
  213. }
  214. @override
  215. void onPaymentSuccess(
  216. String orderNo, PayItemBean paymentWay, GoodsBean storeItemBean) {
  217. ///购买成功消失
  218. LoadingDialog.hide();
  219. memberRepository.clearLastSelectedMember();
  220. ///购买成功之后弹出
  221. onPaySucessShow();
  222. }
  223. void onPaySucessShow() {
  224. try {
  225. WechatQrCodeDialog.dismiss();
  226. AlipayQrCodeDialog.dismiss();
  227. CustomLoadingDialog.hide();
  228. LoadingDialog.hide();
  229. } catch (e) {
  230. debugPrint('zk---onPaymentSuccess error: $e');
  231. }
  232. showPaymentSuccessDialog(onConfirm: () {
  233. if (Get.key.currentState?.canPop() ?? false) {
  234. Get.back();
  235. }
  236. }, onCancel: () {
  237. if (Get.key.currentState?.canPop() ?? false) {
  238. Get.back();
  239. }
  240. });
  241. }
  242. void showPaymentSuccessDialog(
  243. {required VoidCallback onConfirm, required VoidCallback onCancel}) {
  244. CommonConfirmDialog.show(
  245. backDismiss: false,
  246. clickMaskDismiss: false,
  247. titleWidget: Text(StringName.paySuccessTitle,
  248. style: TextStyle(
  249. fontSize: 17.sp,
  250. color: '#333333'.color,
  251. fontWeight: FontWeight.bold)),
  252. descWidget: Text(
  253. StringName.paySuccessDesc,
  254. style: TextStyle(fontSize: 14.sp, color: '#404040'.color),
  255. ),
  256. confirmText: StringName.dialogSure,
  257. cancelOnTap: onCancel,
  258. confirmOnTap: onConfirm);
  259. }
  260. }