PaySuccess.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2024 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\api\service\recharge;
  13. use app\api\model\PaymentTrade as PaymentTradeModel;
  14. use app\common\enum\payment\Method as PaymentMethodEnum;
  15. use app\common\service\BaseService;
  16. use app\api\model\User as UserModel;
  17. use app\api\model\recharge\Order as OrderModel;
  18. use app\api\model\user\BalanceLog as BalanceLogModel;
  19. use app\common\enum\user\balanceLog\Scene as SceneEnum;
  20. use app\common\enum\recharge\order\PayStatus as PayStatusEnum;
  21. use cores\exception\BaseException;
  22. /**
  23. * 余额充值订单支付成功服务类
  24. * Class PaySuccess
  25. * @package app\api\service\order
  26. */
  27. class PaySuccess extends BaseService
  28. {
  29. // 当前订单信息
  30. public OrderModel $orderInfo;
  31. // 当前订单号
  32. private string $orderNo;
  33. // 订单支付方式
  34. private string $method;
  35. // 第三方交易记录ID
  36. private int $tradeId;
  37. // 第三方支付成功返回的数据
  38. private array $paymentData = [];
  39. /**
  40. * 设置当前的订单号
  41. * @param string $orderNo
  42. * @return $this
  43. */
  44. public function setOrderNo(string $orderNo): PaySuccess
  45. {
  46. $this->orderNo = $orderNo;
  47. return $this;
  48. }
  49. /**
  50. * 设置订单支付方式
  51. * @param string $method
  52. * @return $this
  53. */
  54. public function setMethod(string $method): PaySuccess
  55. {
  56. $this->method = $method;
  57. return $this;
  58. }
  59. /**
  60. * 第三方支付交易记录ID
  61. * @param int $tradeId
  62. * @return $this
  63. */
  64. public function setTradeId(int $tradeId): PaySuccess
  65. {
  66. $this->tradeId = $tradeId;
  67. return $this;
  68. }
  69. /**
  70. * 第三方支付成功返回的数据
  71. * @param array $paymentData
  72. * @return $this
  73. */
  74. public function setPaymentData(array $paymentData): PaySuccess
  75. {
  76. $this->paymentData = $paymentData;
  77. return $this;
  78. }
  79. /**
  80. * 订单支付成功业务处理
  81. * @return bool
  82. * @throws BaseException
  83. */
  84. public function handle(): bool
  85. {
  86. // 验证当前参数是否合法
  87. $this->verifyParameters();
  88. // 验证当前订单是否允许支付
  89. if ($this->checkOrderStatusOnPay()) {
  90. // 更新订单状态为已付款
  91. $this->updatePayStatus();
  92. }
  93. return true;
  94. }
  95. /**
  96. * 验证当前参数是否合法
  97. * @throws BaseException
  98. */
  99. private function verifyParameters()
  100. {
  101. if (empty($this->orderNo)) {
  102. throwError('orderNo not found');
  103. }
  104. if (empty($this->method)) {
  105. throwError('method not found');
  106. }
  107. if ($this->tradeId) {
  108. empty($this->paymentData) && throwError('PaymentData not found');
  109. !isset($this->paymentData['tradeNo']) && throwError('PaymentData not found');
  110. }
  111. }
  112. /**
  113. * 获取当前订单的详情信息
  114. * @return OrderModel|null
  115. * @throws BaseException
  116. */
  117. private function getOrderInfo(): ?OrderModel
  118. {
  119. // 获取订单详情 (待支付状态)
  120. if (empty($this->orderInfo)) {
  121. $this->orderInfo = OrderModel::getPayDetail($this->orderNo);
  122. }
  123. // 判断订单是否存在
  124. if (empty($this->orderInfo)) {
  125. throwError('未找到该订单信息');
  126. }
  127. return $this->orderInfo;
  128. }
  129. /**
  130. * 订单模型
  131. * @return OrderModel|null
  132. * @throws BaseException
  133. */
  134. private function orderModel(): ?OrderModel
  135. {
  136. return $this->getOrderInfo();
  137. }
  138. /**
  139. * 验证当前订单是否允许支付
  140. * @return bool
  141. * @throws BaseException
  142. */
  143. private function checkOrderStatusOnPay(): bool
  144. {
  145. // 当前订单信息
  146. $orderInfo = $this->getOrderInfo();
  147. // 检查订单状态是否为已支付
  148. if ($orderInfo['pay_status'] == PayStatusEnum::SUCCESS) {
  149. return false;
  150. }
  151. return true;
  152. }
  153. /**
  154. * 更新订单状态为已付款
  155. * @return void
  156. * @throws BaseException
  157. */
  158. private function updatePayStatus(): void
  159. {
  160. // 当前订单信息
  161. $orderInfo = $this->getOrderInfo();
  162. try {
  163. // 开启事务处理
  164. $this->orderModel()->startTrans();
  165. // 更新订单状态
  166. $this->orderModel()->save([
  167. 'pay_status' => PayStatusEnum::SUCCESS,
  168. 'pay_time' => time(),
  169. 'pay_method' => $this->method,
  170. 'trade_id' => $this->tradeId ?: 0,
  171. ]);
  172. // 累积用户余额
  173. UserModel::setIncBalance((int)$orderInfo['user_id'], (float)$orderInfo['actual_money']);
  174. // 用户余额变动明细
  175. BalanceLogModel::add(SceneEnum::RECHARGE, [
  176. 'user_id' => $orderInfo['user_id'],
  177. 'money' => $orderInfo['actual_money'],
  178. 'store_id' => $this->getStoreId(),
  179. ], ['order_no' => $orderInfo['order_no']]);
  180. // 将第三方交易记录更新为已支付状态
  181. if (in_array($this->method, [PaymentMethodEnum::WECHAT, PaymentMethodEnum::ALIPAY])) {
  182. $this->updateTradeRecord();
  183. }
  184. // 提交事务处理
  185. $this->orderModel()->commit();
  186. } catch (\Throwable $e) {
  187. $this->orderModel()->rollback();
  188. }
  189. }
  190. /**
  191. * 将第三方交易记录更新为已支付状态
  192. */
  193. private function updateTradeRecord()
  194. {
  195. if ($this->tradeId && !empty($this->paymentData)) {
  196. PaymentTradeModel::updateToPaySuccess($this->tradeId, $this->paymentData['tradeNo']);
  197. }
  198. }
  199. }