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.

473 lines
19 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
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. <?php
  2. namespace App\Service\v3\Implementations;
  3. use App\Commons\Log;
  4. use App\Constants\v3\Employee;
  5. use App\Constants\v3\Payment;
  6. use App\Model\v3\Employees;
  7. use App\Model\v3\Order;
  8. use App\Model\v3\OrderGoods;
  9. use App\Model\v3\OrderMain;
  10. use App\Model\v3\Store;
  11. use App\Model\v3\SubscribeMessageTemplate;
  12. use App\Model\v3\User;
  13. use App\Service\v3\Interfaces\MiniprogramServiceInterface;
  14. use EasyWeChat\Factory;
  15. use Hyperf\Guzzle\CoroutineHandler;
  16. use Hyperf\Di\Annotation\Inject;
  17. class MiniprogramService implements MiniprogramServiceInterface
  18. {
  19. /**
  20. * @Inject
  21. * @var Log
  22. */
  23. protected $log;
  24. /**
  25. * @inheritDoc
  26. */
  27. public function sendTemMsgForOnlineOrder($globalOrderId)
  28. {
  29. // 查询订单信息
  30. $order = OrderMain::query()->where(['global_order_id' => $globalOrderId])->first()->toArray();
  31. $payTypes = ['1' => '微信支付', '2' => '余额支付', '3' => '积分支付', '4' => '货到付款'];
  32. $address_store = $order['address'] . ';' .$order['name']. ';'. substr_replace($order['tel'],'****',3,4);
  33. $address = $order['address'] . ';' .$order['name']. ';'. $order['tel'];
  34. // 查询子订单,用于发消息给商户
  35. $order_children = Order::query()
  36. ->with('orderMain')
  37. ->where(['order_main_id' => $globalOrderId])
  38. ->get();
  39. $goods_temp_all = [];
  40. foreach ($order_children as $key => &$item) {
  41. // 订单商品
  42. $order_goods = OrderGoods::query()
  43. ->where(['order_id' => $item->id])
  44. ->get()
  45. ->toArray();
  46. $goods_temp = [];
  47. foreach ($order_goods as $k => &$goods) {
  48. array_push($goods_temp, $goods['name']."*".$goods['number']);
  49. array_push($goods_temp_all, $goods['name']."*".$goods['number']);
  50. }
  51. // 商户/门店的openid
  52. $store = Store::query()->select(['id', 'name', 'user_id'])
  53. ->where(['id' => $item->store_id])
  54. ->first()->toArray();
  55. $store['openid'] = User::query()
  56. ->where(['id' => $store['user_id']])
  57. ->value('openid');
  58. // 模板数据
  59. $data_store = [
  60. 'first' => ['您有新的外卖订单!订单编号:'.$item->order_num, '#ff0000'],
  61. 'keyword' => [
  62. ["您的外卖订单详情:\r\n".implode(";\r\n",$goods_temp), '#ff0000'],
  63. $item->money,
  64. $payTypes[$order['pay_type']],
  65. $item->created_at_text??'',
  66. $address_store,
  67. ],
  68. 'remark' => [$item->note, '#4e6ef2']
  69. ];
  70. $ret_store = $this->sendTempMsg($store['openid'], '-M7DG_ACwJxqdAvyvJuAnPpx4xaLf3VkkN0fckno71c',$data_store);
  71. // // 小程序订阅消息发给商户
  72. // // 支付金额:{{amount1.DATA}}\n订单编号:{{character_string2.DATA}}\n支付时间:{{date3.DATA}}\n商品详情:{{thing4.DATA}}\n备注:{{thing7.DATA}}\n
  73. // $tmplId = 'UfCON4Dj_7aH_Q5k_HvDgzUb3gu67TokPITsJuvCMxc';
  74. // $page = 'pages/shopOrders/shopOrders?status=paid&store_id='.$store['id'];
  75. // $this->sendSubscribeMessage(
  76. // $store['openid'],
  77. // $tmplId,
  78. // [
  79. // 'amount1' => $item->money,
  80. // 'character_string2' => $item->order_num,
  81. // 'date3' => $item->created_at_text?:date('Y-m-d H:i:s'),
  82. // 'thing4' => mb_substr(implode(";", $goods_temp_all),0,18).'..',
  83. // 'thing7' => mb_substr(($item->note?:'无备注'), 0, 18).'..',
  84. // ],
  85. // $page
  86. // );
  87. }
  88. // 模板数据发送消息给用户
  89. $data_user = [
  90. 'first' => '您好,下单成功!订单编号:'.$order['global_order_id'],
  91. 'keyword' => [
  92. implode(";\r\n", $goods_temp_all),
  93. $order['money'],
  94. $payTypes[$order['pay_type']],
  95. $order['created_at_text'],
  96. $address,
  97. ],
  98. 'remark' => '感谢您的光临,欢迎下次再来!'
  99. ];
  100. // 获取用户openid,发送给用户
  101. $user_openid = User::query()->where(['id' => $order['user_id']])->value('openid');
  102. $ret_user = $this->sendTempMsg($user_openid,'-M7DG_ACwJxqdAvyvJuAnPpx4xaLf3VkkN0fckno71c', $data_user);
  103. }
  104. /**
  105. * @inheritDoc
  106. */
  107. public function sendTemMsgForOfflineOrder($globalOrderId)
  108. {
  109. // 主订单信息
  110. $orderMain = OrderMain::query()->where(['global_order_id' => $globalOrderId])->first();
  111. // 查询子订单,用于发消息给商户
  112. $order_children = Order::query()
  113. ->where(['order_main_id' => $globalOrderId])
  114. ->get()
  115. ->toArray();
  116. foreach ($order_children as $key => &$item) {
  117. // 商户/门店的openid
  118. $store = Store::query()
  119. ->where(['id' => $item['store_id']])
  120. ->first()->toArray();
  121. $store['openid'] = User::query()
  122. ->where(['id' => $store['user_id']])
  123. ->value('openid');
  124. // 模板数据
  125. $data_store = [
  126. 'first' => '您有新订单收入!订单编号:'.$item['order_num'],
  127. 'keyword' => [
  128. $store['name']?:'',
  129. $item['created_at_text']??'',
  130. '暂无',
  131. $item['money']
  132. ],
  133. 'remark' => '感谢您的使用!'
  134. ];
  135. $ret_store = $this->sendTempMsg($store['openid'], 'lxVbC6PVpKbiO44bYqLmacl-BaME70D47Q0jn2Link0',$data_store);
  136. // // 小程序订阅消息发给商户
  137. // // 付款金额:{{amount1.DATA}}\n商户名称:{{thing2.DATA}}\n支付方式:{{thing3.DATA}}\n交易单号:{{character_string4.DATA}}\n交易时间:{{time5.DATA}}\n
  138. // $tmplId = 'PCRNmKGb7t98xsz_GPux3rhXjsu68TPI3nXR7749dC0';
  139. // $page = 'pages/faceOrderList/faceOrderList?store_id='.$store['id'];
  140. // $res = $this->sendSubscribeMessage(
  141. // $store['openid'],
  142. // $tmplId,
  143. // [
  144. // 'amount1' => $item['money'],
  145. // 'thing2' => mb_substr($store['name'], 0, 18).'..',
  146. // 'thing3' => mb_substr(Payment::getMessage($orderMain->pay_type), 0, 18).'..',
  147. // 'character_string4' => $item['order_num'],
  148. // 'time5' => $item['created_at_text']??date('Y-m-d H:i:s'),
  149. // ],
  150. // $page
  151. // );
  152. }
  153. }
  154. /**
  155. * @inheritDoc
  156. */
  157. public function sendTemMsgForAward($money, $note, $openid, $time)
  158. {
  159. // 模板数据发送消息给用户
  160. $data_user = [
  161. 'first' => '恭喜!您有一笔新的奖励收入!',
  162. 'keyword' => [
  163. $money,
  164. $note,
  165. $time
  166. ],
  167. 'remark' => '感谢您的使用!'
  168. ];
  169. // 获取用户openid,发送给用户
  170. $ret_user = $this->sendTempMsg($openid,'ypZ7xdHUjWrRG8P-MD42dhpp6kUlh4Unoh7eTSrLZEg', $data_user);
  171. }
  172. /**
  173. * @inheritDoc
  174. */
  175. public function subscribeMsgForSingleRefund($orderId, $refundStoreAmount, $orderGoodsId = '', $note = '')
  176. {
  177. // TODO 暂时不发
  178. return;
  179. $order = Order::query()->where(['id' => $orderId])->first();
  180. $store = Store::query()->where(['id' => $order->store_id])->first();
  181. $storeOpenid = User::query()->where(['id' => $store->user_id])->value('openid');
  182. $goodsInfo = [];
  183. if ($orderGoodsId) {
  184. $goodsInfo = OrderGoods::query()->where(['id' => $orderGoodsId])->pluck('name')->toArray();
  185. } else {
  186. $goodsInfo = OrderGoods::query()->where(['order_id' => $orderId])->pluck('name')->toArray();
  187. }
  188. // 小程序订阅消息发给商户
  189. // 订单编号:{{character_string7.DATA}}\n商品名称:{{thing10.DATA}}\n退款金额:{{amount3.DATA}}\n处理时间:{{date4.DATA}}\n退款说明:{{thing5.DATA}}\n
  190. $tmplId = 'OaWeg0q40NVW2WeO5BY1TFdWi4GsgIY1rFBwo2wDa0g';
  191. $page = 'pages/shopOrders/shopOrders?status=refund&store_id='.$store->id;
  192. $this->sendSubscribeMessage(
  193. $storeOpenid,
  194. $tmplId,
  195. [
  196. 'character_string7' => $order->order_num,
  197. 'thing10' => mb_substr(implode(';', $goodsInfo),0,18).'..',
  198. 'amount3' => $refundStoreAmount,
  199. 'date4' => $order->updated_at_text ?? date('Y-m-d H:i:s'),
  200. 'thing5' => mb_substr($note ?: '退款', 0, 18).'..',
  201. ],
  202. $page
  203. );
  204. }
  205. /**
  206. * @inheritDoc
  207. */
  208. public function subscribeMsgForDeliveryStart($globalOrderId)
  209. {
  210. // 主订单信息
  211. $orderMain = OrderMain::query()->where(['global_order_id' => $globalOrderId])->first();
  212. if (!$orderMain) {
  213. return false;
  214. }
  215. // 订单商品
  216. $orderIds = Order::query()->where(['order_main_id' => $globalOrderId])->pluck('id')->toArray();
  217. $goodsInfo = OrderGoods::query()->whereIn('order_id', $orderIds)->pluck('name')->toArray();
  218. // 骑手信息
  219. $horseman = Employees::query()->where(['id' => $orderMain->horseman_id])->whereJsonContains('position', [(string)Employee::TYPE_HORSEMAN])->first();
  220. // 发送给用户的
  221. // 订单编号:{{character_string6.DATA}}\n商品名称:{{thing8.DATA}}\n骑手信息:{{thing7.DATA}}\n送出时间:{{date3.DATA}}\n温馨提示:{{thing4.DATA}}\n
  222. $userTmplId = env('APP_ENV') == 'prod' ? '6E09Od5Ofy08C3qx3eJrOQiWT75uUwIxgG7ta2W75BQ' : 'jZMTjlflXrAO7bPk5Lq_rFjol9Yuq5i4czwwrJbteqk';
  223. $userPage = 'pages/orderDetail/orderDetail?global_order_id=' . $globalOrderId;
  224. $userOpenid = User::query()->where(['id' => $orderMain->user_id])->value('openid');
  225. $sendHorsemanInfo = $horseman->name.'|电话'.$horseman->tel;
  226. $sendNote = '预计'.$orderMain->delivery_time_note.'送达,点击看订单详细信息哦!';
  227. $sendGoodsInfo = implode(';', $goodsInfo);
  228. $this->sendSubscribeMessage(
  229. $userOpenid,
  230. $userTmplId,
  231. [
  232. 'character_string6' => $orderMain->global_order_id,
  233. 'thing8' => mb_strlen($sendGoodsInfo)>18 ? mb_substr($sendGoodsInfo, 0, 18).'..' : $sendGoodsInfo,
  234. 'thing7' => mb_strlen($sendHorsemanInfo)>18 ? mb_substr($sendHorsemanInfo, 0, 18).'..' : $sendHorsemanInfo,
  235. 'date3' => $orderMain->updated_at_text ?? '',
  236. 'thing4' => mb_strlen($sendNote)>18 ? mb_substr($sendNote, 0, 18).'..' : $sendNote,
  237. ],
  238. $userPage
  239. );
  240. // // 发送给骑手的
  241. // // 订单编号:{{character_string1.DATA}}\n商品信息:{{thing8.DATA}}\n收货地址:{{thing9.DATA}}\n预约时间:{{time17.DATA}}\n温馨提示:{{thing11.DATA}}\n
  242. // $horsemanTmplId = '6gxjnBZ4bLnaMC0g8wRaP46jGUZU7YqfYb1FPpJVr50';
  243. // $horsemanPage = 'pages/deliverymanOrdersDetail/deliverymanOrdersDetail?global_order_id=' . $globalOrderId . '&employees_id=' . $horseman->id;
  244. // $horsemanOpenid = User::query()->where(['id' => $horseman->user_id])->value('openid');
  245. // $deliveryNote = $orderMain->delivery_start_time ? date('Y-m-d H:i:s', $orderMain->delivery_start_time+1800) : date('Y-m-d H:i:s', time()+1800);
  246. //
  247. // if (strpos($orderMain->delivery_time_note, ' - ') !== false) {
  248. // $arr = explode(' - ', $orderMain->delivery_time_note);
  249. // if (is_array($arr) && isset($arr[0]) && $arr[0]) {
  250. // $deliveryNote = date('Y-m-d').' '.$orderMain->delivery_time_note.':00';
  251. // }
  252. // }
  253. //
  254. // $this->sendSubscribeMessage(
  255. // $horsemanOpenid,
  256. // $horsemanTmplId,
  257. // [
  258. // 'character_string1' => $orderMain->global_order_id,
  259. // 'thing8' => mb_substr(implode(';', $goodsInfo),0,18).'..',
  260. // 'thing9' => mb_substr(($orderMain->name.'|'.$orderMain->tel.'|'.$orderMain->address), 0, 18).'..',
  261. // 'time17' => $deliveryNote,
  262. // 'thing11' => '有新配送订单,请注意及时取货,辛苦了!',
  263. // ],
  264. // $horsemanPage
  265. // );
  266. }
  267. /**
  268. * @inheritDoc
  269. */
  270. public function subscribeMsgForOrderComplete($orderMain)
  271. {
  272. // 主订单信息
  273. if (!($orderMain instanceof OrderMain)) {
  274. $orderMain = OrderMain::query()->where(['global_order_id' => $orderMain])->first();
  275. }
  276. if (!$orderMain) {
  277. return false;
  278. }
  279. // 骑手信息
  280. $horseman = Employees::query()->where(['id' => $orderMain->horseman_id])->whereJsonContains('position', [(string)Employee::TYPE_HORSEMAN])->first();
  281. // 发送小程序订阅消息给用户提示用户订单完成
  282. // 订单编号:{{character_string2.DATA}}\n订单金额:{{amount5.DATA}}\n配送地址:{{thing3.DATA}}\n配送人员:{{thing4.DATA}}\n送达时间:{{time6.DATA}}\n
  283. $userTmplId = env('APP_ENV') == 'prod' ? 'r7NktOF1-DZwB-KXLcCI_PgFKmVi1onsClFmL6zQtLY' : 'slYHfLTzKDGWRxnNLyJBr7sb__PEhh9OCrSBpMW_pdE';
  284. $userPage = 'pages/orderDetail/orderDetail?global_order_id=' . $orderMain->global_order_id;
  285. $userOpenid = User::query()->where(['id' => $orderMain->user_id])->value('openid');
  286. $sendAddress = $orderMain->name.'|'.$orderMain->address.'|'.$orderMain->tel;
  287. $sendHorseman = $horseman->name.'|'.$horseman->tel;
  288. $this->sendSubscribeMessage(
  289. $userOpenid,
  290. $userTmplId,
  291. [
  292. 'character_string2' => $orderMain->global_order_id,
  293. 'amount5' => $orderMain->money,
  294. 'thing3' => mb_strlen($sendAddress)>18 ? mb_substr($sendAddress,0,18).'..' : $sendAddress,
  295. 'thing4' => mb_strlen($sendHorseman)>18 ? mb_substr($sendHorseman,0,18).'..' : $sendHorseman,
  296. 'time6' => $orderMain->delivery_time_text?:date('Y-m-d H:i:s'),
  297. ],
  298. $userPage
  299. );
  300. }
  301. /**
  302. * @inheritDoc
  303. */
  304. public function sendTempMsg($openid, $template_id, $data, $redirect_url = '', $applet_config = ['appid' => '', 'pagepath' => ''])
  305. {
  306. if (empty($openid) || empty($template_id) || empty($data)) {
  307. return ;
  308. }
  309. // 先拼个基础的
  310. $template = [
  311. 'touser' => $openid,
  312. 'mp_template_msg' => [
  313. 'appid' => config('wechat.official.app_id'),
  314. 'template_id' => $template_id,
  315. 'url' => $redirect_url,
  316. ]
  317. ];
  318. // 看看有没有小程序跳转的要求
  319. $template['mp_template_msg']['miniprogram'] = $applet_config;
  320. // 重点来了,拼接关键数据data
  321. if (!is_array($data)) { # 数组都不是,请回去
  322. return false;
  323. }
  324. if (is_array($data['first'])) {
  325. $template['mp_template_msg']['data']['first']['value'] = $data['first'][0] ?? '';
  326. $template['mp_template_msg']['data']['first']['color'] = $data['first'][1] ?? '';
  327. } else {
  328. $template['mp_template_msg']['data']['first']['value'] = $data['first'];
  329. }
  330. if (isset($data['keyword'])&&is_array($data['keyword'])) {
  331. foreach ($data['keyword'] as $key => &$keyword) {
  332. $index = $key+1;
  333. if (is_array($keyword)) {
  334. $template['mp_template_msg']['data']['keyword'.$index]['value'] = $keyword[0] ?? '';
  335. $template['mp_template_msg']['data']['keyword'.$index]['color'] = $keyword[1] ?? '';
  336. } else {
  337. $template['mp_template_msg']['data']['keyword'.$index]['value'] = $keyword;
  338. }
  339. }
  340. }
  341. if (is_array($data['remark'])) {
  342. $template['mp_template_msg']['data']['remark']['value'] = $data['remark'][0] ?? '';
  343. $template['mp_template_msg']['data']['remark']['color'] = $data['remark'][1] ?? '';
  344. } else {
  345. $template['mp_template_msg']['data']['remark']['value'] = $data['remark'];
  346. }
  347. $app = Factory::miniProgram(config('wechat.applet'));
  348. $app['guzzle_handler'] = CoroutineHandler::class;
  349. $res = $app->uniform_message->send($template);
  350. if (!isset($res['errcode']) || $res['errcode'] != '0') {
  351. $backtrace = debug_backtrace();
  352. array_shift($backtrace);
  353. $this->log->event('template_message_error', ['from' => json_encode($backtrace), 'res' => json_encode($res), 'msg' => json_encode($template)]);
  354. }
  355. }
  356. public function sendSubscribeMessage($openid, $template_id, $data, $page = '')
  357. {
  358. if (empty($openid) || empty($template_id) || empty($data)) {
  359. return ;
  360. }
  361. $app = Factory::miniProgram(config('wechat.applet'));
  362. $app['guzzle_handler'] = CoroutineHandler::class;
  363. $msgData = [
  364. 'touser' => $openid,
  365. 'template_id' => $template_id,
  366. 'page' => $page,
  367. 'miniprogram_state' => env('APP_ENV') == 'prod' ? 'formal' : 'developer',
  368. 'data' => $data
  369. ];
  370. $res = $app->subscribe_message->send($msgData);
  371. if (!isset($res['errcode']) || $res['errcode'] != '0') {
  372. $backtrace = debug_backtrace();
  373. array_shift($backtrace);
  374. $this->log->event('subscribe_message_error', ['from' => json_encode($backtrace), 'res' => json_encode($res), 'msg' => json_encode($msgData)]);
  375. }
  376. return $res;
  377. }
  378. public function getSubscribeMessageTempList($forUserType)
  379. {
  380. if ($forUserType == '') {
  381. $app = Factory::miniProgram(config('wechat.applet'));
  382. $app['guzzle_handler'] = CoroutineHandler::class;
  383. $result = $app->subscribe_message->getTemplates()['data'];
  384. $res = [];
  385. foreach ($result as $key => &$tmpl) {
  386. $res[] = [
  387. 'template_id' => $tmpl['priTmplId'] ?? '',
  388. 'title' => $tmpl['title'] ?? '',
  389. ];
  390. }
  391. return $res;
  392. } else {
  393. $builder = SubscribeMessageTemplate::query()->select('pri_tmpl_id as template_id', 'title');
  394. if ($forUserType != 'all') {
  395. $builder = $builder->where(['for_user_type' => $forUserType]);
  396. }
  397. return $builder->get()->toArray();
  398. }
  399. }
  400. }