You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
9.6 KiB

  1. <?php
  2. namespace App\Controller\v3;
  3. use App\Constants\v3\LogLabel;
  4. use App\Constants\v3\OrderState;
  5. use App\Constants\v3\OrderType;
  6. use App\Controller\BaseController;
  7. use App\Exception\BusinessException;
  8. use App\Model\v3\Goods;
  9. use App\Model\v3\GoodsActivity;
  10. use App\Model\v3\Order;
  11. use App\Model\v3\OrderGoods;
  12. use App\Model\v3\OrderMain;
  13. use App\Model\v3\User;
  14. use App\Service\v3\Interfaces\BadgeServiceInterface;
  15. use App\Service\v3\Interfaces\CouponRebateServiceInterface;
  16. use App\Service\v3\Interfaces\CouponServiceInterface;
  17. use App\Service\v3\Interfaces\DeviceServiceInterface;
  18. use App\Service\v3\Interfaces\FeiePrintServiceInterface;
  19. use App\Service\v3\Interfaces\FinancialRecordServiceInterface;
  20. use App\Service\v3\Interfaces\GoodsActivityServiceInterface;
  21. use App\Service\v3\Interfaces\MiniprogramServiceInterface;
  22. use App\Service\v3\Interfaces\MqttServiceInterface;
  23. use App\Service\v3\Interfaces\OrderOnlineServiceInterface;
  24. use App\Service\v3\Interfaces\OrderStatisticsServiceInterface;
  25. use App\Service\v3\Interfaces\SeparateAccountsServiceInterface;
  26. use App\Service\v3\Interfaces\UserInfoServiceInterface;
  27. use Exception;
  28. use Hyperf\DbConnection\Db;
  29. use Hyperf\Di\Annotation\Inject;
  30. use Psr\Http\Message\ResponseInterface;
  31. /** @var Inject 注解使用 */
  32. /**
  33. * 建行结果通知接口
  34. */
  35. class CcbNotifyController extends BaseController
  36. {
  37. /**
  38. * @Inject
  39. * @var OrderOnlineServiceInterface
  40. */
  41. protected $orderOnlineService;
  42. /**
  43. * @Inject
  44. * @var SeparateAccountsServiceInterface
  45. */
  46. protected $separateAccountsService;
  47. /**
  48. * @Inject
  49. * @var OrderStatisticsServiceInterface
  50. */
  51. protected $orderStatisticsService;
  52. /**
  53. * @Inject
  54. * @var CouponRebateServiceInterface
  55. */
  56. protected $couponRebateService;
  57. /**
  58. * @Inject
  59. * @var MqttServiceInterface
  60. */
  61. protected $mqttService;
  62. /**
  63. * @Inject
  64. * @var DeviceServiceInterface
  65. */
  66. protected $deviceService;
  67. /**
  68. * @Inject
  69. * @var FeiePrintServiceInterface
  70. */
  71. protected $feiePrintService;
  72. /**
  73. * @Inject
  74. * @var BadgeServiceInterface
  75. */
  76. protected $badgeService;
  77. /**
  78. * @Inject
  79. * @var MiniprogramServiceInterface
  80. */
  81. protected $miniprogramService;
  82. /**
  83. * @Inject
  84. * @var UserInfoServiceInterface
  85. */
  86. protected $userInfoService;
  87. /**
  88. * @Inject
  89. * @var CouponServiceInterface
  90. */
  91. protected $couponService;
  92. /**
  93. * @Inject
  94. * @var GoodsActivityServiceInterface
  95. */
  96. protected $goodsActivityService;
  97. /**
  98. * @Inject
  99. * @var FinancialRecordServiceInterface
  100. */
  101. protected $financialService;
  102. /**
  103. * 支付结果通知
  104. */
  105. public function payResult(): ResponseInterface
  106. {
  107. /*$formData = [
  108. 'Main_Ordr_No' => '主订单编号',
  109. 'Py_Trn_No' => 'Py_Trn_No',
  110. 'Ordr_Amt' => '订单金额',
  111. 'Txnamt' => '支付金额',
  112. 'Pay_Time' => '支付时间',
  113. 'Ordr_Stcd' => '2成功 3失败 4失效',
  114. 'TYPE' => '非必输。Pymd_cd=‘05’返回,支付宝:ALIPAY 微信:WEIXIN 建行:CCB 银联:UNIONPAY(暂不支付)',
  115. 'Sign_Inf' => '签名参数',
  116. ];*/
  117. $formData = $this->request->all();
  118. try {
  119. /*if (!CcbPay::getInstance()->SHA256WithRSAVerify($formData)) {
  120. throw new BusinessException(500, '签名验证失败,收到的数据为:' . json_encode($formData));
  121. }*/
  122. if (!isset($formData['Ordr_Stcd']) || $formData['Ordr_Stcd'] != 2) {
  123. throw new BusinessException(500, 'Ordr_Stcd状态码异常:' . ($formData['Ordr_Stcd'] ?? 'null'));
  124. } else if (!isset($formData['Main_Ordr_No'])) {
  125. throw new BusinessException(500, '未获取到订单号Main_Ordr_No');
  126. }
  127. $orderMain = OrderMain::where([
  128. 'global_order_id' => $formData['Main_Ordr_No'],
  129. 'type' => OrderType::ONLINE,
  130. 'state' => OrderState::UNPAID
  131. ])->first();
  132. if (!$orderMain) {
  133. throw new BusinessException(500, $formData['Main_Ordr_No'] . '订单不存在!');
  134. }
  135. $this->orderOnlineService->doByPaid($orderMain->global_order_id);
  136. $this->separateAccountsService->orderOnlinePaid($orderMain->global_order_id);
  137. //记录当前市场的当天外卖订单数
  138. $this->orderStatisticsService->setForMarket($orderMain->market_id);
  139. // 优惠券返券
  140. $this->couponRebateService->couponRebateInTask($orderMain->global_order_id);
  141. // 喇叭通知,兼容旧音响,MQTT+IOT
  142. $res = $this->mqttService->speakToStore($orderMain->global_order_id);
  143. $res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->global_order_id);
  144. // 打印订单,自动打印
  145. $res = $this->feiePrintService->feiePrint($orderMain->global_order_id);
  146. // 记录badge
  147. $orderChildIds = Order::query()->where(['order_main_id' => $orderMain->global_order_id])->pluck('store_id');
  148. $this->badgeService->doByOrder($orderMain->user_id, $orderChildIds, $orderMain->global_order_id, OrderState::PAID);
  149. // 公众号模板消息
  150. $res = $this->miniprogramService->sendTemMsgForOnlineOrder($orderMain->global_order_id);
  151. co(function () use ($orderMain) {
  152. $openid = User::query()->where(['id' => $orderMain->user_id])->value('openid');
  153. $unionid = $this->userInfoService->getPaidUnionId($openid, ['mch_id' => config('wxpay.mch_id'), 'out_trade_no' => $orderMain->global_order_id]);
  154. if ($unionid) {
  155. User::query()->where(['id' => $orderMain->user_id, 'openid' => $openid])->update(['unionid' => $unionid]);
  156. }
  157. });
  158. return $this->response->json(['Svc_Rsp_St' => '00', 'Rsp_Inf' => 'success']); // 00成功;01失败
  159. } catch (Exception $exception) {
  160. $this->log->event(
  161. LogLabel::ORDER_ONLINE_PAY_NOTIFY_LOG,
  162. ['exception_fail' => $exception->getMessage()]
  163. );
  164. return $this->response->json(['Svc_Rsp_St' => '01', 'Rsp_Inf' => $exception->getMessage()]); // 00成功;01失败
  165. }
  166. }
  167. /**
  168. * 退款通知
  169. */
  170. public function refund(): ResponseInterface
  171. {
  172. /*$formData = [
  173. 'Ittparty_Tms' => '发起方时间戳 yyyymmddhhmmssfff',
  174. 'Ittparty_Jrnl_No' => '该笔直连交易的客户方流水号(不允许重复)',
  175. 'Py_Trn_No' => '支付流水号',
  176. 'Cust_Rfnd_Trcno' => '请求时送入客户方退款流水号,则返回送入的值,否则该字段为空。',
  177. 'Super_Refund_No' => '惠市宝生成,与退款动作唯一匹配',
  178. 'Rfnd_Amt' => '退款金额',
  179. 'Refund_Rsp_St' => '00-退款成功 01-退款失败',
  180. 'Refund_Rsp_Inf' => '退款响应信息',
  181. 'Sign_Inf' => '签名信息',
  182. ];*/
  183. $formData = $this->request->all();
  184. Db::beginTransaction();
  185. try {
  186. /*if (!CcbPay::getInstance()->SHA256WithRSAVerify($formData)) {
  187. throw new BusinessException(500, '签名验证失败,收到的数据为:' . json_encode($formData));
  188. }*/
  189. if (!isset($formData['Refund_Rsp_St'])) {
  190. throw new BusinessException(500, 'Refund_Rsp_St状态码异常:' . ($formData['Ordr_Stcd'] ?? 'null'));
  191. } else if (!isset($formData['Ittparty_Jrnl_No'])) {
  192. throw new BusinessException(500, '未获取到订单号Ittparty_Jrnl_No');
  193. }
  194. $orderMain = OrderMain::whereNotIn('state', [OrderState::UNPAID])
  195. ->where(['global_order_id' => $formData['Ittparty_Jrnl_No']])
  196. ->first();
  197. if (!$orderMain) {
  198. throw new BusinessException(500, $formData['Ittparty_Jrnl_No'] . '订单不存在!');
  199. } else if ($orderMain->state == OrderState::REFUNDED) {
  200. return $this->response->json(['Svc_Rsp_St' => '00', 'Ittparty_Tms' => date('YmdHis000'), 'Rsp_Inf' => 'success']);
  201. } else if ($formData['Refund_Rsp_St'] != '00') { // 建行返回退款失败
  202. $orderMain->state = OrderState::REFUND_REFUSE;
  203. $orderMain->refuse_refund_note = '建行拒绝退款';
  204. $orderMain->save();
  205. Db::commit();
  206. return $this->response->json(['Svc_Rsp_St' => '00', 'Ittparty_Tms' => date('YmdHis000'), 'Rsp_Inf' => 'success']); // 00成功;01失败
  207. }
  208. // 添加退款时间
  209. $orderMain->refund_time = time();
  210. $orderMain->state = OrderState::REFUNDED;
  211. $orderMain->save();
  212. // 退款返还优惠券
  213. $this->couponService->orderRefundCoupons($orderMain->global_order_id);
  214. // 处理特价商品缓存
  215. $orderChildren = Order::query()->where(['order_main_id' => $orderMain->global_order_id])->get()->toArray();
  216. $orderGoods = OrderGoods::query()->whereIn('order_id', array_values(array_column($orderChildren, 'id')))->get()->toArray();
  217. foreach ($orderGoods as &$item) {
  218. if ($item['activity_type'] == 2) { # 活动商品
  219. $this->goodsActivityService->clearCacheRecord($item['goods_id'], $item['number'], $orderMain->user_id);
  220. $goods = GoodsActivity::find($item['goods_id']);
  221. } else {
  222. $goods = Goods::find($item['goods_id']);
  223. }
  224. $goods->inventory = $goods->inventory + $item['number'];
  225. $goods->sales = $goods->sales - $item['number'];
  226. $goods->save();
  227. }
  228. // 添加用户的流水
  229. $this->financialService->userByOLOrderRefund($orderMain->user_id, $orderMain->global_order_id, $orderMain->money);
  230. Db::commit();
  231. // 记录badge
  232. $orderChildIds = array_values(array_column($orderChildren, 'store_id'));
  233. $this->badgeService->doByOrder($orderMain->user_id, $orderChildIds, $orderMain->global_order_id, OrderState::REFUNDED);
  234. return $this->response->json(['Svc_Rsp_St' => '00', 'Ittparty_Tms' => date('YmdHis000'), 'Rsp_Inf' => 'success']); // 00成功;01失败
  235. } catch (\Exception $exception) {
  236. Db::rollBack();
  237. $this->log->event(
  238. LogLabel::ORDER_ONLINE_PAY_NOTIFY_LOG,
  239. ['exception_fail' => $exception->getMessage()]
  240. );
  241. return $this->response->json(['Svc_Rsp_St' => '01', 'Ittparty_Tms' => date('YmdHis000'), 'Rsp_Inf' => $exception->getMessage()]); // 00成功;01失败
  242. }
  243. }
  244. }