← 返回导航

通知渠道模块设计

1. 定位

对接企业微信、钉钉、飞书三个 IM 平台,把系统内的通知(审批待办、预警、日报等)推送到平台成员或群。

与站内通知(notifications)的关系:站内通知是业务事实层(谁该收到什么),本模块是投递层(通过什么通道送出去)。业务模块只调站内通知服务,不感知本模块。

2. 核心能力

能力 说明
渠道配置 每平台一页:基础信息(企业身份与凭证)+ 对人推送 + 群机器人 + 成员绑定 + 发送记录
应用推送 企微 message/send、钉钉工作通知、飞书 im/v1/messages,按绑定关系投递到人
群机器人 每平台可配置多个 webhook,按群管理(名称/安全方式/推送内容范围)
成员绑定 系统用户 ↔ 平台用户 ID;手工绑定为主,手机号批量匹配为辅
场景路由 通知场景(审批/预警/日报…)→ 通道与接收范围的配置
发送记录 每条外发留痕:通道、接收方、摘要、状态、重试次数
连接验证 保存配置时自动验证凭证;任意时刻可手动发送测试消息

3. 边界

4. 投递流程

业务模块 → sys_notifications 落库(与业务同事务提交,业务侧零改动)
              ↓(Celery beat 轮询,≤30s)
        场景路由(key = biz_module.biz_type,该场景发哪些通道)
              ↓
        通道适配器(按平台格式化报文)
              ↓
        Celery 发送队列(限流、重试)
              ↓
        平台 API → 发送记录落库(ntc_send_logs)

5. 关键规则

  1. 分发触发:Celery beat 轮询 sys_notifications(30s 一轮),以 ntc_send_logs.idempotency_key 判重,通知随业务事务回滚则自然不投递;业务模块不感知本模块,后续如需准实时可升级为 after_commit 事件钩子。
  2. token 管理:企微/钉钉/飞书凭证统一缓存(Redis/内存),有效期前 5 分钟主动刷新;接口并发请求共用同一缓存键,防并发重复取号。
  3. 限流:群机器人限速企微/钉钉 20 条/分钟/机器人、飞书约 100 条/分钟且 5 条/秒(按平台分桶配置,默认取保守值);钉钉工作通知同一用户 500 条/天、同内容一天一次。
  4. 重试:仅网络错误与 5xx 重试(指数退避,最多 3 次);4xx(凭证失效、用户不在应用可用范围等)直接置失败不重试,记录错误码。
  5. 内容安全:金额、成本、底价类内容仅推送给有对应数据权限的绑定用户;绑定缺失或权限不足时跳过并在发送记录标记 skipped_no_permission。
  6. 成员绑定:ntc_identities 以(user_id, platform)唯一;手工绑定为主,手机号匹配失败不自动猜测,转人工绑定。
  7. 幂等:每条外发带 idempotency_key(通知 id + 通道 id),重试不产生重复消息。

6. 权限

权限码 用途
ntc.read 查看渠道配置(脱敏)、成员绑定、发送记录
ntc.manage 配置与启停通道、绑定管理、发送测试消息

凭证字段的读取永远脱敏(••• 回显),ntc.manage 也不例外。