# 通知（xlyMsg）

出站通知（钉钉、微信和邮件）通过 `xlyMsg` 模块完成。它**不是**调用方直接访问的 HTTP 接口面，而是范围内服务在业务事件需要向聊天平台或邮箱推送消息时调用的内部 SDK。

## 模块内容

`xlyMsg/src/main/java/com/xly/`：

| 包 | 角色 |
|---|---|
| `dingtalk/service/DingTalkService` + `dingtalk/util/SendDingTalkUtil`、`DingTalkMsgContentUtil`、`LocalCacheClient` | 钉钉企业消息分发。封装 `com.aliyun:dingtalk:2.1.14` 和 `com.aliyun:alibaba-dingtalk-service-sdk:2.0.0`。 |
| `wechat/service/WechatService` + `wechat/util/SendWxUtil`、`Wx_SignatureUtil`、`JedisMsgUtil`、`MsgContentUtil`、`Xml2JsonUtil` | 微信工作平台分发，包含签名和发送，以及 Redis 支撑的 access-token 缓存。 |
| `emial/service/SendEmailService` + impl | 邮件分发（包名拼成了 `emial`）。`xlyFlow` 的 `QuartzTask` 会用它发送定时任务邮件；`xlyEntry` 也有自己的 `com.xly.web.email.SendEmailService`，供 `ScheduledTasks` 驱动的邮件路径使用。两个接口名相同、实现并行保留，属于历史原因。 |
| `notice/service/NoticeService` | 与供应商无关的通知抽象；把“通知用户 X 某事件 Y”的逻辑路由到正确后端。 |

`xlyMsg/build.gradle` 中唯一的框架依赖是 `xlyPersist`。该模块作为库被消费，不会作为自己的服务部署。

## 谁在调用它（范围内调用方）

这些调用让 `xlyMsg` 成为框架相关内容，而不是 plat 层内容：

| 调用方 | 作用 |
|---|---|
| `xlyEntry/.../web/businessweb/TestController.java` | 诊断端点，用于发送测试钉钉消息。 |
| `xlyBusinessService/.../thread/UpdateDingTalkThread.java` | 单据变更后推送钉钉更新的异步线程。 |
| `xlyBusinessService/.../service/impl/CheckExamineFlowServiceImpl.java` | 工作流审批通知；Activiti 任务被重新分配或完成时，待办人会收到聊天消息。 |
| `xlyBusinessService/.../service/impl/GenericProcedureCallServiceImpl.java` | 通用存储过程钩子：任何选择接入的 `gdsmodule` 存储过程都可以通过这条路径发布通知。 |
| `xlyInterface/.../util/DingTalkUtil.java` + `scheduler/ScheduledTasks.java`、`ErpJobRunStatus.java` | 集成侧的定时任务心跳 / 失败告警。 |

## 配置

凭据（钉钉企业应用 key/secret、微信 AppID、agent ID）从各环境 yaml profile 读取。这里没有全局默认值，每个客户部署会填自己的值，所以框架 Wiki 无法给出规范示例。查看 `xlyEntry/src/main/resources/application-<env>.yml` 下的 active profile yaml，确认实际消费的 key。

微信路径使用 Redis 缓存 access token（`wechat/util/JedisMsgUtil.java`），和框架其他部分使用同一个 Redis。哪些服务共享哪些 Redis，见[多服务部署](../reference/maintainer/deployment.md)。

## 这个机制不是什么

- **不是**入站 webhook 接收器。钉钉回调（例如审批按钮点击）和其他 [webhook](webhooks.md) 一样走 `xlyInterface`。
- **不是** `xlyPlat*` 的推送通知路径。plat 层有自己的通道（`xlyPlatSmsService`、JPush、App 侧推送），本 Wiki 将其视为范围外。
