274 lines
11 KiB
PHP
274 lines
11 KiB
PHP
<?php
|
||
|
||
namespace app\http\service;
|
||
|
||
use app\facade\AppConstant;
|
||
use app\facade\RedisCache;
|
||
use think\captcha\Captcha;
|
||
use think\Db;
|
||
use think\facade\Cache;
|
||
use think\facade\Config;
|
||
use think\facade\Env;
|
||
use think\facade\Log;
|
||
|
||
class CommonService
|
||
{
|
||
const TALK_WORDS=[
|
||
'hello_words'=>'您好,欢迎您使用金壶医药商城,请问您有什么疑问,我将为您在线解答。',
|
||
'work_time'=>'工作日9:00-17:30',
|
||
];
|
||
/*protected function initBaseChat($user_store,$cs_store) {
|
||
Log::info('用户ID'.$user_store.',客服ID'.$cs_store);
|
||
$cs_info_data = RedisCache::hget('CHAT_CS_INFO',$cs_store);
|
||
$user_info_data = RedisCache::hget('CHAT_USER_INFO',$user_store);
|
||
|
||
$result['cs_info_data']=$cs_info_data;
|
||
$result['user_info_data']=$user_info_data;
|
||
return $result;
|
||
}*/
|
||
|
||
/*protected function pushToCS($server,$cs_store,$user_info_data) {
|
||
//找出客服对应的fd
|
||
$fd_store=RedisCache::hget('CHAT_CS_FD',$cs_store);
|
||
if ($fd_store) {
|
||
$push_data['message_type']='connect';
|
||
$push_data['data']=["user_info"=>$user_info_data];
|
||
$server->push($fd_store,myResult($push_data['message_type'],$push_data['data']));
|
||
}
|
||
}
|
||
|
||
protected function pushToUser($server,$user_store,$cs_info_data) {
|
||
//找出用户对应的fd
|
||
$fd_store=RedisCache::hget('CHAT_USER_FD',$user_store);
|
||
if ($fd_store) {
|
||
$push_data['message_type']='connect';
|
||
$push_data['data']=["cs_info"=>$cs_info_data];
|
||
$server->push($fd_store,myResult($push_data['message_type'],$push_data['data']));
|
||
}
|
||
}*/
|
||
|
||
//当前在线等待用户数
|
||
protected function pushUserQueueNum($server,$fd=0) {
|
||
$user_queue_num=RedisCache::llen('CHAT_USER_QUEUE');
|
||
$fd_list=[];
|
||
if ($fd>0) {
|
||
//单播
|
||
$fd_list[]=$fd;
|
||
} else {
|
||
//广播在线客服
|
||
$fd_list=RedisCache::hkeys('CHAT_CS_FD_MAP');
|
||
}
|
||
Log::info('向客服'.json_encode($fd_list).'发送在线等待人数'.$user_queue_num);
|
||
foreach ($fd_list as $v) {
|
||
$message_type='userQueueNum';
|
||
$push_data=["user_queue_num"=>$user_queue_num];
|
||
$server->push($v,myResult($message_type,$push_data));
|
||
}
|
||
}
|
||
|
||
//建立对话关系,并通知双方
|
||
protected function createChatRelation($server,$user_fd,$user_store,$cs_fd,$cs_store){
|
||
$now_time=date('Y-m-d H:i:s');
|
||
$cs_info_data = json_decode(RedisCache::hget('CHAT_CS_INFO',$cs_store),true);
|
||
$user_info_data = json_decode(RedisCache::hget('CHAT_USER_INFO',$user_store),true);
|
||
|
||
//建立对话关系
|
||
//RedisCache::hset('CHAT_RELATION', $user_store, $cs_store);
|
||
RedisCache::lpush('CHAT_DATA_'.$user_store.'_'.$cs_store,json_encode(['time'=>$now_time,"content"=>self::TALK_WORDS['hello_words'],"from_id"=>$cs_store,"to_id"=>$user_store]));
|
||
|
||
//通知用户
|
||
$message_type = 'connect';
|
||
$push_data = $cs_info_data;
|
||
$server->push($user_fd,myResult($message_type,$push_data));
|
||
//通知客服
|
||
$message_type = 'connect';
|
||
$push_data = ["user_info"=>$user_info_data];
|
||
$server->push($cs_fd,myResult($message_type,$push_data));
|
||
//发送模版问侯
|
||
$message_type='chatMessage';
|
||
$push_data=["cs_info"=>$cs_info_data,"time"=>$now_time,"content"=>self::TALK_WORDS['hello_words']];
|
||
$server->push($user_fd,myResult($message_type,$push_data));
|
||
|
||
//如果有未存入数据库的离线消息,要发给客服
|
||
//取出用户本次离线消息的记录
|
||
$offline_chat_message_list=RedisCache::lrange('OFFLINE_CHAT_DATA_'.$user_store.'_'.$cs_store);
|
||
if (!$offline_chat_message_list) {
|
||
$offline_chat_message_list=[];
|
||
}
|
||
Log::info('和客服离线留言数据:'.json_encode($offline_chat_message_list));
|
||
if (!checkGuestFlag($user_store)) {
|
||
//还要取出离线留言
|
||
$offline_chat_message_list_0=RedisCache::lrange('OFFLINE_CHAT_DATA_'.$user_store.'_0');
|
||
if ($offline_chat_message_list_0) {
|
||
$offline_chat_message_list=array_merge($offline_chat_message_list,$offline_chat_message_list_0);
|
||
}
|
||
}
|
||
|
||
Log::info('加上和系统离线留言数据:'.json_encode($offline_chat_message_list));
|
||
//组装离线消息信息
|
||
$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=["user_info"=>$user_info_data,"time"=>$v['time'],"content"=>$v['content'],"offline"=>1];
|
||
$server->push($cs_fd,myResult($message_type,$push_data));
|
||
}
|
||
//--
|
||
|
||
//模版问侯也发送给客服,因为是模拟客服发送,需要换种消息类型
|
||
$message_type='systemChatMessage';
|
||
$push_data=["user_info"=>$user_info_data,"time"=>$now_time,"content"=>self::TALK_WORDS['hello_words']];
|
||
$server->push($cs_fd,myResult($message_type,$push_data));
|
||
}
|
||
|
||
//自动分配客服(用户使用)
|
||
protected function assignCS($server,$fd,$store_id,$guest_flag){
|
||
$assign_flag=false;
|
||
$online_cs_list = RedisCache::lrange("CUSTOMER_ONLINE_QUEUE");
|
||
if (count($online_cs_list)>0) {
|
||
if (!$guest_flag) {
|
||
//如果不是游客,则看用户是否有专属客服
|
||
//若专属客服不在线,则自动分配在线客服
|
||
//从数据库中取用户专属客服
|
||
$cs_admin_id = Db::name("users")->where(['user_id' => $store_id])->value('custom_service_id');
|
||
if (in_array($cs_admin_id, $online_cs_list)) {
|
||
$assign_flag = true;
|
||
}
|
||
}
|
||
//如果未分配,则取一个在线客服
|
||
if (!$assign_flag) {
|
||
$cs_admin_id = RedisCache::rpoplpush("CUSTOMER_ONLINE_QUEUE");
|
||
if ($cs_admin_id) {
|
||
$assign_flag=true;
|
||
}
|
||
}
|
||
}
|
||
if ($assign_flag) {
|
||
//获得客服的fd
|
||
$cs_fd=RedisCache::hget('CHAT_CS_FD',$cs_admin_id);;
|
||
//建立对话关系
|
||
$this->createChatRelation($server,$fd,$store_id,$cs_fd,$cs_admin_id);
|
||
} else {
|
||
//没有分配成功,进入等待队列,该队列用户可考虑留言功能
|
||
RedisCache::lpush("CHAT_USER_QUEUE", $store_id);
|
||
$message_type='wait';
|
||
|
||
if (checkGuestFlag($store_id)) {
|
||
$push_data['content']='在线客服服务时间为'.self::TALK_WORDS['work_time'].'。当前暂无客服接待,您可以等待,登录平台可以进行离线留言';
|
||
} else {
|
||
$push_data['content']='在线客服服务时间为'.self::TALK_WORDS['work_time'].'。当前暂无客服接待,您可以离线留言或等待';
|
||
}
|
||
$server->push($fd,myResult($message_type,$push_data));
|
||
|
||
//向所有在线客服发送等待用户数
|
||
$this->pushUserQueueNum($server);
|
||
}
|
||
}
|
||
|
||
//用户关闭通知(用户使用)
|
||
protected function noticeUserLeave($server,$user_store,$cs_store,$remove_flag,$user_info_data){
|
||
//通知用户
|
||
$message_type = 'disconnect';
|
||
//$user_info_data = json_decode(RedisCache::hget('CHAT_USER_INFO',$user_store),true);
|
||
$push_data = $user_info_data;
|
||
//群体通知
|
||
if (is_array($cs_store)) {
|
||
if (count($cs_store) > 0) {
|
||
foreach ($cs_store as $k=>$v) {
|
||
$cs_fd = RedisCache::hget('CHAT_CS_FD', $v);
|
||
if ($cs_fd != null) {
|
||
$push_data['remove_flag']=$remove_flag[$k];
|
||
Log::info('是否需要关闭'.json_encode($push_data['remove_flag']));
|
||
$server->push($cs_fd, myResult($message_type, $push_data));
|
||
}
|
||
}
|
||
/*$cs_fd_list = RedisCache::hmget('CHAT_CS_FD', $cs_store);
|
||
if ($cs_fd_list !== false) {
|
||
foreach ($cs_fd_list as $v) {
|
||
$server->push($v, myResult($message_type, $push_data));
|
||
}
|
||
}*/
|
||
|
||
}
|
||
} else {
|
||
//获得用户的fd
|
||
$cs_fd=RedisCache::hget('CHAT_CS_FD',$cs_store);
|
||
$server->push($cs_fd,myResult($message_type,$push_data));
|
||
}
|
||
}
|
||
|
||
//客服关闭通知(客服使用)
|
||
protected function noticeCSLeave($server,$user_store,$cs_store,$message_type='disconnect'){
|
||
//通知用户
|
||
$cs_info_data = json_decode(RedisCache::hget('CHAT_CS_INFO',$cs_store),true);
|
||
$push_data = $cs_info_data;
|
||
//群体通知
|
||
if (is_array($user_store)) {
|
||
if (count($user_store) > 0) {
|
||
$user_fd_list = RedisCache::hmget('CHAT_USER_FD', $user_store);
|
||
if ($user_fd_list !== false) {
|
||
foreach ($user_fd_list as $v) {
|
||
$server->push($v, myResult($message_type, $push_data));
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
//获得用户的fd
|
||
$user_fd=RedisCache::hget('CHAT_USER_FD',$user_store);
|
||
$server->push($user_fd,myResult($message_type,$push_data));
|
||
}
|
||
}
|
||
|
||
//IP获取地址
|
||
public function getIPArea($ip)
|
||
{
|
||
require_once Env::get('extend_path').'ip2region/Ip2Region.php';
|
||
$ip2region = new \Ip2Region();
|
||
$info = $ip2region->btreeSearch($ip);
|
||
|
||
$city = explode('|', $info['region']);
|
||
|
||
if (0 != $info['city_id']) {
|
||
return $city['2'] . $city['3'] . $city['4'];
|
||
} else {
|
||
return $city['0'];
|
||
}
|
||
}
|
||
|
||
//通过area_id获取地址
|
||
public function getIDArea($area_id)
|
||
{
|
||
$tmp_area_data=Db::name('area')->field('area_name,parent_area_id')->where(['id'=>$area_id])->find();
|
||
if ($tmp_area_data==null) {
|
||
return '';
|
||
}
|
||
if ($tmp_area_data['parent_area_id']!=0) {
|
||
return $this->getIDArea($tmp_area_data['parent_area_id']).'-'.$tmp_area_data['area_name'];
|
||
} else {
|
||
return $tmp_area_data['area_name'];
|
||
}
|
||
}
|
||
|
||
//解析session数据
|
||
protected function unserializePhp($session_data) {
|
||
$return_data = array();
|
||
$offset = 0;
|
||
while ($offset < strlen($session_data)) {
|
||
if (!strstr(substr($session_data, $offset), "|")) {
|
||
return false;
|
||
}
|
||
$pos = strpos($session_data, "|", $offset);
|
||
$num = $pos - $offset;
|
||
$varname = substr($session_data, $offset, $num);
|
||
$offset += $num + 1;
|
||
$data = unserialize(substr($session_data, $offset));
|
||
$return_data[$varname] = $data;
|
||
$offset += strlen(serialize($data));
|
||
}
|
||
return $return_data;
|
||
}
|
||
} |