From 457f417a5274831928ece2a0d301300369b20423 Mon Sep 17 00:00:00 2001 From: heavyrian2012 Date: Sat, 13 Jun 2026 10:13:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E4=B8=93=E4=B8=9A=E7=89=88se?= =?UTF-8?q?rver=20sdk=E6=B7=BB=E5=8A=A0=E8=8E=B7=E5=8F=96=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E6=9C=AA=E8=AF=BB=E6=95=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VerifyAdminSecretTool.java | 114 ++++++++++++++++++ .../java/cn/wildfirechat/common/APIPath.java | 1 + .../pojos/OutputUserUnreadCount.java | 11 ++ .../main/java/cn/wildfirechat/sdk/Main.java | 9 ++ .../java/cn/wildfirechat/sdk/UserAdmin.java | 11 ++ 5 files changed, 146 insertions(+) create mode 100644 VerifyAdminSecretTool.java create mode 100644 common/src/main/java/cn/wildfirechat/pojos/OutputUserUnreadCount.java diff --git a/VerifyAdminSecretTool.java b/VerifyAdminSecretTool.java new file mode 100644 index 00000000..574d6db3 --- /dev/null +++ b/VerifyAdminSecretTool.java @@ -0,0 +1,114 @@ +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Scanner; + +/** + * 此工具为验证IM服务管理密钥是否正确的工具。 + * 通过手机号查询 Wildfire IM 用户信息,如果能够返回正确信息或者未找到表示密钥正确。 + * + * 编译:放到IM服务运行服务器上,执行 javac VerifyAdminSecretTool.java 编译得到 VerifyAdminSecretTool.class, + * 用法:执行 java VerifyAdminSecretTool 按提示输入 IM 服务地址、管理员密钥、电话号码。 + * 程序会调用 /admin/user/get_info 接口并打印返回的 JSON。 + */ +public class VerifyAdminSecretTool { + + private static final SecureRandom RANDOM = new SecureRandom(); + + public static void main(String[] args) throws Exception { + Scanner scanner = new Scanner(System.in); + + System.out.print("请输入 IM 服务地址(如 http://192.168.1.100:18080): "); + String serverUrl = scanner.nextLine().trim(); + + System.out.print("请输入管理员密钥(admin secret): "); + String secret = scanner.nextLine().trim(); + + System.out.print("请输入电话号码: "); + String mobile = scanner.nextLine().trim(); + + scanner.close(); + + if (serverUrl.isEmpty() || secret.isEmpty() || mobile.isEmpty()) { + System.err.println("错误:服务地址、密钥和电话号码均不能为空"); + System.exit(1); + } + + // 构建请求 URL(去掉末尾可能的 /) + if (serverUrl.endsWith("/")) { + serverUrl = serverUrl.substring(0, serverUrl.length() - 1); + } + String urlStr = serverUrl + "/admin/user/get_info"; + + // 构建请求体 + String jsonBody = "{\"mobile\":\"" + mobile + "\",\"includeDeleted\":false}"; + + // 生成认证签名 + int nonce = RANDOM.nextInt(1000000) + 1; + long timestamp = System.currentTimeMillis(); + String signStr = nonce + "|" + secret + "|" + timestamp; + String sign = sha1Hex(signStr); + + // 发送 HTTP POST 请求 + String response = doPost(urlStr, jsonBody, nonce, timestamp, sign); + + // 输出结果 + System.out.println("\n===== 返回结果 ====="); + System.out.println(response); + } + + private static String doPost(String urlStr, String body, int nonce, long timestamp, String sign) throws Exception { + URL url = new URL(urlStr); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + try { + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/json; charset=utf-8"); + conn.setRequestProperty("Connection", "Keep-Alive"); + conn.setRequestProperty("nonce", String.valueOf(nonce)); + conn.setRequestProperty("timestamp", String.valueOf(timestamp)); + conn.setRequestProperty("sign", sign); + conn.setDoOutput(true); + conn.setConnectTimeout(15000); + conn.setReadTimeout(15000); + + // 写入请求体 + try (OutputStream os = conn.getOutputStream()) { + os.write(body.getBytes(StandardCharsets.UTF_8)); + os.flush(); + } + + int responseCode = conn.getResponseCode(); + + // 读取响应 + InputStream is = (responseCode >= 200 && responseCode < 300) + ? conn.getInputStream() + : conn.getErrorStream(); + + StringBuilder sb = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + String line; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + } + + return sb.toString(); + } finally { + conn.disconnect(); + } + } + + private static String sha1Hex(String input) throws NoSuchAlgorithmException { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8)); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(String.format("%02x", b & 0xff)); + } + return sb.toString(); + } +} diff --git a/common/src/main/java/cn/wildfirechat/common/APIPath.java b/common/src/main/java/cn/wildfirechat/common/APIPath.java index 3095f91f..8f9f06f6 100644 --- a/common/src/main/java/cn/wildfirechat/common/APIPath.java +++ b/common/src/main/java/cn/wildfirechat/common/APIPath.java @@ -57,6 +57,7 @@ public interface APIPath { String User_Online_Count = "/admin/user/online_count"; String User_Online_List = "/admin/user/online_list"; String User_Session_List = "/admin/user/session_list"; + String User_Unread_count = "/admin/user/unread_count"; String User_Application_Get_UserInfo = "/admin/user/app_get_user_info"; String Friend_Update_Status = "/admin/friend/status"; diff --git a/common/src/main/java/cn/wildfirechat/pojos/OutputUserUnreadCount.java b/common/src/main/java/cn/wildfirechat/pojos/OutputUserUnreadCount.java new file mode 100644 index 00000000..85a664b4 --- /dev/null +++ b/common/src/main/java/cn/wildfirechat/pojos/OutputUserUnreadCount.java @@ -0,0 +1,11 @@ +package cn.wildfirechat.pojos; + + +import java.util.ArrayList; +import java.util.List; + +public class OutputUserUnreadCount { + public int unreceivedMessageCount; + public int uploadedUnreadCount; +} + diff --git a/sdk/src/main/java/cn/wildfirechat/sdk/Main.java b/sdk/src/main/java/cn/wildfirechat/sdk/Main.java index 217a7c32..dd2c86f1 100644 --- a/sdk/src/main/java/cn/wildfirechat/sdk/Main.java +++ b/sdk/src/main/java/cn/wildfirechat/sdk/Main.java @@ -485,6 +485,15 @@ public class Main { // 商业版专属功能 if (commercialServer) { + // 获取用户的未读情况 + IMResult userUnreadCountIMResult = UserAdmin.getUserUnreadCount("user1"); + if (userUnreadCountIMResult != null && userUnreadCountIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { + System.out.println("get user unread count success"); + } else { + System.out.println("get user unread count failure"); + System.exit(-1); + } + // 获取在线用户总数 IMResult getOnlineUserCountResultIMResult = UserAdmin.getOnlineUserCount(); if (getOnlineUserCountResultIMResult != null && getOnlineUserCountResultIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { diff --git a/sdk/src/main/java/cn/wildfirechat/sdk/UserAdmin.java b/sdk/src/main/java/cn/wildfirechat/sdk/UserAdmin.java index 31f4da07..935347f7 100644 --- a/sdk/src/main/java/cn/wildfirechat/sdk/UserAdmin.java +++ b/sdk/src/main/java/cn/wildfirechat/sdk/UserAdmin.java @@ -414,4 +414,15 @@ public class UserAdmin { InputUserId inputUserId = new InputUserId(userId); return AdminHttpUtils.httpJsonPost(APIPath.User_Session_List, inputUserId, GetUserSessionResult.class); } + + /** + * 获取用户的未读数,只有专业版IM服务支持,未读数不是很准确,只能表示一个大概。 + * @param userId + * @return 用户的未读数,包括未接收消息和客户端上报的未读数。 + * @throws Exception + */ + public static IMResult getUserUnreadCount(String userId) throws Exception { + InputUserId inputUserId = new InputUserId(userId); + return AdminHttpUtils.httpJsonPost(APIPath.User_Unread_count, inputUserId, OutputUserUnreadCount.class); + } }