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用户创建失败,请稍后再试!");
}