Files
连龙刚andClaude fdbb7724fa feat(t17): 数据同步——只读拉取群组/群成员/群消息到本地表,按租户查看
主体(T17 数据同步,/admin/sync 三个独立按钮):
- 同步群组:get_appid_group_list 全量 Next 分页 + 逐群 get_group_info → group_mapping
- 同步群成员(→用户):遍历该租户群取 MemberList → user_mapping(腾讯无全量用户API,靠群成员反推)
- 同步群消息:遍历该租户群 getGroupMsg + IsFinished 滚动全量 → im_message(source=SYNC)
- DB: group_mapping 加 name/owner_account/member_count/last_synced_at;user_mapping 加 nick/last_synced_at
  (init.sql 建表 + ADD COLUMN IF NOT EXISTS 老库升级补丁,幂等)
- TencentImClient: 新增 getAppidGroupList(limit,next[,sdkAppId,secretKey])
- 已知限制:C2C单聊无全量会话API;超大群成员需换 get_group_member_info 分页

附带收尾此前未提交的改动:
- 回调字段名修正(FromAccount→From_Account 等腾讯标准字段) + pickMsgRandom/Time/Type 兼容字段差异
- 租户识别重构:前缀经 TenantService.getByPrefixCode 反查 tenantId(主键雪花化与前缀解耦)
- FreeMarker java.time ?string 坑修复(usage/queue Controller 预格式化) + 消息记录"全部"状态修复
- 新增项目 CLAUDE.md + .claude/memory 基建(gitignore 含密钥记忆,不进 git)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 08:40:46 +08:00

