# 外部 API(`xlyApi`) `xlyApi` 是外部集成方使用的 API 接口面。它作为独立的 Spring Boot WAR 运行(入口类 `xlyApi/src/main/java/com/xly/ApiApplicationBoot.java`),context-path 为 `/xlyApi`,并拥有自己的 `application-*.yml` 文件。 它最关键的设计选择是:**大多数外部端点不是硬编码在 Java 里的,而是 `sysapi` 中的数据行**。新的外部 API 和 xly 其他部分一样,是“注册成数据”的。运行时负责查找 `sApiCode`、验证调用方,并执行元数据指定的内容。 ## 数据驱动分发器:`/api/invoke/{sApiCode}` 最重要的单个端点: ```http POST /xlyApi/api/invoke/{sApiCode} Authorization: Bearer (or query param ?authorizationt=) Content-Type: application/json { ...request body, passed through as `sBody` to the handler... } ``` 处理器:`xlyApi/src/main/java/com/xly/api/web/ApiController.java:223` 中的 `ApiController.invoke()`。该 mapping 是 `@RequestMapping`,框架层不限定 HTTP 方法;每个 API 行的 `sysapi.sMethod` 列声明调用方应使用的动词,并由 `ApiCheckUtil` 在分发时校验。 流程: 1. 读取 `Authorization` header(回退:`authorizationt` 查询参数)。 2. 查找以 `sApiCode` 为键的 `sysapi` 行(通过 `ApiServiceImpl.invoke` → `SELECT … FROM sysapi WHERE sApiCode = #{sApiCode}`)。 3. 如果该行的 `bHasToken` 标志已设置,就 AES 解密 bearer token 取回 `corpid`,再通过 `BrandServiceImpl.selectByCorpid` 到 `sysapibrand` 校验该 `corpid`。如果品牌行的 `iLossTime` 非 0,还会检查 token 内嵌时间戳是否过期。(`sysapithirdtoken` 用于**出站** token,也就是 xly 调第三方 API;这里不用于校验入站 bearer token。) 4. 使用请求 body 合并出的参数 map,执行 `sysapi.sDataSql` 中存放的 SQL 模板。 5. 将调用写入 `sysapilog`。 6. 用 `AjaxResult` 包装结果并返回。 因此,新增一个外部 API 是管理 / PM 任务:向 `sysapi` 插入一行,提供 SQL 模板,设置标志,把 `sApiCode` 和 token 给集成方。不需要改 Java 代码。 ### 需要关注的 `sysapi` 列 | 列 | 含义 | |---|---| | `sApiCode` | 消费方发送的路径变量。每个租户内必须唯一。 | | `sApiName` | 人类可读标签。 | | `sApiUrl` / `sApiUrlRef` | 计算后的 URL,即 `sApiUrlRef + sApiCode`,用于出站分发。 | | `sMethod` | 此 API 期望的 HTTP 方法(`GET`、`POST` 等)。 | | `sHeader`、`sBody`、`sBodyNode`、`sBodyType` | 描述入站请求形状的模板。 | | `sDataSql` | 运行时执行的 SQL 模板。`#{xxx}` 引用会由请求参数填充。 | | `sDataTest`、`sDataTestNode` | BACK API 测试器(`POST /api/apiTest`)使用的请求 / 响应样例。 | | `bHasToken` | `1` 表示要求 `Authorization` 中携带 token;`0` 表示公开。 | ## API 管理端点 `/api/list/...`、`/api/data/...`、`/api/add`、`/api/edit`、`/api/remove` 是管理 `sysapi` 行本身的后台接口面(BACK 的“自定义接口”页面会调用这些)。`POST /api/getSqlTemple` 为给定 API 名称生成 SQL 骨架;`POST /api/apiTest` 使用 `sDataTest` 中的测试夹具跑一次端到端 dry-run。 ## Token 端点:`/token/*` | 端点 | 方法 | 用途 | |---|---|---| | `/token/getToken?corpid=&corpsecret=` | GET / POST | 为集成方的 `(corpid, corpsecret)` 组合签发 bearer token。(mapping 不限定方法。) | 返回的 token 就是 `/api/invoke/{sApiCode}` 期望在 `Authorization` 中收到的值。完整实现位于 `xlyApi/src/main/java/com/xly/api/web/TokenController.java` 及其 service。 对于 xly 自己获取的**第三方** token(为了代表客户调用集群外 API),见 `/thirdtoken/*`,它由 `sysapithirdtoken` 支撑(表注释:第三方token获取接口)。 ## 其他收敛后的接口面 这些是同一个 WAR 中托管的较小专用 API: | 端点前缀 | Controller | 用途 | |---|---|---| | `/online/api/{sApiCode}` | `OnlineController` | 为给定 `sysapi` 行渲染 BACK 浏览器内 API 调试 / 控制台页面(返回 Thymeleaf view,不执行 API)。 | | `/online/onlineword/{sApiCode}` | `OnlineController` | 渲染“word”风格 API 文档页面。 | | `/online/onlinelist` | `OnlineController` | 渲染在线 API 列表页面。 | | `/online/getToken` | `OnlineController` | 渲染浏览器内 token 获取辅助页面。 | | `/pro/get/{sProName}` | `ProContentController` | 渲染 BACK 页面,用于展示某个存储过程源码。 | | `/pro/getData/{sProName}` | `ProContentController` | 返回存储过程源码文本(不是结果集)。 | | `/pro/alert/{redisId}` | `ProContentController` | 为给定 Redis key 渲染预警 / 通知展示页面。 | | `/pro/getAlertValue/{redisId}` | `ProContentController` | 返回 Redis 中 `redisId` 对应的缓存值。 | | `/pro/executeSql` | `ProContentController` | 直接执行 `sSql` 载荷(管理级开发工具)。 | | `/thirdparty/*` | `ThirdPartyController` | 第三方 API 定义 CRUD,以及 `checkPartyApi` 校验器。由 `sysapithirdparty` 支撑。 | | `/thirdtoken/*` | `ThirdTokenController` | 出站 token 配置 CRUD。由 `sysapithirdtoken` 支撑。 | | `/brand/*` | `BrandController` | 伙伴 / 供应商列表(`sysapibrand`)CRUD。 | | `/json/*`, `/json/jsonEdit/{sDomId}` | `JsonController` | BACK API 编辑器使用的 JSON 树编辑辅助端点。 | | `/interfaceDefine/callthirdparty/{interfaceInvoke}` | `InterfaceController` | 分发由 `sysapithirdparty` 定义的出站调用。 | | `/gpt/chatGpt` | `GptController` | 实验性 GPT/chat 接口的透传;不属于框架 Wiki 范围。 | ## 支撑表(数据库层接口面) 这些表保存 API 元数据。所有表都带有 `sBrandsId` / `sSubsidiaryId`,用于租户作用域。 | 表 | 角色 | |---|---| | `sysapi` | `/api/invoke` 使用的 API 定义。 | | `sysapilog` | 每次调用的审计日志。 | | `sysapibrand` | 伙伴 / 供应商目录。 | | `sysapithirdparty` | 出站第三方端点定义。 | | `sysapithirdtoken` | 出站第三方 token 配置。 | | `sysapidbtodb` | DB-to-DB 同步 API 定义。**由 `xlyFlow` 的 `DbToDbController` 拥有,不由 xlyApi 拥有**;列在这里是因为该表位于 xlyApi 的 `sysapi.sql` 中。 | | `sysapidbtodblog` | DB-to-DB 同步运行日志。同上,由 xlyFlow 写入。 | ## 集成方如何使用 典型的首次集成: 1. **让管理员注册你的 API。** 向 `sysapi` 插入一行(通过 BACK 自助页面或直接写库):选择 `sApiCode`,编写 `sDataSql`,如果需要 token 认证则设置 `bHasToken = 1`,保存。 2. **获取 token。** `POST /xlyApi/token/getToken?corpid=&corpsecret=`。 3. **调用 API。** 使用 `Authorization` 中的 token 和 JSON body 调用 `POST /xlyApi/api/invoke/`。 4. **检查日志。** `sysapilog` 会记录每次调用、响应 `iStatus` 和 body。BACK 管理页面也会展示同样的信息。 ## 这个 API 不是什么 - **不是 OpenAPI 描述的接口。** 任意 `sApiCode` 的契约由其 `sysapi.sDataSql` 和 `sBody` 行决定。规格要向注册该 API 的团队获取,而不是从这里的 `/swagger` 端点获取。 - **不是 `xlyEntry` 内部 API 的薄封装。** 这些是有意分开的接口面。不支持从外部调用 `xlyEntry` 上的 `/business/*`。 - **不是入站 webhook 接收器。** 第三方推送事件走 [`xlyInterface`](webhooks.md)。