Appearance
AI 开放接口对接指南
让 AI(内建助手 / 外部 AI / 服务端脚本)用静态令牌调用 SaaS 接口。核心思路见 ADR-0006。
⚠️ 本功能代码已完成、尚未部署。部署前接口不可用;部署后管理类接口再补 Javadoc 并同步到 EOLINK。
一句话原理
AI 令牌 = 一个绑定真实账户、权限被裁剪的长效 Token。带上它调接口,和该账户登录后调接口效果一样(同样的租户隔离、同样的 @Secured),只是只能调显式开放的接口。
令牌形态
hsk_{keyId}_{secret}hsk_前缀让服务端识别这是开放凭证。keyId公开、可展示;secret只在创建时返回一次,库里只存哈希。- 调用时放在请求头:
Authorization: Bearer hsk_xxx_yyy(也支持?token=参数)。
两类凭证
| ASSISTANT(一键授权) | EXTERNAL(生成 API Key) | |
|---|---|---|
| 谁有 | merchant / channel / platform / user | 仅 merchant / channel / platform |
| 给谁用 | 平台内建 AI 助手 | 外部 AI / 服务端集成 |
| 拿明文 | 用户不接触密钥,只看"已授权/未授权" | 生成时明文返回一次 |
| 后台入口 | 系统设置 → AI 开放平台 → 我的 AI 助手 | 系统设置 → AI 开放平台 → API 密钥 |
一、拿到令牌
EXTERNAL(给外部 AI)
后台「API 密钥」页点「生成 API Key」→ 弹窗一次性展示完整 hsk_... → 复制保存。或调接口(以 merchant 为例,channel/platform 同构):
POST /cloud-api/merchant/ai/api-key/generate
Body: { "name": "客服AI", "scopes": [], "expireAt": 0 }
→ data.apiKey = "hsk_xxx_yyy" ← 只此一次管理:/query(列表)、/rotate(轮换,旧的立即失效)、/toggle(停用/启用)、/revoke(吊销)、/scope(改授权范围)。
ASSISTANT(给内建 AI 助手)
用户在「我的 AI 助手」页点授权即可,自己不碰密钥:
POST /cloud-api/{merchant|channel|platform|user}/ai/assistant/authorize # 幂等
POST /cloud-api/{...}/ai/assistant/revoke
GET /cloud-api/{...}/ai/assistant/status → { authorized: true/false }内建 AI 助手后端按需取凭证:GET /feign/ai/assistant/credential?accountType=&fid=(内部接口)。
二、发现能调哪些接口(manifest)
每个服务自动暴露自己的能力清单,带上你的令牌访问:
GET /cloud-api/open-api/manifest # public 的开放接口
GET /cloud-vem/open-api/manifest # vem 的开放接口
GET /cloud-user/open-api/manifest # user 的开放接口
...返回当前令牌 scope 能调的接口列表(path / methods / scope / name / desc / group)。这就是一份活的、永远和代码同步的工具清单,可直接喂给 Agent。网关前缀对应关系见架构总图。
三、调接口
带令牌调 manifest 里列出的接口即可,例如:
GET /cloud-vem/channel/vem/device/merchant/list?name=xx
Authorization: Bearer hsk_xxx_yyy- 调已开放(标了
@OpenApi)且 scope 匹配的接口 → 正常返回,自动限定在令牌绑定的租户内。 - 调未开放的接口 → 403(白名单制,默认拒绝)。
- 令牌被吊销/停用 → 秒级 401。
给开发者:怎么把一个接口开放给 AI
在 Controller 方法(或整个类)上贴 @OpenApi:
java
import cn.hiapi.core.basic.annotations.OpenApi;
@OpenApi(scope = "channel", name = "查询商户列表", desc = "按名称模糊查询渠道下商户", group = "vem-device")
@GetMapping("/merchant/list")
public ResponseEntity<List<?>> getMerchantList(@RequestParam("name") String name) { ... }- 不贴 = AI 调不到(白名单制,安全默认)。
scope:该接口要求的权限码。MVP 阶段直接复用账户现有authority码(如channel);阶段 2 会引入语义化 scope 目录(vem:device:read)。空 scope = 任意开放凭证可调。- 贴了就同时进
/open-api/manifest,AI 自动可发现。 - 只影响开放凭证(
loginType=api_key);普通用户登录调用完全不受这套拦截影响。
安全要点
- secret 只存哈希、明文仅一次;列表只显示
hsk_{keyId}_****。 - scope 是账户权限子集,签发时校验不得越权。
- 白名单制 + 可吊销(秒级)+ 过期 + 轮换;审计经
RequestLog.keyId溯源"哪把 key 调了什么"。 - 失败取向 fail-closed:凭证异常一律拒绝。
相关
- ADR-0006 AI 开放接口用静态令牌
- 方案全文:主仓库
AI开放接口(API-Key)方案设计.md - EOLINK 接口文档指南 · API 设计约定