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.

478 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
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. if ($orderMain->delivery_time_note == '尽快送达') {
  227. $orderMain->delivery_time_note = date('H:i', time()+1800) . '-' . date('H:i', time()+3600);
  228. }
  229. $sendNote = '预计'.$orderMain->delivery_time_note.'送达,点击看订单详细信息哦!';
  230. $sendGoodsInfo = implode(';', $goodsInfo);
  231. $this->sendSubscribeMessage(
  232. $userOpenid,
  233. $userTmplId,
  234. [
  235. 'character_string6' => $orderMain->global_order_id,
  236. 'thing8' => mb_strlen($sendGoodsInfo)>18 ? mb_substr($sendGoodsInfo, 0, 18).'..' : $sendGoodsInfo,
  237. 'thing7' => mb_strlen($sendHorsemanInfo)>18 ? mb_substr($sendHorsemanInfo, 0, 18).'..' : $sendHorsemanInfo,
  238. 'date3' => $orderMain->updated_at_text ?? '',
  239. 'thing4' => mb_strlen($sendNote)>18 ? mb_substr($sendNote, 0, 18).'..' : $sendNote,
  240. ],
  241. $userPage
  242. );
  243. // // 发送给骑手的
  244. // // 订单编号:{{character_string1.DATA}}\n商品信息:{{thing8.DATA}}\n收货地址:{{thing9.DATA}}\n预约时间:{{time17.DATA}}\n温馨提示:{{thing11.DATA}}\n
  245. // $horsemanTmplId = '6gxjnBZ4bLnaMC0g8wRaP46jGUZU7YqfYb1FPpJVr50';
  246. // $horsemanPage = 'pages/deliverymanOrdersDetail/deliverymanOrdersDetail?global_order_id=' . $globalOrderId . '&employees_id=' . $horseman->id;
  247. // $horsemanOpenid = User::query()->where(['id' => $horseman->user_id])->value('openid');
  248. // $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);
  249. //
  250. // if (strpos($orderMain->delivery_time_note, ' - ') !== false) {
  251. // $arr = explode(' - ', $orderMain->delivery_time_note);
  252. // if (is_array($arr) && isset($arr[0]) && $arr[0]) {
  253. // $deliveryNote = date('Y-m-d').' '.$orderMain->delivery_time_note.':00';
  254. // }
  255. // }
  256. //
  257. // $this->sendSubscribeMessage(
  258. // $horsemanOpenid,
  259. // $horsemanTmplId,
  260. // [
  261. // 'character_string1' => $orderMain->global_order_id,
  262. // 'thing8' => mb_substr(implode(';', $goodsInfo),0,18).'..',
  263. // 'thing9' => mb_substr(($orderMain->name.'|'.$orderMain->tel.'|'.$orderMain->address), 0, 18).'..',
  264. // 'time17' => $deliveryNote,
  265. // 'thing11' => '有新配送订单,请注意及时取货,辛苦了!',
  266. // ],
  267. // $horsemanPage
  268. // );
  269. }
  270. /**
  271. * @inheritDoc
  272. */
  273. public function subscribeMsgForOrderComplete($orderMain)
  274. {
  275. // 主订单信息
  276. if (!($orderMain instanceof OrderMain)) {
  277. $orderMain = OrderMain::query()->where(['global_order_id' => $orderMain])->first();
  278. }
  279. if (!$orderMain) {
  280. return false;
  281. }
  282. // 骑手信息
  283. $horseman = Employees::query()->where(['id' => $orderMain->horseman_id])->whereJsonContains('position', [(string)Employee::TYPE_HORSEMAN])->first();
  284. // 发送小程序订阅消息给用户提示用户订单完成
  285. // 订单编号:{{character_string2.DATA}}\n订单金额:{{amount5.DATA}}\n配送地址:{{thing3.DATA}}\n配送人员:{{thing4.DATA}}\n送达时间:{{time6.DATA}}\n
  286. $userTmplId = env('APP_ENV') == 'prod' ? 'r7NktOF1-DZwB-KXLcCI_PgFKmVi1onsClFmL6zQtLY' : 'slYHfLTzKDGWRxnNLyJBr7sb__PEhh9OCrSBpMW_pdE';
  287. $userPage = 'pages/orderDetail/orderDetail?global_order_id=' . $orderMain->global_order_id;
  288. $userOpenid = User::query()->where(['id' => $orderMain->user_id])->value('openid');
  289. $sendAddress = $orderMain->name.'|'.$orderMain->address.'|'.$orderMain->tel;
  290. $sendHorseman = $horseman->name.'|'.$horseman->tel;
  291. $this->sendSubscribeMessage(
  292. $userOpenid,
  293. $userTmplId,
  294. [
  295. 'character_string2' => $orderMain->global_order_id,
  296. 'amount5' => $orderMain->money,
  297. 'thing3' => mb_strlen($sendAddress)>18 ? mb_substr($sendAddress,0,18).'..' : $sendAddress,
  298. 'thing4' => mb_strlen($sendHorseman)>18 ? mb_substr($sendHorseman,0,18).'..' : $sendHorseman,
  299. 'time6' => $orderMain->delivery_time_text?:date('Y-m-d H:i:s'),
  300. ],
  301. $userPage
  302. );
  303. }
  304. /**
  305. * @inheritDoc
  306. */
  307. public function sendTempMsg($openid, $template_id, $data, $redirect_url = '', $applet_config = ['appid' => '', 'pagepath' => ''])
  308. {
  309. if (empty($openid) || empty($template_id) || empty($data)) {
  310. return ;
  311. }
  312. // 先拼个基础的
  313. $template = [
  314. 'touser' => $openid,
  315. 'mp_template_msg' => [
  316. 'appid' => config('wechat.official.app_id'),
  317. 'template_id' => $template_id,
  318. 'url' => $redirect_url,
  319. ]
  320. ];
  321. // 看看有没有小程序跳转的要求
  322. $template['mp_template_msg']['miniprogram'] = $applet_config;
  323. // 重点来了,拼接关键数据data
  324. if (!is_array($data)) { # 数组都不是,请回去
  325. return false;
  326. }
  327. if (is_array($data['first'])) {
  328. $template['mp_template_msg']['data']['first']['value'] = $data['first'][0] ?? '';
  329. $template['mp_template_msg']['data']['first']['color'] = $data['first'][1] ?? '';
  330. } else {
  331. $template['mp_template_msg']['data']['first']['value'] = $data['first'];
  332. }
  333. if (isset($data['keyword'])&&is_array($data['keyword'])) {
  334. foreach ($data['keyword'] as $key => &$keyword) {
  335. $index = $key+1;
  336. if (is_array($keyword)) {
  337. $template['mp_template_msg']['data']['keyword'.$index]['value'] = $keyword[0] ?? '';
  338. $template['mp_template_msg']['data']['keyword'.$index]['color'] = $keyword[1] ?? '';
  339. } else {
  340. $template['mp_template_msg']['data']['keyword'.$index]['value'] = $keyword;
  341. }
  342. }
  343. }
  344. if (is_array($data['remark'])) {
  345. $template['mp_template_msg']['data']['remark']['value'] = $data['remark'][0] ?? '';
  346. $template['mp_template_msg']['data']['remark']['color'] = $data['remark'][1] ?? '';
  347. } else {
  348. $template['mp_template_msg']['data']['remark']['value'] = $data['remark'];
  349. }
  350. $app = Factory::miniProgram(config('wechat.applet'));
  351. $app['guzzle_handler'] = CoroutineHandler::class;
  352. $res = $app->uniform_message->send($template);
  353. if (!isset($res['errcode']) || $res['errcode'] != '0') {
  354. $backtrace = debug_backtrace();
  355. array_shift($backtrace);
  356. $this->log->event('template_message_error', ['from' => json_encode($backtrace), 'res' => json_encode($res), 'msg' => json_encode($template)]);
  357. }
  358. }
  359. public function sendSubscribeMessage($openid, $template_id, $data, $page = '')
  360. {
  361. if (empty($openid) || empty($template_id) || empty($data)) {
  362. return ;
  363. }
  364. $app = Factory::miniProgram(config('wechat.applet'));
  365. $app['guzzle_handler'] = CoroutineHandler::class;
  366. $msgData = [
  367. 'touser' => $openid,
  368. 'template_id' => $template_id,
  369. 'page' => $page,
  370. 'miniprogram_state' => env('APP_ENV') == 'prod' ? 'formal' : 'developer',
  371. 'data' => $data
  372. ];
  373. $res = $app->subscribe_message->send($msgData);
  374. if (!isset($res['errcode']) || $res['errcode'] != '0') {
  375. $backtrace = debug_backtrace();
  376. array_shift($backtrace);
  377. $this->log->event('subscribe_message_error', ['from' => json_encode($backtrace), 'res' => json_encode($res), 'msg' => json_encode($msgData)]);
  378. }
  379. return $res;
  380. }
  381. public function getSubscribeMessageTempList($forUserType)
  382. {
  383. if ($forUserType == '') {
  384. $app = Factory::miniProgram(config('wechat.applet'));
  385. $app['guzzle_handler'] = CoroutineHandler::class;
  386. $result = $app->subscribe_message->getTemplates()['data'];
  387. $res = [];
  388. foreach ($result as $key => &$tmpl) {
  389. $res[] = [
  390. 'template_id' => $tmpl['priTmplId'] ?? '',
  391. 'title' => $tmpl['title'] ?? '',
  392. ];
  393. }
  394. return $res;
  395. } else {
  396. $builder = SubscribeMessageTemplate::query()->select('pri_tmpl_id as template_id', 'title');
  397. if ($forUserType != 'all') {
  398. $builder = $builder->where(['for_user_type' => $forUserType]);
  399. }
  400. return $builder->get()->toArray();
  401. }
  402. }
  403. }