Skip to content

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:凭证异常一律拒绝。

相关