主体(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>
6.0 KiB
6.0 KiB
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 - 缓存/队列:Redis(Jedis)+ Caffeine 本地缓存
- 视图:FreeMarker(
solon-view-freemarker) - 日志:logback(
solon-logging-logback-jakarta) - 腾讯 IM:
tls-sig-api-v2(UserSig 签名)+ 自封装TencentImClient(REST API) - 定时:
solon-scheduling-simple;工作线程:自实现worker/DispatchWorker
构建与运行
# 打包(离线模式,跳过测试)
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(统一响应体) |
核心调用链
- 回调分发(主链路):腾讯服务器 →
CallbackController#callback(/imutil/callback/im) →CallbackServiceImpl(验签 + 落ImMessage+ 入DistQueue)→DispatchWorker消费 → 分发到目标租户/源应用;失败由DispatchRecoverTask重投。 - 管理后台:
AdminController(Sa-Token 会话)+ FreeMarker 页面(resources/templates/*.ftl):login / home / tenant / sourceapp / grant / queue / usage / password / messages / migrate。 - 数据迁移:
MigrateService(C2C 全量分页 + 群消息,msgLookbackDays回溯天数,429 自动重试)。 - 跨租户授权:
CrossTenantService(CrossTenantGrant授权 +CrossTenantAudit审计)。 - 分区与统计:
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)。
- 密码:
PasswordUtilPBKDF2 哈希存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.contextPathsolon.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,databasetencen_im)查改数据。详见.claude/memory/pg-via-dbx.md。 - 回调测试:端点
/imutil/callback/im,本地可用 curl 模拟(见.claude/memory/tencent-callback-test.md)。
当前进度
核心功能 T1–T15 已完成(T12/T13 TRTC 音视频按需暂缓),T14 消息迁移 V1–V4、T16 消息记录查看已完成。详见实施记录文档与 .claude/memory/git-author-and-progress.md。