123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623 |
- <?php
- namespace App\Service;
- use App\Log;
- use App\Models\ChatGroup;
- use App\Models\DjUser;
- use App\Models\Es\ChatGroupMember;
- use App\Models\QrcodeChatGroup;
- use App\Models\QrcodeChatGroupDailyReport;
- use App\Models\QrcodeChatGroupDetail;
- use App\Models\SourceQrcodeGroups;
- use App\Models\System\Users;
- use App\RedisModel;
- use App\Support\EmailQueue;
- use App\Support\qyApi\QyCommon;
- use Illuminate\Support\Facades\DB;
- class GroupChatJoinWayService
- {
- /**
- * 创建群活码规则
- * */
- public static function setRule($params)
- {
- try {
- DB::beginTransaction();
- $params['state'] = uniqid('cgq-') . mt_rand(1000, 9999);
- $chatIds = [];
- foreach ($params['chat_id_list'] as $value) {
- $chatId = $value['chat_id'] ?? null;
- if(!$chatId) continue;
- $enable = $value['enable'] ?? 1;
- $status = $value['status'] ?? 1;
- if($enable && $status) {
- array_push($chatIds, $chatId);
- }
- }
- if(empty($chatIds)) {
- DB::rollBack();
- return 4809;
- }
- # 进群方式
- if($params['join_type'] == 1) {
- $chatIds = array_splice($chatIds, 0, 1);
- }
- $configId = GroupChatJoinWayService::createChatGroupJoinWay($params['corpid'], 2, $chatIds, $params['state']);
- if(is_numeric($configId)) return $configId;
- $params['config_id'] = $configId;
- $result = GroupChatJoinWayService::getChatGroupJoinWay($params['corpid'], $params['config_id']);
- if(is_numeric($result)) return $result;
- $params['qrcode'] = $result['qrcode'];
- // $chatIdsOfQrcode = $result['chat_id_list'];
- # 数据入库
- $ruleId = null;
- $errCode = QrcodeChatGroup::editRule($params, $ruleId);
- if($errCode) {
- DB::rollBack();
- return $errCode;
- }
- # 处理不可用群信息
- foreach ($params['chat_id_list'] as $index=>$chatInfo) {
- $chatId = $chatInfo['chat_id'] ?? null;
- if(!$chatId) unset($params['chat_id_list'][$index]);
- $status = $chatInfo['status'] ?? 1;
- $isUsed = 1;
- if($params['join_type'] == 1 && $index >0) { // 顺序进群仅排序最靠前的群会被配置到活码中
- $isUsed = 0;
- }
- # 提交的chatId是否被创建
- // if(!in_array($chatId, $chatIdsOfQrcode) && $status == 1) {
- // $chatInfo['enable'] = 0;
- // }
- # 数据入库
- QrcodeChatGroupDetail::updateOrCreate([
- 'chat_id' => $chatId,
- 'rule_id' => $ruleId,
- 'corpid' => $params['corpid'],
- ], [
- 'user_limit' => $chatInfo['user_limit'],
- 'status' => $status,
- 'enable' => $chatInfo['enable'] ?? 1,
- 'is_used' => $isUsed,
- 'sort' => $index
- ]);
- }
- DB::commit();
- } catch (\Exception $e) {
- EmailQueue::rPush('创建群活码流程发生异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '创建群活码流程发生异常');
- Log::logError('创建群活码流程发生异常', [
- 'line' => $e->getLine(),
- 'msg' => $e->getMessage(),
- 'param' => $params
- ], 'GroupChatJoinWayCreate');
- DB::rollBack();
- return 4804;
- }
- return 0;
- }
- /**
- * 编辑群活码
- * */
- public static function editRule($params, $ruleId, $configId)
- {
- try{
- # 校验configId是否合法
- $ruleInfo = QrcodeChatGroup::checkConfigId($params['corpid'], $ruleId, $configId);
- if(empty($ruleInfo)) return 4807;
- $params['config_id'] = $configId;
- $state = $ruleInfo->state;
- $params['state'] = $state;
- $params['qrcode'] = $ruleInfo->qrcode;
- # 校验已配置的群信息与本次提交的群信息是否一致
- $chatIdList = QrcodeChatGroupDetail::select(['chat_id'])->where('rule_id', $ruleId)
- ->where('enable', 1)->where('status', 1)->orderBy('sort')->pluck('chat_id')->toArray();
- DB::beginTransaction();
- $errCode = QrcodeChatGroup::editRule($params, $ruleId);
- if($errCode) {
- DB::rollBack();
- return $errCode;
- }
- $updateQrcode = false;
- $chatIds = [];
- foreach ($params['chat_id_list'] as $index=>$chatInfo) {
- $chatId = $chatInfo['chat_id'] ?? null;
- $enable = $chatInfo['enable'] ?? 1;
- $status = $chatInfo['status'] ?? 1;
- $isUsed = 1;
- if(!$chatId) {
- unset($params['chat_id_list'][$index]);
- continue;
- }
- # 与群活码中设置的群不一致
- if($params['join_type'] == 1) {
- if($index) {
- $isUsed = 0;
- } else {
- # 获取当前配置的chat_id与本次的chat_id是否一致
- $result = GroupChatJoinWayService::getChatGroupJoinWay($params['corpid'], $params['config_id']);
- $chatIdsOfQrcode = $result['chat_id_list'];
- if(!in_array($chatId, $chatIdsOfQrcode)) {
- $updateQrcode = true;
- }
- }
- } else {
- if((
- !in_array($chatId, $chatIdList) && $enable==1 && $status==1) ||
- (in_array($chatId, $chatIdList) && ($enable==0 || $status==0))) {
- $updateQrcode = true;
- }
- }
- if($enable && $status) {
- array_push($chatIds, $chatId);
- }
- # 数据入库
- QrcodeChatGroupDetail::updateOrCreate([
- 'corpid' => $params['corpid'],
- 'chat_id' => $chatId,
- 'rule_id' => $ruleId
- ], [
- 'user_limit' => $chatInfo['user_limit'],
- 'enable' => $enable,
- 'status' => $status,
- 'is_used' => $isUsed,
- 'sort' => $index
- ]);
- }
-
- if(empty($chatIds)) {
- DB::rollBack();
- return 4809;
- }
- # 若群活码发生变更则执行群活码更新
- if($updateQrcode) {
- if($params['join_type'] == 1) {
- $chatIds = array_splice($chatIds, 0, 1);
- }
- $qrcodeInfo = ['corpid' => $params['corpid'], 'config_id' => $configId, 'chat_id' =>$chatIds, 'state' => $state];
- RedisModel::lPush(QrcodeChatGroup::UPDATE_QRCODE_CHAT_ID_RDS, json_encode($qrcodeInfo, 256));
- }
- DB::commit();
- } catch (\Exception $e) {
- EmailQueue::rPush('编辑群活码流程发生异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '编辑群活码流程发生异常');
- Log::logError('编辑群活码流程发生异常', [
- 'line' => $e->getLine(),
- 'msg' => $e->getMessage(),
- 'param' => $params,
- 'rule_id' => $ruleId
- ], 'GroupChatJoinWayUpdate');
- DB::rollBack();
- return 4808;
- }
- return 0;
- }
- /**
- * 群活码列表
- * */
- public static function ruleList($corpid, $groupId, $name, $page, $pageSize)
- {
- list($list, $count) = QrcodeChatGroup::getGroupQrcodeList($corpid, $groupId, $name, $page, $pageSize);
- # 获取创建人信息
- $adminIds = $list->pluck('admin_id');
- $adminData = Users::select(['id','name'])->whereIn('id', $adminIds)->get();
- # 获取分组信息
- $groupIds = $list->pluck('group_id');
- $groupData = SourceQrcodeGroups::select(['id', 'name'])->whereIn('id', $groupIds)->where('type', 2)->get();
- # 获取扫码数据
- $ruleIds = $list->pluck('id');
- $scanData = QrcodeChatGroupDailyReport::select(['rule_id', 'scan_num'])->whereIn('rule_id', $ruleIds)
- ->groupBy(['rule_id'])->get();
- foreach ($list as $datum) {
- # 创建人信息
- $adminInfo = $adminData->where('id', $datum->admin_id)->first();
- $datum->creator = $adminInfo->name ?? '';
- # 分组信息
- $groupInfo = $groupData->where('id', $datum->group_id)->first();
- $datum->group_name = $groupInfo->name ?? '';
- # 扫码人数
- $scanInfo = $scanData->where('rule_id', $datum->id)->first();
- $datum->scan = $scanInfo->scan_num ?? 0;
- }
- return [$list, $count];
- }
- /**
- * 群活码详情
- * */
- public static function ruleDetail($corpid, $ruleId, &$errno)
- {
- try {
- $detail = QrcodeChatGroup::getGroupQrcodeDetail($corpid, $ruleId);
- if(empty($detail)) {
- $errno = 4811;
- return [];
- }
- # 获取群活码对应的群组信息配置
- $chatGroupConfig = QrcodeChatGroupDetail::select(['chat_id', 'sort', 'user_limit', 'enable', 'status'])
- ->where('corpid', $corpid)->where('rule_id', $ruleId)->where('enable', 1)->orderBy('sort')
- ->get();
- $detail->chat_id_list = $chatGroupConfig;
- } catch (\Exception $e) {
- Log::logError('群活码详情获取过程发生异常', [
- 'line' => $e->getLine(),
- 'msg' => $e->getMessage(),
- 'rule_id' => $ruleId,
- 'corpid' => $corpid
- ], 'QrcodeChatGroupRuleDetail');
- $errno = 4810;
- return [];
- }
- return $detail;
- }
- public static function qrcodeDetail($corpid, $ruleId, &$errno)
- {
- try {
- $detail = QrcodeChatGroup::getGroupQrcodeDetail($corpid, $ruleId);
- if(empty($detail)) {
- $errno = 4811;
- return '';
- }
- } catch (\Exception $e) {
- Log::logError('群活码详情获取过程发生异常', [
- 'line' => $e->getLine(),
- 'msg' => $e->getMessage(),
- 'rule_id' => $ruleId,
- 'corpid' => $corpid
- ], 'QrcodeChatGroupRuleDetail');
- $errno = 4810;
- return '';
- }
- return $detail->qrcode;
- }
- /**
- * 禁用群活码
- * */
- public static function delQrcode($corpid, $ruleId)
- {
- try {
- DB::beginTransaction();
- # 校验群活码是否存在
- $qrcodeInfo = QrcodeChatGroup::where('enable', 1)->where('status', 1)->where('id', $ruleId)
- ->where('corpid', $corpid)
- ->first();
- if(empty($qrcodeInfo)) {
- DB::rollBack();
- return 4811;
- }
- $qrcodeInfo->del_time = date('Y-m-d H:i:s');
- $qrcodeInfo->status = 0;
- $result = $qrcodeInfo->save();
- if(!$result) {
- DB::rollBack();
- return 4813;
- }
- # 调用企微api执行删除群活码
- $configId = $qrcodeInfo->config_id;
- $responseData = QyCommon::delGroupJoinWay($corpid, $configId);
- if(!isset($responseData['errcode']) || $responseData['errcode']) {
- EmailQueue::rPush('删除客户群进群方式配置', json_encode($responseData['errmsg'], 256), ['xiaohua.hou@kuxuan-inc.com'], '删除客户群进群方式配置');
- return 4813;
- }
- # 修改群活码配置状态
- QrcodeChatGroupDetail::where('rule_id', $ruleId)->update(['enable' => 0]);
- DB::commit();
- } catch (\Exception $e) {
- DB::rollBack();
- Log::logError('删除群活码过程发生异常', [
- 'line' => $e->getLine(),
- 'msg' => $e->getMessage(),
- 'corpid' => $corpid,
- 'rule_id' => $ruleId
- ], 'ChatGroupQrcodeDel');
- return 4812;
- }
- return 0;
- }
- /**
- * 获取群活码总概数据
- * */
- public static function getCondition($corpid, $ruleId)
- {
- # 统计群活码累计数据
- $data = QrcodeChatGroupDailyReport::selectRaw("scan_num as scan_total, sum(join_num) as join_total, " .
- "sum(loss_num) as loss_total, sum(keep_num) as keep_total")
- ->where('corpid', $corpid)->where('rule_id', $ruleId)
- ->first();
- # 统计群活码当日数据
- $today = QrcodeChatGroupDailyReport::selectRaw("scan_num as scan_today, sum(join_num) as join_today, " .
- "sum(loss_num) as loss_today")->where('ref_date', date('Y-m-d'))->where('corpid', $corpid)->where('rule_id', $ruleId)
- ->first();
- # 累计进群人数
- $joinTotal = $data->join_total ?? 0;
- # 累计退群人数
- $lossTotal = $data->loss_total ?? 0;
- # 累计留存人数
- $keepTotal = $data->keep_total ?? 0;
- return [
- 'scan_total' => $data->scan_total ?? 0,
- 'scan_today' => $today->scan_today ?? 0,
- 'join_total' => $joinTotal,
- 'join_today' => $today->join_today ?? 0,
- 'loss_total' => $lossTotal,
- 'loss_today' => $today->loss_today ?? 0,
- 'loss_rate' => $joinTotal ? round($lossTotal / $joinTotal, 4) * 100 . '%' : '0%',
- 'keep_rate' => $joinTotal ? round($keepTotal / $joinTotal, 4) * 100 . '%' : '0%',
- ];
- }
- /**
- * 群活码每日数据分析
- * */
- public static function getDailyReport($corpid, $ruleId, $startDate, $endDate)
- {
- $list = self::getTrendFormatData($startDate, $endDate);
- $data = QrcodeChatGroupDailyReport::selectRaw("ref_date, corpid, rule_id, scan_num as scan_total, sum(keep_num) as keep_total")
- ->where('corpid', $corpid)->where('rule_id', $ruleId)
- ->where('ref_date', '>=', $startDate)
- ->where('ref_date', '<=', $endDate)
- ->groupBy(['corpid','ref_date', 'rule_id'])
- ->get();
- if(!empty($data)) {
- foreach ($data as $datum) {
- $list[$datum->ref_date]['scan_total'] = intval($datum->scan_total);
- $list[$datum->ref_date]['keep_total'] = intval($datum->keep_total);
- }
- }
- return array_values($list);
- }
- /**
- * 群活码扫码进群客户列表
- * */
- public static function getMemberList($corpid, $ruleId, $keyword, $page, $pageSize)
- {
- # 获取客户群ID集合及state
- $state = QrcodeChatGroup::where('id', $ruleId)->where('corpid', $corpid)->where('enable', 1)->value('state');
- if(empty($state)) return [[], 0];
- $chatIds = QrcodeChatGroupDetail::where('rule_id', $ruleId)->pluck('chat_id')->toArray();
- list($list, $count) = ChatGroupMember::getMemberListOfQrcode($corpid, $chatIds, $state, $keyword, $page, $pageSize);
- return [$list, $count];
- }
- /**
- * 群活码配置群的数据分析
- * */
- public static function chatGroupAnalysis($corpid, $ruleId)
- {
- $data = QrcodeChatGroupDailyReport::selectRaw("sum(join_num) as join_total, sum(loss_num) as loss_total, sum(keep_num) as keep_total, chat_id")
- ->where('corpid', $corpid)->where('rule_id', $ruleId)->groupBy(['chat_id'])
- ->get();
- # 获取群名称
- $chatIds = $data->pluck('chat_id');
- $chatGroupList = ChatGroup::select(['chat_id', 'name'])->where('corpid', $corpid)->whereIn('chat_id', $chatIds)->get();
- foreach ($data as $datum) {
- # 群名称
- $chatGroupInfo = $chatGroupList->where('chat_id', $datum->chat_id)->first();
- $datum->chat_group_name = $chatGroupInfo->name ?? '';
- # 留存率
- $joinTotal = $datum->join_total ?? 0;
- $keepTotal = $datum->keep_total ?? 0;
- $datum->keep_rate = $joinTotal ? round($keepTotal / $joinTotal, 4) * 100 . '%' : '0%';
- }
- return $data;
- }
- /**
- * 扫码数据上报
- * */
- public static function scanNumIncr($corpid, $ruleId)
- {
- try {
- $result = QrcodeChatGroupDailyReport::where('corpid', $corpid)->where('rule_id', $ruleId)->increment('scan_num');
- if(!$result) {
- Log::logError('扫码数据上报失败', [
- 'corpid' => $corpid,
- 'rule_id' => $ruleId
- ], 'scanNumIncr');
- return 4814;
- }
- } catch (\Exception $e) {
- Log::logError('扫码数据上报发生异常', [
- 'corpid' => $corpid,
- 'rule_id' => $ruleId,
- 'line' => $e->getLine(),
- 'msg' => $e->getMessage()
- ], 'scanNumIncr');
- }
- return 0;
- }
- /**
- * 创建临时渠道码
- * */
- public static function createTempContactQrcode($corpid, $ruleId, &$errno)
- {
- # 获取群活码配置的客服信息
- $configInfo = QrcodeChatGroup::select(['user_list', 'leading_words', 'state'])
- ->where('id', $ruleId)->where('corpid', $corpid)
- ->where('enable', 1)->first();
- $userListStr = $configInfo->user_list ?? '';
- if(empty($userListStr)) {
- $errno = 4815;
- return [];
- }
- # 随机取出一个客服
- $userList = explode(',', $userListStr);
- $userId = $userList[rand(0, count($userList) -1)];
- # 查询客服对应的二维码
- $userInfo = DjUser::where('corpid', $corpid)->where('user_id', $userId)->first();
- $qrcode = $userInfo->qr_code ?? '';
- if(empty($qrcode)) {
- # 生成临时渠道码
- $params = [
- "type" => 2, //联系方式类型,1-单人, 2-多人
- "scene" => 2, //场景,1-在小程序中联系,2-通过二维码联系
- "remark" => "临时渠道码活码", //联系方式的备注信息
- "skip_verify" => true, //外部客户添加时是否无需验证,默认为true
- "state" => $configInfo->state, //企业自定义的state参数,用于区分不同的添加渠道,不超过30字符
- "user" => [$userId], //客服列表
- ];
- $responseData = QyCommon::momentCommon('add_contact_way', $corpid, $params);
- if(!$responseData) {
- $errno = 4815;
- return [];
- }
- # 更新渠道活码信息到客服信息
- $qrcode = $responseData['qr_code'];
- $userInfo->qr_code = $qrcode;
- $userInfo->save();
- }
- $errno = 0;
- return [
- 'qrcode' => $qrcode,
- 'leading_words' => $configInfo->leading_words
- ];
- }
- /**
- * 获取群组下的群活码规则数
- * */
- public static function chatGroupCountOfGroup($corpid, $groupId)
- {
- return QrcodeChatGroup::where('enable', 1)->where('corpid', $corpid)
- ->where('group_id', $groupId)->count();
- }
- /**
- * 数据结构组装
- * */
- protected static function getTrendFormatData($stDate, $enDate)
- {
- $dayArr = [];
- $stDateStr = strtotime($stDate);
- $enDateStr = strtotime($enDate);
- while ($stDateStr <= $enDateStr) {
- $date = date('Y-m-d', $stDateStr);
- $dayArr[$date] = [
- 'ref_date' => $date,
- 'scan_total' => 0,
- 'keep_total' => 0
- ];
- $stDateStr += 86400;
- }
- return $dayArr;
- }
- /**
- * 创建群活码信息
- * */
- public static function createChatGroupJoinWay(
- $corpid, $scene, $chatIds, $state, $autoCreateRoom=1, $roomBaseName='', $roomBaseId=1, $remark=null
- )
- {
- $responseData = QyCommon::addGroupJoinWay($corpid, $scene, $chatIds, $state, $autoCreateRoom, $roomBaseName, $roomBaseId, $remark);
- if(!isset($responseData['errcode']) || $responseData['errcode']) {
- Log::logError('创建群活码失败', [
- 'corpid' => $corpid, 'scene' => $scene, 'chatIds' => $chatIds, 'state' => $state,
- 'autoCreateRoom' => $autoCreateRoom, 'roomBaseName' => $roomBaseName, 'roomBaseId' => $roomBaseId,
- 'remark' => $remark, 'response' => $responseData
- ], 'CreateChatGroupJoinWay');
- if($responseData['errcode'] != 701170) {
- EmailQueue::rPush('创建群活码失败', json_encode($responseData['errmsg'], 256), ['xiaohua.hou@kuxuan-inc.com'], '创建群活码失败');
- }
- return 4801;
- }
- return $responseData['config_id'];
- }
- /**
- * 获取群活码信息
- * */
- public static function getChatGroupJoinWay($corpid, $configId)
- {
- $responseData = QyCommon::getGroupJoinWay($corpid, $configId);
- if(!isset($responseData['errcode']) || $responseData['errcode']) {
- EmailQueue::rPush('获取群活码信息失败', json_encode($responseData['errmsg'], 256), ['xiaohua.hou@kuxuan-inc.com'], '获取群活码信息失败');
- return 4802;
- }
- $chatIdList = $responseData['join_way']['chat_id_list'] ?? null;
- $qrcode = $responseData['join_way']['qr_code'] ?? null;
- if(!$chatIdList || !$qrcode) return 4803;
- return ['chat_id_list' => $chatIdList, 'qrcode' => $qrcode];
- }
- }
|