where('enable', 1)->update(['enable' => 0]); if(!empty($bindList)) { foreach ($bindList as $item) { $corpid = $item['corpid'] ?? ''; $userId = $item['user_id'] ?? ''; if(empty($corpid) || empty($userId)) { DB::rollback(); return 2812; } AndroidBindCorp::updateOrCreate(['device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId], [ 'enable' => 1, 'admin_id' => $adminId, 'title' => $title, 'sys_group_id' => $sysGroupId, 'forward_status' => $forwardStatus ]); } } DB::commit(); } catch (\Exception $e) { DB::rollback(); Log::logError('安卓设备绑定企微及客服流程发生异常', [ 'title' => $title, 'device_id' => $deviceId, 'bind_list' => $bindList, 'line' => $e->getLine(), 'msg' => $e->getMessage() ], 'EditCorpBind'); EmailQueue::rPush('安卓设备绑定企微及客服流程发生异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '猎羽'); return 2813; } return 0; } /** * 安卓设备绑定信息详情 * */ public static function bindDetail($deviceId, $sysGroupId) { $bindList = AndroidBindCorp::select('corpid', 'user_id')->where('device_id', $deviceId) ->where('sys_group_id', $sysGroupId)->where('enable', 1)->get(); $confInfo = AndroidBindCorp::where('device_id', $deviceId) ->where('sys_group_id', $sysGroupId)->where('enable', 1)->select(['title', 'forward_status'])->first(); return [ 'title' => $confInfo->title ?? '', 'device_id' => $deviceId, 'forward_status' => $confInfo->forward_status ?? 0, 'bind_list' => $bindList ]; } /** * 获取安卓设备列表 * */ public static function getDeviceList($keyword, $corpid, $userId, $sysGroupId, $page, $pageSize) { list($deviceList, $count) = AndroidBindCorp::getDeviceList($keyword, $corpid, $userId, $sysGroupId, $page, $pageSize); $adminIds = $deviceList->pluck('admin_id'); $adminData = Users::query() ->select(['id','name']) ->whereIn('id', $adminIds) ->get(); foreach ($deviceList as $datum) { # 获取操作人信息 $adminInfo = $adminData->where('id', $datum->admin_id)->first(); $datum->creator = isset($adminInfo->name) ? $adminInfo->name : ''; } return [$deviceList, $count]; } /** * 绑定好友共享的目标客服信息 * */ public static function takeoverUserBind($title, $corpid, $userId, $takeoverUsers, $adminId, $sysGroupId) { try { $configId = CustomerShareRelation::where('user_id', $userId)->where('corpid', $corpid)->value('id'); # 共享目标客服关系绑定 $errno = CustomerShareRelation::takeoverUserBind($title, $corpid, $userId, $takeoverUsers, $configId, $adminId, $sysGroupId); } catch (\Exception $e) { Log::logError('绑定好友共享关系流程发生异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage() ], 'TakeoverUserBind'); $errno = 2332; } return $errno; } /** * 共享的目标客服绑定关系列表 * */ public static function takeoverUserBindList($corpid, $userId, $page, $pageSize, $sysGroupId) { try { list($list, $count) = CustomerShareRelation::takeoverUserBindList($corpid, $userId, $page, $pageSize, $sysGroupId); if(!$count) return [[], 0]; $userList = DjUser::select('user_id', 'name')->where('corpid', $corpid)->where('status', 1)->where('enable', 1)->get(); foreach ($list as $item) { # 获取转移客服信息 $handoverUser = $userList->where('user_id', $item->user_id)->first(); $item->handover_user = $handoverUser->name ?? '-'; # 获取接收客服信息 $takeoverUserIdList = explode(',', $item->takeover_users); $takeOverUserList = ''; foreach ($takeoverUserIdList as $datum) { $takeoverUser = $userList->where('user_id', $datum)->first(); $takeOverUserList .= ($takeoverUser->name ?? '-') . ','; } $item->takeover_users_name = trim($takeOverUserList, ','); } } catch (\Exception $e) { Log::logError('共享的目标客服绑定关系列表获取发生异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage() ], 'TakeoverUserBindList'); return [[], 0]; } return [$list, $count]; } /** * 修改共享配置状态 * */ public static function shareConfigStatusChange($corpid, $userId, $status, $sysGroupId, $adminId) { # 校验规则是否存在 $configInfo = CustomerShareRelation::where('sys_group_id', $sysGroupId)->where('corpid', $corpid) ->where('user_id', $userId) ->first(); if(empty($configInfo)) return 2330; if($configInfo->status == $status) return 2333; $configInfo->status = $status; $configInfo->admin_id = $adminId; $result = $configInfo->save(); return $result ? 0 : 2334; } public static function getUploadDataStatus() { $status = RedisModel::get(self::ANDROID_UPLOAD_DATA_STATUS); if(empty($status)) { return 0; } return $status; } public static function getHistoryData($deviceId) { $data = RedisModel::hGet(self::ANDROID_LAST_UPLOAD_DATA, $deviceId); if(empty($data)) { return ['company' => '', 'date' => '']; } else { return json_decode($data, 1); } } public static function receiveUploadData($deviceId, $companyName, $userName, $endUpload, $oneways, &$errcode) { try { # 校验公司名称,并获取企业id $corpInfoList = AuthorizeCorp::getCorpInfoByName($companyName); if ($corpInfoList->isEmpty() || $corpInfoList->count() > 1) { Log::logError('安卓端上传单向好友异常', [ 'device_id' => $deviceId, 'company_name' => $companyName, 'user_name' => $userName, 'end_upload' => $endUpload, 'one_ways' => $oneways, 'message' => '企业名称查询为空或者查询结果为多个', ], 'AndroidUploadDataError'); $errcode = 6000; return; } $corpInfo = $corpInfoList->first(); $corpid = $corpInfo->corpid ?? null; if (empty($corpid)) { Log::logError('安卓端上传单向好友异常', [ 'device_id' => $deviceId, 'company_name' => $companyName, 'user_name' => $userName, 'end_upload' => $endUpload, 'one_ways' => $oneways, 'corp_info' => $corpInfo, 'message' => '企业id查询为空', ], 'AndroidUploadDataError'); $errcode = 6002; return; } # 校验客服名称,并获取客服user_id $userInfoList = DjUser::getUserBySearch(['user_name' => $userName, 'corpid' => $corpid]); if ($userInfoList->isEmpty() || $userInfoList->count() > 1) { Log::logError('安卓端上传单向好友异常', [ 'device_id' => $deviceId, 'company_name' => $companyName, 'user_name' => $userName, 'end_upload' => $endUpload, 'one_ways' => $oneways, 'message' => '客服名称查询为空或者查询结果为多个', ], 'AndroidUploadDataError'); $errcode = 6001; return; } $userInfo = $userInfoList->first(); $userId = $userInfo->user_id ?? null; if (empty($userId)) { Log::logError('安卓端上传单向好友异常', [ 'device_id' => $deviceId, 'company_name' => $companyName, 'user_name' => $userName, 'end_upload' => $endUpload, 'one_ways' => $oneways, 'corp_id' => $corpid, 'user_info' => $userInfo, 'message' => '根据客服名称查询客服id结果为空', ], 'AndroidUploadDataError'); $errcode = 6002; return; } # 根据添加日期以及客户名称尝试获取客户的外部联系人id $externalUserIdArr = []; $date = null; $oneways = json_decode($oneways, 1); foreach ($oneways as $values) { $externalUserInfoList = CustomerDetails::getCustomerDetailsByName($corpid, $userId, $values); if (is_null($externalUserInfoList) || $externalUserInfoList->isEmpty() || $externalUserInfoList->count() > 1) { Log::logError('安卓端上传单向好友异常', [ 'device_id' => $deviceId, 'company_name' => $companyName, 'user_name' => $userName, 'end_upload' => $endUpload, 'one_ways' => $oneways, 'corp_id' => $corpid, 'user_info' => $userInfo, 'message' => '根据客户名称查询客户id结果为空', ], 'AndroidUploadDataError'); continue; } $date = $values['date']; $externalUserInfo = $externalUserInfoList->first(); $externalUserId = $externalUserInfo->external_userid ?? null; if (!empty($externalUserId)) $externalUserIdArr[] = $externalUserId; } # 批量更新客户状态 $updateData = [ 'enable' => 1, 'loss_status' => 0, 'loss_time' => date('Y-m-d H:i:s') ]; if (!empty($externalUserIdArr)) { CustomerDetails::updateData($corpid, $userId, $externalUserIdArr, $updateData); } # 保存完成后,更新缓存中的信息 RedisModel::hSet(self::ANDROID_LAST_UPLOAD_DATA, $deviceId, json_encode(['company' => $companyName, 'date' => $date], 256)); } catch (\Exception $exception) { Log::logError('安卓端上传单向好友程序异常', [ 'device_id' => $deviceId, 'company_name' => $companyName, 'user_name' => $userName, 'end_upload' => $endUpload, 'one_ways' => $oneways, 'message' => $exception->getFile().'('.$exception->getLine().'):'.$exception->getMessage(), 'trace' => $exception->getTraceAsString() ], 'AndroidUploadDataError'); } } public static function sendLogEmail($uploadFiles, $subject, $userName, $corpName, $deviceId, $msgType, $timeInterval, $description) { $localPathArr = []; # 接收上传文件 if(!empty($uploadFiles) && is_array($uploadFiles)) { foreach ($uploadFiles as $uploadFile) { if (empty($uploadFile) || !$uploadFile->isValid()) { return 2311; } $realPath = $uploadFile->getRealPath(); //临时文件的绝对路径 $filename = $uploadFile->getClientOriginalName(); // 使用我们新建的uploads本地存储空间(目录) $result = Storage::disk('uploads')->put($filename, file_get_contents($realPath)); if(!$result) return 2304; $localPathArr[] = storage_path('uploads').'/'.$filename; } } // $address = 'kaijia.li@kuxuan-inc.com'; $address = 'song.shen@kuxuan-inc.com'; $content = [ '客服名称' => $userName, '主体名称' => $corpName, '设备号' => $deviceId, '问题类型' => $msgType, '时间节点' => $timeInterval, '问题描述' => $description, ]; # 邮件发送以及删除本地文件 if(!empty($localPathArr)) { $res = Mail::send('emails.log', ['content' => $content,], function ($email) use ($address, $subject, $localPathArr){ $email->to($address)->subject($subject); foreach($localPathArr as $localPath) { $email->attach($localPath); } }); foreach ($localPathArr as $localPath) { unlink($localPath); } return $res; } } public static function getForwardMemberList($sysGroupId, $keyword) { $bindList = AndroidBindCorp::select('corpid', 'user_id')->where('forward_status', 1) ->where('sys_group_id', $sysGroupId)->where('enable', 1)->get(); if($bindList->isEmpty()) return []; $userSql = []; $corpData = []; foreach($bindList as $bindUser) { $userSql[] = "('".$bindUser->corpid."','".$bindUser->user_id."')"; $corpData[] = $bindUser->corpid; } $accountUserDataList = DjUser::query()->where('enable', 1)->where(function($query) use ($keyword) { if(!empty($keyword)) $query->where('name', 'like', '%'.$keyword.'%'); })->where('status', 1) ->whereRaw("(`corpid`, `user_id`) in (" . implode(",", $userSql).")")->get(); $corpDataList = AuthorizeCorp::query()->whereIn('corpid', $corpData)->where('enable', 1) ->get(); foreach($bindList as $key => $bindUser) { $userInfo = $accountUserDataList->where('corpid', $bindUser->corpid)->where('user_id', $bindUser->user_id)->first(); $bindUser->user_name = $userInfo->name ?? null; $bindUser->system_user_id = $userInfo->id ?? null; $corpInfo = $corpDataList->where('corpid', $bindUser->corpid)->first(); $bindUser->corp_name = $corpInfo->corp_name ?? ''; if(empty($bindUser->user_name)) unset($bindList[$key]); } return $bindList; } public static function waitCreate($deviceId) { # 查询设备对应的企微及客服信息 $userList = AndroidBindCorp::select('corpid', 'user_id', 'forward_status')->where('device_id', $deviceId) ->where('enable', 1)->get(); if(empty($userList)) { Log::logError('此设备号未绑定任何企微信息', [ 'device_id' => $deviceId ], 'waitCreate'); return []; } # 查询支持无障碍模式的企微列表 $corpIds = $userList->pluck('corpid'); $corpList = AuthorizeCorp::select('corpid', 'corp_name')->whereIn('corpid', $corpIds)->where('enable', 1)->get(); $data = []; $forwardStatusData = []; # 查询企微和客服是否配置了邀请入群功能 foreach ($userList as $userInfo) { $corpid = $userInfo->corpid ?? null; $userId = $userInfo->user_id ?? null; if(!$corpid || !$userId) { Log::logError('设备绑定客服基本信息数据异常', [ 'user_info' => $userInfo->toArray(), 'device_id' => $deviceId ], 'waitCreate'); continue; } $corpInfo = $corpList->where('corpid', $corpid)->first(); $corpName = $corpInfo->corp_name ?? null; if(is_null($corpName)) { Log::logError('企微名称获取为空', [ 'device_id' => $deviceId, 'corpid' => $corpid, 'userId' => $userId, ], 'waitCreate'); continue; } $forwardStatusData[] = [ 'companyName' => $corpName, 'corpid' => $corpid, 'forward_status' => $userInfo->forward_status, ]; # 使用更新时间最近的配置 $inviteConfig = ForwardChatGroupRule::query()->where('corpid', $corpid) ->whereRaw("FIND_IN_SET('".$userId."', `users`)") ->where('status', 1)->where('enable', 1) ->orderBy('updated_at', 'desc') ->first(); if(empty($inviteConfig)) { $inviteConfig = ForwardChatGroupRule::query()->where('corpid', $corpid) ->where('is_for_all', 1) ->where('enable', 1)->where('status', 1) ->orderBy('updated_at', 'desc') ->first(); } if(empty($inviteConfig)) { Log::logError('该企微未配置创建转发消息群聊规则', [ 'user_info' => $userInfo->toArray(), 'device_id' => $deviceId ], 'waitCreate'); continue; } if($inviteConfig->create_type == 2 && strtotime($inviteConfig->do_time) > time()) { Log::logError('未到执行时间', [ 'user_info' => $userInfo->toArray(), 'device_id' => $deviceId, 'config_info' => $inviteConfig->toArray() ], 'waitCreate'); continue; } # 满足邀请入群时间,在执行完成后将规则状态改为关闭 // if('9d8eea27-88a5-36ae-ab53-b6baad22ab5a' != $deviceId) { ForwardChatGroupRule::query()->where('id', $inviteConfig->id)->update(['status' => 0]); // } # 规则ID $ruleId = $inviteConfig->id; $ruleInfo = ForwardChatGroupRule::getInfo($ruleId); $forwardUserList = explode(',', $ruleInfo->forward_users); $forwardUserData = []; # 查询客服信息 $userList = DjUser::getUserBySearch(['system_user_ids' => $forwardUserList]); $corpidList = $userList->isNotEmpty() ? array_unique(array_column($userList->toArray(), 'corpid')) : []; $corpList = AuthorizeCorp::getCorpInfoByCorpId($corpidList); foreach ($forwardUserList as $systemUserId) { $userInfo = $userList->where('id', $systemUserId)->first(); $userCorpId = $userInfo->corpid ?? null; $corpInfo = $corpList->where('corpid', $userCorpId)->first(); if($userInfo->user_id == $userId && $userCorpId == $corpid) { # 当群主和转发客服为同一个人的时候跳过不处理 continue; } $forwardUserData[] = [ 'corpid' => $userCorpId, 'corp_name' => $corpInfo->corp_name ?? '', 'user_id' => $userInfo->user_id ?? '', 'user_name' => $userInfo->name ?? '', 'user_alias' => $userInfo->alias ?? '', 'system_user_id' => $systemUserId, ]; } $data[] = [ 'companyName' => $corpName, 'corpid' => $corpid, 'group_name' => $ruleInfo->template_group_name ?? '', 'group_num' => $ruleInfo->group_num ?? 10, 'forward_user_list' => $forwardUserData, ]; } return [ 'create_task_list' => $data, 'forward_status_list' => $forwardStatusData ]; } public static function forwardMessageRecord($deviceId, $requestId, $userName, $corpName, $chatList, $message, $messageFrom) { $chatCount = count(explode(",", $chatList)); # 获取缓存中的转发群聊个数 $totalChatCount = RedisModel::get(self::FORWARD_CHAT_GROUP_COUNT.'-'.$requestId); if(!empty($totalChatCount)) { $newTotalChatCount = $totalChatCount + $chatCount; } else { $newTotalChatCount = $chatCount; } RedisModel::set(self::FORWARD_CHAT_GROUP_COUNT.'-'.$requestId, $newTotalChatCount); RedisModel::expire(self::FORWARD_CHAT_GROUP_COUNT.'-'.$requestId, 86400); # 查询企微 $corpid = AuthorizeCorp::where('corp_name', $corpName)->where('enable', 1)->value('corpid'); Log::logInfo('查询到的企微id:', [ 'corpid' => $corpid ], 'debug'); if(!$corpid) { EmailQueue::rPush('转发日志中的企微不存在于系统', $corpName, ['xiaohua.hou@kuxuan-inc.com'], '猎羽'); Log::logError('转发日志中的企微不存在于系统', [ 'device_id' => $deviceId, 'request_id' => $requestId, 'user_name' => $userName, 'corpName' => $corpName, 'chat_list' => $chatList, 'message' => $message, 'message_from' => $messageFrom ], 'ForwardMessageRecord'); return false; } # 使用deviceId查询绑定的客服信息 $userInfo = AndroidBindCorp::getBindUserByDeviceId($deviceId, $corpid); Log::logInfo('查询到的客服信息:', [ 'user_info' => $userInfo ], 'debug'); if(empty($userInfo)) { // EmailQueue::rPush('未查询到该设备有对应的企微成员绑定信息', $corpName . '-' . $corpid, ['xiaohua.hou@kuxuan-inc.com'], '猎羽'); Log::logError('未查询到该设备有对应的企微成员绑定信息', [ 'device_id' => $deviceId, 'request_id' => $requestId, 'user_name' => $userName, 'corpName' => $corpName, 'chat_list' => $chatList, 'message' => $message, 'message_from' => $messageFrom, 'corpid' => $corpid ], 'ForwardMessageRecord'); return false; } # 查询已有记录信息 $recordInfo = ForwardMsgRecord::getRecordDetail($deviceId, $requestId); Log::logInfo('查询到已有的记录:', [ 'record_info' => $recordInfo ], 'debug'); $timeInterval = ''; if(!empty($recordInfo)) { $timeInterval = self::getForwardTimeInterval($recordInfo->time_interval, $recordInfo->updated_at); Log::logInfo('时间间隔信息:', [ 'time_interval' => $timeInterval ], 'debug'); } $chatGroupTotal = ChatGroupMember::getGroupCountByUserName($userName); $insertData = [ 'time_interval' => $timeInterval, 'chat_group_total' => $chatGroupTotal, 'forward_total' => $newTotalChatCount ]; $rst = ForwardMsgRecord::updateOrCreate([ 'record_id' => $requestId, 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userInfo->user_id ], $insertData); Log::logInfo('模拟点击工具转发消息记录', [ 'device_id' => $deviceId, 'request_id' => $requestId, 'user_name' => $userName, 'corp_name' => $corpName, 'chat_list' => $chatList, 'message' => $message, 'message_from' => $messageFrom, 'chat_count' => $chatCount, 'total_chat_count' => $newTotalChatCount, 'insert_data' => $insertData, 'rst' => $rst ], 'forwardMessageRecord'); return $rst; } public static function getForwardTimeInterval($timeIntervalOld, $lastForwardTime) { $second = time() - strtotime($lastForwardTime); $timeIntervalOld = $timeIntervalOld ? $timeIntervalOld . ',' . $second : $second; $timeIntervalOldArr = explode(',', $timeIntervalOld); if(count($timeIntervalOldArr) > 10) { $timeIntervalOldArr = array_slice($timeIntervalOldArr, '-10'); } return trim(implode(',', $timeIntervalOldArr), ','); } public static function getForwardMsgRecordList($corpid, $page, $pageSize) { list($list, $count) = ForwardMsgRecord::getForwardMsgRecordList($corpid, $page, $pageSize); if(!$count) return [[], 0]; # 获取设备信息 $deviceIds = $list->pluck('device_id'); $deviceConfigList = AndroidBindCorp::select('device_id', 'title')->whereIn('device_id', $deviceIds)->where('corpid', $corpid)->get(); # 获取企微信息 $corpName = AuthorizeCorp::where('corpid', $corpid)->value('corp_name'); # 获取客服信息 $userIds = $list->pluck('user_id'); $userList = DjUser::select('user_id', 'name')->whereIn('user_id', $userIds)->where('corpid', $corpid)->get(); foreach ($list as $item) { # 设备配置信息 $deviceInfo = $deviceConfigList->where('device_id', $item->device_id)->first(); $item->device_title = $deviceInfo->title; # 企微信息 $item->corp_name = $corpName; # 成员信息 $userInfo = $userList->where('user_id', $item->user_id)->first(); $item->user_name = $userInfo->name ?? ''; } return [$list, $count]; } }