|
@@ -0,0 +1,493 @@
|
|
|
+package com.zanxiang.game.module.manage.websocket;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.zanxiang.erp.base.pojo.TokenInfo;
|
|
|
+import com.zanxiang.erp.security.util.SecurityUtil;
|
|
|
+import com.zanxiang.game.module.manage.constant.RedisKeyConstant;
|
|
|
+import com.zanxiang.game.module.manage.enums.KfOperateEnum;
|
|
|
+import com.zanxiang.game.module.manage.enums.KfRoomMsgOwnerEnum;
|
|
|
+import com.zanxiang.game.module.manage.enums.KfRoomMsgTypeEnum;
|
|
|
+import com.zanxiang.game.module.manage.enums.KfWebSocketMsgEnum;
|
|
|
+import com.zanxiang.game.module.manage.pojo.dto.KfWebSocketMsgDTO;
|
|
|
+import com.zanxiang.game.module.manage.pojo.params.KfWebSocketMsgParam;
|
|
|
+import com.zanxiang.game.module.manage.service.IKfQuickReplyService;
|
|
|
+import com.zanxiang.game.module.manage.service.IKfRoomMsgService;
|
|
|
+import com.zanxiang.game.module.manage.service.IKfRoomService;
|
|
|
+import com.zanxiang.game.module.manage.service.IKfSessionUserService;
|
|
|
+import com.zanxiang.game.module.manage.service.api.KfWxApiService;
|
|
|
+import com.zanxiang.game.module.manage.utils.FileUtil;
|
|
|
+import com.zanxiang.game.module.mybatis.entity.KfRoom;
|
|
|
+import com.zanxiang.game.module.mybatis.entity.KfRoomMsg;
|
|
|
+import com.zanxiang.game.module.mybatis.entity.KfSessionUser;
|
|
|
+import com.zanxiang.module.redis.service.IDistributedLockComponent;
|
|
|
+import com.zanxiang.module.util.JsonUtil;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.logging.log4j.util.Strings;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.context.annotation.Lazy;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.web.socket.*;
|
|
|
+import reactor.util.function.Tuple2;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author : lingfeng
|
|
|
+ * @time : 2024-02-23
|
|
|
+ * @description : 客服消息Websocket处理器
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Lazy(value = false)
|
|
|
+@Component
|
|
|
+public class KfMsgWebsocketHandler implements WebSocketHandler {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private KfMsgWebSocketSessionRegistry kfMsgWebSocketSessionRegistry;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IKfRoomService kfRoomService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IKfSessionUserService kfSessionUserService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IKfRoomMsgService kfRoomMsgService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IDistributedLockComponent distributedLockComponent;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private KfWxApiService wxApiService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IKfQuickReplyService kfQuickReplyService;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * websocket连接建立成功
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void afterConnectionEstablished(WebSocketSession session) throws Exception {
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 收到消息
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
|
|
|
+ String msgStr = message.getPayload().toString();
|
|
|
+ //消息解析
|
|
|
+ KfWebSocketMsgParam param = JsonUtil.toObj(msgStr, KfWebSocketMsgParam.class);
|
|
|
+ //消息类型
|
|
|
+ KfWebSocketMsgEnum webSocketMsgType = param.getWebSocketMsgType();
|
|
|
+ //游戏id
|
|
|
+ Long gameId = param.getGameId();
|
|
|
+ //参数验证不通过, 直接结束
|
|
|
+ if (!this.paramCheck(session, webSocketMsgType, param.getToken(), gameId)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //处理不同类型的消息
|
|
|
+ switch (webSocketMsgType) {
|
|
|
+ case WEBSOCKET_MSG_KF_HAND_SHAKE:
|
|
|
+ kfHandShake(session, webSocketMsgType);
|
|
|
+ break;
|
|
|
+ case WEBSOCKET_MSG_KF_CREATE_CONNECT:
|
|
|
+ kfCreateConnect(session, webSocketMsgType, gameId);
|
|
|
+ break;
|
|
|
+ case WEBSOCKET_MSG_USER_CONNECT_JOIN:
|
|
|
+ userConnectJoin(session, param);
|
|
|
+ break;
|
|
|
+ case WEBSOCKET_MSG_ROOM_HISTORY:
|
|
|
+ msgRoomHistory(session, param);
|
|
|
+ break;
|
|
|
+ case WEBSOCKET_MSG_KF_SEND:
|
|
|
+ kfSendMsg(session, param);
|
|
|
+ break;
|
|
|
+ case WEBSOCKET_MSG_FINISH_ROOM_LIST:
|
|
|
+ finishRoomList(session, param);
|
|
|
+ break;
|
|
|
+ case WEBSOCKET_MSG_FINISH_SESSION:
|
|
|
+ kfFinishSession(session, webSocketMsgType, gameId, param.getRoomId());
|
|
|
+ break;
|
|
|
+ case WEBSOCKET_MSG_GET_USER:
|
|
|
+ getUser(session, param);
|
|
|
+ break;
|
|
|
+ case WEBSOCKET_MSG_GET_ROLE_LIST:
|
|
|
+ getRoleList(session, param);
|
|
|
+ break;
|
|
|
+ case WEBSOCKET_MSG_GET_ORDER_LIST:
|
|
|
+ getOrderList(session, param);
|
|
|
+ break;
|
|
|
+ case WEBSOCKET_MSG_QUICK_REPLY:
|
|
|
+ quickReply(session, param);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(webSocketMsgType, "参数错误, 未知的消息类型"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 消息传输发生错误
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 连接被关闭
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
|
|
|
+ //关闭连接
|
|
|
+ session.close();
|
|
|
+ //判断会话是否保存
|
|
|
+ Object kfUserIdObject = session.getAttributes().get("kfUserId");
|
|
|
+ if (kfUserIdObject == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //从session中获取客服id
|
|
|
+ Long kfUserId = Long.valueOf(kfUserIdObject.toString());
|
|
|
+ //移除连接
|
|
|
+ kfMsgWebSocketSessionRegistry.removeSession(kfUserId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean supportsPartialMessages() {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void quickReply(WebSocketSession session, KfWebSocketMsgParam param) {
|
|
|
+ KfWebSocketMsgParam.QuickReplyBean quickReplyBean = param.getQuickReplyBean();
|
|
|
+ if (quickReplyBean == null) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
|
|
|
+ "快捷回复参数错误, 参数对象不可为空, param : " + JsonUtil.toString(param)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //查询
|
|
|
+ if (Objects.equals(quickReplyBean.getKfOperateEnum(), KfOperateEnum.KF_OPERATE_SELECT)) {
|
|
|
+ Tuple2<KfWebSocketMsgDTO.PageBean, List<KfWebSocketMsgDTO.QuickReplyBean>> tuple2 = kfQuickReplyService
|
|
|
+ .quickReplyList(param.getPage());
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(param.getWebSocketMsgType())
|
|
|
+ .page(tuple2.getT1())
|
|
|
+ .quickReplyList(tuple2.getT2())
|
|
|
+ .build());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //处理不同类型的消息
|
|
|
+ Boolean result = null;
|
|
|
+ switch (quickReplyBean.getKfOperateEnum()) {
|
|
|
+ case KF_OPERATE_ADD:
|
|
|
+ result = kfQuickReplyService.quickReplyAdd(param.getQuickReplyBean());
|
|
|
+ break;
|
|
|
+ case KF_OPERATE_DELETE:
|
|
|
+ result = kfQuickReplyService.quickReplyDelete(param.getQuickReplyBean());
|
|
|
+ break;
|
|
|
+ case KF_OPERATE_UPDATE:
|
|
|
+ result = kfQuickReplyService.quickReplyUpdate(param.getQuickReplyBean());
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ if (result != null && result) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.ok(param.getWebSocketMsgType()));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
|
|
|
+ "快捷回复操作失败, param : " + JsonUtil.toString(param)));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void getUser(WebSocketSession session, KfWebSocketMsgParam param) {
|
|
|
+ if (Strings.isBlank(param.getOpenId())) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
|
|
|
+ "获取玩家信息参数错误, openId不可为空, param : " + JsonUtil.toString(param)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ KfWebSocketMsgDTO.UserBean userBean = kfRoomService.getUserBean(param.getOpenId());
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(param.getWebSocketMsgType())
|
|
|
+ .kfUserId(SecurityUtil.getUserId())
|
|
|
+ .user(userBean)
|
|
|
+ .build());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void getRoleList(WebSocketSession session, KfWebSocketMsgParam param) {
|
|
|
+ if (Strings.isBlank(param.getOpenId())) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
|
|
|
+ "获取玩家角色列表参数错误, openId不可为空, param : " + JsonUtil.toString(param)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Tuple2<KfWebSocketMsgDTO.PageBean, List<KfWebSocketMsgDTO.GameRoleBean>> tuple2 = kfRoomService
|
|
|
+ .getRoleBeanList(param.getOpenId(), param.getPage());
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(param.getWebSocketMsgType())
|
|
|
+ .kfUserId(SecurityUtil.getUserId())
|
|
|
+ .page(tuple2.getT1())
|
|
|
+ .roleList(tuple2.getT2())
|
|
|
+ .build());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void getOrderList(WebSocketSession session, KfWebSocketMsgParam param) {
|
|
|
+ if (Strings.isBlank(param.getOpenId())) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
|
|
|
+ "获取玩家订单列表参数错误, openId不可为空, param : " + JsonUtil.toString(param)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Tuple2<KfWebSocketMsgDTO.PageBean, List<KfWebSocketMsgDTO.OrderBean>> tuple2 = kfRoomService
|
|
|
+ .getOrderBeanList(param.getOpenId(), param.getPage());
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(param.getWebSocketMsgType())
|
|
|
+ .kfUserId(SecurityUtil.getUserId())
|
|
|
+ .page(tuple2.getT1())
|
|
|
+ .orderList(tuple2.getT2())
|
|
|
+ .build());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void kfSendMsg(WebSocketSession session, KfWebSocketMsgParam param) {
|
|
|
+ if (param.getRoomId() == null) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), "参数错误,roomId为空"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ KfRoom kfRoom = kfRoomService.getById(param.getRoomId());
|
|
|
+ if (kfRoom == null) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), "参数错误,房间信息不存在"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ KfWebSocketMsgParam.MsgContentBean msgContent = param.getMsgContent();
|
|
|
+ if (msgContent == null) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), "参数错误,消息内容不可为空"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //发送消息
|
|
|
+ Map<String, Object> msgParamMap = new HashMap<>(3);
|
|
|
+ msgParamMap.put("touser", kfRoom.getOpenId());
|
|
|
+ //文本
|
|
|
+ if (Objects.equals(msgContent.getMsgType(), KfRoomMsgTypeEnum.KF_MSG_TYPE_TEXT)) {
|
|
|
+ Map<String, Object> textMap = new HashMap<>(1);
|
|
|
+ textMap.put("content", msgContent.getText());
|
|
|
+ msgParamMap.put("msgtype", KfRoomMsgTypeEnum.KF_MSG_TYPE_TEXT.getValue());
|
|
|
+ msgParamMap.put(KfRoomMsgTypeEnum.KF_MSG_TYPE_TEXT.getValue(), textMap);
|
|
|
+ }
|
|
|
+ //图片
|
|
|
+ if (Objects.equals(msgContent.getMsgType(), KfRoomMsgTypeEnum.KF_MSG_TYPE_IMAGE)) {
|
|
|
+ Map<String, Object> imageMap = new HashMap<>(1);
|
|
|
+ //图片上传到腾讯, 转成 media_id
|
|
|
+ Tuple2<Long, String> tuple2 = wxApiService.mediaUpload(param.getGameId(),
|
|
|
+ FileUtil.urlToMultipartFile(msgContent.getImage()));
|
|
|
+ //素材上传失败, 通知返回通知客户端
|
|
|
+ if (tuple2.getT1() != 0) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), tuple2.getT2()));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ imageMap.put("media_id", tuple2.getT2());
|
|
|
+ msgParamMap.put("msgtype", KfRoomMsgTypeEnum.KF_MSG_TYPE_IMAGE.getValue());
|
|
|
+ msgParamMap.put(KfRoomMsgTypeEnum.KF_MSG_TYPE_IMAGE.getValue(), imageMap);
|
|
|
+ }
|
|
|
+ //调腾讯接口发送消息
|
|
|
+ Tuple2<Long, String> tuple2 = wxApiService.sendCustomMessageApi(param.getGameId(), msgParamMap);
|
|
|
+ //发送失败, 通知返回通知客户端
|
|
|
+ if (tuple2.getT1() != 0) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), tuple2.getT2()));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //发送成功, 消息入库
|
|
|
+ kfRoomMsgService.sendMsgSave(param.getGameId(), kfRoom, msgContent);
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.ok(param.getWebSocketMsgType()));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void kfFinishSession(WebSocketSession session, KfWebSocketMsgEnum webSocketMsgType, Long gameId, Long roomId) {
|
|
|
+ //房间在线状态更新
|
|
|
+ kfRoomService.update(new LambdaUpdateWrapper<KfRoom>()
|
|
|
+ .set(KfRoom::getOnline, Boolean.FALSE)
|
|
|
+ .set(KfRoom::getUpdateTime, LocalDateTime.now())
|
|
|
+ .eq(KfRoom::getId, roomId));
|
|
|
+ //推送完整的已链接房间列表
|
|
|
+ List<KfWebSocketMsgDTO.RoomBean> onlineRoomList = kfRoomService.getOnlineRoomList(gameId);
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(webSocketMsgType)
|
|
|
+ .kfUserId(SecurityUtil.getUserId())
|
|
|
+ .gameId(gameId)
|
|
|
+ .roomList(onlineRoomList)
|
|
|
+ .build());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void finishRoomList(WebSocketSession session, KfWebSocketMsgParam param) {
|
|
|
+ Tuple2<KfWebSocketMsgDTO.PageBean, List<KfWebSocketMsgDTO.RoomBean>> tuple2 = kfRoomService
|
|
|
+ .getFinishRoomList(param.getGameId(), param.getPage());
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(param.getWebSocketMsgType())
|
|
|
+ .kfUserId(SecurityUtil.getUserId())
|
|
|
+ .gameId(param.getGameId())
|
|
|
+ .page(tuple2.getT1())
|
|
|
+ .roomList(tuple2.getT2())
|
|
|
+ .build());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void msgRoomHistory(WebSocketSession session, KfWebSocketMsgParam param) {
|
|
|
+ if (param.getRoomId() == null) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
|
|
|
+ "获取房间历史消息参数错误, roomId不可为空, param : " + JsonUtil.toString(param)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //分页获取房间消息列表
|
|
|
+ Tuple2<KfWebSocketMsgDTO.PageBean, List<KfWebSocketMsgDTO.RoomMsgBean>> tuple2 = kfRoomMsgService
|
|
|
+ .msgRoomHistory(param.getRoomId(), param.getPage());
|
|
|
+ //房间信息设置
|
|
|
+ List<KfWebSocketMsgDTO.RoomBean> roomList = kfRoomService.getRoomByRoomId(param.getRoomId());
|
|
|
+ //游戏列表
|
|
|
+ List<KfWebSocketMsgDTO.GameBean> gameList = kfRoomService.getKfGameByGameId(param.getGameId());
|
|
|
+ //发送消息
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(param.getWebSocketMsgType())
|
|
|
+ .kfUserId(SecurityUtil.getUserId())
|
|
|
+ .page(tuple2.getT1())
|
|
|
+ .gameId(param.getGameId())
|
|
|
+ .roomId(param.getRoomId())
|
|
|
+ .gameList(gameList)
|
|
|
+ .roomList(roomList)
|
|
|
+ .roomMsgList(tuple2.getT2())
|
|
|
+ .build());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void userConnectJoin(WebSocketSession session, KfWebSocketMsgParam param) {
|
|
|
+ if (Strings.isBlank(param.getOpenId())) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
|
|
|
+ "接入玩家参数错误, openId不可为空, param : " + JsonUtil.toString(param)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //触发玩家接入线程锁
|
|
|
+ if (!distributedLockComponent.doLock(RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + param.getOpenId(),
|
|
|
+ 0L, 1L, TimeUnit.MINUTES)) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
|
|
|
+ "玩家已被其他客服接入, param : " + JsonUtil.toString(param)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //玩家更新
|
|
|
+ kfSessionUserService.update(new LambdaUpdateWrapper<KfSessionUser>()
|
|
|
+ .set(KfSessionUser::getIsWait, Boolean.FALSE)
|
|
|
+ .set(KfSessionUser::getUpdateTime, LocalDateTime.now())
|
|
|
+ .eq(KfSessionUser::getOpenId, param.getOpenId())
|
|
|
+ );
|
|
|
+ //玩家信息
|
|
|
+ KfSessionUser kfSessionUser = kfSessionUserService.getById(param.getOpenId());
|
|
|
+ //房间更新
|
|
|
+ Long roomId = kfRoomService.userJoinRoom(param.getOpenId(), param.getGameId());
|
|
|
+ //玩家未读消息更新到房间
|
|
|
+ kfRoomMsgService.update(new LambdaUpdateWrapper<KfRoomMsg>()
|
|
|
+ .set(KfRoomMsg::getRoomId, roomId)
|
|
|
+ .set(KfRoomMsg::getUserId, kfSessionUser == null ? null : kfSessionUser.getUserId())
|
|
|
+ .set(KfRoomMsg::getKfUserId, SecurityUtil.getUserId())
|
|
|
+ .set(KfRoomMsg::getUpdateTime, LocalDateTime.now())
|
|
|
+ .eq(KfRoomMsg::getOpenId, param.getOpenId())
|
|
|
+ .eq(KfRoomMsg::getGameId, param.getGameId())
|
|
|
+ .ne(KfRoomMsg::getMsgOwner, KfRoomMsgOwnerEnum.KF_MSG_OWNER_KF.getValue())
|
|
|
+ .eq(KfRoomMsg::getReadStatus, Boolean.FALSE));
|
|
|
+ //发送消息, 给该客服返回完整的已接入房间列表
|
|
|
+ List<KfWebSocketMsgDTO.RoomBean> roomList = kfRoomService.getOnlineRoomList(param.getGameId());
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(param.getWebSocketMsgType())
|
|
|
+ .kfUserId(SecurityUtil.getUserId())
|
|
|
+ .gameId(param.getGameId())
|
|
|
+ .roomList(roomList)
|
|
|
+ .build());
|
|
|
+ //发送消息, 给所有在线客服推送完整待接入列表
|
|
|
+ List<KfWebSocketMsgDTO.WaitUserBean> waitUserList = kfSessionUserService.getWaitUserList(param.getGameId());
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(param.getWebSocketMsgType())
|
|
|
+ .gameId(param.getGameId())
|
|
|
+ .waitUserList(waitUserList)
|
|
|
+ .build());
|
|
|
+ //释放锁
|
|
|
+ distributedLockComponent.unlock(RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + param.getOpenId());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void kfCreateConnect(WebSocketSession session, KfWebSocketMsgEnum msgTypeEnum, Long gameId) {
|
|
|
+ //获取待接入列表
|
|
|
+ List<KfWebSocketMsgDTO.WaitUserBean> waitUserList = kfSessionUserService.getWaitUserList(gameId);
|
|
|
+ //获取已接入房间列表
|
|
|
+ List<KfWebSocketMsgDTO.RoomBean> roomList = kfRoomService.getOnlineRoomList(gameId);
|
|
|
+ //发送消息
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(msgTypeEnum)
|
|
|
+ .kfUserId(SecurityUtil.getUserId())
|
|
|
+ .gameId(gameId)
|
|
|
+ .waitUserList(waitUserList)
|
|
|
+ .roomList(roomList)
|
|
|
+ .build());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void kfHandShake(WebSocketSession session, KfWebSocketMsgEnum msgTypeEnum) {
|
|
|
+ //获取游戏列表
|
|
|
+ List<KfWebSocketMsgDTO.GameBean> gameList = kfRoomService.getKfGameList();
|
|
|
+ //发送消息
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.builder()
|
|
|
+ .webSocketMsgType(msgTypeEnum)
|
|
|
+ .kfUserId(SecurityUtil.getUserId())
|
|
|
+ .gameList(gameList)
|
|
|
+ .build());
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean paramCheck(WebSocketSession session, KfWebSocketMsgEnum webSocketMsgType, String token, Long gameId) {
|
|
|
+ //gameId参数为空
|
|
|
+ if (gameId == null) {
|
|
|
+ //心跳和握手消息, 不需要携带gameId
|
|
|
+ if (!Objects.equals(KfWebSocketMsgEnum.WEBSOCKET_MSG_KF_HAND_SHAKE, webSocketMsgType)
|
|
|
+ && !Objects.equals(KfWebSocketMsgEnum.WEBSOCKET_MSG_QUICK_REPLY, webSocketMsgType)) {
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(webSocketMsgType, "参数错误, gameId为空"));
|
|
|
+ return Boolean.FALSE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //令牌为空
|
|
|
+ if (Strings.isBlank(token)) {
|
|
|
+ log.error("非法参数, token令牌和客服id不可为空");
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(webSocketMsgType, "非法参数, token令牌和kfUserId不可为空"));
|
|
|
+ return Boolean.FALSE;
|
|
|
+ }
|
|
|
+ //令牌验证
|
|
|
+ TokenInfo tokenInfo;
|
|
|
+ try {
|
|
|
+ tokenInfo = SecurityUtil.parseToken(token);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("token验证异常, token : {}, e : {}", token, e.getMessage());
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(webSocketMsgType, "token验证异常, " + e.getMessage()));
|
|
|
+ return Boolean.FALSE;
|
|
|
+ }
|
|
|
+ if (tokenInfo == null) {
|
|
|
+ log.error("参数错误, 令牌验证不通过, token : {}", token);
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(webSocketMsgType, "参数错误, 令牌验证不通过"));
|
|
|
+ return Boolean.FALSE;
|
|
|
+ }
|
|
|
+ //将token设置到当前线程
|
|
|
+ try {
|
|
|
+ SecurityUtil.fillToken(token);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("token刷新到本地线程失败, token : {}, e : {}", token, e.getMessage());
|
|
|
+ this.sendMessage(session, KfWebSocketMsgDTO.fail(webSocketMsgType, "token刷新到本地线程失败"));
|
|
|
+ return Boolean.FALSE;
|
|
|
+ }
|
|
|
+ //添加会话
|
|
|
+ WebSocketSession webSocketSession = kfMsgWebSocketSessionRegistry.getSession(SecurityUtil.getUserId());
|
|
|
+ if (webSocketSession == null) {
|
|
|
+ session.getAttributes().put("kfUserId", SecurityUtil.getUserId());
|
|
|
+ kfMsgWebSocketSessionRegistry.addSession(SecurityUtil.getUserId(), session);
|
|
|
+ }
|
|
|
+ //返回验证通过
|
|
|
+ return Boolean.TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * session直接发送消息
|
|
|
+ *
|
|
|
+ * @param session : 会话对象
|
|
|
+ */
|
|
|
+ private void sendMessage(WebSocketSession session, KfWebSocketMsgDTO kfWebSocketMsgDTO) {
|
|
|
+ try {
|
|
|
+ session.sendMessage(new TextMessage(JsonUtil.toString(kfWebSocketMsgDTO)));
|
|
|
+ } catch (IOException ignored) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|