RefundService.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <?php
  2. namespace addons\YunfastPay\common\services;
  3. use addons\YunfastPay\common\enums\YunfastPayEnum;
  4. use addons\YunfastPay\common\models\PaymentOrder;
  5. use addons\YunfastPay\common\models\RefundOrder;
  6. use addons\YunfastPay\common\models\User;
  7. use addons\YunfastPay\common\services\trans\nocash\RefundTrans;
  8. use common\enums\RabbitMqEnum;
  9. use common\logic\order\OrderRefundLogic;
  10. use common\models\order\OrderRefund;
  11. use Yii;
  12. use yii\data\Pagination;
  13. use yii\helpers\Json;
  14. /**
  15. * 退款
  16. * @package addons\YunfastPay\common\services
  17. */
  18. class RefundService extends BaseService
  19. {
  20. /**
  21. * @var RefundTrans
  22. */
  23. protected $refundTrans;
  24. /**
  25. * @var OrderRefund
  26. */
  27. protected $refund;
  28. /**
  29. * @var PaymentOrder
  30. */
  31. protected $payment;
  32. /**
  33. * @var YunPayService
  34. */
  35. protected $yunPay;
  36. /**
  37. * @var string
  38. */
  39. protected $orderNo;
  40. /**
  41. * 订单退款
  42. *
  43. * @param string $order_no
  44. * @param string $refund_source
  45. * @return boolean
  46. */
  47. public function orderRefund(OrderRefund $refund, array $refund_params, string $order_no = '', string $refund_source = YunfastPayEnum::MALL_ORDER)
  48. {
  49. $this->refund = $refund;
  50. $this->payment = $this->getPayment($refund->order_id, $order_no, $refund_source);
  51. $this->yunPay = new YunPayService(['mall_id' => $this->mall_id]);
  52. $this->getRefundTrans();
  53. $res = $this->yunPay->sendPayRq($this->refundTrans);
  54. // 添加日志
  55. $this->addRefundLog($res, $refund_params, $refund_source);
  56. if ($this->getTransStatus($res) == '100') {
  57. // 返回100直接售后
  58. return true;
  59. }
  60. if ($this->getTransStatus($res) == '101') {
  61. // 返回101等候售后
  62. return $this->error('订单处理中');
  63. }
  64. return $this->error($res['respMsg'] ?? '');
  65. }
  66. /**
  67. * 当前订单是否属于插件
  68. *
  69. * @param OrderRefund $refund
  70. * @param string $order_no
  71. * @param string $refund_source
  72. * @return boolean
  73. */
  74. public function isAddonsOrder(OrderRefund $refund, string $order_no = '', string $refund_source = YunfastPayEnum::MALL_ORDER)
  75. {
  76. $this->refund = $refund;
  77. $this->payment = $this->getPayment($refund->order_id, $order_no, $refund_source);
  78. return !empty($this->payment) ? true : false;
  79. }
  80. /**
  81. * 是否已退款
  82. *
  83. * @param OrderRefund $refund
  84. * @param string $refund_source
  85. * @return boolean
  86. */
  87. public function isRefund(OrderRefund $refund, string $refund_source = YunfastPayEnum::MALL_ORDER)
  88. {
  89. $order = RefundOrder::getOrderByRefundId($refund->id, $refund_source);
  90. if (!empty($order)) {
  91. return $order->isRefundOk();
  92. }
  93. return false;
  94. }
  95. /**
  96. * @param integer $order_id
  97. * @param string $order_no
  98. * @param string $refund_source
  99. * @return PaymentOrder
  100. */
  101. protected function getPayment(int $order_id, string $order_no = '', string $refund_source = YunfastPayEnum::MALL_ORDER)
  102. {
  103. return !empty($this->payment)
  104. ? $this->payment
  105. : PaymentOrder::getPaymentByOrderId($order_id, $order_no, $refund_source);
  106. }
  107. /**
  108. * @return RefundTrans
  109. */
  110. protected function getRefundTrans()
  111. {
  112. return $this->refundTrans = new RefundTrans(
  113. $this->getOrderNo(),
  114. $this->payment->order_no,
  115. date('Ymd', $this->payment->created_at),
  116. $this->refund->refund_price,
  117. );
  118. }
  119. /**
  120. * @return string
  121. */
  122. protected function getOrderNo()
  123. {
  124. return !empty($this->orderNo)
  125. ? $this->orderNo
  126. : $this->refund->order_no;
  127. }
  128. /**
  129. * 添加退款日志
  130. *
  131. * @param array $result
  132. * @return void
  133. */
  134. protected function addRefundLog(array $result, array $refund_params, string $refund_source = YunfastPayEnum::MALL_ORDER)
  135. {
  136. // 异步执行
  137. Yii::$app->services->rabbitMq->push(
  138. RabbitMqEnum::EXCHANGE_ORDER,
  139. RabbitMqEnum::ORDER_QUEUE,
  140. [
  141. 'mall_id' => $this->mall_id,
  142. 'user_id' => $this->refund->user_id,
  143. 'refund_id' => $this->refund->id,
  144. 'order_id' => $this->refund->order_id,
  145. 'order_no' => $this->getOrderNo(),
  146. 'refund_amount' => $this->refund->refund_price,
  147. 'req_data' => $this->yunPay->getReqData(),
  148. 'res_data' => $result,
  149. 'refund_params' => $refund_params,
  150. 'status' => $this->getTransStatus($result),
  151. 'refund_source' => $refund_source,
  152. ],
  153. RefundOrder::class,
  154. 'addLog'
  155. );
  156. // RefundOrder::addLog([
  157. // 'mall_id' => $this->mall_id,
  158. // 'user_id' => $this->refund->user_id,
  159. // 'refund_id' => $this->refund->id,
  160. // 'order_id' => $this->refund->order_id,
  161. // 'order_no' => $this->getOrderNo(),
  162. // 'refund_amount' => $this->refund->refund_price,
  163. // 'req_data' => $this->yunPay->getReqData(),
  164. // 'res_data' => $result,
  165. // 'status' => $this->getTransStatus($result),
  166. // ]);
  167. }
  168. /**
  169. * 回调
  170. *
  171. * @param array $respData
  172. * @return boolean
  173. */
  174. public function notify(array $respData)
  175. {
  176. /**
  177. * @var RefundOrder
  178. */
  179. $order = RefundOrder::getOrderByNo($this->mall_id, $respData['outOrderId']);
  180. if ($order->status == '100') return true;
  181. // 交易成功
  182. if ('100' == $respData['transStatus']) {
  183. // 云库存取消自提的退款会传refund_source,其他的都是 YunfastPayEnum::MALL_ORDER,云库存自提不走主商城售后
  184. if ($order->refund_source === YunfastPayEnum::MALL_ORDER) {
  185. // 退款
  186. $logic = new OrderRefundLogic();
  187. $params = Json::decode($order->refund_params);
  188. $res = $logic->execute($this->mall_id, array_merge($params, [
  189. 'is_notify' => true // 设置为回调模式
  190. ]));
  191. if ($res == false) {
  192. Yii::error('订单回调退款订单失败%s', $respData['outOrderId']);
  193. }
  194. }
  195. return true;
  196. } else if ('102' == $respData['transStatus']) {
  197. // 交易失败
  198. $order->changeStatus('102');
  199. return true;
  200. } else {
  201. // 未知结果,这种情况不会有。
  202. return $this->error('未知情况');
  203. }
  204. }
  205. /**
  206. * 获取订单分页列表
  207. *
  208. * @param array $params
  209. * @return array
  210. */
  211. public function getPageList(array $params)
  212. {
  213. $limit = $params['limit'] ?? 20;
  214. $page = $params['page'] ?? 1;
  215. $model = RefundOrder::find();
  216. $model->andWhere(['mall_id' => $this->mall_id]);
  217. $model->with(['user']);
  218. if (!empty($params['user_id'])) {
  219. $model->andWhere(['user_id' => $params['user_id']]);
  220. }
  221. if (!empty($params['user_keyword'])) {
  222. $model->andWhere([
  223. 'user_id' => User::getUserIdsByKeyword($this->mall_id, $params['user_keyword'])
  224. ]);
  225. }
  226. if (!empty($params['order_no'])) {
  227. $model->andWhere(['order_no' => $params['order_no']]);
  228. }
  229. if (!empty($params['time'])) {
  230. $model->andFilterWhere([
  231. 'between',
  232. 'created_at',
  233. strtotime($params['time'][0]),
  234. strtotime($params['time'][1])
  235. ]);
  236. }
  237. $pagination = new Pagination(['totalCount' => $model->count(), 'pageSize' => $limit]);
  238. $model->limit($pagination->limit)->offset($pagination->offset);
  239. $list = $model->orderBy('id desc')
  240. ->asArray()
  241. ->all();
  242. $data['list'] = $list;
  243. $data['page_count'] = $pagination->pageCount;
  244. $data['current_page'] = $page + 1;
  245. return $data;
  246. }
  247. }