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.

409 lines
16 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
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;
  3. use App\Constants\LogLabel;
  4. use App\Model\Goods;
  5. use App\Model\Order;
  6. use App\Model\OrderGoods;
  7. use App\Model\OrderMain;
  8. use App\Model\OrderSalesStatistic;
  9. use App\Model\SpecCombination;
  10. use App\Model\Store;
  11. use App\Model\StoreAccount;
  12. use App\Model\SystemConfig;
  13. use App\Model\Users;
  14. use App\Service\CouponRebateServiceInterface;
  15. use App\Service\DeviceServiceInterface;
  16. use App\Service\FeiePrintServiceInterface;
  17. use App\Service\MiniprogramServiceInterface;
  18. use App\Service\MqttServiceInterface;
  19. use App\Service\OrderServiceInterface;
  20. use App\Service\SeparateAccountsServiceInterface;
  21. use App\Service\UserServiceInterface;
  22. use EasyWeChat\Factory;
  23. use Hyperf\DbConnection\Db;
  24. use Hyperf\Guzzle\CoroutineHandler;
  25. use Exception;
  26. use Hyperf\Di\Annotation\Inject;
  27. use Hyperf\HttpMessage\Stream\SwooleStream;
  28. use Symfony\Component\HttpFoundation\Request;
  29. class NotifyController extends BaseController
  30. {
  31. const AWARD_LIMIT_AMOUNT = 3;
  32. /**
  33. * @Inject
  34. * @var MqttServiceInterface
  35. */
  36. protected $mqttSpeakerService;
  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 UserServiceInterface
  55. */
  56. protected $userService;
  57. /**
  58. * @Inject
  59. * @var CouponRebateServiceInterface
  60. */
  61. protected $couponRebateService;
  62. /**
  63. * @Inject
  64. * @var OrderServiceInterface
  65. */
  66. protected $orderService;
  67. /**
  68. * @Inject
  69. * @var SeparateAccountsServiceInterface
  70. */
  71. protected $separateAccountsService;
  72. public function wxminiOnline()
  73. {
  74. $config = config('wxpay');
  75. $app = Factory::payment($config);
  76. $app['guzzle_handler'] = CoroutineHandler::class;
  77. $get = $this->request->getQueryParams();
  78. $post = $this->request->getParsedBody();
  79. $cookie = $this->request->getCookieParams();
  80. $files = $this->request->getUploadedFiles();
  81. $server = $this->request->getServerParams();
  82. $xml = $this->request->getBody()->getContents();
  83. $app['request'] = new Request($get,$post,[],$cookie,$files,$server,$xml);
  84. // 通知回调,进行业务处理
  85. $response = $app->handlePaidNotify(function ($message, $fail) use ($app) {
  86. Db::beginTransaction();
  87. try {
  88. // 支付失败或者通知失败
  89. if (
  90. empty($message)
  91. || $message['return_code'] != 'SUCCESS'
  92. || !isset($message['result_code'])
  93. || $message['result_code'] != 'SUCCESS'
  94. ) {
  95. $this->log->event(
  96. LogLabel::PAY_NOTIFY_WXMINI,
  97. $message
  98. );
  99. Db::rollBack();
  100. return $fail('Unknown error but FAIL');
  101. }
  102. // 查询订单
  103. $orderMain = OrderMain::query()
  104. ->where([
  105. 'global_order_id' => $message['out_trade_no'],
  106. 'type' => OrderMain::ORDER_TYPE_ONLINE
  107. ])
  108. ->first();
  109. // 订单不存在
  110. if (empty($orderMain) || $orderMain->state == OrderMain::ORDER_STATE_DELIVERY) {
  111. $this->log->event(
  112. LogLabel::PAY_NOTIFY_WXMINI,
  113. ['global_order_id_fail' => $message['out_trade_no']]
  114. );
  115. Db::rollBack();
  116. return true;
  117. }
  118. $this->orderService->onlinePaid($message['out_trade_no']);
  119. $this->separateAccountsService->orderOnlinePaid($message['out_trade_no']);
  120. // // 修改订单、子订单状态
  121. // $currentTime = time();
  122. // $orderMain->state = OrderMain::ORDER_STATE_UNTAKE;
  123. // $orderMain->time_pay = $currentTime;
  124. // $orderMain->pay_time = date('Y-m-d H:i:s', $currentTime);
  125. // $orderMain->save();
  126. //
  127. // $upOrder = Order::query()
  128. // ->where(['order_main_id' => $orderMain->id])
  129. // ->update(['state' => OrderMain::ORDER_STATE_UNTAKE, 'pay_time' => $orderMain->pay_time]);
  130. //
  131. // // 更新商户销量
  132. // $upStoreScore = Store::query()
  133. // ->whereIn('id', explode(',', $orderMain->store_ids))
  134. // ->update(['score' => Db::raw('score+1')]);
  135. //
  136. // // 更新商品库存和销量
  137. // $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time'])
  138. // ->where(['order_main_id' => $orderMain->id])
  139. // ->get()
  140. // ->toArray();
  141. // $orderGoods = OrderGoods::query()->select(['good_id AS id', 'number', 'combination_id'])
  142. // ->whereIn('order_id', array_values(array_column($orders, 'id')))
  143. // ->get()
  144. // ->toArray();
  145. // foreach ($orderGoods as $key => &$goodsItem) {
  146. //
  147. // $goods = Goods::find($goodsItem['id']);
  148. //
  149. // // 库存处理,有规格
  150. // if ($goodsItem['combination_id']) {
  151. // $combination = SpecCombination::find($goodsItem['combination_id']);
  152. // $combination->number = $combination->number - $goodsItem['number'];
  153. // $combination->save();
  154. // } else {
  155. // $goods->inventory = $goods->inventory - $goodsItem['number'];
  156. // }
  157. //
  158. // $goods->sales = $goods->sales - $goodsItem['number'];
  159. // $goods->save();
  160. //
  161. // }
  162. //
  163. // // 月销流水
  164. // $statistics = [];
  165. // foreach ($orders as $key => &$order) {
  166. // $statistics[] = [
  167. // 'money' => $order['money'],
  168. // 'user_id' => $order['user_id'],
  169. // 'store_id' => $order['store_id'],
  170. // 'market_id' => $orderMain->market_id,
  171. // 'order_id' => $order['id'],
  172. // 'createtime' => strtotime($order['pay_time']),
  173. // ];
  174. // }
  175. //
  176. // if (is_array($statistics) && !empty($statistics)) {
  177. // $inSalesStatistics = OrderSalesStatistic::query()->insert($statistics);
  178. // }
  179. // 优惠券返券
  180. $this->couponRebateService->couponRebateInTask($orderMain->id);
  181. // 喇叭通知,兼容旧音响,MQTT+IOT
  182. $res = $this->mqttSpeakerService->speakToStore($orderMain->id);
  183. $res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->id);
  184. // 公众号模板消息
  185. $res = $this->miniprogramService->sendTemMsgForOnlineOrder($orderMain->id);
  186. // 打印订单,自动打印
  187. $res = $this->feiePrintService->feiePrint($orderMain->global_order_id);
  188. Db::commit();
  189. return true;
  190. } catch (Exception $e) {
  191. $this->log->event(
  192. LogLabel::PAY_NOTIFY_WXMINI,
  193. ['exception_fail' => $e->getMessage()]
  194. );
  195. Db::rollBack();
  196. return $fail('Exception');
  197. }
  198. });
  199. return $this->response
  200. ->withHeader('Content-Type', 'text/xml')
  201. ->withStatus(200)
  202. ->withBody(new SwooleStream($response->getContent()));
  203. }
  204. public function wxminiOffline()
  205. {
  206. $config = config('wxpay');
  207. $app = Factory::payment($config);
  208. $app['guzzle_handler'] = CoroutineHandler::class;
  209. $get = $this->request->getQueryParams();
  210. $post = $this->request->getParsedBody();
  211. $cookie = $this->request->getCookieParams();
  212. $files = $this->request->getUploadedFiles();
  213. $server = $this->request->getServerParams();
  214. $xml = $this->request->getBody()->getContents();
  215. $app['request'] = new Request($get,$post,[],$cookie,$files,$server,$xml);
  216. // 通知回调,进行业务处理
  217. $response = $app->handlePaidNotify(function ($message, $fail) use ($app) {
  218. Db::beginTransaction();
  219. try {
  220. // 支付失败或者通知失败
  221. if (
  222. empty($message)
  223. || $message['return_code'] != 'SUCCESS'
  224. || !isset($message['result_code'])
  225. || $message['result_code'] != 'SUCCESS'
  226. ) {
  227. $this->log->event(
  228. LogLabel::PAY_NOTIFY_WXMINI,
  229. $message
  230. );
  231. Db::rollBack();
  232. return $fail('Unknown error but FAIL');
  233. }
  234. // 查询订单
  235. $orderMain = OrderMain::query()
  236. ->where([
  237. 'global_order_id' => $message['out_trade_no'],
  238. 'type' => OrderMain::ORDER_TYPE_OFFLINE
  239. ])
  240. ->first();
  241. // 订单不存在
  242. if (empty($orderMain)) {
  243. $this->log->event(
  244. LogLabel::PAY_NOTIFY_WXMINI,
  245. ['global_order_id_fail' => $message['out_trade_no']]
  246. );
  247. Db::rollBack();
  248. return true;
  249. }
  250. $orderPaid = $this->orderService->offlinePaid($message['out_trade_no']);
  251. $separate = $this->separateAccountsService->orderOfflinePaid($message['out_trade_no']);
  252. // // 修改订单、子订单状态
  253. // $currentTime = time();
  254. // $orderMain->state = OrderMain::ORDER_STATE_UNTAKE;
  255. // $orderMain->dm_state = OrderMain::ORDER_STATE_UNTAKE;
  256. // $orderMain->time_pay = $currentTime;
  257. // $orderMain->pay_time = date('Y-m-d H:i:s', $currentTime);
  258. // $orderMain->save();
  259. //
  260. // $upOrder = Order::query()
  261. // ->where(['order_main_id' => $orderMain->id])
  262. // ->update([
  263. // 'state' => OrderMain::ORDER_STATE_UNTAKE,
  264. // 'dm_state' => OrderMain::ORDER_STATE_UNTAKE,
  265. // 'pay_time' => date('Y-m-d H:i:s', $currentTime)
  266. // ]);
  267. // // 查询子订单,当面付目前实际上只有一个子订单
  268. // $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time'])
  269. // ->where(['order_main_id' => $orderMain->id])
  270. // ->get()
  271. // ->toArray();
  272. //
  273. // // 商户钱包、流水资金、奖励、发布模板消息处理
  274. // foreach ($orders as $key => $orderItem) {
  275. //
  276. // $recordBase = [
  277. // 'user_id' => $orderItem['user_id'],
  278. // 'order_id' => $orderItem['id'],
  279. // 'store_id' => $orderItem['store_id'],
  280. // 'type' => 1,
  281. // 'time' => date('Y-m-d H:i:s', $currentTime),
  282. // 'add_time' => $currentTime,
  283. // ];
  284. //
  285. // // 钱包
  286. // $store = Store::find($orderItem['store_id']);
  287. // $store->store_wallet = bcadd($store->store_wallet, $orderItem['money'], 2);
  288. // $store->save();
  289. //
  290. // // 流水
  291. // $record = [
  292. // 'money' => $orderItem['money'],
  293. // 'note' => '当面付订单收入',
  294. // 'category' => 2,
  295. // ];
  296. // StoreAccount::query()->insert(array_merge($recordBase, $record));
  297. //
  298. // // 平台新用户奖励给商户
  299. // $isStageNewUser = $this->userService->isPlatformNewUser($orderItem['user_id'], $orderMain->id);
  300. // $needAward = false;
  301. // $awardAmount = 0;
  302. // if ($isStageNewUser) {
  303. // $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_new_user'])->value('value');
  304. // // 流水
  305. // $record = [
  306. // 'money' => $awardAmount,
  307. // 'note' => '新用户下单成功,平台奖励',
  308. // 'category' => 3,
  309. // ];
  310. // $needAward = true;
  311. // } else {
  312. // $isStoreFirstOrderToday = $this->userService->isStoreFirstOrderToday($orderItem['user_id'],$orderItem['store_id'],$orderItem['id'], self::AWARD_LIMIT_AMOUNT);
  313. // if ($isStoreFirstOrderToday && $orderItem['money'] >= self::AWARD_LIMIT_AMOUNT) {
  314. // $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_each_order'])->value('value');
  315. // // 流水
  316. // $record = [
  317. // 'money' => $awardAmount,
  318. // 'note' => '用户下单成功,平台奖励',
  319. // 'category' => 4,
  320. // ];
  321. // $needAward = true;
  322. // }
  323. // }
  324. //
  325. // if ($needAward && $awardAmount) {
  326. // // 奖励钱包
  327. // $store->refresh();
  328. // $store->award_money = bcadd($store->award_money, $awardAmount, 2);
  329. // $store->save();
  330. //
  331. // // 流水
  332. // StoreAccount::query()->insert(array_merge($recordBase, $record));
  333. //
  334. // // 发布公众号消息
  335. // $openid = Users::query()->where(['id' => $store['user_id']])->value('openid');
  336. // $res = $this->miniprogramService->sendTemMsgForAward($record['money'], $record['note'], $openid, $recordBase['time']);
  337. // }
  338. // }
  339. // 喇叭通知,兼容旧音响,MQTT+IOT
  340. $res = $this->mqttSpeakerService->speakToStore($orderMain->id);
  341. $res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->id);
  342. // 公众号模板消息
  343. $res = $this->miniprogramService->sendTemMsgForOfflineOrder($orderMain->id);
  344. Db::commit();
  345. return true;
  346. } catch (Exception $e) {
  347. $this->log->event(
  348. LogLabel::PAY_NOTIFY_WXMINI,
  349. ['exception_fail' => $e->getMessage()]
  350. );
  351. Db::rollBack();
  352. return $fail('Exception');
  353. }
  354. });
  355. return $this->response
  356. ->withHeader('Content-Type', 'text/xml')
  357. ->withStatus(200)
  358. ->withBody(new SwooleStream($response->getContent()));
  359. }
  360. }