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.

383 lines
13 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  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\Constants\v3\Payment;
  7. use App\Controller\BaseController;
  8. use App\Model\v3\Order;
  9. use App\Model\v3\OrderGoods;
  10. use App\Model\v3\OrderMain;
  11. use App\Service\v3\Interfaces\BadgeServiceInterface;
  12. use App\Service\v3\Interfaces\CouponRebateServiceInterface;
  13. use App\Service\v3\Interfaces\CouponServiceInterface;
  14. use App\Service\v3\Interfaces\DeviceServiceInterface;
  15. use App\Service\v3\Interfaces\FeiePrintServiceInterface;
  16. use App\Service\v3\Interfaces\FinancialRecordServiceInterface;
  17. use App\Service\v3\Interfaces\GoodsActivityServiceInterface;
  18. use App\Service\v3\Interfaces\MiniprogramServiceInterface;
  19. use App\Service\v3\Interfaces\MqttServiceInterface;
  20. use App\Service\v3\Interfaces\OrderOfflineServiceInterface;
  21. use App\Service\v3\Interfaces\OrderOnlineServiceInterface;
  22. use App\Service\v3\Interfaces\SeparateAccountsServiceInterface;
  23. use EasyWeChat\Factory;
  24. use Hyperf\DbConnection\Db;
  25. use Hyperf\Guzzle\CoroutineHandler;
  26. use Exception;
  27. use Hyperf\Di\Annotation\Inject;
  28. use Hyperf\HttpMessage\Stream\SwooleStream;
  29. use Symfony\Component\HttpFoundation\Request;
  30. class NotifyController extends BaseController
  31. {
  32. /**
  33. * @Inject
  34. * @var MqttServiceInterface
  35. */
  36. protected $mqttService;
  37. /**
  38. * @Inject
  39. * @var DeviceServiceInterface
  40. */
  41. protected $deviceService;
  42. /**
  43. * @Inject
  44. * @var MiniprogramServiceInterface
  45. */
  46. protected $miniprogramService;
  47. /**
  48. * @Inject
  49. * @var FeiePrintServiceInterface
  50. */
  51. protected $feiePrintService;
  52. /**
  53. * @Inject
  54. * @var CouponRebateServiceInterface
  55. */
  56. protected $couponRebateService;
  57. /**
  58. * @Inject
  59. * @var OrderOnlineServiceInterface
  60. */
  61. protected $orderOnlineService;
  62. /**
  63. * @Inject
  64. * @var OrderOfflineServiceInterface
  65. */
  66. protected $orderOfflineService;
  67. /**
  68. * @Inject
  69. * @var SeparateAccountsServiceInterface
  70. */
  71. protected $separateAccountsService;
  72. /**
  73. * @Inject
  74. * @var CouponServiceInterface
  75. */
  76. protected $couponService;
  77. /**
  78. * @Inject
  79. * @var FinancialRecordServiceInterface
  80. */
  81. protected $financialService;
  82. /**
  83. * @Inject
  84. * @var BadgeServiceInterface
  85. */
  86. protected $badgeService;
  87. /**
  88. * @Inject
  89. * @var GoodsActivityServiceInterface
  90. */
  91. protected $goodsActivityService;
  92. public function wxminiOnline()
  93. {
  94. $config = config('wxpay');
  95. $app = Factory::payment($config);
  96. $app['guzzle_handler'] = CoroutineHandler::class;
  97. $get = $this->request->getQueryParams();
  98. $post = $this->request->getParsedBody();
  99. $cookie = $this->request->getCookieParams();
  100. $files = $this->request->getUploadedFiles();
  101. $server = $this->request->getServerParams();
  102. $xml = $this->request->getBody()->getContents();
  103. $app['request'] = new Request($get,$post,[],$cookie,$files,$server,$xml);
  104. // 通知回调,进行业务处理
  105. $response = $app->handlePaidNotify(function ($message, $fail) use ($app) {
  106. Db::beginTransaction();
  107. try {
  108. // 支付失败或者通知失败
  109. if (
  110. empty($message)
  111. || $message['return_code'] != 'SUCCESS'
  112. || !isset($message['result_code'])
  113. || $message['result_code'] != 'SUCCESS'
  114. ) {
  115. $this->log->event(
  116. LogLabel::ORDER_OFFLINE_PAY_NOTIFY_LOG,
  117. $message
  118. );
  119. Db::rollBack();
  120. return $fail('Unknown error but FAIL');
  121. }
  122. // 查询订单
  123. $orderMain = OrderMain::query()
  124. ->where(['global_order_id' => $message['out_trade_no'],'type' => OrderType::ONLINE,'state' => OrderState::UNPAID])
  125. ->first();
  126. // 订单不存在
  127. if (empty($orderMain)) {
  128. $this->log->event(
  129. LogLabel::ORDER_OFFLINE_PAY_NOTIFY_LOG,
  130. ['global_order_id_fail' => $message['out_trade_no']]
  131. );
  132. Db::rollBack();
  133. return true;
  134. }
  135. $this->orderOnlineService->doByPaid($orderMain->global_order_id);
  136. $this->separateAccountsService->orderOnlinePaid($orderMain->global_order_id);
  137. // 优惠券返券
  138. $this->couponRebateService->couponRebateInTask($orderMain->global_order_id);
  139. // 喇叭通知,兼容旧音响,MQTT+IOT
  140. $res = $this->mqttService->speakToStore($orderMain->global_order_id);
  141. $res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->global_order_id);
  142. // 公众号模板消息
  143. $res = $this->miniprogramService->sendTemMsgForOnlineOrder($orderMain->global_order_id);
  144. // 打印订单,自动打印
  145. $res = $this->feiePrintService->feiePrint($orderMain->global_order_id);
  146. Db::commit();
  147. // 记录badge
  148. $orderChildIds = Order::query()->where(['order_main_id' => $orderMain->global_order_id])->pluck('store_id');
  149. $this->badgeService->doByOrder($orderMain->user_id, $orderChildIds, $orderMain->global_order_id, OrderState::PAID);
  150. return true;
  151. } catch (Exception $e) {
  152. $this->log->event(
  153. LogLabel::ORDER_ONLINE_PAY_NOTIFY_LOG,
  154. ['exception_fail' => $e->getMessage()]
  155. );
  156. Db::rollBack();
  157. return $fail('Exception');
  158. }
  159. });
  160. return $this->response
  161. ->withHeader('Content-Type', 'text/xml')
  162. ->withStatus(200)
  163. ->withBody(new SwooleStream($response->getContent()));
  164. }
  165. public function wxminiOffline()
  166. {
  167. $config = config('wxpay');
  168. $app = Factory::payment($config);
  169. $app['guzzle_handler'] = CoroutineHandler::class;
  170. $get = $this->request->getQueryParams();
  171. $post = $this->request->getParsedBody();
  172. $cookie = $this->request->getCookieParams();
  173. $files = $this->request->getUploadedFiles();
  174. $server = $this->request->getServerParams();
  175. $xml = $this->request->getBody()->getContents();
  176. $app['request'] = new Request($get,$post,[],$cookie,$files,$server,$xml);
  177. // 通知回调,进行业务处理
  178. $response = $app->handlePaidNotify(function ($message, $fail) use ($app) {
  179. Db::beginTransaction();
  180. try {
  181. // 支付失败或者通知失败
  182. if (
  183. empty($message)
  184. || $message['return_code'] != 'SUCCESS'
  185. || !isset($message['result_code'])
  186. || $message['result_code'] != 'SUCCESS'
  187. ) {
  188. $this->log->event(
  189. LogLabel::ORDER_OFFLINE_PAY_NOTIFY_LOG,
  190. $message
  191. );
  192. Db::rollBack();
  193. return $fail('Unknown error but FAIL');
  194. }
  195. // 查询订单
  196. $orderMain = OrderMain::query()
  197. ->where([
  198. 'global_order_id' => $message['out_trade_no'],
  199. 'type' => OrderType::OFFLINE,
  200. 'state' => OrderState::UNPAID
  201. ])
  202. ->first();
  203. // 订单不存在
  204. if (empty($orderMain)) {
  205. $this->log->event(
  206. LogLabel::ORDER_OFFLINE_PAY_NOTIFY_LOG,
  207. ['global_order_id_fail' => $message['out_trade_no']]
  208. );
  209. Db::rollBack();
  210. return true;
  211. }
  212. $orderPaid = $this->orderOfflineService->doByPaid($orderMain->global_order_id);
  213. $separate = $this->separateAccountsService->orderOfflinePaid($orderMain->global_order_id);
  214. // 喇叭通知,兼容旧音响,MQTT+IOT
  215. $res = $this->mqttService->speakToStore($orderMain->global_order_id);
  216. $res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->global_order_id);
  217. // 公众号模板消息
  218. $res = $this->miniprogramService->sendTemMsgForOfflineOrder($orderMain->global_order_id);
  219. Db::commit();
  220. return true;
  221. } catch (Exception $e) {
  222. $this->log->event(
  223. LogLabel::ORDER_OFFLINE_PAY_NOTIFY_LOG,
  224. ['exception_fail' => $e->getMessage()]
  225. );
  226. Db::rollBack();
  227. return $fail('Exception');
  228. }
  229. });
  230. return $this->response
  231. ->withHeader('Content-Type', 'text/xml')
  232. ->withStatus(200)
  233. ->withBody(new SwooleStream($response->getContent()));
  234. }
  235. public function wxminiRefund()
  236. {
  237. $config = config('wxpay');
  238. $app = Factory::payment($config);
  239. $app['guzzle_handler'] = CoroutineHandler::class;
  240. $get = $this->request->getQueryParams();
  241. $post = $this->request->getParsedBody();
  242. $cookie = $this->request->getCookieParams();
  243. $files = $this->request->getUploadedFiles();
  244. $server = $this->request->getServerParams();
  245. $xml = $this->request->getBody()->getContents();
  246. $app['request'] = new Request($get,$post,[],$cookie,$files,$server,$xml);
  247. // 通知回调,进行业务处理
  248. $response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail) use ($app) {
  249. Db::beginTransaction();
  250. try {
  251. // 支付失败或者通知失败
  252. if (
  253. empty($message)
  254. || $message['return_code'] != 'SUCCESS'
  255. || !isset($reqInfo['refund_status'])
  256. || $reqInfo['refund_status'] != 'SUCCESS'
  257. ) {
  258. $this->log->event(
  259. LogLabel::ORDER_REFUND_NOTIFY_LOG,
  260. array_merge($message, $reqInfo)
  261. );
  262. Db::rollBack();
  263. return $fail('Unknown error but FAIL');
  264. }
  265. // 查询订单
  266. $orderMain = OrderMain::query()
  267. ->whereIn('state', [OrderState::PAID, OrderState::DELIVERY, OrderState::COMPLETED, OrderState::EVALUATED, OrderState::REFUNDING])
  268. ->where(['global_order_id' => $message['global_order_id'], 'pay_type' => Payment::WECHAT])
  269. ->whereRaw('refund_time is null')
  270. ->first();
  271. // 订单不存在
  272. if (empty($orderMain)) {
  273. $this->log->event(
  274. LogLabel::ORDER_REFUND_NOTIFY_LOG,
  275. ['global_order_id_fail' => $message['out_trade_no']]
  276. );
  277. Db::rollBack();
  278. return true;
  279. }
  280. // 添加退款时间
  281. $orderMain->refund_time = time();
  282. $orderMain->state = OrderState::REFUNDED;
  283. $orderMain->save();
  284. // 退款返还优惠券
  285. $this->couponService->orderRefundCoupons($orderMain->global_order_id);
  286. // 处理特价商品缓存
  287. $orderChildren = Order::query()->where(['order_main_id' => $orderMain->global_order_id])->get()->toArray();
  288. $orderGoods = OrderGoods::query()
  289. ->where(['activity_type' => 2])
  290. ->whereIn('order_id', array_values(array_column($orderChildren, 'id')))->get();
  291. foreach ($orderGoods as $key => &$item) {
  292. $this->goodsActivityService->clearCacheRecord($item['goods_id'], $item['number'], $orderMain->userId);
  293. }
  294. // 添加用户的流水
  295. $this->financialService->userByOLOrderRefund($orderMain->user_id, $orderMain->global_order_id, $orderMain->money);
  296. Db::commit();
  297. // 记录badge
  298. $orderChildIds = array_values(array_column($orderChildren, 'store_id'));
  299. $this->badgeService->doByOrder($orderMain->user_id, $orderChildIds, $orderMain->global_order_id, OrderState::REFUNDED);
  300. return true;
  301. } catch (Exception $e) {
  302. $this->log->event(
  303. LogLabel::ORDER_REFUND_NOTIFY_LOG,
  304. ['exception_fail' => $e->getMessage()]
  305. );
  306. Db::rollBack();
  307. return $fail('Exception');
  308. }
  309. });
  310. return $this->response
  311. ->withHeader('Content-Type', 'text/xml')
  312. ->withStatus(200)
  313. ->withBody(new SwooleStream($response->getContent()));
  314. }
  315. }