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.

453 lines
17 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
  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']."/".($goods['goods_unit']));
  49. array_push($goods_temp_all, $goods['name']."*".$goods['number']."/".($goods['goods_unit']));
  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??'',
  82. 'thing4' => implode(";", $goods_temp_all),
  83. 'thing7' => $item->note?:'无备注',
  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' => $store['name'],
  146. 'thing3' => Payment::getMessage($orderMain->pay_type),
  147. 'character_string4' => $item['order_num'],
  148. 'time5' => $item['created_at_text']??'',
  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 = '')
  176. {
  177. $order = Order::query()->where(['id' => $orderId])->first();
  178. $store = Store::query()->where(['id' => $order->store_id])->first();
  179. $storeOpenid = User::query()->where(['id' => $store->user_id])->value('openid');
  180. $goodsInfo = [];
  181. if ($orderGoodsId) {
  182. $goodsInfo = OrderGoods::query()->where(['id' => $orderGoodsId])->pluck('name')->toArray();
  183. } else {
  184. $goodsInfo = OrderGoods::query()->where(['order_id' => $orderId])->pluck('name')->toArray();
  185. }
  186. // 小程序订阅消息发给商户
  187. // 订单编号:{{character_string7.DATA}}\n商品名称:{{thing10.DATA}}\n退款金额:{{amount3.DATA}}\n处理时间:{{date4.DATA}}\n退款说明:{{thing5.DATA}}\n
  188. $tmplId = 'OaWeg0q40NVW2WeO5BY1TFdWi4GsgIY1rFBwo2wDa0g';
  189. $page = 'pages/shopOrders/shopOrders?status=refund&store_id='.$store->id;
  190. $this->sendSubscribeMessage(
  191. $storeOpenid,
  192. $tmplId,
  193. [
  194. 'character_string7' => $order->order_num,
  195. 'thing10' => implode(';', $goodsInfo),
  196. 'amount3' => $refundStoreAmount,
  197. 'date4' => $order->updated_at_text ?? '',
  198. 'thing5' => $order->refund_note ?: '退款',
  199. ],
  200. $page
  201. );
  202. }
  203. /**
  204. * @inheritDoc
  205. */
  206. public function subscribeMsgForDeliveryStart($globalOrderId)
  207. {
  208. // 主订单信息
  209. $orderMain = OrderMain::query()->where(['global_order_id' => $globalOrderId])->first();
  210. if (!$orderMain) {
  211. return false;
  212. }
  213. // 订单商品
  214. $orderIds = Order::query()->where(['order_main_id' => $globalOrderId])->pluck('id');
  215. $goodsInfo = OrderGoods::query()->whereIn('order_id', $orderIds)->pluck('name');
  216. // 骑手信息
  217. $horseman = Employees::query()->where(['id' => $orderMain->horseman_id])->whereJsonContains('position', [(string)Employee::TYPE_HORSEMAN])->first();
  218. // 发送给用户的
  219. // 订单编号:{{character_string6.DATA}}\n商品名称:{{thing8.DATA}}\n骑手信息:{{thing7.DATA}}\n送出时间:{{date3.DATA}}\n温馨提示:{{thing4.DATA}}\n
  220. $userTmplId = 'jZMTjlflXrAO7bPk5Lq_rFjol9Yuq5i4czwwrJbteqk';
  221. $userPage = 'pages/orderDetail/orderDetail?global_order_id=' . $globalOrderId;
  222. $userOpenid = User::query()->where(['id' => $orderMain->user_id])->value('openid');
  223. $this->sendSubscribeMessage(
  224. $userOpenid,
  225. $userTmplId,
  226. [
  227. 'character_string6' => $orderMain->global_order_id,
  228. 'thing8' => implode(';', $goodsInfo),
  229. 'thing7' => $horseman->name.'(电话:'.$horseman->tel.')',
  230. 'date3' => $orderMain->updated_at_text ?? '',
  231. 'thing4' => '懒族骑手已经拿到您订单货品,马上开始配送,请您耐心等待,您可以点击订单详情查看,感谢使用!',
  232. ],
  233. $userPage
  234. );
  235. // 发送给骑手的
  236. // 订单编号:{{character_string1.DATA}}\n商品信息:{{thing8.DATA}}\n收货地址:{{thing9.DATA}}\n预约时间:{{time17.DATA}}\n温馨提示:{{thing11.DATA}}\n
  237. $horsemanTmplId = '6gxjnBZ4bLnaMC0g8wRaP46jGUZU7YqfYb1FPpJVr50';
  238. $horsemanPage = 'pages/deliverymanOrdersDetail/deliverymanOrdersDetail?global_order_id=' . $globalOrderId . '&employees_id=' . $horseman->id;
  239. $horsemanOpenid = User::query()->where(['id' => $horseman->user_id])->value('openid');
  240. $this->sendSubscribeMessage(
  241. $horsemanOpenid,
  242. $horsemanTmplId,
  243. [
  244. 'character_string1' => $orderMain->global_order_id,
  245. 'thing8' => implode(';', $goodsInfo),
  246. 'thing9' => $orderMain->name . ' - ' . $orderMain->address . '(电话:'.$orderMain->tel.')',
  247. 'time17' => $orderMain->delivery_time_note ?? '尽快送达',
  248. 'thing4' => '后台已经派发此订单给您,请注意及时取货配送,您可以点击订单详情查看,辛苦了!',
  249. ],
  250. $horsemanPage
  251. );
  252. }
  253. /**
  254. * @inheritDoc
  255. */
  256. public function subscribeMsgForOrderComplete($orderMain)
  257. {
  258. // 主订单信息
  259. if (!($orderMain instanceof OrderMain)) {
  260. $orderMain = OrderMain::query()->where(['global_order_id' => $orderMain])->first();
  261. }
  262. if (!$orderMain) {
  263. return false;
  264. }
  265. // 骑手信息
  266. $horseman = Employees::query()->where(['id' => $orderMain->horseman_id])->whereJsonContains('position', [(string)Employee::TYPE_HORSEMAN])->first();
  267. // 发送小程序订阅消息给用户提示用户订单完成
  268. // 订单编号:{{character_string2.DATA}}\n订单金额:{{amount5.DATA}}\n配送地址:{{thing3.DATA}}\n配送人员:{{thing4.DATA}}\n送达时间:{{time6.DATA}}\n
  269. $userTmplId = 'slYHfLTzKDGWRxnNLyJBr7sb__PEhh9OCrSBpMW_pdE';
  270. $userPage = 'pages/orderDetail/orderDetail?global_order_id=' . $orderMain->global_order_id;
  271. $userOpenid = User::query()->where(['id' => $orderMain->user_id])->value('openid');
  272. $this->sendSubscribeMessage(
  273. $userOpenid,
  274. $userTmplId,
  275. [
  276. 'character_string2' => $orderMain->global_order_id,
  277. 'amount5' => $orderMain->money,
  278. 'thing3' => $orderMain->name . ' - ' . $orderMain->address . '(电话:'.$orderMain->tel.')',
  279. 'thing4' => $horseman->name.'(电话:'.$horseman->tel.')',
  280. 'time6' => date('Y-m-d H:i:s', $orderMain->complete_time_text),
  281. ],
  282. $userPage
  283. );
  284. }
  285. /**
  286. * @inheritDoc
  287. */
  288. public function sendTempMsg($openid, $template_id, $data, $redirect_url = '', $applet_config = ['appid' => '', 'pagepath' => ''])
  289. {
  290. if (empty($openid) || empty($template_id) || empty($data)) {
  291. return ;
  292. }
  293. // 先拼个基础的
  294. $template = [
  295. 'touser' => $openid,
  296. 'mp_template_msg' => [
  297. 'appid' => config('wechat.official.app_id'),
  298. 'template_id' => $template_id,
  299. 'url' => $redirect_url,
  300. ]
  301. ];
  302. // 看看有没有小程序跳转的要求
  303. $template['mp_template_msg']['miniprogram'] = $applet_config;
  304. // 重点来了,拼接关键数据data
  305. if (!is_array($data)) { # 数组都不是,请回去
  306. return false;
  307. }
  308. if (is_array($data['first'])) {
  309. $template['mp_template_msg']['data']['first']['value'] = $data['first'][0] ?? '';
  310. $template['mp_template_msg']['data']['first']['color'] = $data['first'][1] ?? '';
  311. } else {
  312. $template['mp_template_msg']['data']['first']['value'] = $data['first'];
  313. }
  314. if (isset($data['keyword'])&&is_array($data['keyword'])) {
  315. foreach ($data['keyword'] as $key => &$keyword) {
  316. $index = $key+1;
  317. if (is_array($keyword)) {
  318. $template['mp_template_msg']['data']['keyword'.$index]['value'] = $keyword[0] ?? '';
  319. $template['mp_template_msg']['data']['keyword'.$index]['color'] = $keyword[1] ?? '';
  320. } else {
  321. $template['mp_template_msg']['data']['keyword'.$index]['value'] = $keyword;
  322. }
  323. }
  324. }
  325. if (is_array($data['remark'])) {
  326. $template['mp_template_msg']['data']['remark']['value'] = $data['remark'][0] ?? '';
  327. $template['mp_template_msg']['data']['remark']['color'] = $data['remark'][1] ?? '';
  328. } else {
  329. $template['mp_template_msg']['data']['remark']['value'] = $data['remark'];
  330. }
  331. $app = Factory::miniProgram(config('wechat.applet'));
  332. $app['guzzle_handler'] = CoroutineHandler::class;
  333. $res = $app->uniform_message->send($template);
  334. if (!isset($res['errcode']) || $res['errcode'] != '0') {
  335. $backtrace = debug_backtrace();
  336. array_shift($backtrace);
  337. $this->log->event('template_message_error', ['from' => json_encode($backtrace), 'res' => json_encode($res), 'msg' => json_encode($template)]);
  338. }
  339. }
  340. public function sendSubscribeMessage($openid, $template_id, $data, $page = '')
  341. {
  342. if (empty($openid) || empty($template_id) || empty($data)) {
  343. return ;
  344. }
  345. $app = Factory::miniProgram(config('wechat.applet'));
  346. $app['guzzle_handler'] = CoroutineHandler::class;
  347. $msgData = [
  348. 'touser' => $openid,
  349. 'template_id' => $template_id,
  350. 'page' => $page,
  351. 'miniprogram_state' => env('APP_ENV')=='prod' ? 'formal' : 'developer',
  352. 'data' => $data
  353. ];
  354. $res = $app->subscribe_message->send($msgData);
  355. if (!isset($res['errcode']) || $res['errcode'] != '0') {
  356. $backtrace = debug_backtrace();
  357. array_shift($backtrace);
  358. $this->log->event('subscribe_message_error', ['from' => json_encode($backtrace), 'res' => json_encode($res), 'msg' => json_encode($msgData)]);
  359. }
  360. return $res;
  361. }
  362. public function getSubscribeMessageTempList($forUserType)
  363. {
  364. if ($forUserType == '') {
  365. $app = Factory::miniProgram(config('wechat.applet'));
  366. $app['guzzle_handler'] = CoroutineHandler::class;
  367. $result = $app->subscribe_message->getTemplates()['data'];
  368. $res = [];
  369. foreach ($result as $key => &$tmpl) {
  370. $res[] = [
  371. 'template_id' => $tmpl['priTmplId'] ?? '',
  372. 'title' => $tmpl['title'] ?? '',
  373. ];
  374. }
  375. return $res;
  376. } else {
  377. $builder = SubscribeMessageTemplate::query()->select('pri_tmpl_id as template_id', 'title');
  378. if ($forUserType != 'all') {
  379. $builder = $builder->where(['for_user_type' => $forUserType]);
  380. }
  381. return $builder->get()->toArray();
  382. }
  383. }
  384. }