From 244fadd1e6727af230fa44dba68cec6ecf4709d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=89=AF=28004796=29?= Date: Fri, 29 Dec 2023 12:45:41 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=9A=E8=AF=9D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-dev.yml | 9 +++ .../src/main/resources/application-prod.yml | 9 +++ .../src/main/resources/application.yml | 5 -- .../main/java/com/ruoyi/cai/agora/Agora.java | 27 +++---- .../ruoyi/cai/executor/ExecutorConstant.java | 2 +- .../com/ruoyi/cai/util/RestTemplateUtil.java | 31 ++++++++ .../java/com/ruoyi/cai/ws/bean/FdCtxData.java | 9 +++ .../main/java/com/ruoyi/cai/ws/bean/Room.java | 5 -- .../java/com/ruoyi/cai/ws/bean/RoomData.java | 2 + .../ruoyi/cai/ws/cache/FdCtxDataCache.java | 10 +++ .../com/ruoyi/cai/ws/cache/RoomCtxCache.java | 24 +++++- .../com/ruoyi/cai/ws/cache/RoomDataCache.java | 31 ++++---- .../com/ruoyi/cai/ws/cache/UserDataCache.java | 13 ++-- .../cai/ws/constant/UserDataConstant.java | 8 ++ .../com/ruoyi/cai/ws/processon/OpenLogic.java | 15 ++-- .../com/ruoyi/cai/ws/service/RoomService.java | 48 +++++++++++- ruoyi-websocket/pom.xml | 5 ++ .../websocket/config/AgoraProperties.java | 14 ++++ .../com/ruoyi/websocket/dto/WsRMsgGen.java | 76 ++++++++++++++++++- .../handler/AbstractMessageHandle.java | 40 ++++++++++ .../websocket/handler/IMessageHandler.java | 10 +++ .../{handle => handler}/IOpenLogic.java | 2 +- .../handler/MessageHandleApplication.java | 60 +++++++++++++++ ...Handler.java => RoomWebSocketHandler.java} | 6 +- .../handler/message/AgreeMessageHandle.java | 47 ++++++++++++ .../message/CanCallTimeMessageHandler.java | 25 ++++++ .../handler/message/CancelMessageHandler.java | 46 +++++++++++ .../handler/message/GiftMessageHandler.java | 60 +++++++++++++++ .../handler/message/HangupMessageHandler.java | 53 +++++++++++++ .../message/HeartbeatMessageHandler.java | 34 +++++++++ .../handler/message/MessageHandler.java | 25 ++++++ .../handler/message/RefuseMessageHandler.java | 54 +++++++++++++ .../websocket/util/RoomWebSocketUtil.java | 10 ++- 33 files changed, 746 insertions(+), 69 deletions(-) create mode 100644 ruoyi-cai/src/main/java/com/ruoyi/cai/util/RestTemplateUtil.java create mode 100644 ruoyi-cai/src/main/java/com/ruoyi/cai/ws/constant/UserDataConstant.java create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/config/AgoraProperties.java create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/AbstractMessageHandle.java create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/IMessageHandler.java rename ruoyi-websocket/src/main/java/com/ruoyi/websocket/{handle => handler}/IOpenLogic.java (78%) create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/MessageHandleApplication.java rename ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/{PlusWebSocketHandler.java => RoomWebSocketHandler.java} (93%) create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/AgreeMessageHandle.java create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/CanCallTimeMessageHandler.java create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/CancelMessageHandler.java create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/GiftMessageHandler.java create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/HangupMessageHandler.java create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/HeartbeatMessageHandler.java create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/MessageHandler.java create mode 100644 ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/RefuseMessageHandler.java diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 3f1fcc05..f1cea25a 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -162,3 +162,12 @@ sms: sdkAppId: appid #地域信息默认为 ap-guangzhou 如无特殊改变可不用设置 territory: ap-guangzhou +spring: + rabbitmq: + addresses: 127.0.0.1 #ip地址 + username: admin # 账号 + password: admin # 密码 +agora: + app-id: app + key: key + secret: secret diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 8d61ad46..f1ba5218 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -165,3 +165,12 @@ sms: sdkAppId: appid #地域信息默认为 ap-guangzhou 如无特殊改变可不用设置 territory: ap-guangzhou +spring: + rabbitmq: + addresses: 127.0.0.1 #ip地址 + username: admin # 账号 + password: admin # 密码 +agora: + app-id: app + key: key + secret: secret diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index cfd50d3e..4a402006 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -250,8 +250,3 @@ management: show-details: ALWAYS logfile: external-file: ./logs/sys-console.log -spring: - rabbitmq: - addresses: 127.0.0.1 #ip地址 - username: admin # 账号 - password: admin # 密码 diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/agora/Agora.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/agora/Agora.java index b9eb3d53..504acc7a 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/agora/Agora.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/agora/Agora.java @@ -2,44 +2,39 @@ package com.ruoyi.cai.agora; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.cai.util.RestTemplateUtil; +import com.ruoyi.websocket.config.AgoraProperties; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; import java.util.*; @Component public class Agora { - private RestTemplate restTemplate = new RestTemplate(); - - private final String APP_ID = "appId"; + @Autowired + private AgoraProperties agoraProperties; public String getAuthorizationHeader(){ - // 客户 ID - final String customerKey = "Your customer key"; - // 客户密钥 - final String customerSecret = "Your customer secret"; - // 拼接客户 ID 和客户密钥并使用 base64 编码 - String plainCredentials = customerKey + ":" + customerSecret; + String plainCredentials = agoraProperties.getKey() + ":" + agoraProperties.getSecret(); String base64Credentials = new String(Base64.getEncoder().encode(plainCredentials.getBytes())); // 创建 authorization header - String authorizationHeader = "Basic " + base64Credentials; - return authorizationHeader; + return "Basic " + base64Credentials; } public List getChannelUsers(String roomId){ String url = "http://api.sd-rtn.com/dev/v1/channel/user/%s/%s"; - url = String.format(url, APP_ID, roomId); + url = String.format(url, agoraProperties.getAppId(), roomId); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.set("Authorization", getAuthorizationHeader()); HttpEntity httpEntity = new HttpEntity<>(headers); - JSONObject jsonobject = restTemplate.getForObject(url,JSONObject.class,httpEntity); + JSONObject jsonobject = RestTemplateUtil.restTemplate.getForObject(url,JSONObject.class,httpEntity); // "success":true,"data":{"channel_exist":true,"mode":2,"broadcasters":[1001,1025],"audience":[],"audience_total":0}} if(jsonobject == null){ return Collections.emptyList(); @@ -51,7 +46,7 @@ public class Agora { public void closeChannel(String roomId){ String url = "http://api.sd-rtn.com/dev/v1/kicking-rule"; Map param = new HashMap<>(); - param.put("appid",APP_ID); + param.put("appid",agoraProperties.getAppId()); param.put("cname",roomId); param.put("time",0); param.put("privileges",Collections.emptyList()); @@ -59,7 +54,7 @@ public class Agora { headers.setContentType(MediaType.APPLICATION_JSON); headers.set("Authorization", getAuthorizationHeader()); HttpEntity httpEntity = new HttpEntity<>(param, headers); - restTemplate.postForObject(url, httpEntity, JSONObject.class); + RestTemplateUtil.restTemplate.postForObject(url, httpEntity, JSONObject.class); } } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/executor/ExecutorConstant.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/executor/ExecutorConstant.java index 69838e8d..c7e7187e 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/executor/ExecutorConstant.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/executor/ExecutorConstant.java @@ -41,7 +41,7 @@ public class ExecutorConstant { CPU_NUM << 2, 5, TimeUnit.SECONDS, - new ArrayBlockingQueue<>(50), + new ArrayBlockingQueue<>(5), init("roomThreadPoll-%d"), new ThreadPoolExecutor.CallerRunsPolicy()); ROOM_EXECUTOR = TtlExecutors.getTtlExecutor(roomExecutor); diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/util/RestTemplateUtil.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/util/RestTemplateUtil.java new file mode 100644 index 00000000..4661650f --- /dev/null +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/util/RestTemplateUtil.java @@ -0,0 +1,31 @@ +package com.ruoyi.cai.util; + +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +public class RestTemplateUtil { + + public static RestTemplate restTemplate = null; + + static { + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setConnectTimeout(3000); + requestFactory.setReadTimeout(3000); + restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(requestFactory)); + List> messageConverters = restTemplate.getMessageConverters(); + //添加转换器 + for (HttpMessageConverter messageConverter : messageConverters) { + if (messageConverter instanceof StringHttpMessageConverter) { + StringHttpMessageConverter converter = (StringHttpMessageConverter) messageConverter; + converter.setDefaultCharset(StandardCharsets.UTF_8); + } + } + } + +} diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/FdCtxData.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/FdCtxData.java index 733aaed2..9b813a37 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/FdCtxData.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/FdCtxData.java @@ -1,5 +1,6 @@ package com.ruoyi.cai.ws.bean; +import com.ruoyi.cai.ws.constant.UserDataConstant; import lombok.Data; @Data @@ -11,4 +12,12 @@ public class FdCtxData { private Integer userType; private Long tarUserId; private Integer tarUserType; + + public boolean isReceiver(){ + return userType == UserDataConstant.TYPE_RECEIVER; + } + + public boolean isCaller(){ + return userType == UserDataConstant.TYPE_CALLER; + } } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/Room.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/Room.java index e9a5a22b..0e7387de 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/Room.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/Room.java @@ -1,13 +1,8 @@ package com.ruoyi.cai.ws.bean; -import com.ruoyi.cai.ws.constant.HangUpEnums; import com.ruoyi.cai.ws.constant.RoomStatusEnums; -import com.ruoyi.cai.ws.service.CheckConnectionDTO; import lombok.Data; -import java.util.HashMap; -import java.util.Map; - @Data public class Room { diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/RoomData.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/RoomData.java index 3b0f717c..e705ce87 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/RoomData.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/bean/RoomData.java @@ -11,6 +11,8 @@ public class RoomData { private String skillName; private Integer status; private BigDecimal videoDivide; + private Integer payCoin = 0; + private Integer payIncome = 0; private Long hangUpTime; private Long beginTime; diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/FdCtxDataCache.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/FdCtxDataCache.java index 667577d0..856d1fee 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/FdCtxDataCache.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/FdCtxDataCache.java @@ -3,6 +3,7 @@ package com.ruoyi.cai.ws.cache; import com.alibaba.fastjson2.JSON; import com.ruoyi.cai.ws.bean.FdCtxData; import com.ruoyi.cai.ws.constant.RedisConstant; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.SearchStrategy; import org.springframework.data.redis.core.StringRedisTemplate; @@ -24,4 +25,13 @@ public class FdCtxDataCache { redisTemplate.opsForValue().set(getKey(fdCtxData.getSessionKey()),str,5, TimeUnit.DAYS); } + public FdCtxData getByRoomId(String sessionKey){ + String key = getKey(sessionKey); + String s = redisTemplate.opsForValue().get(key); + if(StringUtils.isEmpty(s)){ + return null; + } + return JSON.parseObject(s,FdCtxData.class); + } + } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/RoomCtxCache.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/RoomCtxCache.java index d5eb95b7..7cd0e4f2 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/RoomCtxCache.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/RoomCtxCache.java @@ -1,11 +1,14 @@ package com.ruoyi.cai.ws.cache; import com.ruoyi.cai.ws.constant.RedisConstant; +import com.ruoyi.cai.ws.constant.UserDataConstant; import com.ruoyi.websocket.holder.WebSocketSessionHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -24,6 +27,16 @@ public class RoomCtxCache { redisTemplate.expire(key,7, TimeUnit.DAYS); } + public List getSessionKeysByRoomId(String roomId){ + String key = getKey(roomId); + Map entries = redisTemplate.opsForHash().entries(key); + List res = new ArrayList<>(); + for (Object o : entries.keySet()) { + res.add(String.valueOf(o)); + } + return res; + } + public String getSessionKeyByRoomIdAndUserType(String roomId,Integer userType){ String key = getKey(roomId); Map entries = redisTemplate.opsForHash().entries(key); @@ -38,6 +51,15 @@ public class RoomCtxCache { } public String getSessionKeyReceiverByRoomId(String roomId){ - return getSessionKeyByRoomIdAndUserType(roomId,UserDataCache.TYPE_RECEIVER); + return getSessionKeyByRoomIdAndUserType(roomId, UserDataConstant.TYPE_RECEIVER); + } + + public String getSessionKeyCallerByRoomId(String roomId){ + return getSessionKeyByRoomIdAndUserType(roomId, UserDataConstant.TYPE_CALLER); + } + + public void del(String roomId) { + String key = getKey(roomId); + redisTemplate.delete(key); } } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/RoomDataCache.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/RoomDataCache.java index cc27db53..b67b806b 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/RoomDataCache.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/RoomDataCache.java @@ -22,17 +22,6 @@ import java.util.Map; @Component public class RoomDataCache { - // 房间状态 - private final static int STATUS_CREATE = 0; // 刚创建 - private final static int STATUS_CALLER_CONNECT = 1; // 呼叫方连接上 - private final static int STATUS_CALLER_CANCEL = 2; // 呼叫方取消通话 - private final static int STATUS_RECEIVER_CONNECT = 3; // 接收方连接上 - private final static int STATUS_CONNECT_CANCEL = 4; // 收到通话未接听 - private final static int STATUS_TIMEOUT_CANCEL = 5; // 超时未接听 - private final static int STATUS_REFUSE = 6; // 接收方已拒绝 - private final static int STATUS_AGREE = 7; // 已接听 - private final static int STATUS_HANGUP = 8; // 通话结束 - @Autowired private RedissonClient redissonClient; @Autowired @@ -65,10 +54,11 @@ public class RoomDataCache { "end\n" + "return redis.call('hMSet', KEYS[1], 'status', 8, 'hangupTime', ARGV[1])"; - public void hangUp(String roomId) { + public boolean hangUp(String roomId) { DefaultRedisScript redisScript = new DefaultRedisScript<>(HANG_UP,Boolean.class); String currentTime = String.valueOf(System.currentTimeMillis() / 1000); - stringRedisTemplate.execute(redisScript, Collections.singletonList(getKey(roomId)), currentTime); + Boolean execute = stringRedisTemplate.execute(redisScript, Collections.singletonList(getKey(roomId)), currentTime); + return BooleanUtils.isTrue(execute); } public void setStatus(String roomId, RoomStatusEnums status) { @@ -87,4 +77,19 @@ public class RoomDataCache { Boolean execute = stringRedisTemplate.execute(redisScript, Collections.singletonList(getKey(roomId))); return BooleanUtils.isTrue(execute); } + + private final static String SET_STATUS_AGREE = + "local status = tonumber(redis.call('hget', KEYS[1], 'status'))\n" + + "local beginTime = tonumber(redis.call('hget', KEYS[1], 'beginTime'))\n" + + "if status ~= 3 or beginTime > 0 then\n" + + " return 0\n" + + "end\n" + + "return redis.call('hmset', KEYS[1], 'status', 7, 'beginTime', ARGV[1])"; + + public boolean setStatusAgree(String roomId) { + DefaultRedisScript redisScript = new DefaultRedisScript<>(SET_STATUS_AGREE,Boolean.class); + String currentTime = String.valueOf(System.currentTimeMillis() / 1000); + Boolean execute = stringRedisTemplate.execute(redisScript, Collections.singletonList(getKey(roomId)),currentTime); + return BooleanUtils.isTrue(execute); + } } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/UserDataCache.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/UserDataCache.java index 631b63ba..82b803e5 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/UserDataCache.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/cache/UserDataCache.java @@ -3,6 +3,7 @@ package com.ruoyi.cai.ws.cache; import com.alibaba.fastjson2.JSON; import com.ruoyi.cai.ws.bean.UserData; import com.ruoyi.cai.ws.constant.RedisConstant; +import com.ruoyi.cai.ws.constant.UserDataConstant; import com.ruoyi.cai.ws.util.MapGetUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; @@ -12,21 +13,19 @@ import java.util.Map; @Component public class UserDataCache { - public final static int TYPE_CALLER = 1; // 视频发起者 - public final static int TYPE_RECEIVER = 2; // 视频接收者 @Autowired private StringRedisTemplate redisTemplate; public String getKey(String roomId,int type){ - return String.format(RedisConstant.USER_ROOM_DATA,roomId,type==TYPE_CALLER?"caller":"receiver"); + return String.format(RedisConstant.USER_ROOM_DATA,roomId,type== UserDataConstant.TYPE_CALLER?"caller":"receiver"); } public UserData getCallerUserDataByRoom(String roomId){ - return getUserDataByRoom(roomId,TYPE_CALLER); + return getUserDataByRoom(roomId,UserDataConstant.TYPE_CALLER); } public UserData getReceiverUserDataByRoom(String roomId){ - return getUserDataByRoom(roomId,TYPE_RECEIVER); + return getUserDataByRoom(roomId,UserDataConstant.TYPE_RECEIVER); } public UserData getUserDataByRoom(String roomId,int type){ @@ -58,11 +57,11 @@ public class UserDataCache { } public void initCaller(UserData callerUserData) { - init(callerUserData,TYPE_CALLER); + init(callerUserData,UserDataConstant.TYPE_CALLER); } public void initReceiver(UserData callerUserData) { - init(callerUserData,TYPE_RECEIVER); + init(callerUserData,UserDataConstant.TYPE_RECEIVER); } public void hMSet(String roomId,Integer userType,Map data) { diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/constant/UserDataConstant.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/constant/UserDataConstant.java new file mode 100644 index 00000000..e2d5d914 --- /dev/null +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/constant/UserDataConstant.java @@ -0,0 +1,8 @@ +package com.ruoyi.cai.ws.constant; + +public class UserDataConstant { + + public final static int TYPE_CALLER = 1; // 视频发起者 + public final static int TYPE_RECEIVER = 2; // 视频接收者 + +} diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/processon/OpenLogic.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/processon/OpenLogic.java index 80d8db4e..fdd940ed 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/processon/OpenLogic.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/processon/OpenLogic.java @@ -10,11 +10,12 @@ import com.ruoyi.cai.ws.bean.Room; import com.ruoyi.cai.ws.cache.*; import com.ruoyi.cai.ws.constant.HangUpEnums; import com.ruoyi.cai.ws.constant.RoomStatusEnums; +import com.ruoyi.cai.ws.constant.UserDataConstant; import com.ruoyi.cai.ws.service.CheckConnectionDTO; import com.ruoyi.cai.ws.service.RoomService; import com.ruoyi.cai.ws.util.WsExceptionUtil; import com.ruoyi.websocket.dto.WsRMsgGen; -import com.ruoyi.websocket.handle.IOpenLogic; +import com.ruoyi.websocket.handler.IOpenLogic; import com.ruoyi.websocket.util.RoomWebSocketUtil; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -80,13 +81,13 @@ public class OpenLogic implements IOpenLogic { fdCtxData.setRoomId(room.getRoomId()); fdCtxData.setUserId(userId); if(userId.equals(room.getCallUserData().getId())){ - fdCtxData.setUserType(UserDataCache.TYPE_CALLER); + fdCtxData.setUserType(UserDataConstant.TYPE_CALLER); fdCtxData.setTarUserId(room.getReceiverUserData().getId()); - fdCtxData.setTarUserType(UserDataCache.TYPE_RECEIVER); + fdCtxData.setTarUserType(UserDataConstant.TYPE_RECEIVER); } else { - fdCtxData.setUserType(UserDataCache.TYPE_RECEIVER); + fdCtxData.setUserType(UserDataConstant.TYPE_RECEIVER); fdCtxData.setTarUserId(room.getCallUserData().getId()); - fdCtxData.setTarUserType(UserDataCache.TYPE_CALLER); + fdCtxData.setTarUserType(UserDataConstant.TYPE_CALLER); } fdCtxDataCache.save(fdCtxData); roomCtxCache.addFd(sessionKey,roomId,fdCtxData.getUserType()); @@ -101,7 +102,7 @@ public class OpenLogic implements IOpenLogic { Map map = new HashMap<>(); map.put("connectTime", DateUtil.currentSeconds()); map.put("heartTime",DateUtil.currentSeconds()); - userDataCache.hMSet(room.getRoomId(), UserDataCache.TYPE_CALLER,map); + userDataCache.hMSet(room.getRoomId(), UserDataConstant.TYPE_CALLER,map); roomDataCache.setStatus(room.getRoomId(),RoomStatusEnums.STATUS_CALLER_CONNECT); onlineDataCache.add(room.getRoomId()); userService.updateVideoStatus(userId,1); @@ -142,7 +143,7 @@ public class OpenLogic implements IOpenLogic { Map map = new HashMap<>(); map.put("connectTime", DateUtil.currentSeconds()); map.put("heartTime",DateUtil.currentSeconds()); - userDataCache.hMSet(room.getRoomId(), UserDataCache.TYPE_RECEIVER,map); + userDataCache.hMSet(room.getRoomId(), UserDataConstant.TYPE_RECEIVER,map); boolean res = roomDataCache.setStatusReceiverConnection(room.getRoomId()); if(!res){ return; diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/service/RoomService.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/service/RoomService.java index 42189e53..9698aa35 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/service/RoomService.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/ws/service/RoomService.java @@ -1,22 +1,25 @@ package com.ruoyi.cai.ws.service; import cn.hutool.core.date.DateUtil; +import com.ruoyi.cai.domain.CaiAccount; +import com.ruoyi.cai.service.CaiAccountService; import com.ruoyi.cai.ws.bean.Room; import com.ruoyi.cai.ws.bean.RoomData; import com.ruoyi.cai.ws.bean.UserData; -import com.ruoyi.cai.ws.cache.CallerRoomCache; -import com.ruoyi.cai.ws.cache.RoomDataCache; -import com.ruoyi.cai.ws.cache.UserDataCache; +import com.ruoyi.cai.ws.cache.*; import com.ruoyi.cai.ws.constant.HangUpEnums; import com.ruoyi.cai.ws.constant.RoomStatusEnums; -import com.ruoyi.cai.ws.util.WsExceptionUtil; +import com.ruoyi.websocket.util.WebSocketUtils; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.HashMap; +import java.util.List; import java.util.Map; @Component +@Slf4j public class RoomService { @Autowired private RoomDataCache roomDataCache; @@ -24,6 +27,12 @@ public class RoomService { private UserDataCache userDataCache; @Autowired private CallerRoomCache callerRoomCache; + @Autowired + private CaiAccountService accountService; + @Autowired + private FdCtxDataCache fdCtxDataCache; + @Autowired + private RoomCtxCache roomCtxCache; public Room load(String roomId){ Room room = new Room(); @@ -65,6 +74,15 @@ public class RoomService { } } + public void closeAllFd(String roomId){ + List sessionKeysByRoomId = roomCtxCache.getSessionKeysByRoomId(roomId); + for (String sessionKey : sessionKeysByRoomId) { + WebSocketUtils.close(sessionKey); + } + // 删除房间FD,避免重连 + roomCtxCache.del(roomId); + } + public void delCallRoom(Long fromUid) { callerRoomCache.del(fromUid); } @@ -100,4 +118,26 @@ public class RoomService { return DateUtil.currentSeconds() - beginTime; } + + public Long canCallTime(Room room) { + try { + Long callId = room.getCallUserData().getId(); + CaiAccount account = accountService.getByUserId(callId); + if(account == null){ + return 0L; + } + RoomData roomData = room.getRoomData(); + int blockAmount = roomData.getPayCoin() + roomData.getPayIncome(); + long totalAmount = account.getTotalCoin()+account.getIncomeCoin() + blockAmount; + long totalSecond = (totalAmount / roomData.getCallPrice()) / 60; + long useTime = 0; + if(roomData.getBeginTime() != null){ + useTime = DateUtil.currentSeconds() - roomData.getBeginTime(); + } + return totalSecond - useTime; + }catch (Exception e){ + log.error("计算可通话时间失败!",e); + return 0L; + } + } } diff --git a/ruoyi-websocket/pom.xml b/ruoyi-websocket/pom.xml index ead8c5cc..129d43bb 100644 --- a/ruoyi-websocket/pom.xml +++ b/ruoyi-websocket/pom.xml @@ -22,6 +22,11 @@ com.ruoyi ruoyi-common + + com.ruoyi + ruoyi-cai + 4.8.2 + org.springframework.boot spring-boot-starter-websocket diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/config/AgoraProperties.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/config/AgoraProperties.java new file mode 100644 index 00000000..6139027a --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/config/AgoraProperties.java @@ -0,0 +1,14 @@ +package com.ruoyi.websocket.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@ConfigurationProperties(prefix = "agora") +public class AgoraProperties { + private String appId; + private String key; + private String secret; +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/dto/WsRMsgGen.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/dto/WsRMsgGen.java index 81d8f0c5..c5a0bcd2 100644 --- a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/dto/WsRMsgGen.java +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/dto/WsRMsgGen.java @@ -1,6 +1,7 @@ package com.ruoyi.websocket.dto; -import org.apache.poi.hssf.record.OldCellRecord; +import com.alibaba.fastjson.JSON; +import com.ruoyi.cai.domain.CaiGift; import java.util.HashMap; import java.util.Map; @@ -32,9 +33,9 @@ public class WsRMsgGen { map.put("content",content); map.put("linkType",0); map.put("linkUrl",null); - map.put("fromUid",0); - map.put("toUid",0); - map.put("cancalltime",0); + map.put("fromUid",null); + map.put("toUid",null); + map.put("cancalltime",null); WsR> ok = WsR.ok(map); ok.setMethod("notice"); ok.setMsg("提示!"); @@ -59,4 +60,71 @@ public class WsRMsgGen { ok.setMsg(message); return ok; } + + public static WsR canCallTime(long time) { + Map map = new HashMap<>(); + map.put("tip",time); + WsR> ok = WsR.ok(map); + ok.setMethod("cancalltime"); + ok.setMsg("提示!"); + return ok; + } + + public static WsR rechargeNotice(String content) { + Map map = new HashMap<>(); + map.put("type",1); + map.put("content",content); + map.put("linkType",2); + map.put("linkUrl","rechargeCoin"); + map.put("fromUid",null); + map.put("toUid",null); + map.put("cancalltime",null); + WsR> ok = WsR.ok(map); + ok.setMethod("notice"); + ok.setMsg("提示!"); + return ok; + } + + public static WsR gift(CaiGift gift, Long callerId, Long receiverId) { + Map content = new HashMap<>(); + content.put("giftid",gift.getId()); + content.put("giftname",gift.getName()); + content.put("gifticon",gift.getImg()); + content.put("giftsvga",gift.getSvga()); + Map map = new HashMap<>(); + map.put("type",3); + map.put("content", JSON.toJSONString(content)); + map.put("linkType",null); + map.put("linkUrl",null); + map.put("fromUid",callerId); + map.put("toUid",receiverId); + map.put("cancalltime",null); + WsR> ok = WsR.ok(map); + ok.setMethod("notice"); + ok.setMsg("提示!"); + return ok; + } + + public static WsR heartbeat() { + Map content = new HashMap<>(); + WsR> ok = WsR.ok(content); + ok.setMethod("heartbeat"); + ok.setMsg("检测成功!"); + return ok; + } + + public static WsR chatData(String txt, Long from, Long to) { + Map map = new HashMap<>(); + map.put("type",2); + map.put("content", txt); + map.put("linkType",null); + map.put("linkUrl",null); + map.put("fromUid",from); + map.put("toUid",to); + map.put("cancalltime",null); + WsR> ok = WsR.ok(map); + ok.setMethod("notice"); + ok.setMsg("提示!"); + return ok; + } } diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/AbstractMessageHandle.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/AbstractMessageHandle.java new file mode 100644 index 00000000..e66f9dfb --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/AbstractMessageHandle.java @@ -0,0 +1,40 @@ +package com.ruoyi.websocket.handler; + +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.cache.RoomCtxCache; +import com.ruoyi.websocket.dto.WsR; +import com.ruoyi.websocket.util.RoomWebSocketUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public abstract class AbstractMessageHandle implements IMessageHandler { + + @Autowired + private RoomCtxCache roomCtxCache; + + protected void sendToCurrent(FdCtxData fdCtxData, WsR r){ + RoomWebSocketUtil.sendSendMessage(fdCtxData.getSessionKey(), r); + } + + protected void sendToTar(FdCtxData fdCtxData, WsR r) { + String sessionKey = roomCtxCache.getSessionKeyByRoomIdAndUserType(fdCtxData.getRoomId(), fdCtxData.getTarUserType()); + RoomWebSocketUtil.sendSendMessage(sessionKey, r); + } + + protected void sendToReceiver(String roomId, WsR r){ + String receiverSessionKey = roomCtxCache.getSessionKeyReceiverByRoomId(roomId); + RoomWebSocketUtil.sendSendMessage(receiverSessionKey, r); + } + + protected void sendToAll(String roomId, WsR ... r ){ + List sessionKeys = roomCtxCache.getSessionKeysByRoomId(roomId); + for (WsR wsR : r) { + RoomWebSocketUtil.sendSendMessage(sessionKeys, wsR); + } + + } + +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/IMessageHandler.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/IMessageHandler.java new file mode 100644 index 00000000..73e86b62 --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/IMessageHandler.java @@ -0,0 +1,10 @@ +package com.ruoyi.websocket.handler; + +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.bean.Room; + +public interface IMessageHandler { + + void processOn(Room room, FdCtxData fdCtxData, JSONObject map); +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handle/IOpenLogic.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/IOpenLogic.java similarity index 78% rename from ruoyi-websocket/src/main/java/com/ruoyi/websocket/handle/IOpenLogic.java rename to ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/IOpenLogic.java index cb6da728..d9219973 100644 --- a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handle/IOpenLogic.java +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/IOpenLogic.java @@ -1,4 +1,4 @@ -package com.ruoyi.websocket.handle; +package com.ruoyi.websocket.handler; import org.springframework.web.socket.WebSocketSession; diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/MessageHandleApplication.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/MessageHandleApplication.java new file mode 100644 index 00000000..77eafc15 --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/MessageHandleApplication.java @@ -0,0 +1,60 @@ +package com.ruoyi.websocket.handler; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.bean.Room; +import com.ruoyi.cai.ws.cache.FdCtxDataCache; +import com.ruoyi.cai.ws.constant.HangUpEnums; +import com.ruoyi.cai.ws.service.CheckConnectionDTO; +import com.ruoyi.cai.ws.service.RoomService; +import com.ruoyi.cai.ws.util.WsExceptionUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.util.Map; + +/** + * ws消息处理器统一入口 + */ +@Component +public class MessageHandleApplication { + + @Autowired + private Map map; + @Autowired + private RoomService roomService; + @Autowired + private FdCtxDataCache fdCtxDataCache; + + public void processOn(WebSocketSession session, TextMessage message) { + String payload = message.getPayload(); + JSONObject jsonObject = JSON.parseObject(payload); + Object method = jsonObject.get("method"); + if(method == null){ + return; + } + Map attributes = session.getAttributes(); + String roomId = (String) attributes.get("roomId"); + String sessionKey = (String) attributes.get("token"); + Room room = roomService.load(roomId); + if(room == null){ + WsExceptionUtil.throwException("房间不可用", sessionKey,HangUpEnums.OTHER, roomId); + return; + } + CheckConnectionDTO checkConnect = roomService.checkConnect(room); + if(checkConnect != null){ + WsExceptionUtil.throwException(sessionKey,checkConnect.getMessage(),checkConnect.getHangUpEnums(),roomId); + return; + } + IMessageHandler handler = map.get(String.valueOf(method)); + if(handler == null){ + return; + } + FdCtxData fdCtxData = fdCtxDataCache.getByRoomId(sessionKey); + handler.processOn(room,fdCtxData, jsonObject); + + } +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/PlusWebSocketHandler.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/RoomWebSocketHandler.java similarity index 93% rename from ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/PlusWebSocketHandler.java rename to ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/RoomWebSocketHandler.java index 00a7369c..96bbfa20 100644 --- a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/PlusWebSocketHandler.java +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/RoomWebSocketHandler.java @@ -1,7 +1,6 @@ package com.ruoyi.websocket.handler; import com.ruoyi.websocket.constant.WebSocketConstants; -import com.ruoyi.websocket.handle.IOpenLogic; import com.ruoyi.websocket.holder.WebSocketSessionHolder; import com.ruoyi.websocket.util.WebSocketUtils; import lombok.extern.slf4j.Slf4j; @@ -19,10 +18,12 @@ import java.util.Map; */ @Slf4j @Component -public class PlusWebSocketHandler extends AbstractWebSocketHandler { +public class RoomWebSocketHandler extends AbstractWebSocketHandler { @Autowired private IOpenLogic openLogic; + @Autowired + private MessageHandleApplication messageHandleApplication; /** * 连接成功后 */ @@ -46,6 +47,7 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { String token = String.valueOf(session.getAttributes().get(WebSocketConstants.TOKEN)); + messageHandleApplication.processOn(session,message); } @Override diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/AgreeMessageHandle.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/AgreeMessageHandle.java new file mode 100644 index 00000000..dce397e5 --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/AgreeMessageHandle.java @@ -0,0 +1,47 @@ +package com.ruoyi.websocket.handler.message; + +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.cai.domain.CaiUserCall; +import com.ruoyi.cai.service.CaiUserCallService; +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.bean.Room; +import com.ruoyi.cai.ws.cache.RoomDataCache; +import com.ruoyi.cai.ws.constant.RoomStatusEnums; +import com.ruoyi.websocket.dto.WsRMsgGen; +import com.ruoyi.websocket.handler.AbstractMessageHandle; +import com.ruoyi.websocket.handler.IMessageHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * 被叫同意接听处理 + */ +@Component("agree") +public class AgreeMessageHandle extends AbstractMessageHandle implements IMessageHandler { + + @Autowired + private RoomDataCache roomDataCache; + @Autowired + private CaiUserCallService userCallService; + + @Override + public void processOn(Room room, FdCtxData fdCtxData, JSONObject map) { + if(!fdCtxData.isReceiver()){ + return; + } + boolean agree = roomDataCache.setStatusAgree(room.getRoomId()); + if(!agree){ + return; + } + // 通知可进行接通 + userCallService.update(Wrappers.lambdaUpdate(CaiUserCall.class) + .eq(CaiUserCall::getId,room.getRoomId()) + .set(CaiUserCall::getStatus, RoomStatusEnums.STATUS_AGREE.getCode()) + .set(CaiUserCall::getBeginTime, LocalDateTime.now())); + String message = "提示:禁止任何涉黄、任何微信QQ引导到其它平台行为"; + sendToAll(room.getRoomId(), WsRMsgGen.startVideo(room.getRoomId(),0L),WsRMsgGen.sysNotice(message)); + } +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/CanCallTimeMessageHandler.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/CanCallTimeMessageHandler.java new file mode 100644 index 00000000..7549fa5e --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/CanCallTimeMessageHandler.java @@ -0,0 +1,25 @@ +package com.ruoyi.websocket.handler.message; + +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.bean.Room; +import com.ruoyi.cai.ws.service.RoomService; +import com.ruoyi.websocket.dto.WsRMsgGen; +import com.ruoyi.websocket.handler.AbstractMessageHandle; +import com.ruoyi.websocket.handler.IMessageHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 获取可通话时长 + */ +@Component("cancalltime") +public class CanCallTimeMessageHandler extends AbstractMessageHandle implements IMessageHandler { + @Autowired + private RoomService roomService; + @Override + public void processOn(Room room, FdCtxData fdCtxData, JSONObject map) { + Long time = roomService.canCallTime(room); + sendToCurrent(fdCtxData,WsRMsgGen.canCallTime(time)); + } +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/CancelMessageHandler.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/CancelMessageHandler.java new file mode 100644 index 00000000..80d5dd5c --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/CancelMessageHandler.java @@ -0,0 +1,46 @@ +package com.ruoyi.websocket.handler.message; + +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.cai.domain.CaiUserCall; +import com.ruoyi.cai.service.CaiUserCallService; +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.bean.Room; +import com.ruoyi.cai.ws.constant.HangUpEnums; +import com.ruoyi.cai.ws.constant.RoomStatusEnums; +import com.ruoyi.cai.ws.service.RoomService; +import com.ruoyi.websocket.dto.WsRMsgGen; +import com.ruoyi.websocket.handler.AbstractMessageHandle; +import com.ruoyi.websocket.handler.IMessageHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 主叫方取消通话 + */ +@Component("cancel") +public class CancelMessageHandler extends AbstractMessageHandle implements IMessageHandler { + @Autowired + private CaiUserCallService userCallService; + @Autowired + private RoomService roomService; + @Override + public void processOn(Room room, FdCtxData fdCtxData, JSONObject map) { + if(!fdCtxData.isCaller()){ + return; + } + if(!RoomStatusEnums.STATUS_CALLER_CONNECT.getCode().equals(room.getStatus()) + && !RoomStatusEnums.STATUS_RECEIVER_CONNECT.getCode().equals(room.getStatus())){ + return; + } + String roomId = room.getRoomId(); + sendToCurrent(fdCtxData,WsRMsgGen.hangup("通话已取消",roomId, HangUpEnums.CANCEL.getCode())); + sendToReceiver(roomId,WsRMsgGen.hangup("对方已取消",roomId, HangUpEnums.CANCEL.getCode())); + roomService.closeAllFd(roomId); + // IM TODO + // 更新房间状态 + userCallService.update(Wrappers.lambdaUpdate(CaiUserCall.class) + .eq(CaiUserCall::getId,roomId) + .set(CaiUserCall::getStatus,RoomStatusEnums.STATUS_CALLER_CANCEL.getCode())); + } +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/GiftMessageHandler.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/GiftMessageHandler.java new file mode 100644 index 00000000..66e04fa3 --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/GiftMessageHandler.java @@ -0,0 +1,60 @@ +package com.ruoyi.websocket.handler.message; + +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.cai.domain.CaiAccount; +import com.ruoyi.cai.domain.CaiGift; +import com.ruoyi.cai.dto.app.query.GiveGiftRes; +import com.ruoyi.cai.service.CaiAccountService; +import com.ruoyi.cai.service.CaiGiftService; +import com.ruoyi.cai.service.CaiUserGiftService; +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.bean.Room; +import com.ruoyi.websocket.dto.WsRMsgGen; +import com.ruoyi.websocket.handler.AbstractMessageHandle; +import com.ruoyi.websocket.handler.IMessageHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component("gift") +public class GiftMessageHandler extends AbstractMessageHandle implements IMessageHandler { + @Autowired + private CaiGiftService giftService; + @Autowired + private CaiAccountService accountService; + @Autowired + private CaiUserGiftService userGiftService; + @Override + public void processOn(Room room, FdCtxData fdCtxData, JSONObject map) { + Long giftId = map.getLong("giftId"); + if(giftId == null){ + return; + } + Long giftCount = map.getLongValue("giftCount",1L); + CaiGift gift = giftService.getById(giftId); + if(gift == null){ + return; + } + Long giftAmount = gift.getPrice() * giftCount; + CaiAccount account = accountService.getByUserId(fdCtxData.getUserId()); + Long userAccount = account.getIncomeCoin() + account.getCoin(); + if(userAccount < giftAmount){ + sendToCurrent(fdCtxData,WsRMsgGen.rechargeNotice("余额不足,点此充值")); + return; + } + if(fdCtxData.isCaller() && (userAccount - giftAmount) < room.getRoomData().getCallPrice()){ + sendToCurrent(fdCtxData,WsRMsgGen.rechargeNotice("赠送后通话时间不足1分钟,点此充值")); + return; + } + GiveGiftRes giveGiftRes = new GiveGiftRes(); + giveGiftRes.setType(3); + giveGiftRes.setToUserId(fdCtxData.getTarUserId()); + giveGiftRes.setGiftId(giftId); + giveGiftRes.setGiftCount(giftCount); + boolean b = userGiftService.giveGift(giveGiftRes); + if(!b){ + sendToCurrent(fdCtxData,WsRMsgGen.sysNotice("赠送失败,请重试")); + return; + } + sendToAll(room.getRoomId(),WsRMsgGen.gift(gift,fdCtxData.getUserId(),fdCtxData.getTarUserId())); + } +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/HangupMessageHandler.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/HangupMessageHandler.java new file mode 100644 index 00000000..b1868767 --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/HangupMessageHandler.java @@ -0,0 +1,53 @@ +package com.ruoyi.websocket.handler.message; + +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.bean.Room; +import com.ruoyi.cai.ws.cache.RoomCtxCache; +import com.ruoyi.cai.ws.cache.RoomDataCache; +import com.ruoyi.cai.ws.constant.HangUpEnums; +import com.ruoyi.cai.ws.service.RoomService; +import com.ruoyi.websocket.dto.WsR; +import com.ruoyi.websocket.dto.WsRMsgGen; +import com.ruoyi.websocket.handler.AbstractMessageHandle; +import com.ruoyi.websocket.handler.IMessageHandler; +import com.ruoyi.websocket.util.RoomWebSocketUtil; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * 挂断处理 + */ +@Component("hangup") +public class HangupMessageHandler extends AbstractMessageHandle implements IMessageHandler { + @Autowired + private RoomService roomService; + @Autowired + private RoomDataCache roomDataCache; + + @Override + public void processOn(Room room, FdCtxData fdCtxData, JSONObject map) { + if(StringUtils.isEmpty(room.getRoomId())){ + return; + } + // 经测试,app端挂断时,可能会把旧的房间id传上来,所以需要判断id与fd上下文的一致性 + if(!room.getRoomId().equals(fdCtxData.getRoomId())){ + return; + } + boolean b = roomDataCache.hangUp(room.getRoomId()); + if(!b){ + return; + } + // 触发结算 TODO + + Integer type = fdCtxData.isCaller() ? HangUpEnums.FROM.getCode() : HangUpEnums.TO.getCode(); + sendToCurrent(fdCtxData,WsRMsgGen.hangup("您已挂断",room.getRoomId(), type)); + sendToTar(fdCtxData,WsRMsgGen.hangup("对方已挂断",room.getRoomId(), type)); + roomService.closeAllFd(room.getRoomId()); + } + + +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/HeartbeatMessageHandler.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/HeartbeatMessageHandler.java new file mode 100644 index 00000000..bf06f98a --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/HeartbeatMessageHandler.java @@ -0,0 +1,34 @@ +package com.ruoyi.websocket.handler.message; + +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.bean.Room; +import com.ruoyi.cai.ws.cache.UserDataCache; +import com.ruoyi.websocket.dto.WsRMsgGen; +import com.ruoyi.websocket.handler.AbstractMessageHandle; +import com.ruoyi.websocket.handler.IMessageHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * 心跳处理 + */ +@Component("heartbeat") +public class HeartbeatMessageHandler extends AbstractMessageHandle implements IMessageHandler { + @Autowired + private UserDataCache userDataCache; + @Override + public void processOn(Room room, FdCtxData fdCtxData, JSONObject map) { + if(!room.isCanCall()){ + return; + } + Map update = new HashMap<>(); + update.put("heartTime", DateUtil.currentSeconds()); + userDataCache.hMSet(room.getRoomId(),fdCtxData.getUserType(),update); + sendToCurrent(fdCtxData, WsRMsgGen.heartbeat()); + } +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/MessageHandler.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/MessageHandler.java new file mode 100644 index 00000000..f0d5f904 --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/MessageHandler.java @@ -0,0 +1,25 @@ +package com.ruoyi.websocket.handler.message; + +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.bean.Room; +import com.ruoyi.websocket.dto.WsRMsgGen; +import com.ruoyi.websocket.handler.AbstractMessageHandle; +import com.ruoyi.websocket.handler.IMessageHandler; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +/** + * 聊天消息处理 + */ +@Component("message") +public class MessageHandler extends AbstractMessageHandle implements IMessageHandler { + @Override + public void processOn(Room room, FdCtxData fdCtxData, JSONObject map) { + String txt = map.getString("txt"); + if(StringUtils.isEmpty(txt) || !room.isOnline()){ + return; + } + sendToAll(room.getRoomId(),WsRMsgGen.chatData(txt,fdCtxData.getUserId(),fdCtxData.getTarUserId())); + } +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/RefuseMessageHandler.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/RefuseMessageHandler.java new file mode 100644 index 00000000..7a5fb60f --- /dev/null +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/handler/message/RefuseMessageHandler.java @@ -0,0 +1,54 @@ +package com.ruoyi.websocket.handler.message; + +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.cai.domain.CaiUserCall; +import com.ruoyi.cai.service.CaiUserCallService; +import com.ruoyi.cai.ws.bean.FdCtxData; +import com.ruoyi.cai.ws.bean.Room; +import com.ruoyi.cai.ws.cache.RoomCtxCache; +import com.ruoyi.cai.ws.cache.RoomDataCache; +import com.ruoyi.cai.ws.constant.HangUpEnums; +import com.ruoyi.cai.ws.constant.RoomStatusEnums; +import com.ruoyi.cai.ws.service.RoomService; +import com.ruoyi.websocket.dto.WsRMsgGen; +import com.ruoyi.websocket.handler.AbstractMessageHandle; +import com.ruoyi.websocket.handler.IMessageHandler; +import com.ruoyi.websocket.util.RoomWebSocketUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 被叫方拒绝通话 + */ +@Component("cancalltime") +public class RefuseMessageHandler extends AbstractMessageHandle implements IMessageHandler { + @Autowired + private RoomDataCache roomDataCache; + @Autowired + private RoomCtxCache roomCtxCache; + @Autowired + private RoomService roomService; + @Autowired + private CaiUserCallService userCallService; + @Override + public void processOn(Room room, FdCtxData fdCtxData, JSONObject map) { + if(!fdCtxData.isReceiver() || !RoomStatusEnums.STATUS_RECEIVER_CONNECT.getCode().equals(room.getStatus())){ + return; + } + boolean b = roomDataCache.hangUp(room.getRoomId()); + if(!b){ + return; + } + sendToCurrent(fdCtxData, WsRMsgGen.hangup("已拒绝",room.getRoomId(), HangUpEnums.REFUSE.getCode())); + sendToTar(fdCtxData,WsRMsgGen.hangup("对方已拒绝",room.getRoomId(), HangUpEnums.REFUSE.getCode())); + roomService.closeAllFd(room.getRoomId()); + + //发送IM通知 TODO + + // 更新房间状态 + userCallService.update(Wrappers.lambdaUpdate(CaiUserCall.class) + .eq(CaiUserCall::getId,room.getRoomId()) + .set(CaiUserCall::getStatus,RoomStatusEnums.STATUS_REFUSE.getCode())); + } +} diff --git a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/util/RoomWebSocketUtil.java b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/util/RoomWebSocketUtil.java index 7ba1b735..088a9eaa 100644 --- a/ruoyi-websocket/src/main/java/com/ruoyi/websocket/util/RoomWebSocketUtil.java +++ b/ruoyi-websocket/src/main/java/com/ruoyi/websocket/util/RoomWebSocketUtil.java @@ -1,15 +1,19 @@ package com.ruoyi.websocket.util; import com.alibaba.fastjson2.JSON; -import com.ruoyi.common.core.domain.R; import com.ruoyi.websocket.dto.WsR; -import java.util.HashMap; -import java.util.Map; +import java.util.List; public class RoomWebSocketUtil { public static void sendSendMessage(String sessionKey,WsR r){ WebSocketUtils.sendMessage(sessionKey, JSON.toJSONString(r)); } + public static void sendSendMessage(List sessionKey, WsR r){ + for (String s : sessionKey) { + WebSocketUtils.sendMessage(s, JSON.toJSONString(r)); + } + } + }