zoujiajian 1 tahun lalu
induk
melakukan
e60a88a415

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpKfAccountSessionChat.java

@@ -16,6 +16,8 @@ public class CorpKfAccountSessionChat extends BaseEntity{
 
 	private String msgid;
 
+	private Integer orign;
+
 	private String servicerUserid;
 
 	private String externalUserid;

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpKfAccountSessionConfig.java

@@ -24,6 +24,11 @@ public class CorpKfAccountSessionConfig extends BaseEntity{
 	 */
 	private Integer maxNum;
 
+	/**
+	 * 未回复结束对话间隔
+	 */
+	private Integer noReplyTime;
+
 	/**
 	 * 欢迎语
 	 */

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpKfServicerSessionRecord.java

@@ -23,4 +23,20 @@ public class CorpKfServicerSessionRecord extends BaseEntity{
 	 * 0接待中 1已结束,2.转接
 	 */
 	private Integer serviceState;
+
+	/**
+	 * 消息id
+	 */
+	private String msgId;
+
+	/**
+	 * 0未评价 1.满意 2.一般 3.不满意
+	 * 满意度
+	 */
+	private Integer satisfaction;
+
+	/**
+	 * 是否发送满意度测评 默认false
+	 */
+	private Boolean sendSatisfaction;
 }

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/kf/CorpKfUserInfo.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.kf;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfUserInfo
+ * 创建者: JavaZou
+ * 创建时间:2025/1/2 16:14
+ */
+@Getter
+@Setter
+public class CorpKfUserInfo {
+	@JsonProperty("external_userid")
+	private String externalUserid;
+
+	private String ncikname;
+
+	private String avatar;
+
+	private String unionid;
+
+	private Integer gender;
+}

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/kf/WxCorpChatMsg.java

@@ -22,6 +22,9 @@ public class WxCorpChatMsg {
 
 	private String servicer_userid;
 
+	//消息来源。3-微信客户发送的消息 4-系统推送的事件消息 5-接待人员在企业微信客户端发送的消息
+	private Integer origin;
+
 	private List<Item> item;
 
 	@Getter

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/kf/WxCorpTextMsg.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.kf;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: WxCorpTextMsg
+ * 创建者: JavaZou
+ * 创建时间:2025/1/2 15:41
+ */
+@Getter
+@Setter
+public class WxCorpTextMsg {
+	private String content;
+
+	private String menu_id;
+}

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/kf/WxCpKfMsgListResp.java

@@ -56,5 +56,7 @@ public class WxCpKfMsgListResp {
     //聊天记录事件
     @JsonProperty("msgtype")
     private WxCorpChatMsg mergedMsg;
+    //文本消息
+    private WxCorpTextMsg text;
   }
 }

+ 4 - 2
netflix-service/src/main/java/com/cyksj/service/corp/WxCorpOps.java

@@ -222,7 +222,7 @@ public interface WxCorpOps {
 	/**
 	 * 获取客服账号接待人员
 	 */
-	CorpKfServicerResp getKfServicerList(String corpId,String openKfId);
+	CorpKfServicerResp getKfServicerList(String corpId,String openKfId) throws Exception;
 
 	void moveWaitingQueue(String corpId, String openKfId, String externalUserId) throws Exception;
 
@@ -234,5 +234,7 @@ public interface WxCorpOps {
 	/**
 	 * 发送满意度调查msg
 	 */
-	void sendSatisfactionMsg() throws Exception;
+	void sendSatisfactionMsg(String msgId) throws Exception;
+
+	CorpKfUserInfo getCorpKfUserInfo(String externalUserid) throws Exception;
 }

+ 105 - 49
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java

@@ -3,6 +3,7 @@ package com.cyksj.service.corp.impl;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
@@ -572,6 +573,7 @@ public class CorpServiceImpl implements CorpService {
 		List<WxCpKfMsgListResp.WxCpKfMsgItem> enterSessionList = null;
 		List<WxCpKfMsgListResp.WxCpKfMsgItem> sessionStatusChanges = null;
 		List<WxCorpChatMsg> mergedMsgs = null;
+		List<WxCpKfMsgListResp.WxCpKfMsgItem> textList = null;
 		for (WxCpKfMsgListResp.WxCpKfMsgItem item : msgList) {
 			if (item.getEvent() != null && item.getEvent().getEventType().equals("enter_session")) {
 				//会话事件
@@ -597,23 +599,56 @@ public class CorpServiceImpl implements CorpService {
 				mergedMsg.setServicer_userid(item.getServicerUserId());
 				mergedMsg.setExternal_userid(item.getExternalUserId());
 				mergedMsg.setMsgid(item.getMsgId());
+				mergedMsg.setOrigin(item.getOrigin());
 				mergedMsgs.add(mergedMsg);
 			}
+			if (StrUtil.equals("text", item.getMsgType())) {
+				textList.add(item);
+			}
 		}
 		//进入会话事件
 		enterSessionEvent(corpKfAccount, corpKfAccountSessionConfig, corpId, enterSessionList);
 		//会话更变事件
 		sessionStatusChange(corpId, openKfId, sessionStatusChanges);
-		//消息发送失败事件
-		//拒收客户消息变更事件
 		//同步客服聊天记录
 		syncChatMsg(openKfId, mergedMsgs);
+		//同步满意度
+		syncSessionSatisfaction(openKfId, textList);
 		corpKfAccountSyncMsgProgress.setCursor(cursor);
+		//同步信息
 		while (wxCpKfMsgListResp.getHasMore() == 1) {
 			syncCorpKfMsg(corpKfAccount, corpKfAccountSessionConfig, corpId, wxCpKfMsgListResp.getNextCursor(), token, limit, corpKfAccountSyncMsgProgress);
 		}
 	}
 
+	private void syncSessionSatisfaction(String openKfId, List<WxCpKfMsgListResp.WxCpKfMsgItem> textList) {
+		Integer satisfaction = null;
+		for (WxCpKfMsgListResp.WxCpKfMsgItem item : textList) {
+			WxCorpTextMsg text = item.getText();
+			//自定义菜单id
+			if (text.getMenu_id()!=null) {
+				//满意
+				if ("101".equals(text.getMenu_id())) {
+					satisfaction = 1;
+				}
+				//一般
+				if ("102".equals(text.getMenu_id())) {
+					satisfaction = 2;
+				}
+				//不满意
+				if ("103".equals(text.getMenu_id())) {
+					satisfaction = 3;
+				}
+				if (satisfaction != null) {
+					corpKfServicerSessionRecordMapper.update(null, Wrappers.lambdaUpdate(CorpKfServicerSessionRecord.class)
+							.set(CorpKfServicerSessionRecord::getSatisfaction, satisfaction)
+							.eq(CorpKfServicerSessionRecord::getOpenKfId, openKfId)
+							.eq(CorpKfServicerSessionRecord::getMsgId, item.getMsgId()));
+				}
+			}
+		}
+	}
+
 	private void syncChatMsg(String openKfId, List<WxCorpChatMsg> mergedMsgs) {
 		CorpKfAccountSessionChat corpKfAccountSessionChat = null;
 		for (WxCorpChatMsg mergedMsg : mergedMsgs) {
@@ -629,6 +664,7 @@ public class CorpServiceImpl implements CorpService {
 				corpKfAccountSessionChat.setMsgType(item.getMsgtype());
 				corpKfAccountSessionChat.setMsgContent(item.getMsg_content());
 				corpKfAccountSessionChat.setMsgid(mergedMsg.getMsgid());
+				corpKfAccountSessionChat.setOrign(mergedMsg.getOrigin());
 				corpKfAccountSessionChatMapper.insert(corpKfAccountSessionChat);
 			}
 		}
@@ -702,64 +738,81 @@ public class CorpServiceImpl implements CorpService {
 					log.info("external_userid:{}已有未结束的会话,无需分配", event.getExternalUserId());
 					return;
 				}
-				//配置接待人员
-				//是否有空闲人员
-				int hour = DateTime.now().hour(true);
-				corpKfAccountFollowMapper.selectList(Wrappers.lambdaQuery(CorpKfAccountFollow.class)
+			}
+			//是否设置非值班提示
+			if (corpKfAccountSessionConfig != null && StrUtil.isNotEmpty(corpKfAccountSessionConfig.getNoDutyTips())) {
+				DateTime now = DateTime.now();
+				int thisHour = DateUtil.hour(now, true);
+				//0-6 0周一
+				int dayOfWeek = DateUtil.dayOfWeek(now);
+				//是否值班期
+				Integer dutyHourCount = corpKfAccountFollowMapper.selectCount(Wrappers.lambdaQuery(CorpKfAccountFollow.class)
 						.eq(CorpKfAccountFollow::getOpenKfId, openKfId)
-						.le(CorpKfAccountFollow::getStartTime, hour)
-						.ge(CorpKfAccountFollow::getEndTime, hour));
-				//获取接待人员列表
-				CorpKfServicerResp corpKfServicerResp = wxCorpOps.getKfServicerList(corpId, openKfId);
-				List<CorpKfServicerResp.CorpKfServicer> servicerList = corpKfServicerResp.getServicerList();
-				//目前值班客服id
-				List<String> corpKfServiceIds = new ArrayList<>();
-				List<CorpKfServicerResp.CorpKfServicer> corpKfServicers = servicerList.stream().filter(servicer -> {
-					if (servicer.getUserid() != null && servicer.getStatus() == 0) {
-						corpKfServiceIds.add(servicer.getUserid());
-						return true;
-					}
-					return false;
-				}).collect(Collectors.toList());
-				if (CollUtil.isEmpty(corpKfServicers)) {
-					//非值班 移入等待池并发送非值班提示消息
-					moveWaitingQueue(corpId, openKfId, event.getExternalUserId());
-					String noDutyTips = corpKfAccountSessionConfig.getNoDutyTips();
-					if (StrUtil.isNotEmpty(noDutyTips)) {
-						//发送提示
-						sendCorpKfTextTips(corpId, event.getExternalUserId(), openKfId, noDutyTips);
-					}
-					return;
-				}
-				//是否有空闲接待人员
-				List<CorpKfServicerDto> corpKfServicerDtos = corpKfServicerSessionRecordMapper.getAvailableServicer(openKfId);
-				if (CollUtil.isEmpty(corpKfServicerDtos)) {
-					//暂无分配会话
-					//随机分配一个客服
-					CorpKfServicerResp.CorpKfServicer corpKfServicer = corpKfServicers.get(RandomUtil.randomInt(corpKfServicers.size()));
-					//变更会话状态
-					transCorpKfSessionToServicer(corpId, openKfId, corpKfServicer.getUserid(), event.getExternalUserId());
-				}
-				//筛选符合条件的客服
-				//默认接入最少的优先分配 接待人最少的在集合前面
-				//最多接待人数
-				Integer maxNum = corpKfAccountSessionConfig.getMaxNum();
-				List<CorpKfServicerDto> filterKfCs = corpKfServicerDtos.stream().filter(kfCs -> corpKfServiceIds.contains(kfCs.getServicerUserid()) && kfCs.getNum() < maxNum).collect(Collectors.toList());
-				if (CollUtil.isEmpty(filterKfCs)) {
-					//未有可接待的客服 移入等待池并发送进入等待池消息
+						.le(CorpKfAccountFollow::getStartTime, thisHour)
+						.ge(CorpKfAccountFollow::getEndTime, thisHour)
+						.apply(" and JSON_CONTAINS(duty_week,'\"%s\"')", dayOfWeek));
+				//非值班时间 发送通知
+				if (dutyHourCount == 0) {
+					//非值班时间 移入等待池并发送进入等待池消息
+					log.info("当前客服账号:{}处于非值班时间:{},将客服:{}移入等待池", openKfId, thisHour, event.getExternalUserId());
 					moveWaitingQueue(corpId, openKfId, event.getExternalUserId());
 					String queueTips = corpKfAccountSessionConfig.getQueueTips();
 					sendCorpKfTextTips(corpId, event.getExternalUserId(), openKfId, queueTips);
 					return;
 				}
-				//选择第一个分配接待
-				CorpKfServicerDto corpKfServicerDto = filterKfCs.get(0);
+			}
+			//获取接待人员列表
+			CorpKfServicerResp corpKfServicerResp = wxCorpOps.getKfServicerList(corpId, openKfId);
+			List<CorpKfServicerResp.CorpKfServicer> servicerList = corpKfServicerResp.getServicerList();
+			//目前值班客服id
+			List<String> corpKfServiceIds = new ArrayList<>();
+			List<CorpKfServicerResp.CorpKfServicer> corpKfServicers = servicerList.stream().filter(servicer -> {
+				if (servicer.getUserid() != null && servicer.getStatus() == 0) {
+					corpKfServiceIds.add(servicer.getUserid());
+					return true;
+				}
+				return false;
+			}).collect(Collectors.toList());
+			//客服是否已经开始值班
+			//没有值班人员 接入等待池
+			if (CollUtil.isEmpty(corpKfServicers)) {
+				moveWaitingQueue(corpId, openKfId, event.getExternalUserId());
+				String queueTips = corpKfAccountSessionConfig.getQueueTips();
+				sendCorpKfTextTips(corpId, event.getExternalUserId(), openKfId, queueTips);
+				return;
+			}
+			//是否有空闲接待人员
+			List<CorpKfServicerDto> corpKfServicerDtos = corpKfServicerSessionRecordMapper.getAvailableServicer(openKfId);
+			//暂无分配会话 初始化
+			if (CollUtil.isEmpty(corpKfServicerDtos)) {
+				//随机分配一个客服
+				CorpKfServicerResp.CorpKfServicer corpKfServicer = corpKfServicers.get(RandomUtil.randomInt(corpKfServicers.size()));
 				//变更会话状态
-				transCorpKfSessionToServicer(corpId, openKfId, corpKfServicerDto.getServicerUserid(), event.getExternalUserId());
+				transCorpKfSessionToServicer(corpId, openKfId, corpKfServicer.getUserid(), event.getExternalUserId());
+				return;
 			}
+			//筛选符合条件的客服
+			//默认接入最少的优先分配 接待人最少的在集合前面
+			//不超过最多接待人数
+			Integer maxNum = corpKfAccountSessionConfig.getMaxNum();
+			List<CorpKfServicerDto> filterKfCs = corpKfServicerDtos.stream().filter(kfCs -> corpKfServiceIds.contains(kfCs.getServicerUserid()) && kfCs.getNum() < maxNum).collect(Collectors.toList());
+			if (CollUtil.isEmpty(filterKfCs)) {
+				//未有可接待的客服 移入等待池并发送进入等待池消息
+				moveWaitingQueue(corpId, openKfId, event.getExternalUserId());
+				String queueTips = corpKfAccountSessionConfig.getQueueTips();
+				sendCorpKfTextTips(corpId, event.getExternalUserId(), openKfId, queueTips);
+				return;
+			}
+			//选择第一个分配接待
+			CorpKfServicerDto corpKfServicerDto = filterKfCs.get(0);
+			//变更会话状态
+			transCorpKfSessionToServicer(corpId, openKfId, corpKfServicerDto.getServicerUserid(), event.getExternalUserId());
 		}
 	}
 
+	/**
+	 * 变更用户会话状态
+	 */
 	private void transCorpKfSessionToServicer(String corpId, String openKfId, String userid, String externalUserId) throws Exception {
 		//记录接待人员会话
 		CorpKfServicerSessionRecord corpKfServicerSessionRecord = new CorpKfServicerSessionRecord();
@@ -776,6 +829,9 @@ public class CorpServiceImpl implements CorpService {
 	 * 发送微信客服会话文本消息
 	 */
 	public void sendCorpKfTextTips(String corpId, String externalUserid, String openKfId, String content) throws Exception {
+		if (StrUtil.isEmpty(content)) {
+			return;
+		}
 		WxCorpKfMsgSendRequest wxCpKfMsgSendRequest = new WxCorpKfMsgSendRequest();
 		wxCpKfMsgSendRequest.setMsgType("text");
 		wxCpKfMsgSendRequest.setToUser(externalUserid);

+ 31 - 8
netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java

@@ -920,7 +920,7 @@ public class WxCorpOpsImpl implements WxCorpOps {
 
 		WxCpKfMsgListResp resp = Jsons.parseObject(res.body(), WxCpKfMsgListResp.class);
 		if (resp.getErrcode() != 0) {
-			throw BusinessRuntimeException.getInstance("读取消息: " + resp.getErrmsg());
+			throw BusinessRuntimeException.getInstance("读取消息错误: " + resp.getErrmsg());
 		}
 		return resp;
 	}
@@ -942,7 +942,7 @@ public class WxCorpOpsImpl implements WxCorpOps {
 
 		WxCpKfMsgSendResp resp = Jsons.parseObject(res.body(), WxCpKfMsgSendResp.class);
 		if (resp.getErrcode() != 0) {
-			throw BusinessRuntimeException.getInstance("发送欢迎语等事件响应消息: " + resp.getErrmsg());
+			throw BusinessRuntimeException.getInstance("发送欢迎语等事件响应消息错误: " + resp.getErrmsg());
 		}
 		return resp;
 	}
@@ -962,7 +962,7 @@ public class WxCorpOpsImpl implements WxCorpOps {
 
 		CorpKfServicerResp resp = Jsons.parseObject(res.body(), CorpKfServicerResp.class);
 		if (resp.getErrcode() != 0) {
-			throw BusinessRuntimeException.getInstance("获取微信客服接待人员响应消息: " + resp.getErrmsg());
+			throw BusinessRuntimeException.getInstance("获取微信客服接待人员响应消息错误: " + resp.getErrmsg());
 		}
 		return resp;
 	}
@@ -988,7 +988,7 @@ public class WxCorpOpsImpl implements WxCorpOps {
 
 		CorpKfSessionResp resp = Jsons.parseObject(res.body(), CorpKfSessionResp.class);
 		if (resp.getErrcode() != 0) {
-			throw BusinessRuntimeException.getInstance("移入等待池响应消息: " + resp.getErrmsg());
+			throw BusinessRuntimeException.getInstance("移入等待池响应消息错误: " + resp.getErrmsg());
 		}
 	}
 
@@ -1014,15 +1014,15 @@ public class WxCorpOpsImpl implements WxCorpOps {
 
 		CorpKfSessionResp resp = Jsons.parseObject(res.body(), CorpKfSessionResp.class);
 		if (resp.getErrcode() != 0) {
-			throw BusinessRuntimeException.getInstance("客服接入会话响应消息: " + resp.getErrmsg());
+			throw BusinessRuntimeException.getInstance("客服接入会话响应消息错误: " + resp.getErrmsg());
 		}
 	}
 
 	@Override
-	public void sendSatisfactionMsg() throws Exception {
-		String url = " https://qyapi.weixin.qq.com/cgi-bin/kf/send_msg_on_event?access_token=" + getKfAccessToken(yhlXWxCorpConfig.getCorpId());
+	public void sendSatisfactionMsg(String msgId) throws Exception {
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/kf/send_msg_on_event?access_token=" + getKfAccessToken(yhlXWxCorpConfig.getCorpId());
 		CorpKfSatisfactionMsg corpKfSatisfactionMsg = new CorpKfSatisfactionMsg();
-		corpKfSatisfactionMsg.setCode("satisfaction");
+		corpKfSatisfactionMsg.setCode(msgId);
 		corpKfSatisfactionMsg.setMsgtype("msgtype");
 		corpKfSatisfactionMsg.setMsgmenu(SATISFACTION_CONTENT);
 		HttpResponse<String> res =
@@ -1041,4 +1041,27 @@ public class WxCorpOpsImpl implements WxCorpOps {
 			throw BusinessRuntimeException.getInstance("满意度调查内容错误: " + resp.getErrmsg());
 		}
 	}
+
+	@Override
+	public CorpKfUserInfo getCorpKfUserInfo(String externalUserid) throws Exception {
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/kf/customer/batchget?access_token=" + getKfAccessToken(yhlXWxCorpConfig.getCorpId());
+		JSONObject params = new JSONObject();
+		params.putOpt("external_userid_list", List.of(externalUserid));
+		HttpResponse<String> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.headers(J11HttpC.ReqType.raw_json)
+						.body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(params), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofString());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("客户基础信息: " + res.body());
+		}
+		JSONObject re = Jsons.parseObject(res.body(), JSONObject.class);
+		if (re.getInt("errcode") != 0) {
+			throw BusinessRuntimeException.getInstance("客户基础信息错误: " + re.getStr("errmsg"));
+		}
+		List<CorpKfUserInfo> customerList = re.getJSONArray("customer_list").toList(CorpKfUserInfo.class);
+		return customerList.isEmpty() ? null : customerList.get(0);
+	}
 }

+ 41 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/wxkf/CorpKfMsgController.java

@@ -1,7 +1,14 @@
 package com.cyksj.web.controller.manage.corp.wxkf;
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.corp.kf.CorpKfServicerSessionRecordMapper;
+import com.cyksj.model.entity.CorpKfServicerSessionRecord;
+import com.cyksj.model.kf.CorpKfUserInfo;
 import com.cyksj.service.corp.WxCorpOps;
 import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -18,11 +25,43 @@ import org.springframework.web.bind.annotation.RestController;
 public class CorpKfMsgController {
 	private final WxCorpOps wxCorpOps;
 
+	private final CorpKfServicerSessionRecordMapper corpKfServicerSessionRecordMapper;
+
 	/**
 	 * 发送满意度调查消息
 	 */
 	@PostMapping("/send/satisfaction/msg")
-	public void sendSatisfactionMsg() throws Exception {
-		wxCorpOps.sendSatisfactionMsg();
+	public void sendSatisfactionMsg(String msgId) throws Exception {
+		wxCorpOps.sendSatisfactionMsg(msgId);
+		CorpKfServicerSessionRecord corpKfServicerSessionRecord = corpKfServicerSessionRecordMapper.selectOne(Wrappers.lambdaQuery(CorpKfServicerSessionRecord.class)
+				.eq(CorpKfServicerSessionRecord::getMsgId, msgId)
+				.last("limit 1"));
+		//更新发送满意度字段
+		if (corpKfServicerSessionRecord != null) {
+			corpKfServicerSessionRecord.setSendSatisfaction(true);
+			corpKfServicerSessionRecordMapper.updateById(corpKfServicerSessionRecord);
+		}
+	}
+
+	/**
+	 * 获取客户用户信息
+	 */
+	@GetMapping("/get/user/info")
+	public Result<CorpKfUserInfo> getUserInfo(String externalUserid) throws Exception {
+		CorpKfUserInfo corpKfUserInfo = wxCorpOps.getCorpKfUserInfo(externalUserid);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(corpKfUserInfo);
+	}
+
+	/**
+	 * 查询用户会话
+	 */
+	@GetMapping("/get/session")
+	public Result<CorpKfServicerSessionRecord> getUserSession(String userid, String externalUserid) {
+		CorpKfServicerSessionRecord corpKfServicerSessionRecord = corpKfServicerSessionRecordMapper.selectOne(Wrappers.lambdaQuery(CorpKfServicerSessionRecord.class)
+				.eq(CorpKfServicerSessionRecord::getServicerUserId, userid)
+				.eq(CorpKfServicerSessionRecord::getExternalUserid, externalUserid)
+				.eq(CorpKfServicerSessionRecord::getServiceState, 0)
+				.last("limit 1"));
+		return GatewayResponse.SUCCESS.newBuilder().toResult(corpKfServicerSessionRecord);
 	}
 }