文件
hl-api-changelog/changelogs-v2/2026-10/04_8754_通知事件配置内部接口新增短信模板就绪字段-修改接口-管理后台.md
T

205 行
8.1 KiB
Markdown
原始文件 Blame 文件历史

此文件含有不可见的 Unicode 字符
此文件含有人类无法区分的不可见的 Unicode 字符,但可以由计算机进行不同的处理。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
schema: "hl-changelog/v2"
ticket: "8754"
title: "通知中心内部接口「按事件码查通知事件配置」出参新增 smsTemplateReady(短信模板是否已配真实号)"
consumer: "internal"
author: "jw(GIT)"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "not_required"
frontend_status: "not_required"
frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: ""
status_note: "GET /internal/notification/event-config/{eventCode} 出参纯新增派生字段 smsTemplateReady(模板号非空且非哨兵 TODO_PLACEHOLDER 为 true),首个调用方为 order-v3 补发成团通知。内部接口不经网关,前端无需对接。已合并 dev-v3(PR #8775,merge aac6a6a13)并部署 TEST,经 order-v3 补发链路验证哨兵 / 假模板号 / 还原三态读数正确。管理后台侧变化见同日 04_8754 修改接口·管理后台那份。"
updated_at: "2026-10-04"
base: "dev-v3"
---
# user-service: 内部接口「按事件码查通知事件配置」新增 smsTemplateReady
> **服务**: hl-user-service(内部接口,网关不放行)
> **PR**: `#8775`(已合入 `dev-v3`,合并提交 `aac6a6a13`)
> **Issue**: #8754
---
## ⚠️ 关键变化
🟢 `GET /internal/notification/event-config/{eventCode}` 出参**纯新增**一个派生字段 `smsTemplateReady`(Boolean):短信模板号非空且不是哨兵 `TODO_PLACEHOLDER` 时为 `true`。入参、其余出参、错误行为不变。
🟢 新增首个调用方:order-v3 补发成团通知(`NotificationSendLogFeignClient#getEventConfig`)据此判断短信能不能真发,补发回执才能如实计数。
---
## 一、背景
「先开发、模板后补」期间,事件配置的 `sms_enabled=1` 而 `sms_template_code='TODO_PLACEHOLDER'`:通知中心照常进短信通道,但 `SmsChannelSender` 遇哨兵只记 SKIP_NO_TEMPLATE、不真发。调用方只看 `smsEnabled` 会把发不出去的短信算成送达。哨兵判定原只写在 `SmsChannelSender` 里,本单收成 `SmsTemplateCodes.isConfigured` 一处,发送侧与本接口共用,调用方不必知道哨兵字面量。
---
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 按事件码查通知事件配置 | GET | `/internal/notification/event-config/{eventCode}` | 修改 | 出参新增派生字段 `smsTemplateReady` |
---
## 三、接口详情
### 1. 按事件码查通知事件配置 `GET /internal/notification/event-config/{eventCode}`
**VO**: `Result<NotificationEventConfigRespVO>`
#### 使用场景
服务间只读查询某通知事件的通道开关与模板配置。order-v3 补发成团通知时调用,按 `inappEnabled`、`smsEnabled && smsTemplateReady` 判断两条客户通道能否真发出。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| eventCode | Path | String | ✅ | 事件编码 | **不变**,如 `GROUP_BATCH_FORMED` |
| X-Internal-Token | Header | String | ✅ | 集群内部令牌 | **不变**,与其他 `/internal/**` 相同 |
#### 出参
| 字段 | 类型 | 说明 |
|------|------|------|
| smsTemplateReady | Boolean | 🆕 短信模板是否已就绪:`smsTemplateCode` 非空且不是 `TODO_PLACEHOLDER` 为 `true`。派生字段,不落库。与 `smsEnabled=1` 同时成立短信才会进入真实发送 |
| eventCode / eventName / categoryCode | String | **不变** |
| inappEnabled / smsEnabled / miniappEnabled / oaEnabled / weworkEnabled | Integer | **不变**,0=关 1=开 |
| smsTemplateCode / smsSignName / smsFieldMapping 等模板字段 | String | **不变** |
#### 请求示例
```http
GET /internal/notification/event-config/GROUP_BATCH_FORMED HTTP/1.1
Host: hl-user-service
X-Internal-Token: <集群内部令牌>
```
#### 响应示例
```json
{
"code": 200,
"message": "success",
"data": {
"eventCode": "GROUP_BATCH_FORMED",
"eventName": "成团通知",
"categoryCode": "GROUP_BATCH",
"inappEnabled": 1,
"inappTitleTemplate": "您报名的团已成团",
"inappContentTemplate": "您报名的${productName}(出发日期${departDate})已成团,请留意后续出行安排。",
"inappLinkTemplate": "/packages/order/detail/detail?id=${orderId}",
"smsEnabled": 1,
"smsTemplateCode": "TODO_PLACEHOLDER",
"smsSignName": null,
"smsFieldMapping": "{\"productName\":\"${productName}\",\"departureDate\":\"${departDate}\",\"batchNo\":\"${groupBatchNo}\"}",
"miniappEnabled": 0,
"oaEnabled": 0,
"weworkEnabled": 0,
"weworkReceiverType": null,
"smsTemplateReady": false
},
"success": true
}
```
#### 空数据 / 降级响应
事件不存在时 `data=null`(不变),调用方应视为所有通道不可达。order-v3 侧降级(调用失败 / 熔断)返回失败结果 `100903`,补发接口据此返回 589595,不会把失败当成「未配置」。
#### 错误响应
缺少或错误的 `X-Internal-Token` 被 `InternalAuthInterceptor` 拦截(不变):**HTTP 403**,响应体如下(注意字段是 `msg` 不是 `message`):
```json
{
"code": 403,
"msg": "内部接口禁止外部访问"
}
```
#### 业务边界
- `smsTemplateReady` 只看模板号,不看 `smsEnabled`;调用方须两者同时判断。
- 不判断阿里云凭据是否配置:TEST 未配凭据时短信为模拟成功(只打日志不真发),本字段仍可能为 `true`。
---
## 四、契约约束与正确调用方式
- 判断「短信能否真发」:`smsEnabled == 1 && smsTemplateReady == true`。不要在调用方写死 `TODO_PLACEHOLDER` 字面量。
- 调用方本地 VO 建议 `@JsonIgnoreProperties(ignoreUnknown = true)`,只取需要的字段。
---
## 五、数据库行为
- 本接口只读,零写入;`smsTemplateReady` 由 `sms_template_code` 派生,不落库。
- 同批迁移 `V20261003_8754` 改了 `notification_event_config` 中 `GROUP_BATCH_FORMED` 一行(开短信、模板号哨兵、变量映射),与本接口契约无关。
---
## 六、边界行为
- `smsTemplateCode` 为 `null` / 空串 / `TODO_PLACEHOLDER` → `false`;其他任意值 → `true`(不校验是否为阿里云真实存在的模板号)。
## 六.6、修改前后对比
| 场景 | 改前 | 改后 |
|---|---|---|
| 模板号为哨兵 | 出参无此字段,调用方只能自己比对字面量 | `smsTemplateReady=false` |
| 模板号为真实值 | 同上 | `smsTemplateReady=true` |
## 六.7、影响评估
- **是否破坏向后兼容**:否,纯新增字段;改前全仓零调用方。
- **回滚**:revert PR #8775 后重新部署 user-service(order-v3 读不到该字段时按「短信未就绪」保守计数)。
---
## 七、不影响范围
- 其他 `/internal/notification/**` 接口、通知分发逻辑、短信发送行为(哨兵判定结果与改前逐字等价)。
- 管理后台通知配置接口。
---
## 八、测试环境已验证
**环境**:TEST **验证时间**:2026-10-03 20:43~20:50
**构建身份**:user-service `dev-v3 @ aac6a6a13`。
本接口不经网关,经它唯一的调用方 order-v3 补发链路间接验证:
| 配置状态 | order-v3 补发回执 | 说明 |
|---|---|---|
| `smsEnabled=1`,`smsTemplateCode=TODO_PLACEHOLDER` | `smsReady=false`、`smsCount=0` | order-v3 读到 `smsTemplateReady=false` |
| 后台把模板号改成假号 `SMS_TEST_8754` | `smsReady=true`、`smsCount=2` | 读到 `smsTemplateReady=true`;后台改配置时清了缓存,3 秒后即生效 |
| 还原为 `TODO_PLACEHOLDER` | `smsReady=false` | 读到 `smsTemplateReady=false` |
本地:`InternalNotificationControllerTest` 15 例(含哨兵 → `false` 且序列化进 JSON)、`SmsTemplateCodesTest` 2 例、`SmsChannelSenderTest` 37 例;user-service 全量 4211 例 0 失败。
---
## 十、相关文档
- Issue `#8754`;PR `#8775`;管理后台侧变化见同日 `04_8754` 修改接口·管理后台那份
## 关联 / 联系人
### 链接
- **Issue**: [#8754](https://git.1814.love/wx/HL/issues/8754)
- **PR**: [#8775](https://git.1814.love/wx/HL/pulls/8775)
- **Merge commit**: [aac6a6a13](https://git.1814.love/wx/HL/commit/aac6a6a13)
### 联系人
- **后端负责人**: @jw