Files
zyt/artifacts/im-chat-history/callback.md
T
2026-09-09 15:47:48 +08:00

5.2 KiB
Raw Blame History

腾讯 IM 单聊消息即时归档回调

接收地址为 POST https://<业务域名>/api/im/messageNotify。接口调用 DiagnosisLogic::archiveImCallbackMessage(array $payload): int,归档成功、幂等重复或业务层安全忽略均返回腾讯原生应答:

{"ActionStatus":"OK","ErrorCode":0,"ErrorInfo":""}

归档抛异常时返回 HTTP 500 与 ActionStatus=FAIL,不会在写库失败时返回成功。错误响应和日志均不包含消息正文、签名、Token 或数据库异常内容。

部署配置

在服务端 .env 配置以下区段;鉴权 Token 应与腾讯 IM 控制台填写的值完全相同,以下内容仅为占位说明:

[IM]
CALLBACK_TOKEN = "在部署时填入独立生成的回调鉴权Token"

加载路径是 server/config/im.phpenv('im.callback_token', '')。本项目 ThinkPHP Env 也支持进程环境变量 PHP_IM_CALLBACK_TOKEN。Token 为空或只有空白时接口返回 HTTP 503,拒绝全部回调;不会降级为免签名。部署后按既有流程刷新配置缓存和 PHP 常驻进程。

应用 ID 与现有 project.trtc.sdkAppId 配置一致(来自既有 [TRTC] SDK_APP_ID)。只核对 IM/TRTC 应用 ID,无需把 TRTC SecretKey 放入回调 URL 或这个配置文件。

腾讯 IM 控制台进入当前应用的“回调配置”:

  1. 填写上述 HTTPS 回调 URL,并开启回调。
  2. 勾选 发单聊消息之后回调,对应 C2C.CallbackAfterSendMsg。该事件可实时同步客户端或 REST API 单聊消息。腾讯官方单聊回调文档
  3. 在回调 URL 的配置中开启鉴权,填写与 [IM] CALLBACK_TOKEN 相同的 Token。腾讯会追加 SignRequestTime 参数;签名算法为 sha256(Token + RequestTime),时间偏差不得超过一分钟。腾讯官方鉴权说明
  4. 如需超时补投,开启事件发生之后回调的超时重试选项;这类回调默认不重试。官方默认回调超时为 2 秒,应监测归档耗时。失败回包不等同于已开启或保证重试,需结合控制台重试设置与历史拉取补偿。腾讯官方回调超时说明

部署只需新增接口与配置,不需要为患者添加登录 Token。自动控制器路由已支持 /api/im/messageNotifyAPI InitMiddleware 正常实例化控制器,LoginMiddleware 仅对 ImController/messageNotify 跳过用户会话查找,随后由控制器强制腾讯签名校验。其他 API 的登录要求不变。服务本身仍需满足项目原有安装与 HTTPS 入口条件。

接口校验与失败响应

  • 只接受真实 POST 方法,不能通过方法覆盖头把 GET 伪装成 POST。
  • 正文最大 1 MiB;检查 Content-Length 及实际正文长度,JSON 必须是对象,最大解析深度 64。
  • SdkAppid 必须与配置一致;Sign 使用恒定时间 hash_equals 比较,签名时间窗口为正负 60 秒。
  • 请求正文必须有字符串 CallbackCommand;URL 中存在同名命令时必须完全相同。
  • 其他已经通过鉴权、命令一致的回调返回 OK 并忽略,不会进入患者归档。
  • HTTP 400 表示 JSON 或命令无效,403 表示鉴权失败,405 表示请求方法错误,413 表示正文超限,503 表示鉴权配置缺失,500 表示归档失败。

网关或 Web 服务器访问日志应对这个路径省略查询参数,避免默认 $request_uri 日志记录 URL 中的 Sign;应用代码只输出固定归档失败标记。正文内的患者/医生匹配与幂等规则由 archiveImCallbackMessage 负责。

虚构 curl 示例(未执行)

以下域名使用保留的 .invalid 后缀,Token、账户、消息和应用 ID 全是虚构值,只演示参数形状。不要将此示例直接指向生产环境。

DEMO_TOKEN='fictional-example-token'
REQUEST_TIME=$(date +%s)
SIGN=$(printf '%s' "${DEMO_TOKEN}${REQUEST_TIME}" | sha256sum | cut -d ' ' -f 1)
curl --request POST \
  "https://im-callback.example.invalid/api/im/messageNotify?SdkAppid=1400000000&CallbackCommand=C2C.CallbackAfterSendMsg&RequestTime=${REQUEST_TIME}&Sign=${SIGN}" \
  --header 'Content-Type: application/json' \
  --data '{"CallbackCommand":"C2C.CallbackAfterSendMsg","From_Account":"patient_1001","To_Account":"doctor_2001","MsgSeq":7,"MsgRandom":8,"MsgTime":1700000000,"MsgKey":"7_8_1700000000","SendMsgResult":0,"MsgBody":[{"MsgType":"TIMTextElem","MsgContent":{"Text":"虚构测试消息"}}]}'

验证结果

php server/tests/ImCallbackTest.php:81 项断言通过,使用真实控制器、ThinkPHP Request/Json 与 LoginMiddleware,归档逻辑、配置和日志由内存替身替代。覆盖官方签名样例、正负一分钟边界、缺失配置、错误 App ID、伪造签名、命令一致性、JSON 结构、正文上限、无登录回调、写库及日志失败、幂等返回 0,以及其他 action 不能借用回调免登录分支。

新增控制器、签名服务、配置、中间件和测试 PHP 语法检查通过;修改文件 git diff --check 通过。测试使用虚构配置,不加载真实 .env,未连接业务数据库,也没有调用腾讯 API 或修改腾讯控制台。