2026-07-16 21:00:33 +08:00

6.6 KiB
Raw Blame History

由壹点通知中心接入指南

本文面向需要接入“由壹点”统一钉钉单聊通知的业务项目。业务项目只调用通知中心,不直接持有钉钉应用密钥,也不直接调用钉钉机器人接口。

1. 接入边界

  • 通知中心负责:统一机器人身份、项目隔离、签名认证、幂等防重、异步投递、有限重试、已读状态查询和跳转域名校验。
  • 业务项目负责:确定通知触发时机、取得准确的钉钉 userId、生成稳定的幂等键、提交业务内容、保存通知中心返回的投递 ID。
  • 钉钉 AppKey、AppSecret、RobotCode 只能保存在通知中心。
  • 业务项目只能保存自己独有的项目 HMAC 密钥;禁止把密钥提交到 Git、发送到前端或写入浏览器环境变量。

2. 接入前需要提供的信息

向通知中心维护人员提交以下信息:

字段 要求 示例
projectCode 2~40 位小写字母、数字、下划线或短横线;创建后不再修改 fixed_asset
projectName 用户能理解的简短产品名称 固定资产
allowedHosts 卡片按钮允许跳转的 HTTPS 域名,不含协议、端口和路径 asset.jiansun.vip
负责人 至少一名业务负责人和一名技术负责人 姓名及联系方式
使用场景 说明触发条件、接收人和预计发送量 资产报废待审批
是否需要免登 默认否;只有卡片进入项目后需要自动建立登录态时才开启 否

通知中心维护人员完成登记后,通过安全渠道提供:

  • YYD_NOTIFICATION_PROJECT_CODE
  • YYD_NOTIFICATION_PROJECT_SECRET
  • YYD_NOTIFICATION_CENTER_URL

3. 业务项目环境变量

YYD_NOTIFICATION_CENTER_URL=https://sc.jiansun.vip/notification-center
YYD_NOTIFICATION_PROJECT_CODE=fixed_asset
YYD_NOTIFICATION_PROJECT_SECRET=由通知中心单独分配的项目密钥

这些变量只允许出现在业务后端的生产环境中。前端代码不得直接调用通知中心。

4. 发送接口

接口:POST /v1/notifications

{
  "idempotencyKey": "disposal_applied:53:approver-user-id:v1",
  "recipientUserId": "钉钉userId",
  "title": "资产报废待审批",
  "content": "**申请时间:** 2026年7月16日 14:30\n\n**资产:** 摄影灯 A-102\n\n**申请人:** 张三",
  "actionTitle": "立即审批",
  "actionUrl": "https://asset.jiansun.vip/workflows/disposals/53"
}

字段约束:

字段 规则
idempotencyKey 必填,最长 160 字符;同一业务事件、同一收件人必须稳定不变
recipientUserId 必填,只能使用企业通讯录中的钉钉 userId
title 必填,最长 100 字符;只写业务主题,不要添加 【项目名】,拼接项目名后的最终标题不能超过 120 字符
content 必填,Markdown,业务正文最长 4800 字符;不要自行添加首行标题,各字段之间必须空一行,通知中心加上统一首行后的最终正文也不能超过 4800 字符
actionTitle 可选,最长 20 字符,默认“查看详情”
actionUrl 必填,标准 443 端口的完整 HTTPS 地址,域名必须在项目白名单内

通知中心会自动生成最终标题:

【{项目名称}】{业务标题}

例如业务项目提交“资产报废待审批”,用户最终看到的是:

【固定资产】资产报废待审批

卡片正文首行也由通知中心统一生成为 ### 【项目名称】业务标题。为兼容已接入项目,业务正文如果仍以三级 Markdown 标题(###)开头,通知中心会先移除该旧标题,再生成统一首行,避免出现双标题;其它级别标题按正文原样保留。

5. 请求签名

每次请求必须携带:

  • x-yyd-project-code
  • x-yyd-timestamp:Unix 秒
  • x-yyd-nonce:16~100 位,每次请求重新生成
  • x-yyd-signature:HMAC-SHA256 十六进制字符串

签名原文:

timestamp\nnonce\nHTTP_METHOD\nPATH\nSHA256(rawBody)

注意:

  • PATH 是通知中心内部接口路径,如 /v1/notifications,不包含公网反向代理前缀 /notification-center,也不包含域名和查询参数。
  • 计算签名的 rawBody 必须与实际发送的请求正文逐字节一致。
  • 服务器时间与通知中心相差不能超过五分钟。
  • nonce 不能复用,即使上一次请求失败也要生成新的 nonce。

可直接复用的实现见 examples/node/notification-client.mjs。

6. 幂等和多人通知

当前接口一次只接收一名收件人。向多人发送时,业务项目应逐人创建通知,每个人使用独立但稳定的幂等键:

{事件类型}:{业务记录ID}:{recipientUserId}:{消息版本}

例如:

survey_created:73a3f3e9:15891598262598724:v1
survey_created:73a3f3e9:16408293139985728:v1

相同 projectCode + idempotencyKey:

  • 请求内容相同:返回原投递记录,不重复发送。
  • 请求内容不同:返回 409 IDEMPOTENCY_CONFLICT,业务项目必须修正幂等键设计,不能通过随机换键绕过。

7. 接收返回值和查询状态

创建成功返回 HTTP 202,表示通知中心已接受任务,不代表钉钉已经送达。业务项目应保存返回的 id,必要时调用:

GET /v1/notifications/{id}

查询请求也必须签名,GET 请求正文为空字符串。状态含义和处理方式见 错误与状态规范。

8. 钉钉 H5 免登是可选能力

普通通知接入不需要实现免登。只有用户点击卡片后必须自动进入业务登录态时,才申请开启项目 login 配置。

开启后业务项目还必须:

  1. 提供精确的 HTTPS 回调地址和允许回跳的站内路径前缀。
  2. 后端接收一次性票据,并通过签名接口兑换钉钉 userId。
  3. 在创建本地 Session 前重新核验账号绑定、在职状态和业务权限。

通知中心票据只能证明钉钉身份,不能替代业务项目自身的授权判断。

9. 最小上线验证

接入完成后至少验证:

  1. 本人收到单聊通知。
  2. 另一名真实员工收到单聊通知。
  3. 最终标题包含正确的项目来源。
  4. 卡片按钮只能跳转到项目白名单域名。
  5. 使用相同幂等键重复请求不会重复发送。
  6. 无效 userId 能得到明确失败状态。
  7. 创建接口返回 202 后,最终状态能进入 sent、unread 或 read。
  8. 日志、错误页和前端响应中均没有项目密钥。

完整清单见 新项目接入清单。