Commit cdce65e4 by zhangxingmin

push

parent 78494475
...@@ -21,13 +21,12 @@ import com.yd.communication.feign.request.*; ...@@ -21,13 +21,12 @@ import com.yd.communication.feign.request.*;
import com.yd.communication.feign.request.http.GenerateTokenRequest; import com.yd.communication.feign.request.http.GenerateTokenRequest;
import com.yd.communication.feign.response.*; import com.yd.communication.feign.response.*;
import com.yd.communication.feign.response.http.GenerateTokenResponse; import com.yd.communication.feign.response.http.GenerateTokenResponse;
import com.yd.communication.feign.response.http.QuerySfpUserResponse;
import com.yd.communication.service.model.CoSession; import com.yd.communication.service.model.CoSession;
import com.yd.communication.service.service.ICoOperationLogService; import com.yd.communication.service.service.ICoOperationLogService;
import com.yd.communication.service.service.ICoSessionService; import com.yd.communication.service.service.ICoSessionService;
import com.yd.communication.service.service.IRecordingTaskService; import com.yd.communication.service.service.IRecordingTaskService;
import com.yd.communication.service.utils.CffpTokenUtil;
import com.yd.communication.service.utils.RandomUtil; import com.yd.communication.service.utils.RandomUtil;
import com.yd.communication.service.utils.SfpTokenUtil;
import com.yd.oss.feign.client.ApiOssFeignClient; import com.yd.oss.feign.client.ApiOssFeignClient;
import com.yd.oss.feign.request.ApiUploadFileRequest; import com.yd.oss.feign.request.ApiUploadFileRequest;
import com.yd.oss.feign.response.ApiUploadResponse; import com.yd.oss.feign.response.ApiUploadResponse;
...@@ -35,6 +34,7 @@ import lombok.extern.slf4j.Slf4j; ...@@ -35,6 +34,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
...@@ -43,11 +43,12 @@ import org.springframework.stereotype.Service; ...@@ -43,11 +43,12 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
@Slf4j @Slf4j
...@@ -75,19 +76,71 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -75,19 +76,71 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
@Resource @Resource
private RestTemplate restTemplate; private RestTemplate restTemplate;
@Value("${sfp.api.base-url:https://mdev.anjibao.cn/sfpApi}") @Resource
private String sfpApiBaseUrl; private Environment env; // 注入 Environment 用于获取环境配置
/**
* 根据当前环境动态获取 SFP API 基础地址
*/
private String getSfpApiBaseUrl() {
String activeProfile = env.getProperty("spring.profiles.active", "dev");
log.info("当前环境: {}, 获取 SFP API 地址", activeProfile);
if ("prod".equalsIgnoreCase(activeProfile) || "production".equalsIgnoreCase(activeProfile)) {
// 生产环境
return "https://hoservice.ydhomeoffice.cn/hoserviceApi";
} else {
// 测试/开发环境
return "https://mdev.anjibao.cn/sfpApi";
}
}
/**
* 远程调用 /user/parse/token 接口解析 Token,获取用户信息
* @param authorization 请求头中的原始 X-Authorization 值(含前缀)
* @return 用户信息对象
*/
private QuerySfpUserResponse parseTokenRemotely(String authorization) {
if (StringUtils.isBlank(authorization)) {
throw new BusinessException("Token 不能为空");
}
// 直接传递原始 authorization,远程接口内部自行剥离前缀
String token = authorization;
String url = getSfpApiBaseUrl() + "/user/parse/token";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
Map<String, String> requestBody = new HashMap<>();
requestBody.put("token", token);
HttpEntity<Map<String, String>> entity = new HttpEntity<>(requestBody, headers);
log.info("【远程解析Token】url={}, token前50字符={}", url, token.substring(0, Math.min(50, token.length())));
try {
ResponseEntity<JsonResult> responseEntity = restTemplate.postForEntity(url, entity, JsonResult.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
JsonResult body = responseEntity.getBody();
if (body != null && body.isSuccess()) {
Object data = body.getData();
if (data != null) {
QuerySfpUserResponse userInfo = JSONObject.parseObject(JSONObject.toJSONString(data), QuerySfpUserResponse.class);
if (userInfo.getId() == null) {
throw new BusinessException("远程解析Token返回的用户ID为空");
}
log.info("【远程解析Token】成功,userId={}", userInfo.getId());
return userInfo;
}
}
}
log.error("【远程解析Token】失败,response={}", responseEntity);
throw new BusinessException("远程解析Token失败,请重新登录");
} catch (Exception e) {
log.error("【远程解析Token】异常", e);
throw new BusinessException("解析Token异常:" + e.getMessage());
}
}
/** /**
* 客户创建会话 * 客户创建会话
* @param scope
* @param resourceType
* @param resourceId
* @param resourceInit
* @param ownerId
* @param ownerType
* @param userId
* @return
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public CoSession createSession(String scope, String resourceType, String resourceId, public CoSession createSession(String scope, String resourceType, String resourceId,
...@@ -130,37 +183,29 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -130,37 +183,29 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
// 获取 Token(调用 /user/generate/token) // 获取 Token(调用 /user/generate/token)
String token = null; String token = null;
GenerateTokenResponse tokenResp =null; GenerateTokenResponse tokenResp = null;
try { try {
// 构建请求体
GenerateTokenRequest tokenRequest = new GenerateTokenRequest(); GenerateTokenRequest tokenRequest = new GenerateTokenRequest();
// 注意:userId 是 String,转为 Long。若 userId 可能为空,需做判空处理
if (StringUtils.isNotBlank(userId)) { if (StringUtils.isNotBlank(userId)) {
tokenRequest.setSfpUserId(Long.valueOf(userId)); tokenRequest.setSfpUserId(Long.valueOf(userId));
} else { } else {
// 如果 userId 为空,可以尝试用 ownerId 或抛出业务异常,根据业务定
throw new BusinessException("userId 不能为空,无法生成 Token"); throw new BusinessException("userId 不能为空,无法生成 Token");
} }
// 发起 POST 请求 String url = getSfpApiBaseUrl() + "/user/generate/token";
String url = sfpApiBaseUrl + "/user/generate/token";
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON); headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<GenerateTokenRequest> entity = new HttpEntity<>(tokenRequest, headers); HttpEntity<GenerateTokenRequest> entity = new HttpEntity<>(tokenRequest, headers);
log.info("【Token生成】sfpApiBaseUrl = {}", sfpApiBaseUrl); log.info("【Token生成】完整URL = {}", url);
log.info("【Token生成】完整URL = {}", sfpApiBaseUrl + "/user/generate/token"); log.info("【Token生成】请求体 = {}", JSONObject.toJSONString(tokenRequest));
log.info("【Token生成】请求体GenerateTokenRequest = {}", JSONObject.toJSONString(tokenRequest));
log.info("【Token生成】请求体entity = {}", JSONObject.toJSONString(entity));
ResponseEntity<JsonResult> responseEntity = restTemplate.postForEntity(url, entity, JsonResult.class); ResponseEntity<JsonResult> responseEntity = restTemplate.postForEntity(url, entity, JsonResult.class);
log.info("【Token生成】返回体responseEntity = {}", JSONObject.toJSONString(responseEntity)); log.info("【Token生成】返回体 = {}", JSONObject.toJSONString(responseEntity));
if (responseEntity.getStatusCode().is2xxSuccessful()) { if (responseEntity.getStatusCode().is2xxSuccessful()) {
JsonResult body = responseEntity.getBody(); JsonResult body = responseEntity.getBody();
if (body != null && body.isSuccess()) { if (body != null && body.isSuccess()) {
// 假设 body.getData() 返回的是 LinkedHashMap,需要转为 GenerateTokenResponse
// 或者直接使用 fastjson 转换
Object data = body.getData(); Object data = body.getData();
if (data != null) { if (data != null) {
tokenResp = JSONObject.parseObject(JSONObject.toJSONString(data), GenerateTokenResponse.class); tokenResp = JSONObject.parseObject(JSONObject.toJSONString(data), GenerateTokenResponse.class);
...@@ -186,7 +231,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -186,7 +231,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
roomRedisInfoDTO.setName(tokenResp.getName()); roomRedisInfoDTO.setName(tokenResp.getName());
roomRedisInfoDTO.setMobile(tokenResp.getMobile()); roomRedisInfoDTO.setMobile(tokenResp.getMobile());
} }
roomRedisInfoDTO.setToken(token); // 设置 token roomRedisInfoDTO.setToken(token);
roomRedisInfoDTO.setUserId(userId); roomRedisInfoDTO.setUserId(userId);
roomRedisInfoDTO.setControlHolderType(session.getControlHolderType()); roomRedisInfoDTO.setControlHolderType(session.getControlHolderType());
roomRedisInfoDTO.setControlHolderId(session.getControlHolderId()); roomRedisInfoDTO.setControlHolderId(session.getControlHolderId());
...@@ -222,9 +267,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -222,9 +267,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
} }
/** /**
* 创建会话 * 创建会话(对外接口)
* @param request
* @return
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
...@@ -246,26 +289,26 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -246,26 +289,26 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
return Result.success(); return Result.success();
} }
// 2. 构建房间链接(从配置读取) // 2. 构建房间链接
String roomLink = roomBaseUrl + "&roomId=" + session.getRoomId() + "&pwd=" + session.getRoomPwd(); String roomLink = roomBaseUrl + "&roomId=" + session.getRoomId() + "&pwd=" + session.getRoomPwd();
log.info("【创建会话】生成房间链接: {}", roomLink); log.info("【创建会话】生成房间链接: {}", roomLink);
// 3. 生成二维码图片字节数组(PNG格式) // 3. 生成二维码图片字节数组
byte[] qrCodeBytes = QRCodeUtils.generateQRCode(roomLink, 300, 300); byte[] qrCodeBytes = QRCodeUtils.generateQRCode(roomLink, 300, 300);
// 4. 将字节数组转换为 MultipartFile // 4. 将字节数组转换为 MultipartFile
String fileName = session.getCoSessionBizId() + ".png"; String fileName = session.getCoSessionBizId() + ".png";
MultipartFile multipartFile = new ByteArrayMultipartFile( MultipartFile multipartFile = new ByteArrayMultipartFile(
qrCodeBytes, // 图片字节数组 qrCodeBytes,
"file", // 字段名,与 Feign @RequestPart("file") 匹配 "file",
fileName, // 原始文件名 fileName,
"image/png" // 内容类型 "image/png"
); );
// 5. 构建 OSS 上传请求参数 // 5. 构建 OSS 上传请求参数
ApiUploadFileRequest ossRequest = new ApiUploadFileRequest(); ApiUploadFileRequest ossRequest = new ApiUploadFileRequest();
ossRequest.setObjectBizId(session.getCoSessionBizId()); // 必填,使用会话业务ID ossRequest.setObjectBizId(session.getCoSessionBizId());
ossRequest.setObjectType("co_session_qr"); // 自定义对象类型 ossRequest.setObjectType("co_session_qr");
ossRequest.setObjectName("协同会话二维码"); ossRequest.setObjectName("协同会话二维码");
ossRequest.setProjectBizId(""); ossRequest.setProjectBizId("");
ossRequest.setTenantBizId(""); ossRequest.setTenantBizId("");
...@@ -278,24 +321,23 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -278,24 +321,23 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
throw new BusinessException("二维码上传失败:" + (uploadResult != null ? uploadResult.getMsg() : "未知错误")); throw new BusinessException("二维码上传失败:" + (uploadResult != null ? uploadResult.getMsg() : "未知错误"));
} }
// 7. 获取文件访问 URL(假设 ApiUploadResponse 包含 url 字段) // 7. 获取文件访问 URL
ApiUploadResponse uploadData = uploadResult.getData(); ApiUploadResponse uploadData = uploadResult.getData();
String roomQrCodeUrl = uploadData.getUrl(); // 若字段名为 fileUrl 则对应调整 String roomQrCodeUrl = uploadData.getUrl();
log.info("【创建会话】OSS上传成功,文件URL: {}", roomQrCodeUrl); log.info("【创建会话】OSS上传成功,文件URL: {}", roomQrCodeUrl);
//8. 更新会话信息表数据 // 8. 更新会话信息
session.setRoomQrCode(roomQrCodeUrl); session.setRoomQrCode(roomQrCodeUrl);
session.setRoomLink(roomLink); session.setRoomLink(roomLink);
iCoSessionService.saveOrUpdate(session); iCoSessionService.saveOrUpdate(session);
//设置房间链接失效时间(用于扫码和链接直接访问,加载页面后调用校验接口判断是否失效) // 设置房间链接失效时间(用于扫码和链接直接访问)
//设置房间链接失效时间(用于扫码和链接直接访问)
redisUtil.setCacheObject(RedisEnum.ROOM_LINK.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd(), redisUtil.setCacheObject(RedisEnum.ROOM_LINK.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd(),
session.getRoomLink(), session.getRoomLink(),
RedisEnum.ROOM_LINK.getTimeout(), RedisEnum.ROOM_LINK.getTimeout(),
RedisEnum.ROOM_LINK.getTimeUnit()); RedisEnum.ROOM_LINK.getTimeUnit());
// 计算链接失效时间点(当前时间 + 缓存过期时长) // 计算链接失效时间点
long expireMillis = RedisEnum.ROOM_LINK.getTimeUnit().toMillis(RedisEnum.ROOM_LINK.getTimeout()); long expireMillis = RedisEnum.ROOM_LINK.getTimeUnit().toMillis(RedisEnum.ROOM_LINK.getTimeout());
Date expirationDate = new Date(System.currentTimeMillis() + expireMillis); Date expirationDate = new Date(System.currentTimeMillis() + expireMillis);
...@@ -307,7 +349,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -307,7 +349,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
response.setStatus(session.getStatus()); response.setStatus(session.getStatus());
response.setRoomLink(roomLink); response.setRoomLink(roomLink);
response.setRoomQrCode(roomQrCodeUrl); response.setRoomQrCode(roomQrCodeUrl);
response.setExpirationTime(expirationDate); // 设置过期时间 response.setExpirationTime(expirationDate);
log.info("【创建会话】成功,roomId={}, sessionBizId={}", session.getRoomId(), session.getCoSessionBizId()); log.info("【创建会话】成功,roomId={}, sessionBizId={}", session.getRoomId(), session.getCoSessionBizId());
return Result.success(response); return Result.success(response);
...@@ -344,7 +386,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -344,7 +386,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
joinResponse.setSessionBizId(session.getCoSessionBizId()); joinResponse.setSessionBizId(session.getCoSessionBizId());
// 获取资源所有者缓存中的登录信息 // 获取资源所有者缓存中的登录信息
RoomRedisInfoDTO roomRedisInfoDTO = redisUtil.getCacheObject(RedisEnum.ROOM.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd(),RoomRedisInfoDTO.class); RoomRedisInfoDTO roomRedisInfoDTO = redisUtil.getCacheObject(RedisEnum.ROOM.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd(), RoomRedisInfoDTO.class);
if (roomRedisInfoDTO == null) { if (roomRedisInfoDTO == null) {
log.error("【加入会话】会话发起者缓存信息不存在,roomId={}", session.getRoomId()); log.error("【加入会话】会话发起者缓存信息不存在,roomId={}", session.getRoomId());
throw new BusinessException("会话发起者登录信息失效,建议联系会话发起者再次发起"); throw new BusinessException("会话发起者登录信息失效,建议联系会话发起者再次发起");
...@@ -357,8 +399,8 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -357,8 +399,8 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
log.info("【加入会话】成功, roomId={}, participantId={}, controlHolderType={}", log.info("【加入会话】成功, roomId={}, participantId={}, controlHolderType={}",
session.getRoomId(), session.getParticipantId(), session.getControlHolderType()); session.getRoomId(), session.getParticipantId(), session.getControlHolderType());
//删除房间链接缓存(只能访问一次,下次重新生成 // 删除房间链接缓存(注释掉,保留一次有效
// redisUtil.deleteObject(RedisEnum.ROOM_LINK.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd()); // redisUtil.deleteObject(RedisEnum.ROOM_LINK.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd());
return Result.success(joinResponse); return Result.success(joinResponse);
} catch (Exception e) { } catch (Exception e) {
...@@ -368,21 +410,16 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -368,21 +410,16 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
} }
/** /**
* 顾问加入会话 * 顾问加入会话(内部方法)
* @param roomId
* @param roomPwd
* @param participantId
* @param participantType
* @return
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public CoSession joinSession(String roomId,String roomPwd, String participantId, String participantType) { public CoSession joinSession(String roomId, String roomPwd, String participantId, String participantType) {
log.info("【加入会话-内部】开始, roomId={}, roomPwd={}, participantId={}, participantType={}", roomId, roomPwd, participantId, participantType); log.info("【加入会话-内部】开始, roomId={}, roomPwd={}, participantId={}, participantType={}", roomId, roomPwd, participantId, participantType);
try { try {
//校验房间链接是否失效 // 校验房间链接是否失效
String roomLink = redisUtil.getCacheObject(RedisEnum.ROOM_LINK.getPrefix() + roomId + ":" + roomPwd); String roomLink = redisUtil.getCacheObject(RedisEnum.ROOM_LINK.getPrefix() + roomId + ":" + roomPwd);
if (StringUtils.isBlank(roomLink)) { if (StringUtils.isBlank(roomLink)) {
throw new BusinessException(ResultCode.LINK_INVALID.getCode(),"访问链接已失效,请重新生成"); throw new BusinessException(ResultCode.LINK_INVALID.getCode(), "访问链接已失效,请重新生成");
} }
LambdaQueryWrapper<CoSession> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<CoSession> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(CoSession::getRoomId, roomId) wrapper.eq(CoSession::getRoomId, roomId)
...@@ -400,11 +437,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -400,11 +437,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
log.warn("【加入会话-内部】会话已结束,roomId={}", session.getRoomId()); log.warn("【加入会话-内部】会话已结束,roomId={}", session.getRoomId());
throw new BusinessException("会话已结束,不能再次加入房间"); throw new BusinessException("会话已结束,不能再次加入房间");
} }
// if (StringUtils.isNotBlank(session.getParticipantId()) && !session.getParticipantId().equals(participantId)) {
// log.warn("【加入会话-内部】房间被占用,当前参与者={}, 新参与者={}",
// session.getParticipantId(), participantId);
// throw new BusinessException("当前房间被占用,不能加入到房间");
// }
// 若为待开始状态,设置开始时间并转移控制权 // 若为待开始状态,设置开始时间并转移控制权
if (CoSessionStatusEnum.DKS.getItemValue().equals(session.getStatus())) { if (CoSessionStatusEnum.DKS.getItemValue().equals(session.getStatus())) {
...@@ -412,13 +444,11 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -412,13 +444,11 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
session.setStartTime(LocalDateTime.now()); session.setStartTime(LocalDateTime.now());
log.info("【加入会话-内部】设置开始时间={}", session.getStartTime()); log.info("【加入会话-内部】设置开始时间={}", session.getStartTime());
} }
// 待开始状态下,控制权自动移交给参与者(顾问)
session.setControlHolderType(ControlHolderTypeEnum.PARTICIPANT.getItemValue()); session.setControlHolderType(ControlHolderTypeEnum.PARTICIPANT.getItemValue());
session.setControlHolderId(participantId); session.setControlHolderId(participantId);
log.info("【加入会话-内部】待开始状态,控制权移交给参与者={}", participantId); log.info("【加入会话-内部】待开始状态,控制权移交给参与者={}", participantId);
} else { } else {
// 如果会话已经是进行中,但可能控制权不在顾问,此处强制转移给顾问(根据业务需求,可调整) // 如果会话已经是进行中,但可能控制权不在顾问,此处强制转移给顾问
// 如果不希望强制转移,可注释掉以下行
session.setControlHolderType(ControlHolderTypeEnum.PARTICIPANT.getItemValue()); session.setControlHolderType(ControlHolderTypeEnum.PARTICIPANT.getItemValue());
session.setControlHolderId(participantId); session.setControlHolderId(participantId);
log.info("【加入会话-内部】强制控制权移交给参与者={}", participantId); log.info("【加入会话-内部】强制控制权移交给参与者={}", participantId);
...@@ -433,7 +463,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -433,7 +463,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
log.info("【加入会话-内部】数据库更新成功,新状态={}", session.getStatus()); log.info("【加入会话-内部】数据库更新成功,新状态={}", session.getStatus());
// 更新 Redis 缓存 // 更新 Redis 缓存
RoomRedisInfoDTO roomRedisInfoDTO = redisUtil.getCacheObject(RedisEnum.ROOM.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd(),RoomRedisInfoDTO.class); RoomRedisInfoDTO roomRedisInfoDTO = redisUtil.getCacheObject(RedisEnum.ROOM.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd(), RoomRedisInfoDTO.class);
if (roomRedisInfoDTO != null) { if (roomRedisInfoDTO != null) {
roomRedisInfoDTO.setControlHolderType(session.getControlHolderType()); roomRedisInfoDTO.setControlHolderType(session.getControlHolderType());
roomRedisInfoDTO.setControlHolderId(session.getControlHolderId()); roomRedisInfoDTO.setControlHolderId(session.getControlHolderId());
...@@ -465,13 +495,11 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -465,13 +495,11 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
/** /**
* 获取会话状态 * 获取会话状态
* @param request
* @return
*/ */
@Override @Override
public Result<GetStatusResponse> getStatus(GetStatusRequest request) { public Result<GetStatusResponse> getStatus(GetStatusRequest request) {
CoSession coSession = iCoSessionService.lambdaQuery() CoSession coSession = iCoSessionService.lambdaQuery()
.eq(CoSession::getCoSessionBizId,request.getSessionBizId()) .eq(CoSession::getCoSessionBizId, request.getSessionBizId())
.last(" limit 1 ") .last(" limit 1 ")
.one(); .one();
if (coSession == null) { if (coSession == null) {
...@@ -480,10 +508,9 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -480,10 +508,9 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
GetStatusResponse response = new GetStatusResponse(); GetStatusResponse response = new GetStatusResponse();
String roomLink = redisUtil.getCacheObject(RedisEnum.ROOM_LINK.getPrefix() + coSession.getRoomId() + ":" + coSession.getRoomPwd()); String roomLink = redisUtil.getCacheObject(RedisEnum.ROOM_LINK.getPrefix() + coSession.getRoomId() + ":" + coSession.getRoomPwd());
if (StringUtils.isBlank(roomLink)) { if (StringUtils.isBlank(roomLink)) {
//2-已失效 response.setStatus(2); // 已失效
response.setStatus(2); } else {
}else { response.setStatus(1); // 有效
response.setStatus(1);
} }
return Result.success(response); return Result.success(response);
} }
...@@ -511,7 +538,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -511,7 +538,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
} }
/** /**
* 结束会话(客户调用) * 结束会话
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
...@@ -528,7 +555,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -528,7 +555,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
} }
log.info("【结束会话】找到会话,当前状态={}", coSession.getStatus()); log.info("【结束会话】找到会话,当前状态={}", coSession.getStatus());
// 结束会话关闭共享,更新信息
coSession.setStatus(CoSessionStatusEnum.YJS.getItemValue()); coSession.setStatus(CoSessionStatusEnum.YJS.getItemValue());
coSession.setEndTime(LocalDateTime.now()); coSession.setEndTime(LocalDateTime.now());
iCoSessionService.saveOrUpdate(coSession); iCoSessionService.saveOrUpdate(coSession);
...@@ -538,7 +564,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -538,7 +564,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
redisUtil.deleteObject(RedisEnum.ROOM.getPrefix() + coSession.getRoomId() + ":" + coSession.getRoomPwd()); redisUtil.deleteObject(RedisEnum.ROOM.getPrefix() + coSession.getRoomId() + ":" + coSession.getRoomPwd());
log.info("【结束会话】Redis缓存已删除"); log.info("【结束会话】Redis缓存已删除");
// 添加操作日志,协同-操作日志表
operationLogService.log( operationLogService.log(
coSession.getCoSessionBizId(), coSession.getCoSessionBizId(),
null, null,
...@@ -561,7 +586,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -561,7 +586,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
} }
/** /**
* 切换控制权(顾问调用) * 切换控制权
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
...@@ -586,7 +611,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -586,7 +611,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
public void transferControlUp(Integer oprType, String roomId) { public void transferControlUp(Integer oprType, String roomId) {
log.info("【切换控制权-内部】开始, oprType={}, roomId={}", oprType, roomId); log.info("【切换控制权-内部】开始, oprType={}, roomId={}", oprType, roomId);
try { try {
// 根据房间号查询会话信息
LambdaQueryWrapper<CoSession> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<CoSession> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(CoSession::getRoomId, roomId).last(" limit 1 "); wrapper.eq(CoSession::getRoomId, roomId).last(" limit 1 ");
CoSession session = iCoSessionService.getOne(wrapper); CoSession session = iCoSessionService.getOne(wrapper);
...@@ -596,14 +620,11 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -596,14 +620,11 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
} }
log.info("【切换控制权-内部】找到会话, 当前控制者={}:{}", session.getControlHolderType(), session.getControlHolderId()); log.info("【切换控制权-内部】找到会话, 当前控制者={}:{}", session.getControlHolderType(), session.getControlHolderId());
// 移交控制权
if (oprType == 1) { if (oprType == 1) {
// 1-开启客户操作,控制权移交给资源所有者(客户)
session.setControlHolderType(ControlHolderTypeEnum.OWNER.getItemValue()); session.setControlHolderType(ControlHolderTypeEnum.OWNER.getItemValue());
session.setControlHolderId(session.getOwnerId()); session.setControlHolderId(session.getOwnerId());
log.info("【切换控制权-内部】开启客户操作,控制权移交给所有者={}", session.getOwnerId()); log.info("【切换控制权-内部】开启客户操作,控制权移交给所有者={}", session.getOwnerId());
} else if (oprType == 2) { } else if (oprType == 2) {
// 2-关闭客户操作,控制权移交给参与者(顾问)
session.setControlHolderType(ControlHolderTypeEnum.PARTICIPANT.getItemValue()); session.setControlHolderType(ControlHolderTypeEnum.PARTICIPANT.getItemValue());
session.setControlHolderId(session.getParticipantId()); session.setControlHolderId(session.getParticipantId());
log.info("【切换控制权-内部】关闭客户操作,控制权移交给参与者={}", session.getParticipantId()); log.info("【切换控制权-内部】关闭客户操作,控制权移交给参与者={}", session.getParticipantId());
...@@ -616,8 +637,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -616,8 +637,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
log.info("【切换控制权-内部】数据库更新成功,新控制者={}:{}", log.info("【切换控制权-内部】数据库更新成功,新控制者={}:{}",
session.getControlHolderType(), session.getControlHolderId()); session.getControlHolderType(), session.getControlHolderId());
// 更新房间缓存redis信息 RoomRedisInfoDTO roomRedisInfoDTO = redisUtil.getCacheObject(RedisEnum.ROOM.getPrefix() + roomId + ":" + session.getRoomPwd(), RoomRedisInfoDTO.class);
RoomRedisInfoDTO roomRedisInfoDTO = redisUtil.getCacheObject(RedisEnum.ROOM.getPrefix() + roomId + ":" +session.getRoomPwd(),RoomRedisInfoDTO.class);
if (roomRedisInfoDTO != null) { if (roomRedisInfoDTO != null) {
roomRedisInfoDTO.setControlHolderId(session.getControlHolderId()); roomRedisInfoDTO.setControlHolderId(session.getControlHolderId());
roomRedisInfoDTO.setControlHolderType(session.getControlHolderType()); roomRedisInfoDTO.setControlHolderType(session.getControlHolderType());
...@@ -627,7 +647,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -627,7 +647,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
} else { } else {
log.warn("【切换控制权-内部】Redis缓存不存在,可能已过期"); log.warn("【切换控制权-内部】Redis缓存不存在,可能已过期");
} }
// 添加操作日志,协同-操作日志表
operationLogService.log( operationLogService.log(
session.getCoSessionBizId(), session.getCoSessionBizId(),
session.getParticipantId(), session.getParticipantId(),
...@@ -667,7 +686,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -667,7 +686,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
} }
roomRedisInfoDTO.setControlHolderType(session.getControlHolderType()); roomRedisInfoDTO.setControlHolderType(session.getControlHolderType());
roomRedisInfoDTO.setControlHolderId(session.getControlHolderId()); roomRedisInfoDTO.setControlHolderId(session.getControlHolderId());
// 查询出来的信息更新回缓存里面 // 查询出来的信息更新回缓存
redisUtil.setCacheObject(RedisEnum.ROOM.getPrefix() + roomId + ":" + session.getRoomPwd(), roomRedisInfoDTO, redisUtil.setCacheObject(RedisEnum.ROOM.getPrefix() + roomId + ":" + session.getRoomPwd(), roomRedisInfoDTO,
RedisEnum.ROOM.getTimeout(), RedisEnum.ROOM.getTimeUnit()); RedisEnum.ROOM.getTimeout(), RedisEnum.ROOM.getTimeUnit());
log.info("【获取当前控制者】从数据库加载并更新缓存,控制者={}:{}", log.info("【获取当前控制者】从数据库加载并更新缓存,控制者={}:{}",
...@@ -702,7 +721,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -702,7 +721,6 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
if (history == null || history.equals("[]") || history.isEmpty()) { if (history == null || history.equals("[]") || history.isEmpty()) {
history = "[" + newPageJson + "]"; history = "[" + newPageJson + "]";
} else { } else {
// 简单追加(生产环境建议用JSONArray处理)
history = history.substring(0, history.length() - 1) + "," + newPageJson + "]"; history = history.substring(0, history.length() - 1) + "," + newPageJson + "]";
} }
iCoSessionService.updateCurrentPageAndHistory(roomId, newPageJson, history, operatorId); iCoSessionService.updateCurrentPageAndHistory(roomId, newPageJson, history, operatorId);
...@@ -714,7 +732,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -714,7 +732,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
} }
/** /**
* 根据房间号获取会话信息 * 根据房间号获取会话
*/ */
@Override @Override
public CoSession getByRoomId(String roomId) { public CoSession getByRoomId(String roomId) {
...@@ -736,90 +754,70 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService { ...@@ -736,90 +754,70 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
/** /**
* 根据房间号和密码获取会话详情 * 根据房间号和密码获取会话详情
*
* @param roomId 房间号
* @param roomPwd 房间密码
* @return 完整会话信息
*/ */
@Override @Override
public Result<SessionDetailResponse> get(String roomId, String roomPwd) { public Result<SessionDetailResponse> get(String roomId, String roomPwd) {
log.info("【根据房间号和密码获取会话详情】roomId={}, roomPwd={}", roomId,roomPwd); log.info("【根据房间号和密码获取会话详情】roomId={}, roomPwd={}", roomId, roomPwd);
if (StringUtils.isBlank(roomId)) { if (StringUtils.isBlank(roomId)) {
throw new BusinessException("房间号不能为空"); throw new BusinessException("房间号不能为空");
} }
if (StringUtils.isBlank(roomPwd)) { if (StringUtils.isBlank(roomPwd)) {
throw new BusinessException("房间密码不能为空"); throw new BusinessException("房间密码不能为空");
} }
//查询会话详情
LambdaQueryWrapper<CoSession> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<CoSession> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(CoSession::getRoomId, roomId) wrapper.eq(CoSession::getRoomId, roomId)
.eq(CoSession::getRoomPwd,roomPwd) .eq(CoSession::getRoomPwd, roomPwd)
.last(" limit 1 "); .last(" limit 1 ");
CoSession session = iCoSessionService.getOne(wrapper); CoSession session = iCoSessionService.getOne(wrapper);
if (session == null) { if (session == null) {
throw new BusinessException("会话信息不存在"); throw new BusinessException("会话信息不存在");
} }
SessionDetailResponse response = new SessionDetailResponse(); SessionDetailResponse response = new SessionDetailResponse();
BeanUtils.copyProperties(session,response); BeanUtils.copyProperties(session, response);
return Result.success(response); return Result.success(response);
} }
/** /**
* 判断资源创建者和参与者是否是同一个人 * 判断资源创建者和参与者是否是同一个人
*
* @param roomId 房间号
* @param roomPwd 房间密码
* @return true-是同一人 false-不是同一人
*/ */
@Override @Override
public Result<Boolean> isMy(String roomId, String roomPwd, HttpServletRequest httpRequest) { public Result<Boolean> isMy(String roomId, String roomPwd, HttpServletRequest httpRequest) {
log.info("【判断资源创建者和参与者是否是同一个人】roomId={}, roomPwd={}", roomId,roomPwd); log.info("【判断资源创建者和参与者是否是同一个人】roomId={}, roomPwd={}", roomId, roomPwd);
if (StringUtils.isBlank(roomId)) { if (StringUtils.isBlank(roomId)) {
throw new BusinessException("房间号不能为空"); throw new BusinessException("房间号不能为空");
} }
if (StringUtils.isBlank(roomPwd)) { if (StringUtils.isBlank(roomPwd)) {
throw new BusinessException("房间密码不能为空"); throw new BusinessException("房间密码不能为空");
} }
//解析SFP参与者的token信息,提取用户ID
//解析 Token
String authorization = httpRequest.getHeader("X-Authorization"); String authorization = httpRequest.getHeader("X-Authorization");
if (StringUtils.isBlank(authorization)) { if (StringUtils.isBlank(authorization)) {
throw new BusinessException("访问者(参与者)token信息不能为空"); throw new BusinessException("访问者(参与者)token信息不能为空");
} }
//参与者用户ID
Long userId = null; // 通过远程接口解析 Token 获取用户信息
String userIdStr = SfpTokenUtil.getUserIdFromToken(authorization); QuerySfpUserResponse userInfo = parseTokenRemotely(authorization);
if (StringUtils.isNotBlank(userIdStr)) { Long userId = userInfo.getId();
try {
userId = Long.valueOf(userIdStr);
} catch (NumberFormatException ignored) {
log.info("【判断资源创建者和参与者是否是同一个人】errorMsg={}", ignored.getMessage());
}
}
if (userId == null) { if (userId == null) {
throw new BusinessException("访问者(参与者)token的用户ID解析为空"); throw new BusinessException("访问者(参与者)token的用户ID解析为空");
} }
//查询会话信息
LambdaQueryWrapper<CoSession> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<CoSession> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(CoSession::getRoomId, roomId) wrapper.eq(CoSession::getRoomId, roomId)
.eq(CoSession::getRoomPwd,roomPwd) .eq(CoSession::getRoomPwd, roomPwd)
.last(" limit 1 "); .last(" limit 1 ");
CoSession session = iCoSessionService.getOne(wrapper); CoSession session = iCoSessionService.getOne(wrapper);
if (session == null) { if (session == null) {
throw new BusinessException("会话信息不存在"); throw new BusinessException("会话信息不存在");
} }
//比较参与者的用户ID和创建者的用户ID是否相同,相同代表同一个人
String creatorId = session.getOwnerId(); String creatorId = session.getOwnerId();
if (userId.equals(creatorId)) { if (userId.toString().equals(creatorId)) {
//是同一个人
return Result.success(true); return Result.success(true);
} }
return Result.success(false); return Result.success(false);
} }
private boolean autoStartRecording() { private boolean autoStartRecording() {
return true; // 从配置读取 return true;
} }
} }
\ No newline at end of file
package com.yd.communication.feign.response.http;
import lombok.Data;
import java.util.Date;
@Data
public class QuerySfpUserResponse {
private Long id;//serial idPRIauto_increment
private String name;//userName
private String mobile;//手机号
private Integer gender;//性别,1,男,2,女
private String age;//年龄
private String manageMobile;//管理经纪人手机号(保单托管)
private Date loginDate;//登录时间(用于判断该用户是否登录过期 30天, 登录成功更新,退出或者切换账号更新)
private Integer loginState;//是否登录(0=No, 1=Yes)
private String customerSource;//客户来源
private String level;//用户等级
private String levelName;//用户等级名称
private Integer isVip;//是否vip
private Date vipExpireDate;//vip到期时间
private Date inactivateDate;//激活到期时间
private Integer remainingTimes;//剩余次数
private Integer isMax;//是否达到最大购买次数 0-否 1-是
private Integer userType;//用户类型
private Long roleId;//用户角色ID
private String systemType; //系统类型(tvm、sfp、policyManage)
private String tenantProjectRoleIds;//租户项目角色ID列表
private String flag;//标识
private String remark;//备注
private String wxNickname;//微信昵称
private String wxOpenId;//用户小程序登录的openid
private String wxOpenIdGzh;//用户公众号登录的openid
private Integer isBlacklist;//是否黑名单 0-否 1-是
private Integer isActive;//是否启用(0=No, 1=Yes)
private Date createdAt;//创建时间
private String createdBy;//创建人
private Date updatedAt;//修改时间
private String updatedBy;//修改人
/**
* 律家保-法税卡激活接口,请求⽅用户唯⼀识别号 (用于跳转到律家保页面的挂参)
*/
private String ljbRefId;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment