import 'package:flutter/cupertino.dart'; import 'package:injectable/injectable.dart'; import 'package:location/data/bean/goods_bean.dart'; import 'package:location/data/bean/pay_item_bean.dart'; import 'package:location/data/repositories/member_repository.dart'; import 'package:synchronized/synchronized.dart'; import '../data/api/response/order_first_check_response.dart'; import '../di/get_it.dart'; import '../handler/event_handler.dart'; import 'async_util.dart'; class PaymentStatus { PaymentStatus._(); //订单状态 //0-查询失败,继续轮询 //1-未支付,继续轮询 //2-支付成功 //3-支付关闭 //4-已退款 static const int payStatusFail = 0; static const int payStatusUnpaid = 1; static const int payStatusSuccess = 2; static const int payStatusClose = 3; static const int payStatusRefund = 4; } @lazySingleton class PaymentStatusManager { final MemberRepository memberRepository; PaymentStatusManager(this.memberRepository); static PaymentStatusManager getInstance() { return getIt.get(); } final Map callbackMap = {}; final Map pollingSubscriptionMap = {}; final _lock = Lock(); void _startCheckPolling( String orderNo, PayItemBean paymentWay, GoodsBean storeItemBean, {String? receiptData}) async { await _lock.synchronized(() async { pollingSubscriptionMap[orderNo]?.cancel(); debugPrint('开始轮询支付状态: orderNo = $orderNo'); CancelableFuture orderFuture = AsyncUtil.retry( () => _queryOrderStatus(orderNo, receiptData: receiptData), Duration(seconds: 2), predicate: (error) { if (error is PaymentStatusException) { return error.status == PaymentStatus.payStatusFail || error.status == PaymentStatus.payStatusUnpaid; } return true; }, maxRetry: 50); orderFuture.then((status) async { debugPrint('支付成功: orderNo = $orderNo'); await _lock.synchronized(() { callbackMap[orderNo] ?.onPaymentSuccess(orderNo, paymentWay, storeItemBean); callbackMap.remove(orderNo); }); reportPaySuccess(storeItemBean.amount, orderNo, storeItemBean.name, paymentWay.payMethod); }).catchError((error) async { ///失败回调 callbackMap[orderNo]?.onPaymentFail(); await _lock.synchronized(() { callbackMap.remove(orderNo); }); debugPrint('支付失败: orderNo = $orderNo, error = $error'); }); pollingSubscriptionMap[orderNo] = orderFuture; }); } Future _queryOrderStatus(String orderNo, {String? receiptData}) { return memberRepository .orderStatus(orderNo, receiptData: receiptData) .then((status) async { if (status == PaymentStatus.payStatusSuccess) { return status; } throw PaymentStatusException(status); }); } ///检查是否是第一次支付 Future onOrderFirstCheck() { return memberRepository. orderFirstCheck() .then((checkResponse) { return checkResponse; }); } void reportPaySuccess( int price, String orderId, String itemName, int paymentWay) { EventHandler.reportPay(price, orderId, itemName, paymentWay); } void checkPaymentStatus( String orderNo, PayItemBean paymentWay, GoodsBean storeItemBean, {String? receiptData}) { final way = paymentWay.copyWith(); final goods = storeItemBean.copyWith(); // recordKeyInfoToDisk(orderNo, paymentWay, storeItemBean); _startCheckPolling(orderNo, way, goods, receiptData: receiptData); } void registerPaymentSuccessCallback( String orderNo, PaymentStatusCallback callback) async { await _lock.synchronized(() { callbackMap[orderNo] = callback; }); } void unregisterPaymentSuccessCallback(PaymentStatusCallback callback) async { await _lock.synchronized(() { callbackMap.removeWhere((key, value) => value == callback); }); } void removePollingSubscription(String orderNo) { pollingSubscriptionMap[orderNo]?.cancel(); pollingSubscriptionMap.remove(orderNo); callbackMap.remove(orderNo); } } class PaymentStatusException implements Exception { final int status; PaymentStatusException(this.status); @override String toString() { return '支付状态异常: status = $status'; } } abstract class PaymentStatusCallback { void onPaymentSuccess( String orderNo, PayItemBean paymentWay, GoodsBean storeItemBean); void onPaymentFail(); }