From 1f93719ee52a15197c99904eca3a57fc348c6866 Mon Sep 17 00:00:00 2001 From: wells <123456@qq.com> Date: Sat, 8 Aug 2026 15:20:45 +0800 Subject: [PATCH] =?UTF-8?q?OpenIMApiClient=20=E6=9B=BF=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/constant/OpenImConstants.java | 8 ++- .../tailbet/common/enums/PlatformEnum.java | 64 +++++++++++++++++++ .../tailbet/controller/UserController.java | 11 ++-- src/main/java/com/tailbet/job/GameJob.java | 49 ++++++++++---- .../java/com/tailbet/model/dto/LoginDTO.java | 22 +++++++ .../com/tailbet/model/dto/RegisterDTO.java | 3 + .../com/tailbet/openim/OpenIMApiClient.java | 9 ++- .../openim/OpenIMCallbackController.java | 13 +++- .../tailbet/service/impl/PushServiceImpl.java | 25 ++++++-- .../tailbet/service/impl/UserServiceImpl.java | 12 ++-- 10 files changed, 176 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/tailbet/common/enums/PlatformEnum.java diff --git a/src/main/java/com/tailbet/common/constant/OpenImConstants.java b/src/main/java/com/tailbet/common/constant/OpenImConstants.java index 1478e0d..3d530dc 100644 --- a/src/main/java/com/tailbet/common/constant/OpenImConstants.java +++ b/src/main/java/com/tailbet/common/constant/OpenImConstants.java @@ -1,5 +1,7 @@ package com.tailbet.common.constant; +import com.tailbet.common.enums.PlatformEnum; + /** * OpenIM 协议相关常量 *

@@ -117,13 +119,13 @@ public final class OpenImConstants { * 服务端代操作使用的平台 ID(Web)。 * 与 App 端 iOS/Android 平台隔离,避免顶掉用户已登录 session。 */ - public static final int PLATFORM_ID_SERVER_WEB = 5; + public static final int PLATFORM_ID_SERVER_WEB = PlatformEnum.WEB.getCode(); /** App 端 iOS 平台 ID */ - public static final int PLATFORM_ID_IOS = 1; + public static final int PLATFORM_ID_IOS = PlatformEnum.IOS.getCode(); /** App 端 Android 平台 ID */ - public static final int PLATFORM_ID_ANDROID = 2; + public static final int PLATFORM_ID_ANDROID = PlatformEnum.ANDROID.getCode(); // ==================== 会话摘要 / 未读 ==================== diff --git a/src/main/java/com/tailbet/common/enums/PlatformEnum.java b/src/main/java/com/tailbet/common/enums/PlatformEnum.java new file mode 100644 index 0000000..f9a4706 --- /dev/null +++ b/src/main/java/com/tailbet/common/enums/PlatformEnum.java @@ -0,0 +1,64 @@ +package com.tailbet.common.enums; + +/** + * OpenIM 平台 ID 枚举 + *

+ * 表示用户连接所在的终端平台。 + *

