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.

417 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
  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('positions', [(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 sendTempMsg($openid, $template_id, $data, $redirect_url = '', $applet_config = ['appid' => '', 'pagepath' => ''])
  257. {
  258. if (empty($openid) || empty($template_id) || empty($data)) {
  259. return ;
  260. }
  261. // 先拼个基础的
  262. $template = [
  263. 'touser' => $openid,
  264. 'mp_template_msg' => [
  265. 'appid' => config('wechat.official.app_id'),
  266. 'template_id' => $template_id,
  267. 'url' => $redirect_url,
  268. ]
  269. ];
  270. // 看看有没有小程序跳转的要求
  271. $template['mp_template_msg']['miniprogram'] = $applet_config;
  272. // 重点来了,拼接关键数据data
  273. if (!is_array($data)) { # 数组都不是,请回去
  274. return false;
  275. }
  276. if (is_array($data['first'])) {
  277. $template['mp_template_msg']['data']['first']['value'] = $data['first'][0] ?? '';
  278. $template['mp_template_msg']['data']['first']['color'] = $data['first'][1] ?? '';
  279. } else {
  280. $template['mp_template_msg']['data']['first']['value'] = $data['first'];
  281. }
  282. if (isset($data['keyword'])&&is_array($data['keyword'])) {
  283. foreach ($data['keyword'] as $key => &$keyword) {
  284. $index = $key+1;
  285. if (is_array($keyword)) {
  286. $template['mp_template_msg']['data']['keyword'.$index]['value'] = $keyword[0] ?? '';
  287. $template['mp_template_msg']['data']['keyword'.$index]['color'] = $keyword[1] ?? '';
  288. } else {
  289. $template['mp_template_msg']['data']['keyword'.$index]['value'] = $keyword;
  290. }
  291. }
  292. }
  293. if (is_array($data['remark'])) {
  294. $template['mp_template_msg']['data']['remark']['value'] = $data['remark'][0] ?? '';
  295. $template['mp_template_msg']['data']['remark']['color'] = $data['remark'][1] ?? '';
  296. } else {
  297. $template['mp_template_msg']['data']['remark']['value'] = $data['remark'];
  298. }
  299. $app = Factory::miniProgram(config('wechat.applet'));
  300. $app['guzzle_handler'] = CoroutineHandler::class;
  301. $res = $app->uniform_message->send($template);
  302. if (!isset($res['errcode']) || $res['errcode'] != '0') {
  303. $backtrace = debug_backtrace();
  304. array_shift($backtrace);
  305. $this->log->event('template_message_error', ['from' => json_encode($backtrace), 'res' => json_encode($res), 'msg' => json_encode($template)]);
  306. }
  307. }
  308. public function sendSubscribeMessage($openid, $template_id, $data, $page = '')
  309. {
  310. if (empty($openid) || empty($template_id) || empty($data)) {
  311. return ;
  312. }
  313. $app = Factory::miniProgram(config('wechat.applet'));
  314. $app['guzzle_handler'] = CoroutineHandler::class;
  315. $msgData = [
  316. 'touser' => $openid,
  317. 'template_id' => $template_id,
  318. 'page' => $page,
  319. 'miniprogram_state' => env('APP_ENV')=='prod' ? 'formal' : 'developer',
  320. 'data' => $data
  321. ];
  322. $res = $app->subscribe_message->send($msgData);
  323. if (!isset($res['errcode']) || $res['errcode'] != '0') {
  324. $backtrace = debug_backtrace();
  325. array_shift($backtrace);
  326. $this->log->event('subscribe_message_error', ['from' => json_encode($backtrace), 'res' => json_encode($res), 'msg' => json_encode($msgData)]);
  327. }
  328. return $res;
  329. }
  330. public function getSubscribeMessageTempList($forUserType)
  331. {
  332. if ($forUserType == '') {
  333. $app = Factory::miniProgram(config('wechat.applet'));
  334. $app['guzzle_handler'] = CoroutineHandler::class;
  335. $result = $app->subscribe_message->getTemplates()['data'];
  336. $res = [];
  337. foreach ($result as $key => &$tmpl) {
  338. $res[] = [
  339. 'template_id' => $tmpl['priTmplId'] ?? '',
  340. 'title' => $tmpl['title'] ?? '',
  341. ];
  342. }
  343. return $res;
  344. } else {
  345. $builder = SubscribeMessageTemplate::query()->select('pri_tmpl_id as template_id', 'title');
  346. if ($forUserType != 'all') {
  347. $builder = $builder->where(['for_user_type' => $forUserType]);
  348. }
  349. return $builder->get()->toArray();
  350. }
  351. }
  352. }