主题
07 — 通知公告推送(HMAC)
第三方将平台广播公告写入门户通知公告域(portal_notice / inbox)。
与事项推送(02)分管道:用户侧进 /api/notice/inbox,不进 /api/portal/matters。
推荐先读:08-待办与通知公告-集成手册.md(选型 + 双管道示例)
代码锚点:OpenNoticeController、OpenNoticeHmacFilter、OpenNotice*Request。
设计方案:doc/36-第三方推送-通知公告与待办.md。
基路径:/api/open/notices
方法:全部为 POST。
1. 鉴权头
与 02-事项推送-HMAC.md 完全一致:
| Header | 必填 | 说明 |
|---|---|---|
X-Client-Id | 是 | SSO client_id |
X-Timestamp | 是 | Unix 秒 |
X-Signature | 是 | HMAC-SHA256 的 Hex |
X-Idempotency-Key | 否 | 记入 portal_notice_push_log,便于对账(管理端「消息日志」) |
时间窗:±300 秒。Client 须存在、启用、绑定 system_code、CONFIDENTIAL 且可解析 client_secret。
签名串:
text
{clientId}\n{timestamp}\n{rawBody}system_code 始终取自 Client 绑定,不要在 body 里依赖自带 systemCode。
一期安全:TLS + HMAC(无 L3 载荷信封)。签名算法细节与伪代码见 02 §2 或 08 §2。
2. 接口清单
| 方法 | 路径 | 语义 |
|---|---|---|
| POST | /api/open/notices/publish | 按 system_code + externalId 首次发布;已存在 → code=409 |
| POST | /api/open/notices/recall | 按绑定 system_code + externalId 撤回 |
成功 publish 的 data:
| 字段 | 说明 |
|---|---|
noticeId / noticeCode | 门户公告标识 |
externalId | 回显 |
dispatchMode | SYNC / ASYNC(预估受众 >500 异步) |
dispatchStatus / estimatedRecipients / taskCode? | 投递信息 |
3. PUBLISH — POST /api/open/notices/publish
| 字段 | 必填 | 说明 |
|---|---|---|
externalId | 是 | 对方业务主键;与 Client system_code 幂等 |
noticeType | 否 | 默认 NOTICE;允许 ALERT / REMIND |
title | 是 | 标题 |
summary | 否 | 摘要 |
content | 否 | 正文 |
pcUrl / mobileUrl | 否 | 跳转 URL |
initiatorUsername | 否 | 门户登录名;空则记 open:{clientId} |
audience | 是 | 见下表 |
audience
| 字段 | 条件 | 说明 |
|---|---|---|
mode | 必填 | USERS / DEPTS / ALL |
usernames | mode=USERS | 门户登录名列表(须已存在) |
deptCodes | mode=DEPTS | 部门业务编码 |
includeSubDepts | mode=DEPTS | 是否含下级,默认 true |
同键再次 publish → 409(一期不做内容 upsert)。受众解析结果为空 → 400。
请求示例
指定用户
json
{
"externalId": "ANN-1001",
"title": "放假通知",
"summary": "摘要",
"content": "正文",
"audience": { "mode": "USERS", "usernames": ["zhangsan"] }
}按部门
json
{
"externalId": "ANN-DEPT-1",
"title": "部门通知",
"audience": {
"mode": "DEPTS",
"deptCodes": ["D001"],
"includeSubDepts": true
}
}全员
json
{
"externalId": "ANN-ALL-1",
"title": "全员公告",
"audience": { "mode": "ALL" }
}curl
bash
CLIENT_ID="demo-client"
SECRET="your-client-secret"
TS=$(date +%s)
BODY='{"externalId":"ANN-1001","title":"放假通知","audience":{"mode":"USERS","usernames":["zhangsan"]}}'
SIG=$(node -e "const c=require('crypto');const b=process.argv[1],id=process.argv[2],ts=process.argv[3],s=process.argv[4];console.log(c.createHmac('sha256',s).update(id+'\n'+ts+'\n'+b).digest('hex'))" "$BODY" "$CLIENT_ID" "$TS" "$SECRET")
curl -sS -X POST "https://portal.example.com/api/open/notices/publish" \
-H "Content-Type: application/json" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Timestamp: $TS" \
-H "X-Signature: $SIG" \
-d "$BODY"成功响应示例
json
{
"code": 0,
"message": "success",
"data": {
"dispatchMode": "SYNC",
"noticeId": 1234567890123456789,
"noticeCode": "ANN-...",
"externalId": "ANN-1001",
"dispatchStatus": "SUCCESS",
"estimatedRecipients": 1,
"taskCode": null
},
"traceId": "a1b2c3d4e5f6"
}4. RECALL — POST /api/open/notices/recall
| 字段 | 必填 | 说明 |
|---|---|---|
externalId | 是 | 对方业务主键 |
公告须已存在,否则 404「公告不存在: {systemCode}/{externalId}」。
撤回后个人 inbox 不再展示;进行中的异步投递会尝试取消。
bash
TS=$(date +%s)
BODY='{"externalId":"ANN-1001"}'
SIG=$(node -e "const c=require('crypto');const b=process.argv[1],id=process.argv[2],ts=process.argv[3],s=process.argv[4];console.log(c.createHmac('sha256',s).update(id+'\n'+ts+'\n'+b).digest('hex'))" "$BODY" "$CLIENT_ID" "$TS" "$SECRET")
curl -sS -X POST "https://portal.example.com/api/open/notices/recall" \
-H "Content-Type: application/json" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Timestamp: $TS" \
-H "X-Signature: $SIG" \
-d "$BODY"5. 错误与联调提示
| 现象 | 排查 |
|---|---|
缺少 HMAC 鉴权头 | 三个头是否齐全、是否被网关剥离 |
HMAC 签名校验失败 | body 是否被重新序列化;换行是否为 \n;secret 是否最新 |
Client 未绑定 system_code | 管理端补绑 |
code=409 公告已存在 | 同 externalId 勿重复 publish;需改内容请另开新 externalId 或先业务侧约定 |
受众解析结果为空 | 用户名/部门编码是否在门户存在 |
| 用户在「事项」里找不到 | 公告只出现在「通知公告」收件箱 |
6. 与事项推送选型
| 场景 | 用哪条 |
|---|---|
| 审批待办、办理态、重开 | /api/open/matters |
| 流程抄送/少数人知会 | /api/open/matters(NOTICE + parties) |
| 全员/按部门广播公告、可撤回 | 本接口 /api/open/notices |
同一业务主键不要两条管道各推一条。
公共约定见 01-接入准备.md;双管道速查见 08。