企微短剧业务系统

MassMsgService.php 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. <?php
  2. namespace App\Service;
  3. use App\Log;
  4. use App\Models\AndroidToolRequestLog;
  5. use App\Models\AuthorizeCorp;
  6. use App\Models\ChatGroupMassMsgRecord;
  7. use App\Models\DjUser;
  8. use App\Models\MassMsgRecord;
  9. use App\Models\MassMsgSendNotice;
  10. use App\Models\MomentRecord;
  11. use App\Models\PeriodMassMsg\PeriodMassMsg;
  12. use App\Models\PeriodMassMsg\PeriodMassMsgRecord;
  13. use App\Models\System\AdminManageCorp;
  14. class MassMsgService
  15. {
  16. /**
  17. * 获取群发成员发送任务列表
  18. * */
  19. public static function getMassMsgTaskStatus($corpid, $msgId, $limit, $cursor)
  20. {
  21. # 获取accessToken
  22. $accessToken = AuthorizeCorp::getAccessToken($corpid, '获取群发成员发送任务状态');
  23. if(empty($accessToken)) {
  24. return false;
  25. }
  26. $postData = [
  27. 'msgid' => $msgId,
  28. 'limit' => $limit,
  29. 'cursor' => $cursor
  30. ];
  31. $requestUri = config('qyWechat.mass_msg_task_status');
  32. $requestUri .= $accessToken;
  33. $response = HttpService::httpPost($requestUri, json_encode($postData));
  34. $responseData = json_decode($response, true);
  35. return $responseData;
  36. }
  37. /**
  38. * 处理群发信息 / 欢迎语中的推广链接类型附件
  39. * @param string $corpid 企业id
  40. * @param string $jumpLink 目标链接
  41. * */
  42. public static function getPromoteLink($corpid, $jumpLink)
  43. {
  44. $htmlLink = env('DOMAIN', 'http://dj.wenxingshuju.com/') . 'playlet/qwh5/dist/index.html#/extend';
  45. $param = [
  46. 'corpid' => $corpid,
  47. 'jumpLink' => urlencode($jumpLink)
  48. ];
  49. return $htmlLink . '?' . http_build_query($param);
  50. }
  51. public static function drawPid($attachments, &$pid, $logName)
  52. {
  53. Log::logInfo('提取开始', $attachments, $logName);
  54. $drawPids = [];
  55. foreach ($attachments as $datum) {
  56. if (isset($datum['msgtype'])) {
  57. $url = null;
  58. // 小程序
  59. if (
  60. ($datum['msgtype'] == 'miniprogram')
  61. &&
  62. isset($datum['miniprogram']['page'])
  63. &&
  64. !empty($datum['miniprogram']['page'])
  65. ) {
  66. $url = $datum['miniprogram']['page'];
  67. }
  68. // 链接
  69. if (
  70. ($datum['msgtype'] == 'link')
  71. &&
  72. isset($datum['link']['url'])
  73. &&
  74. !empty($datum['link']['url'])
  75. ) {
  76. $url = $datum['link']['url'];
  77. }
  78. // H5推广
  79. if (
  80. ($datum['msgtype'] == 'promote')
  81. &&
  82. isset($datum['promote']['jump_url'])
  83. &&
  84. !empty($datum['promote']['jump_url'])
  85. ) {
  86. $url = $datum['promote']['jump_url'];
  87. }
  88. // 欢迎语中的H5推广会被转换成普通链接方式
  89. if (
  90. ($datum['msgtype'] == 'link')
  91. &&
  92. isset($datum['link']['jump_url'])
  93. &&
  94. !empty($datum['link']['jump_url'])
  95. ) {
  96. $url = $datum['link']['jump_url'];
  97. }
  98. // 属于其他类型
  99. if (is_null($url)) continue;
  100. Log::logInfo('提取URL', [
  101. 'url' => $url
  102. ], $logName);
  103. // 处理url
  104. $filedExistNum = 0;
  105. self::dealUrl($url, $filedExistNum, $drawPids, $logName);
  106. if ($filedExistNum > 1) {
  107. Log::logError('提取推广链接PID存在多个字段', $datum, $logName);
  108. return false;
  109. }
  110. }
  111. // if (count($drawPids) > 1) {
  112. // Log::logError('提取推广链接PID存在多个值', $datum, $logName);
  113. // return false;
  114. // }
  115. if (count($drawPids) > 1) {
  116. Log::logError('提取推广链接PID存在多个值', $datum, $logName);
  117. $pid = $drawPids;
  118. } else {
  119. if (!empty($drawPids)) $pid = $drawPids;
  120. }
  121. // if (!empty($drawPids)) $pid = current($drawPids);
  122. Log::logInfo('提取结束', $attachments, $logName);
  123. }
  124. return true;
  125. }
  126. public static function dealUrl($url, &$filedExistNum, &$drawPids, $logName)
  127. {
  128. $url = str_replace("%25", "%", $url);
  129. $url = str_replace("&amp;", "&", $url);
  130. $url = urldecode($url);
  131. $urlArr = parse_url($url);
  132. if (!isset($urlArr['query']) && empty($urlArr['query'])) return false;
  133. Log::logInfo('提取url', [
  134. 'url' => $url,
  135. 'filedExistNum' => $filedExistNum,
  136. 'drawPids' => $drawPids
  137. ], $logName);
  138. parse_str($urlArr['query'], $query);
  139. // 柚子 pathId
  140. if (isset($query['pathId']) && !empty($query['pathId'])) {
  141. $filedExistNum ++;
  142. $drawPids[] = $query['pathId'];
  143. }
  144. // 嘉书 article
  145. if (isset($query['article']) && !empty($query['article'])) {
  146. $filedExistNum ++;
  147. $drawPids[] = $query['article'];
  148. }
  149. // 迈步 pid
  150. if (isset($query['pid']) && !empty($query['pid'])) {
  151. $filedExistNum ++;
  152. $drawPids[] = $query['pid'];
  153. }
  154. // 点众阳光 referral_id
  155. // if (isset($query['referral_id']) && !empty($query['referral_id'])) {
  156. // $filedExistNum ++;
  157. // $drawPids[] = $query['referral_id'];
  158. // }
  159. foreach ($query as $urlVal) {
  160. self::dealUrl($urlVal, $filedExistNum, $drawPids, $logName);
  161. }
  162. Log::logInfo('提取url结果', [
  163. 'url' => $url,
  164. 'filedExistNum' => $filedExistNum,
  165. 'drawPids' => $drawPids
  166. ], $logName);
  167. }
  168. public static function drawChannel($attachments, &$channel, $logName)
  169. {
  170. Log::logInfo('提取开始', $attachments, $logName);
  171. $drawChannels = [];
  172. foreach ($attachments as $datum) {
  173. if (isset($datum['msgtype'])) {
  174. $url = null;
  175. // 小程序
  176. if (
  177. ($datum['msgtype'] == 'miniprogram')
  178. &&
  179. isset($datum['miniprogram']['page'])
  180. &&
  181. !empty($datum['miniprogram']['page'])
  182. ) {
  183. $url = $datum['miniprogram']['page'];
  184. }
  185. // 链接
  186. if (
  187. ($datum['msgtype'] == 'link')
  188. &&
  189. isset($datum['link']['url'])
  190. &&
  191. !empty($datum['link']['url'])
  192. ) {
  193. $url = $datum['link']['url'];
  194. }
  195. // H5推广
  196. if (
  197. ($datum['msgtype'] == 'promote')
  198. &&
  199. isset($datum['promote']['jump_url'])
  200. &&
  201. !empty($datum['promote']['jump_url'])
  202. ) {
  203. $url = $datum['promote']['jump_url'];
  204. }
  205. // 欢迎语中的H5推广会被转换成普通链接方式
  206. if (
  207. ($datum['msgtype'] == 'link')
  208. &&
  209. isset($datum['link']['jump_url'])
  210. &&
  211. !empty($datum['link']['jump_url'])
  212. ) {
  213. $url = $datum['link']['jump_url'];
  214. }
  215. // 属于其他类型
  216. if (is_null($url)) continue;
  217. Log::logInfo('提取URL', [
  218. 'url' => $url
  219. ], $logName);
  220. // 处理url
  221. $filedExistNum = 0;
  222. self::dealUrlNew($url, $filedExistNum, $drawChannels, $logName);
  223. if ($filedExistNum > 1) {
  224. Log::logError('提取渠道channel存在多个字段', $datum, $logName);
  225. return false;
  226. }
  227. }
  228. if (count($drawChannels) > 1) {
  229. Log::logError('提取渠道channel存在多个值', $datum, $logName);
  230. return false;
  231. }
  232. if (!empty($drawChannels)) $channel = current($drawChannels);
  233. Log::logInfo('提取结束', $attachments, $logName);
  234. }
  235. return true;
  236. }
  237. /**
  238. * 获取待确认发送的消息列表
  239. * */
  240. public static function senderConfirmList($deviceId)
  241. {
  242. # 查询支持无障碍模式的企微列表
  243. $corpIds = AdminManageCorp::select('corpid')->where('is_delete', 0)->whereIn('sys_user_id', [2, 3, 38, 51])->distinct()->pluck('corpid');
  244. $corpidList = AuthorizeCorp::whereIn('id', $corpIds)->where('enable', 1)->pluck('corpid');
  245. # 查询待发送群发消息记录
  246. $msgList = MassMsgRecord::select('corpid')->where('status', 1)
  247. ->whereIn('corpid', $corpidList)
  248. ->where('send_time', '>=', date('Y-m-d H:i:s', strtotime('-60 minutes')))
  249. ->groupBy(['corpid'])
  250. ->get();
  251. # 查询待发送的智能推送消息记录
  252. $periodMsgList = PeriodMassMsgRecord::select('corpid')->where('status', 1)
  253. ->whereIn('corpid', $corpidList)
  254. ->where('create_time', '>=', date('Y-m-d H:i:s', strtotime('-60 minutes')))
  255. ->groupBy(['corpid'])
  256. ->get();
  257. # 查询待确认发送的客户群消息
  258. $chatGroupMsgList = ChatGroupMassMsgRecord::select('corpid')->where('status', 1)
  259. ->whereIn('corpid', $corpidList)
  260. ->where('create_time', '>=', date('Y-m-d H:i:s', strtotime('-60 minutes')))
  261. ->groupBy(['corpid'])
  262. ->get();
  263. $corpList = AuthorizeCorp::select('corpid', 'corp_name')->whereIn('corpid', $corpidList)->where('enable', 1)->get();
  264. $msgList = array_unique(array_merge(
  265. $msgList->pluck('corpid')->toArray(), $periodMsgList->pluck('corpid')->toArray(),
  266. $chatGroupMsgList->pluck('corpid')->toArray()
  267. ));
  268. $data = [];
  269. foreach ($msgList as $item) {
  270. # 获取企微名称
  271. $corpInfo = $corpList->where('corpid', $item)->first();
  272. $companyName = $corpInfo->corp_name;
  273. $data[] = [
  274. 'companyName' => $companyName,
  275. 'corpid' => $item
  276. ];
  277. # 获取客服名
  278. // $userInfo = $userList->where('user_id', $item->sender)->where('corpid', $item->corpid)->first();
  279. // $item->userName = $userInfo->name;
  280. }
  281. Log::logInfo('设备请求日志', [
  282. 'type' => 1,
  283. 'device_id' => $deviceId,
  284. 'msg_list' => $data
  285. ], 'SenderConfirmList');
  286. return $data;
  287. }
  288. public static function dealUrlNew($url, &$filedExistNum, &$drawChannels, $logName)
  289. {
  290. $url = str_replace("%25", "%", $url);
  291. $url = str_replace("&amp;", "&", $url);
  292. $url = urldecode($url);
  293. $urlArr = parse_url($url);
  294. if (!isset($urlArr['query']) && empty($urlArr['query'])) return false;
  295. Log::logInfo('提取url', [
  296. 'url' => $url,
  297. 'filedExistNum' => $filedExistNum,
  298. 'drawChannels' => $drawChannels
  299. ], $logName);
  300. parse_str($urlArr['query'], $query);
  301. if (isset($query['channel']) && !empty($query['channel'])) {
  302. $filedExistNum ++;
  303. $drawChannels[] = $query['channel'];
  304. }
  305. if (isset($query['wxAppId']) && !empty($query['wxAppId'])) {
  306. $filedExistNum ++;
  307. $drawChannels[] = $query['wxAppId'];
  308. }
  309. foreach ($query as $urlVal) {
  310. self::dealUrl($urlVal, $filedExistNum, $drawChannels, $logName);
  311. }
  312. Log::logInfo('提取url结果', [
  313. 'url' => $url,
  314. 'filedExistNum' => $filedExistNum,
  315. 'drawChannels' => $drawChannels
  316. ], $logName);
  317. }
  318. public static function sendNoticeList($params, $page, $pageSize)
  319. {
  320. $corpStat = AuthorizeCorp::getAllCorpList();
  321. $sys_corp_id_list = AdminManageCorp::getSysGroupCorpList($params['sys_group_id']);
  322. if(empty($sys_corp_id_list)) {
  323. return [[], 0];
  324. }
  325. $corp_list = $corpStat->whereIn('id', $sys_corp_id_list)->all();
  326. $params['corp_id_list'] = array_column($corp_list, 'corpid');
  327. # 如果筛选了客服
  328. $params['user_sql'] = [];
  329. if(!empty($userName)) {
  330. $userRes = DjUser::getUserBySearch([
  331. 'corpid' => $params['corp_id'],
  332. 'user_name' => $params['user_name'],
  333. 'corp_list' => $params['corp_id_list'] ?? null,
  334. ]);
  335. if($userRes->isEmpty()) {
  336. return [[], 0];
  337. }
  338. foreach($userRes as $userInfo) {
  339. $params['user_sql'][] = '("' . $userInfo->corpid . '","' . $userInfo->user_id . '")';
  340. }
  341. }
  342. list($data, $count) = MassMsgSendNotice::getNoticeList($params, $page, $pageSize);
  343. # 查询公司账号下得所有客服信息
  344. $userDataList = DjUser::getUserBySearch(['corp_list' => $params['corp_id_list']]);
  345. # 查询智能群发组id
  346. $ruleIdList = array_column($data->toArray(), 'rule_id');
  347. $periodMassMsgList = PeriodMassMsg::getInfoById($ruleIdList);
  348. # 遍历数据,将企微名称以及客服名称写入
  349. foreach($data as $item) {
  350. # 企微名称
  351. $corpInfo = $corpStat->where('corpid', $item->corpid)->first();
  352. $item->corp_name = $corpInfo->corp_name ?? '';
  353. # 客服名称
  354. $userInfo = $userDataList->where('corpid', $item->corpid)->where('user_id', $item->user_id)->first();
  355. $item->user_name = $userInfo->name ?? '';
  356. # 提醒信息
  357. $item->notice = '【'.$item->corp_name.'】'.'客服【'.$item->user_name.'】'.'群发消息超2小时未点击发送';
  358. # 发送状态
  359. $item->send_status_text = $item->send_status == 1 ? '待发送' : '已发送';
  360. # 消息类型
  361. $item->msg_type_text = $item->msg_type == 1 ? '群发消息' : ($item->msg_type == 2 ? '客户群群发消息' : '智能群发消息');
  362. # 智能群发组id
  363. $item->group_id = null;
  364. if(3 == $item->msg_type) {
  365. $periodMassMsgInfo = $periodMassMsgList->where('id', $item->rule_id)->first();
  366. $item->group_id = $periodMassMsgInfo->group_id ?? null;
  367. }
  368. }
  369. return [$data, $count];
  370. }
  371. public static function sendNoticeListNew($params, $page, $pageSize) {
  372. $corpStat = AuthorizeCorp::getAllCorpList();
  373. $sys_corp_id_list = AdminManageCorp::getSysGroupCorpList($params['sys_group_id']);
  374. if(empty($sys_corp_id_list)) {
  375. return [[], 0];
  376. }
  377. $corp_list = $corpStat->whereIn('id', $sys_corp_id_list)->all();
  378. $params['corp_id_list'] = array_column($corp_list, 'corpid');
  379. # 如果筛选了客服
  380. $params['user_sql'] = [];
  381. // if(!empty($params['user_name'])) {
  382. $userRes = DjUser::getUserBySearch([
  383. 'corpid' => $params['corp_id'],
  384. 'user_name' => $params['user_name'],
  385. 'corp_list' => $params['corp_id_list'] ?? null,
  386. ]);
  387. if($userRes->isEmpty()) {
  388. return [[], 0];
  389. }
  390. foreach($userRes as $userInfo) {
  391. $params['user_sql'][] = '("' . $userInfo->corpid . '","' . $userInfo->user_id . '")';
  392. }
  393. // }
  394. switch($params['msg_type']) {
  395. case 1: // 客户群发
  396. list($data, $count) = MassMsgRecord::getNoticeList($params, $page, $pageSize);
  397. $msgTypeText = '客户群发消息';
  398. break;
  399. case 2: // 客户群群发
  400. list($data, $count) = ChatGroupMassMsgRecord::getNoticeList($params, $page, $pageSize);
  401. $msgTypeText = '客户群群发消息';
  402. break;
  403. case 3: // 智能群发
  404. list($data, $count) = PeriodMassMsgRecord::getNoticeList($params, $page, $pageSize);
  405. $msgTypeText = '智能群发消息';
  406. break;
  407. case 4: // 客户朋友圈
  408. list($data, $count) = MomentRecord::getNoticeList($params, $page, $pageSize);
  409. $msgTypeText = '客户朋友圈消息';
  410. break;
  411. }
  412. # 查询公司账号下得所有客服信息
  413. $userDataList = DjUser::getUserBySearch(['corp_list' => $params['corp_id_list']]);
  414. # 查询智能群发组id
  415. $ruleIdList = array_column($data->toArray(), 'rule_id');
  416. $periodMassMsgList = PeriodMassMsg::getInfoById($ruleIdList);
  417. # 遍历数据,将企微名称以及客服名称写入
  418. foreach($data as $item) {
  419. # 企微名称
  420. $corpInfo = $corpStat->where('corpid', $item->corpid)->first();
  421. $item->corp_name = $corpInfo->corp_name ?? '';
  422. # 客服名称
  423. $userInfo = $userDataList->where('corpid', $item->corpid)->where('user_id', $item->sender)->first();
  424. $item->user_name = $userInfo->name ?? '';
  425. # 提醒信息
  426. if(in_array($params['msg_type'], [1, 3, 4])) {
  427. $item->notice = '【'.$item->corp_name.'】'.'客服【'.$item->user_name.'】'.'超30分钟未点击发送'.$msgTypeText;
  428. } else if($params['msg_type'] == 2) {
  429. $item->notice = '【'.$item->corp_name.'】'.'客服【'.$item->user_name.'】'.'超20分钟未点击发送'.$msgTypeText;
  430. }
  431. $item->msg_type = $params['msg_type'];
  432. $item->msg_type_text = $msgTypeText;
  433. # 智能群发组id
  434. $item->group_id = null;
  435. if(3 == $item->msg_type) {
  436. $periodMassMsgInfo = $periodMassMsgList->where('id', $item->rule_id)->first();
  437. $item->group_id = $periodMassMsgInfo->group_id ?? null;
  438. }
  439. }
  440. return [$data, $count];
  441. }
  442. }