+ * + * @author socialapp团队 + * @since 1.0.0 + */ +public enum PlatformEnum { + + IOS(1, "iOS"), + ANDROID(2, "Android"), + WINDOWS(3, "Windows"), + OSX(4, "macOS"), + WEB(5, "Web"), + MINI_WEB(6, "小程序或轻量 Web"), + LINUX(7, "Linux"), + APAD(8, "Android 平板"), + IPAD(9, "iPad"), + ADMIN(10, "管理端"), + HARMONYOS(11, "HarmonyOS"), + BOT(12, "Bot"); + + /** + * 平台 ID + */ + private final int code; + + /** + * 平台名称 + */ + private final String name; + + PlatformEnum(int code, String name) { + this.code = code; + this.name = name; + } + + public int getCode() { + return code; + } + + public String getName() { + return name; + } + + /** + * 根据 code 获取枚举 + * + * @param code 平台 ID + * @return 对应的枚举值,未找到返回 null + */ + public static PlatformEnum fromCode(int code) { + for (PlatformEnum platform : values()) { + if (platform.code == code) { + return platform; + } + } + return null; + } +} diff --git a/src/main/java/com/tailbet/controller/UserController.java b/src/main/java/com/tailbet/controller/UserController.java index 4b4e981..aaf1e10 100644 --- a/src/main/java/com/tailbet/controller/UserController.java +++ b/src/main/java/com/tailbet/controller/UserController.java @@ -7,10 +7,11 @@ import com.tailbet.model.vo.LoginUserVo; import com.tailbet.model.vo.LoginVo; import com.tailbet.model.vo.R; import com.tailbet.model.vo.UserContext; -import com.tailbet.openim.OpenIMClient; +import com.tailbet.openim.OpenIMApiClient; import com.tailbet.service.IUserService; import com.tailbet.util.JwtUtil; import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; /** @@ -23,13 +24,13 @@ public class UserController { private final IUserService userService; private final JwtUtil jwtUtil; - private final OpenIMClient openIMClient; + private final OpenIMApiClient openIMApiClient; /** * 注册 */ @PostMapping("/register") - public R register(@RequestBody RegisterDTO dto) { + public R register(@RequestBody @Validated RegisterDTO dto) { userService.register(dto.getUsername(), dto.getPassword()); return R.ok(); @@ -39,10 +40,10 @@ public class UserController { * 登录 */ @PostMapping("/login") - public R login(@RequestBody LoginDTO dto) { + public R login(@RequestBody @Validated LoginDTO dto) { Long userId = userService.login(dto.getUsername(), dto.getPassword()); String token = jwtUtil.generateToken(userId, dto.getUsername()); - String openIMToken = openIMClient.getUserToken(String.valueOf(userId)); + String openIMToken = openIMApiClient.getUserToken(String.valueOf(userId), 2); // platformID 2=Android LoginVo vo = new LoginVo(); vo.setToken(token); diff --git a/src/main/java/com/tailbet/job/GameJob.java b/src/main/java/com/tailbet/job/GameJob.java index 4ae7c2d..3ad4525 100644 --- a/src/main/java/com/tailbet/job/GameJob.java +++ b/src/main/java/com/tailbet/job/GameJob.java @@ -18,7 +18,7 @@ import com.tailbet.model.entity.RedPacketRecv; import com.tailbet.model.entity.SysConfig; import com.tailbet.model.entity.PendingTask; import com.tailbet.model.PendingTaskInfo; -import com.tailbet.openim.OpenIMClient; +import com.tailbet.openim.OpenIMApiClient; import com.tailbet.service.IGameService; import com.tailbet.service.IRedPacketService; import com.tailbet.service.IFakeUserService; @@ -54,7 +54,8 @@ public class GameJob { private final IGameService gameService; private final IRedPacketService redPacketService; private final IFakeUserService fakeUserService; - private final OpenIMClient openIMClient; + private final OpenIMApiClient openIMApiClient; + private final com.tailbet.config.OpenIMProperties openIMProperties; // 局状态监控(使用内存缓存,实际生产应使用Redis) private final Map roundTasks = new ConcurrentHashMap<>(); @@ -534,8 +535,13 @@ public class GameJob { User user = userMapper.selectById(white.getUserId()); if (user != null) { // 通过OpenIM发送通知 - openIMClient.sendUserMessage(String.valueOf(user.getId()), - "尾数试算完成,请前往修改尾数。期号: " + round.getRoundNo()); + openIMApiClient.sendMsg( + openIMProperties.getAdminUserId(), + String.valueOf(user.getId()), + 1, // sessionType 1=单聊 + 101, // contentType 101=文本 + java.util.Map.of("content", "尾数试算完成,请前往修改尾数。期号: " + round.getRoundNo()) + ); log.info("通知白名单用户尾数试算完成: userId={}, roundId={}", user.getId(), roundId); } } @@ -546,24 +552,39 @@ public class GameJob { */ private void broadcastStartBet(Long groupId, String roundNo) { // 注意: 实际生产中需要通过Group表映射获取OpenIM群ID - openIMClient.sendGroupMessage(String.valueOf(groupId), - roundNo + "期开始下注"); + openIMApiClient.sendMsg( + openIMProperties.getAdminUserId(), + String.valueOf(groupId), + 3, // sessionType 3=群聊 + 101, // contentType 101=文本 + java.util.Map.of("content", roundNo + "期开始下注") + ); } /** * 广播结束下注 */ private void broadcastEndBet(Long groupId, String roundNo) { - openIMClient.sendGroupMessage(String.valueOf(groupId), - roundNo + "期结束下注"); + openIMApiClient.sendMsg( + openIMProperties.getAdminUserId(), + String.valueOf(groupId), + 3, // sessionType 3=群聊 + 101, // contentType 101=文本 + java.util.Map.of("content", roundNo + "期结束下注") + ); } /** * 广播开始发红包 */ private void broadcastStartRp(Long groupId, String roundNo) { - openIMClient.sendGroupMessage(String.valueOf(groupId), - roundNo + "期开始发红包"); + openIMApiClient.sendMsg( + openIMProperties.getAdminUserId(), + String.valueOf(groupId), + 3, // sessionType 3=群聊 + 101, // contentType 101=文本 + java.util.Map.of("content", roundNo + "期开始发红包") + ); } /** @@ -581,7 +602,13 @@ public class GameJob { message += "\n\n近30期:\n" + history; } - openIMClient.sendGroupMessage(String.valueOf(groupId), message); + openIMApiClient.sendMsg( + openIMProperties.getAdminUserId(), + String.valueOf(groupId), + 3, // sessionType 3=群聊 + 101, // contentType 101=文本 + java.util.Map.of("content", message) + ); } /** diff --git a/src/main/java/com/tailbet/model/dto/LoginDTO.java b/src/main/java/com/tailbet/model/dto/LoginDTO.java index 34b25c0..b855377 100644 --- a/src/main/java/com/tailbet/model/dto/LoginDTO.java +++ b/src/main/java/com/tailbet/model/dto/LoginDTO.java @@ -1,5 +1,7 @@ package com.tailbet.model.dto; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import lombok.Data; /** @@ -16,4 +18,24 @@ public class LoginDTO { * 密码 */ private String password; + /** + * 平台ID + * @see com.tailbet.common.enums.PlatformEnum + *
    + *
  • 1=iOS
  • + *
  • 2=Android
  • + *
  • 3=Windows
  • + *
  • 4=macOS
  • + *
  • 5=Web
  • + *
  • 6=小程序或轻量 Web
  • + *
  • 7=Linux
  • + *
  • 8=Android 平板
  • + *
  • 9=iPad
  • + *
  • 10=管理端
  • + *
  • 11=HarmonyOS
  • + *
  • 12=Bot
  • + *
+ */ + @NotNull(message = "platformID不能为空") + private Integer platformID; } diff --git a/src/main/java/com/tailbet/model/dto/RegisterDTO.java b/src/main/java/com/tailbet/model/dto/RegisterDTO.java index 45c1738..5a86c99 100644 --- a/src/main/java/com/tailbet/model/dto/RegisterDTO.java +++ b/src/main/java/com/tailbet/model/dto/RegisterDTO.java @@ -1,5 +1,6 @@ package com.tailbet.model.dto; +import jakarta.validation.constraints.NotEmpty; import lombok.Data; /** @@ -10,10 +11,12 @@ public class RegisterDTO { /** * 账号 */ + @NotEmpty(message = "username不能为空") private String username; /** * 密码 */ + @NotEmpty(message = "password不能为空") private String password; } diff --git a/src/main/java/com/tailbet/openim/OpenIMApiClient.java b/src/main/java/com/tailbet/openim/OpenIMApiClient.java index dd4b799..eb7ca21 100644 --- a/src/main/java/com/tailbet/openim/OpenIMApiClient.java +++ b/src/main/java/com/tailbet/openim/OpenIMApiClient.java @@ -6,6 +6,7 @@ import com.tailbet.common.enums.ErrorCodeEnum; import com.tailbet.common.exception.BusinessException; import com.tailbet.config.OpenIMProperties; import lombok.Data; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -49,6 +50,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * @author socialapp团队 * @since 1.0.0 */ +@RequiredArgsConstructor @Slf4j @Component public class OpenIMApiClient { @@ -90,11 +92,8 @@ public class OpenIMApiClient { */ private final AtomicBoolean deleteConversationsSupported = new AtomicBoolean(false); - /** - * OpenIM 专用 RestTemplate - */ - @Resource(name = "openIMRestTemplate") - private RestTemplate restTemplate; + private final RestTemplate restTemplate; + /** * JSON 工具(合并 OpenIM ex 字段) diff --git a/src/main/java/com/tailbet/openim/OpenIMCallbackController.java b/src/main/java/com/tailbet/openim/OpenIMCallbackController.java index 6c308b9..d8236fb 100644 --- a/src/main/java/com/tailbet/openim/OpenIMCallbackController.java +++ b/src/main/java/com/tailbet/openim/OpenIMCallbackController.java @@ -6,7 +6,7 @@ import com.tailbet.service.IBetService; import com.tailbet.service.IGameService; import com.tailbet.service.IRedPacketService; import com.tailbet.service.IGroupService; -import com.tailbet.openim.OpenIMClient; +import com.tailbet.openim.OpenIMApiClient; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; @@ -24,7 +24,8 @@ public class OpenIMCallbackController { private final IGameService gameService; private final IRedPacketService redPacketService; private final IGroupService groupService; - private final OpenIMClient openIMClient; + private final OpenIMApiClient openIMApiClient; + private final com.tailbet.config.OpenIMProperties openIMProperties; /** * 接收群消息回调 @@ -164,7 +165,13 @@ public class OpenIMCallbackController { */ private void sendGroupMessage(String openimGroupId, String message) { try { - openIMClient.sendGroupMessage(openimGroupId, message); + openIMApiClient.sendMsg( + openIMProperties.getAdminUserId(), + openimGroupId, + 3, // sessionType 3=群聊 + 101, // contentType 101=文本 + java.util.Map.of("content", message) + ); } catch (Exception e) { log.error("发送群消息失败: {}", e.getMessage()); } diff --git a/src/main/java/com/tailbet/service/impl/PushServiceImpl.java b/src/main/java/com/tailbet/service/impl/PushServiceImpl.java index d5a4486..eff7ff3 100644 --- a/src/main/java/com/tailbet/service/impl/PushServiceImpl.java +++ b/src/main/java/com/tailbet/service/impl/PushServiceImpl.java @@ -5,7 +5,7 @@ import com.tailbet.mapper.UserMapper; import com.tailbet.mapper.DigitWhiteMapper; import com.tailbet.model.entity.DigitWhite; import com.tailbet.model.entity.User; -import com.tailbet.openim.OpenIMClient; +import com.tailbet.openim.OpenIMApiClient; import com.tailbet.service.IPushService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; @@ -24,7 +24,8 @@ public class PushServiceImpl implements IPushService { private final UserMapper userMapper; private final DigitWhiteMapper digitWhiteMapper; - private final OpenIMClient openIMClient; + private final OpenIMApiClient openIMApiClient; + private final com.tailbet.config.OpenIMProperties openIMProperties; /** * 推送尾数试算完成通知给白名单用户 @@ -94,8 +95,13 @@ public class PushServiceImpl implements IPushService { } // 通过OpenIM单聊发送(生产环境可扩展FCM/APNs离线推送) - openIMClient.sendUserMessage(String.valueOf(user.getId()), - message.getTitle() + " - " + message.getContent()); + openIMApiClient.sendMsg( + openIMProperties.getAdminUserId(), + String.valueOf(user.getId()), + 1, // sessionType 1=单聊 + 101, // contentType 101=文本 + java.util.Map.of("content", message.getTitle() + " - " + message.getContent()) + ); log.info("推送发送成功: userId={}, type={}", message.getUserId(), message.getType()); } catch (Exception e) { @@ -110,9 +116,14 @@ public class PushServiceImpl implements IPushService { @Override public void broadcastToGroup(Long groupId, IPushService.PushMessage message) { try { - // 通过OpenIM群消息发送 - openIMClient.sendGroupMessage(String.valueOf(groupId), - message.getContent()); + // 通过OpenIM群消息发送(使用管理员身份发送) + openIMApiClient.sendMsg( + openIMProperties.getAdminUserId(), + String.valueOf(groupId), + 3, // sessionType 3=群聊 + 101, // contentType 101=文本 + java.util.Map.of("content", message.getContent()) + ); log.info("群广播发送成功: groupId={}, type={}", groupId, message.getType()); } catch (Exception e) { log.error("群广播发送失败: groupId={}, type={}, error={}", diff --git a/src/main/java/com/tailbet/service/impl/UserServiceImpl.java b/src/main/java/com/tailbet/service/impl/UserServiceImpl.java index a2381ca..09cc1d7 100644 --- a/src/main/java/com/tailbet/service/impl/UserServiceImpl.java +++ b/src/main/java/com/tailbet/service/impl/UserServiceImpl.java @@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.tailbet.model.entity.User; import com.tailbet.mapper.UserMapper; import com.tailbet.model.dto.UpdateUserDTO; -import com.tailbet.openim.OpenIMClient; +import com.tailbet.openim.OpenIMApiClient; import com.tailbet.service.IUserService; import com.tailbet.util.JwtUtil; import com.tailbet.util.PasswordUtil; @@ -26,8 +26,7 @@ public class UserServiceImpl extends ServiceImpl implements IU private final UserMapper userMapper; private final PasswordUtil passwordUtil; - private final JwtUtil jwtUtil; - private final OpenIMClient openIMClient; + private final OpenIMApiClient openIMApiClient; /** @@ -59,9 +58,10 @@ public class UserServiceImpl extends ServiceImpl implements IU userMapper.insert(user); // 在OpenIM创建用户 - boolean openIMResult = openIMClient.createUser(String.valueOf(user.getId()), user.getNickname()); - if (!openIMResult) { - log.warn("OpenIM用户创建失败: userId={}, username={}", user.getId(), username); + try { + openIMApiClient.userRegister(String.valueOf(user.getId()), user.getNickname(), null); + } catch (Exception e) { + log.warn("OpenIM用户创建失败: userId={}, username={}, error={}", user.getId(), username, e.getMessage()); throw new RuntimeException("OpenIM用户创建失败,请稍后再试!"); }