payment_status_manager.dart 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import 'package:electronic_assistant/data/repositories/account_repository.dart';
  2. import 'package:electronic_assistant/data/repositories/store_repository.dart';
  3. import 'package:electronic_assistant/handler/event_handler.dart';
  4. import 'package:electronic_assistant/utils/async_util.dart';
  5. import 'package:flutter/cupertino.dart';
  6. import 'package:synchronized/synchronized.dart';
  7. import '../../data/bean/payment_way.dart';
  8. import '../../data/bean/store_item.dart';
  9. class PaymentStatusManager {
  10. PaymentStatusManager._();
  11. //订单状态
  12. //0-查询失败,继续轮询
  13. //1-未支付,继续轮询
  14. //2-支付成功
  15. //3-支付关闭
  16. //4-已退款
  17. static const int payStatusFail = 0;
  18. static const int payStatusUnpaid = 1;
  19. static const int payStatusSuccess = 2;
  20. static const int payStatusClose = 3;
  21. static const int payStatusRefund = 4;
  22. final Map<String, PaymentStatusCallback> callbackMap = {};
  23. final Map<String, CancelableFuture> pollingSubscriptionMap = {};
  24. final _lock = Lock();
  25. void _startCheckPolling(
  26. String orderNo, PaymentWay paymentWay, StoreItem storeItemBean,
  27. {String? receiptData}) async {
  28. await _lock.synchronized(() async {
  29. pollingSubscriptionMap[orderNo]?.cancel();
  30. debugPrint('开始轮询支付状态: orderNo = $orderNo');
  31. CancelableFuture orderFuture = AsyncUtil.retryWithExponentialBackoff(
  32. () {
  33. return storeRepository
  34. .orderStatus(orderNo, receiptData: receiptData)
  35. .then((status) {
  36. if (status == payStatusSuccess) {
  37. return true;
  38. } else {
  39. throw PaymentStatusException(status);
  40. }
  41. });
  42. },
  43. 10,
  44. predicate: (error) {
  45. if (error is PaymentStatusException) {
  46. return error.status == payStatusFail ||
  47. error.status == payStatusUnpaid;
  48. }
  49. return true;
  50. });
  51. orderFuture.then((data) async {
  52. debugPrint('支付成功: orderNo = $orderNo');
  53. accountRepository.refreshUserInfo();
  54. await _lock.synchronized(() {
  55. callbackMap[orderNo]
  56. ?.onPaymentSuccess(orderNo, paymentWay, storeItemBean);
  57. callbackMap.remove(orderNo);
  58. });
  59. reportPaySuccess(storeItemBean.amount, orderNo, storeItemBean.name,
  60. paymentWay.payMethod);
  61. }).catchError((error) {
  62. debugPrint('支付失败: orderNo = $orderNo, error = $error');
  63. });
  64. pollingSubscriptionMap[orderNo] = orderFuture;
  65. });
  66. }
  67. void reportPaySuccess(
  68. int price, String orderId, String itemName, int paymentWay) {
  69. EventHandler.reportPay(price, orderId, itemName, paymentWay);
  70. }
  71. void checkPaymentStatus(
  72. String orderNo, PaymentWay paymentWay, StoreItem storeItemBean,
  73. {String? receiptData}) {
  74. // recordKeyInfoToDisk(orderNo, paymentWay, storeItemBean);
  75. _startCheckPolling(orderNo, paymentWay, storeItemBean,
  76. receiptData: receiptData);
  77. }
  78. void registerPaymentSuccessCallback(
  79. String orderNo, PaymentStatusCallback callback) async {
  80. await _lock.synchronized(() {
  81. callbackMap[orderNo] = callback;
  82. });
  83. }
  84. void unregisterPaymentSuccessCallback(PaymentStatusCallback callback) async {
  85. await _lock.synchronized(() {
  86. callbackMap.removeWhere((key, value) => value == callback);
  87. });
  88. }
  89. }
  90. class PaymentStatusException implements Exception {
  91. final int status;
  92. PaymentStatusException(this.status);
  93. @override
  94. String toString() {
  95. return '支付状态异常: status = $status';
  96. }
  97. }
  98. abstract class PaymentStatusCallback {
  99. void onPaymentSuccess(
  100. String orderNo, PaymentWay paymentWay, StoreItem storeItemBean);
  101. }
  102. final paymentStatusManager = PaymentStatusManager._();