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.

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