|
|
@@ -2,7 +2,9 @@ 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.io.FileUtil;
|
|
|
+import cn.hutool.core.util.RandomUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import cn.hutool.http.HttpUtil;
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
@@ -18,10 +20,13 @@ import com.cyksj.config.corp.YHLXWxCorpConfig;
|
|
|
import com.cyksj.dto.CorpOauth2UserInfo;
|
|
|
import com.cyksj.mapper.OrderDonMapper;
|
|
|
import com.cyksj.mapper.corp.*;
|
|
|
+import com.cyksj.mapper.corp.kf.CorpKfAccountFollowMapper;
|
|
|
import com.cyksj.mapper.corp.kf.CorpKfAccountMapper;
|
|
|
import com.cyksj.mapper.corp.kf.CorpKfAccountSessionConfigMapper;
|
|
|
+import com.cyksj.mapper.corp.kf.CorpKfWaitingQueueUserMapper;
|
|
|
import com.cyksj.model.dto.WxCorpEncryptDto;
|
|
|
import com.cyksj.model.entity.*;
|
|
|
+import com.cyksj.model.kf.CorpKfServicerResp;
|
|
|
import com.cyksj.model.kf.WxCorpKfMsgSendRequest;
|
|
|
import com.cyksj.model.kf.WxCpKfEventMsg;
|
|
|
import com.cyksj.model.kf.WxCpKfMsgListResp;
|
|
|
@@ -50,6 +55,7 @@ import java.io.File;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.Random;
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
@@ -106,9 +112,15 @@ public class CorpServiceImpl implements CorpService {
|
|
|
@Autowired
|
|
|
private CorpKfAccountMapper corpKfAccountMapper;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private CorpKfAccountFollowMapper corpKfAccountFollowMapper;
|
|
|
+
|
|
|
@Autowired
|
|
|
private CorpKfAccountSessionConfigMapper corpKfAccountSessionConfigMapper;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private CorpKfWaitingQueueUserMapper corpKfWaitingQueueUserMapper;
|
|
|
+
|
|
|
@PostConstruct
|
|
|
private void init() {
|
|
|
corpMessageRouter = new CorpMessageRouter(this)
|
|
|
@@ -521,7 +533,7 @@ public class CorpServiceImpl implements CorpService {
|
|
|
WxCpKfMsgListResp wxCpKfMsgListResp = wxCorpOps.syncMsg(message.getToUserName(), null, message.getToken(), null, openKfId);
|
|
|
List<WxCpKfMsgListResp.WxCpKfMsgItem> msgList = wxCpKfMsgListResp.getMsgList();
|
|
|
//欢迎语
|
|
|
- sendWelcomeMsg(message, msgList);
|
|
|
+ enterSessionEvent(message, msgList);
|
|
|
//消息发送失败事件
|
|
|
//拒收客户消息变更事件
|
|
|
//同步客服聊天记录
|
|
|
@@ -537,44 +549,96 @@ public class CorpServiceImpl implements CorpService {
|
|
|
/**
|
|
|
* 微信客服欢迎语
|
|
|
*/
|
|
|
- public void sendWelcomeMsg(CorpXmlMessage message, List<WxCpKfMsgListResp.WxCpKfMsgItem> msgList) throws Exception {
|
|
|
+ public void enterSessionEvent(CorpXmlMessage message, List<WxCpKfMsgListResp.WxCpKfMsgItem> msgList) throws Exception {
|
|
|
String openKfId = message.getOpenKfId();
|
|
|
List<WxCpKfMsgListResp.WxCpKfMsgItem> enterSessionList = msgList.stream()
|
|
|
.filter((item) -> item.getEvent() != null && item.getEvent().getEventType().equals("enter_session")).collect(Collectors.toList());
|
|
|
+ CorpKfAccount corpKfAccount = corpKfAccountMapper.selectOne(Wrappers.lambdaQuery(CorpKfAccount.class)
|
|
|
+ .eq(CorpKfAccount::getOpenKfId, openKfId)
|
|
|
+ .last("limit 1"));
|
|
|
+ if (corpKfAccount == null) {
|
|
|
+ log.info("客服账号:{}已被删除或不存在", openKfId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //账号会话设置
|
|
|
+ CorpKfAccountSessionConfig corpKfAccountSessionConfig = corpKfAccountSessionConfigMapper.selectOne(Wrappers.lambdaQuery(CorpKfAccountSessionConfig.class)
|
|
|
+ .eq(CorpKfAccountSessionConfig::getOpenKfId, openKfId)
|
|
|
+ .last("limit 1"));
|
|
|
//欢迎语
|
|
|
if (enterSessionList.size() > 0) {
|
|
|
WxCpKfMsgListResp.WxCpKfMsgItem wxCpKfMsgItem = enterSessionList.get(enterSessionList.size() - 1);
|
|
|
WxCpKfEventMsg event = wxCpKfMsgItem.getEvent();
|
|
|
String welcomeCode = event.getWelcomeCode();
|
|
|
- CorpKfAccount corpKfAccount = corpKfAccountMapper.selectOne(Wrappers.lambdaQuery(CorpKfAccount.class)
|
|
|
- .eq(CorpKfAccount::getOpenKfId, openKfId)
|
|
|
- .last("limit 1"));
|
|
|
- if (corpKfAccount == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
- WxCorpKfMsgSendRequest wxCpKfMsgSendRequest = new WxCorpKfMsgSendRequest();
|
|
|
- wxCpKfMsgSendRequest.setMsgType("text");
|
|
|
- wxCpKfMsgSendRequest.setCode(welcomeCode);
|
|
|
- WxCorpKfMsgSendRequest.WxCpKfTextMsg textMsg = new WxCorpKfMsgSendRequest.WxCpKfTextMsg();
|
|
|
- //账号会话设置
|
|
|
- CorpKfAccountSessionConfig corpKfAccountSessionConfig = corpKfAccountSessionConfigMapper.selectOne(Wrappers.lambdaQuery(CorpKfAccountSessionConfig.class)
|
|
|
- .eq(CorpKfAccountSessionConfig::getOpenKfId, openKfId)
|
|
|
- .last("limit 1"));
|
|
|
+ //如果满足发送欢迎语条件(条件为:用户在过去48小时里未收过欢迎语,且未向客服发过消息),会返回该字段。
|
|
|
+ //可用该welcome_code调用发送事件响应消息接口给客户发送欢迎语。
|
|
|
if (corpKfAccountSessionConfig == null) {
|
|
|
log.info("openKfId:{}未设置会话设置", openKfId);
|
|
|
return;
|
|
|
}
|
|
|
- if (StrUtil.isEmpty(corpKfAccountSessionConfig.getWelcomeContent())) {
|
|
|
- log.info("openKfId:{}未设置会话欢迎语设置", openKfId);
|
|
|
- return;
|
|
|
+ if (StrUtil.isNotEmpty(welcomeCode)) {
|
|
|
+ WxCorpKfMsgSendRequest wxCpKfMsgSendRequest = new WxCorpKfMsgSendRequest();
|
|
|
+ wxCpKfMsgSendRequest.setMsgType("text");
|
|
|
+ wxCpKfMsgSendRequest.setCode(welcomeCode);
|
|
|
+ WxCorpKfMsgSendRequest.WxCpKfTextMsg textMsg = new WxCorpKfMsgSendRequest.WxCpKfTextMsg();
|
|
|
+ if (StrUtil.isEmpty(corpKfAccountSessionConfig.getWelcomeContent())) {
|
|
|
+ log.info("openKfId:{}未设置会话欢迎语设置", openKfId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ textMsg.setContent(corpKfAccountSessionConfig.getWelcomeContent());
|
|
|
+ wxCpKfMsgSendRequest.setText(textMsg);
|
|
|
+ wxCpKfMsgSendRequest.setToUser(welcomeCode);
|
|
|
+ wxCpKfMsgSendRequest.setOpenKfid(event.getOpenKfid());
|
|
|
+ wxCorpOps.sendMsgOnEvent(message.getToUserName(), wxCpKfMsgSendRequest);
|
|
|
+ } else {
|
|
|
+ //配置接待人员
|
|
|
+ //是否有空闲人员
|
|
|
+ int hour = DateTime.now().hour(true);
|
|
|
+ corpKfAccountFollowMapper.selectList(Wrappers.lambdaQuery(CorpKfAccountFollow.class)
|
|
|
+ .eq(CorpKfAccountFollow::getOpenKfId, openKfId)
|
|
|
+ .le(CorpKfAccountFollow::getStartTime, hour)
|
|
|
+ .ge(CorpKfAccountFollow::getEndTime, hour));
|
|
|
+ //获取接待人员列表
|
|
|
+ CorpKfServicerResp corpKfServicerResp = wxCorpOps.getKfServicerList(message.getToUserName(), openKfId);
|
|
|
+ List<CorpKfServicerResp.CorpKfServicer> servicerList = corpKfServicerResp.getServicerList();
|
|
|
+ List<CorpKfServicerResp.CorpKfServicer> corpKfServicers = servicerList.stream().filter(servicer -> servicer.getUserid() != null && servicer.getStatus() == 0).collect(Collectors.toList());
|
|
|
+ if (CollUtil.isEmpty(corpKfServicers)) {
|
|
|
+ //非值班 移入等待池并发送非值班提示消息
|
|
|
+ moveWaitingQueue(message.getToUserName(), openKfId, event.getExternalUserId());
|
|
|
+ String noDutyTips = corpKfAccountSessionConfig.getNoDutyTips();
|
|
|
+ if (StrUtil.isNotEmpty(noDutyTips)) {
|
|
|
+ //发送提示
|
|
|
+ sendCorpKfTextTips(message.getToUserName(), event.getExternalUserId(), openKfId, noDutyTips);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //未有可接待的客服 移入等待池并发送进入等待池消息
|
|
|
+ moveWaitingQueue(message.getToUserName(), openKfId, event.getExternalUserId());
|
|
|
+ String queueTips = corpKfAccountSessionConfig.getQueueTips();
|
|
|
+ sendCorpKfTextTips(message.getToUserName(), event.getExternalUserId(), openKfId, queueTips);
|
|
|
}
|
|
|
- textMsg.setContent(corpKfAccountSessionConfig.getWelcomeContent());
|
|
|
- wxCpKfMsgSendRequest.setText(textMsg);
|
|
|
- wxCpKfMsgSendRequest.setToUser(welcomeCode);
|
|
|
- wxCpKfMsgSendRequest.setOpenKfid(event.getOpenKfid());
|
|
|
- wxCorpOps.sendMsgOnEvent(message.getToUserName(), wxCpKfMsgSendRequest);
|
|
|
- } else {
|
|
|
- log.error("企业微信客服 事件消息回调 时间内容为空.");
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送微信客服会话文本消息
|
|
|
+ */
|
|
|
+ public void sendCorpKfTextTips(String corpId, String externalUserid, String openKfId, String content) throws Exception {
|
|
|
+ WxCorpKfMsgSendRequest wxCpKfMsgSendRequest = new WxCorpKfMsgSendRequest();
|
|
|
+ wxCpKfMsgSendRequest.setMsgType("text");
|
|
|
+ wxCpKfMsgSendRequest.setToUser(externalUserid);
|
|
|
+ wxCpKfMsgSendRequest.setOpenKfid(openKfId);
|
|
|
+ WxCorpKfMsgSendRequest.WxCpKfTextMsg textMsg = new WxCorpKfMsgSendRequest.WxCpKfTextMsg();
|
|
|
+ textMsg.setContent(content);
|
|
|
+ wxCpKfMsgSendRequest.setText(textMsg);
|
|
|
+ wxCorpOps.sendMsgOnEvent(corpId, wxCpKfMsgSendRequest);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void moveWaitingQueue(String corpId, String openKfId, String externalUserId) throws Exception {
|
|
|
+ CorpKfWaitingQueueUser corpKfWaitingQueueUser = new CorpKfWaitingQueueUser();
|
|
|
+ corpKfWaitingQueueUser.setOpenKfId(openKfId);
|
|
|
+ corpKfWaitingQueueUser.setExternalUserid(externalUserId);
|
|
|
+ corpKfWaitingQueueUserMapper.insert(corpKfWaitingQueueUser);
|
|
|
+ //移入等待池
|
|
|
+ wxCorpOps.moveWaitingQueue(corpId, openKfId, externalUserId);
|
|
|
+ }
|
|
|
}
|