83 lines
6.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- Last updated: 2026-07-09 | Commit: b679d47 -->
# tencent-im-util
腾讯 IM 回调分发工具:接收腾讯 IM 的消息回调,落库后按租户/源应用分发。配套管理后台、用量统计、关系链/消息迁移等。
> 本文件为**项目级技术上下文**(行为准则见全局 `~/.claude/CLAUDE.md`)。密钥一律不写在此处,配置项以 `app.yml` 为准。
## 技术栈
- **框架**Solon`solon-parent`,非 Spring),Java 21`solon-web`
- **鉴权**Sa-Token`sa-token-solon-plugin`
- **持久层**MyBatis-Plus`mybatis-plus-extension-solon-plugin`+ PostgreSQL + HikariCP
- **缓存/队列**RedisJedis+ Caffeine 本地缓存
- **视图**FreeMarker`solon-view-freemarker`
- **日志**logback`solon-logging-logback-jakarta`
- **腾讯 IM**`tls-sig-api-v2`UserSig 签名)+ 自封装 `TencentImClient`REST API
- **定时**`solon-scheduling-simple`**工作线程**:自实现 `worker/DispatchWorker`
## 构建与运行
```bash
# 打包(离线模式,跳过测试)
mvn -o package -DskipTests
# 运行
java -jar target/tencent-im-util.jar
```
> ⚠️ **不要用 `mvn solon:solon`**(本项目下不可用,会失败)。详见 `.claude/memory/run-app-jar.md`。
> 端口 `8092`contextPath `/imutil`(即所有路由前缀 `/imutil`)。控制台中文需 UTF-8 终端(已在 `logback.xml` 修正 charset)。
## 目录结构(`src/main/java/com/imutil`
| 包 | 职责 |
|---|---|
| `controller` | `AdminController`(`/admin/*` 后台)、`CallbackController`(`/callback/im` 回调入口)、`HealthController``SigController`(UserSig 下发) |
| `service` + `service/impl` | 业务逻辑(接口 + 实现) |
| `entity` | MyBatis-Plus 实体:`Tenant`/`SourceApp`/`ImMessage`/`DistQueue`/`UsageStat`/`MigrateTask`/`UserMapping`/`GroupMapping`/`Recording`/`TrtcRoom`/`CrossTenantGrant`/`CrossTenantAudit`/`PullWatermark`/`ApiCallLog`/`AdminUser` |
| `mapper` | MyBatis 映射,含 `PartitionMapper`PG 分区管理) |
| `filter` | `AdminAuthFilter`(后台鉴权)、`TenantAuthFilter`(租户鉴权)、`GlobalExceptionFilter`(全局异常) |
| `task` | 定时任务:`DispatchRecoverTask`(死信重投)、`PartitionCreateTask`(分区创建)、`PullCheckTask``UsageStatTask` |
| `tencent` | `TencentImClient`REST API + 429 限速重试)、`TencentCallbackSign`(回调签名校验)、`UserSigUtil` |
| `worker` | `DispatchWorker`(消费分发队列) |
| `common` | 工具类:`PasswordUtil`(PBKDF2)、`RedisService``LocalCache``RateLimiter``Jsons``Httpx``Ids``MsgKeys``TenantContext``HealthService``BizException` |
| `model` | `Result`(统一响应体) |
## 核心调用链
1. **回调分发(主链路)**:腾讯服务器 → `CallbackController#callback`(`/imutil/callback/im`) → `CallbackServiceImpl`(验签 + 落 `ImMessage` + 入 `DistQueue`)→ `DispatchWorker` 消费 → 分发到目标租户/源应用;失败由 `DispatchRecoverTask` 重投。
2. **管理后台**`AdminController`Sa-Token 会话)+ FreeMarker 页面(`resources/templates/*.ftl`):login / home / tenant / sourceapp / grant / queue / usage / password / messages / migrate。
3. **数据迁移**`MigrateService`C2C 全量分页 + 群消息,`msgLookbackDays` 回溯天数,429 自动重试)。
4. **跨租户授权**`CrossTenantService``CrossTenantGrant` 授权 + `CrossTenantAudit` 审计)。
5. **分区与统计**`PartitionService`(按 `msg_time` 分区裁剪)+ `PartitionCreateTask``UsageStatService` + `UsageStatTask`
## 项目约定(务必遵守)
- **Long ID → String**:雪花 ID 等 `Long` 序列化给前端**必须** `String.valueOf()`,否则 JS 精度丢失(全局规则 10.1)。
- **FreeMarker + java.time 坑**ftl 里**禁止**对 `LocalDateTime`/`OffsetDateTime``?string(pattern)`(抛 `NonMethodException`)。改为 Controller 端 `DateTimeFormatter.format` 预格式化成 `xxxStr` 字段,ftl 用 `${obj.xxxStr!}`。详见 `.claude/memory/freemarker-java-time.md`
- **LocalDate / DateTimeFormatter**pattern 含 `H/m/s` 时只能用 `LocalDateTime`,禁用 `LocalDate.now()`(全局规则 10.2)。
- **中文注释**:所有注释用简体中文,标识符保持英文(全局规则 9)。
- **密码**`PasswordUtil` PBKDF2 哈希存 `admin_user.password_hash``iterations:salt:hash`);改密走 `/admin/password`
- **配置不提交**`app.yml` 含密钥(Redis 密码 / `tencent.secretKey` / admin 默认密码),长期处于未提交状态,**勿提交**;如需本地覆盖敏感值用 `app-env.yml`(已 gitignore)。
## 关键配置(`src/main/resources/app.yml`,值为准)
- `server.port` / `server.contextPath`
- `solon.dataSources.db1`PostgreSQL 连接)
- `imutil.redis`host/port/password/database
- `imutil.tencent``sdkAppId`/`secretKey`/`adminUserId`/`apiHost`/`usersigExpireDays`/`callbackToken`——`callbackToken` 留空则跳过回调签名校验,仅联调用)
- `imutil.admin``defaultUsername`/`defaultPassword`——仅首次初始化 `admin_user`
- `imutil.migrate``msgLookbackDays` 等)
- `sa-token.*`
## 文档与外部资源
- **实施记录与测试用例**Obsidian 库 `8 腾讯IM&音视频分发\实施记录与测试用例.md`(项目外,按 T1–T16 任务编号组织;**不进 git**)。
- **项目记忆**`.claude/memory/`(已 gitignore,含账号/密码/密钥提醒等;索引见其 `MEMORY.md`)。召回失效时跑 `/memory-sync` 重新同步到会话目录。
- **数据库操作**:本机无 `psql`,用 DBX MCP`192.168.10.118-pg`database `tencen_im`)查改数据。详见 `.claude/memory/pg-via-dbx.md`
- **回调测试**:端点 `/imutil/callback/im`,本地可用 curl 模拟(见 `.claude/memory/tencent-callback-test.md`)。
## 当前进度
核心功能 T1T15 已完成(T12/T13 TRTC 音视频按需暂缓),T14 消息迁移 V1–V4、T16 消息记录查看已完成。详见实施记录文档与 `.claude/memory/git-author-and-progress.md`