server=$server; $this->fd=$request->fd; //取IP地址,后续用于区域判别和记录 $this->ip=$request->server['remote_addr']; //取会话数据 if (isset($request->cookie[Config::get("access.SESSION_DEFAULT_NAME")])) { $this->session_id=$request->cookie[Config::get("access.SESSION_DEFAULT_NAME")]; $this->session_data=$this->unserializePhp(Cache::store('session_store')->get($this->session_id)); //切换缓存 Cache::store('default'); } else { $this->construct_flag=false; Log::info('没有会话ID的数据:'.json_encode($request)); } if ($this->construct_flag) { //用户类型 if (strpos($request->header['origin'], 'admin')) { $this->user_type = 'cs_admin'; } if ($this->user_type == 'user') { //缺省游客信息 $user_info_data['guest_flag'] = true; $user_info_data['user_name'] = '游客'; $user_info_data['area_name'] = '-'; $this->session_data['user_id'] = $this->session_data['user_id'] ?? 0; //存储用户fd对应表 if ($this->session_data['user_id'] == 0) { $this->store_id = $this->session_id; } else { $this->store_id = $this->session_data['user_id']; //取用户信息 $user_info_result = Db::name("users") ->field('phone as user_name,area_id,buyer_status,custom_service_id') ->where(['user_id' => $this->store_id]) ->find(); if ($user_info_result != null) { $user_info_data = $user_info_result; if ($user_info_result['buyer_status'] != 0) { //取得用户的采购商名称 $user_info_data['buyer_name'] = Db::name('buyer')->where(['buyer_user_id' => $this->store_id])->value('name'); } if ($user_info_result['custom_service_id'] != 0) { //取得用户的专属客服信息 $user_info_data['sp_cs_info'] = Db::name('admin_user')->field('mobile,nickname,cs_code,cs_status')->where(['admin_user_id' => $user_info_result['custom_service_id']])->find(); } if ($user_info_result['area_id'] != 0) { $user_info_data['area_name'] = $this->getIDArea($user_info_result['area_id']); } else { $user_info_data['area_name'] = '-'; } $user_info_data['guest_flag'] = false; $this->guest_flag = false; } } $user_info_data['ip_addr'] = $this->ip; $user_info_data['ip_area'] = $this->getIPArea($this->ip); $old_fd = RedisCache::hget('CHAT_USER_FD', $this->store_id); if ($old_fd != $this->fd) { if ($old_fd) { //如果存在fd,说明用户已经有一个窗口建立了连接,需要先关闭原来的连接 $server->disconnect($old_fd, 1000, '重复开启对话'); $chat_deal = new ChatCloseService($server, $old_fd); $chat_deal->onClose(); } RedisCache::hset('CHAT_USER_FD', $this->store_id, $this->fd); //存储fd和用户信息对应缓存 RedisCache::hset('CHAT_USER_FD_MAP', $this->fd, $this->store_id); //存储用户信息 //增加用户ID,以便通讯使用 $user_info_data['user_store'] = $this->store_id; //存储session_id,以便ping时保持会话 $user_info_data['session_id']=$this->session_id; RedisCache::hset('CHAT_USER_INFO', $this->store_id, json_encode($user_info_data)); } //相等什么都不做,实际的可能性也不存在 } else { //客服 $this->session_data['admin_user_id'] = $this->session_data['admin_user_id'] ?? 0; //存储客服fd对应表 if ($this->session_data['admin_user_id'] == 0) { $this->init_flag = false; } else { $this->store_id = $this->session_data['admin_user_id']; //判断是客服还是普通工作人员 $admin_info_data = Db::name("admin_user") ->field('admin_user_id as cs_store,mobile,cs_code,nickname,cs_status') ->where(['admin_user_id' => $this->store_id]) ->find(); if ($admin_info_data==null) { $this->init_flag = false; } else { if ($admin_info_data['cs_status']==1) { //客服人员 $old_fd = RedisCache::hget('CHAT_CS_FD', $this->store_id); if ($old_fd != $this->fd) { if ($old_fd) { //如果存在fd,说明客服已经有一个窗口建立了连接,需要先关闭原来的连接 $server->disconnect($old_fd, 1000, '重复开启对话'); $chat_deal = new ChatCloseService($server, $old_fd); $chat_deal->onClose(); } //存储session_id,以便ping时保持会话 $admin_info_data['session_id'] = $this->session_id; RedisCache::hset('CHAT_CS_FD', $this->store_id, $this->fd); RedisCache::hset('CHAT_CS_FD_MAP', $this->fd, $this->store_id); //存储客服信息 RedisCache::hset('CHAT_CS_INFO', $this->store_id, json_encode($admin_info_data)); } //相等什么都不做,实际的可能性也不存在 } else { //普通工作人员 $this->user_type = 'normal_admin'; $old_fd = RedisCache::hget('CHAT_ADMIN_FD', $this->store_id); if ($old_fd != $this->fd) { if ($old_fd) { //如果存在fd,说明工作人员已经有一个窗口建立了连接,需要先关闭原来的连接 $server->disconnect($old_fd, 1000, '重复开启对话'); $chat_deal = new ChatCloseService($server, $old_fd); $chat_deal->onClose(); } //存储session_id,以便ping时保持会话 $admin_info_data['session_id'] = $this->session_id; RedisCache::hset('CHAT_ADMIN_FD', $this->store_id, $this->fd); RedisCache::hset('CHAT_ADMIN_FD_MAP', $this->fd, $this->store_id); //存储客服信息 RedisCache::hset('CHAT_ADMIN_INFO', $this->store_id, json_encode($admin_info_data)); } //相等什么都不做,实际的可能性也不存在 } } } } } } public function onOpen() { if ($this->construct_flag) { if ($this->user_type=='user') { $this->onUserOpen(); } else { $this->onCSOpen(); } } else { $message_type='initError'; $push_data['content']='初始化连接异常'; $this->server->push($this->fd,myResult($message_type,$push_data)); } } public function onUserOpen() { //连接成功通知 $result['message_type']='success'; $result['data']='在线客服已连接'; //返回连接成功的消息 $this->server->push($this->fd,myResult($result['message_type'],$result['data'])); //离线消息部分 if (!$this->guest_flag) { $cs_id_list=[]; $offline_chat_message_list=[]; //是注册用户,则需要处理离线消息部分 //先取出所有的keys $offline_chat_list=RedisCache::keys('OFFLINE_CHAT_DATA_'.$this->store_id.'_*'); foreach ($offline_chat_list as $v) { //取出用户本次离线消息的记录 $offline_chat_message_list=array_merge($offline_chat_message_list,RedisCache::lrange($v)); //取出客服目前的存储id $cs_id_list[]=substr($v,strlen('OFFLINE_CHAT_DATA_'.$this->store_id.'_')); } //数据库中未读离线消息处理 $user_where['user_id'] = $this->store_id; //$user_where['offline_flag'] = 0;//由于目前未读消息只有可能是离线消息,暂不增加离线字段判断 $user_where['read_flag'] = 0; $chat_message=Db::name('chat_message')->field('admin_user_id,offline_flag,message')->where($user_where)->select(); //把数据置为已读 $update_data['read_flag'] = 1; Db::name('chat_message')->where($user_where)->update($update_data); foreach ($chat_message as $k=>$v) { $chat_message_list=json_decode($v['message'],true); $offline_chat_message_list=array_merge($offline_chat_message_list,$chat_message_list); //取出客服目前的存储id $cs_id_list[]=$v['admin_user_id']; } //取出客服信息 $cs_info_data = Db::name("admin_user") ->where(['admin_user_id' => $cs_id_list]) ->column('admin_user_id as cs_store,mobile,cs_code,nickname','admin_user_id'); //组装离线消息信息 $offline_chat_message_array=[]; foreach ($offline_chat_message_list as $k=>$v) { $tmp_message=json_decode($v,true); $offline_chat_message_array[$tmp_message['time'].$k]=$tmp_message; } ksort($offline_chat_message_array); foreach ($offline_chat_message_array as $v) { $message_type='chatMessage'; $push_data=["cs_info"=>$cs_info_data[$v['from_id']],"time"=>$v['time'],"content"=>$v['content'],"offline"=>1]; $this->server->push($this->fd,myResult($message_type,$push_data)); } } //分配客服 $this->assignCS($this->server,$this->fd,$this->store_id,$this->guest_flag); } public function onCSOpen() { if (!$this->init_flag) { $message_type='initError'; $push_data['content']='请先登录管理系统'; } else { //暂时没有其他事情,由客服手动决定是否开始接受客户请求 $message_type='success'; $push_data['content']='在线办公已连接'; } $this->server->push($this->fd,myResult($message_type,$push_data)); if ($this->user_type == 'cs_admin') { if ($message_type=='success') { Log::info('发送等待用户数'); //发送等待用户数 $this->pushUserQueueNum($this->server,$this->fd); } } } }