Back to skills
extension
Category: OtherAPI key required

hk-saas-api

CLIENT-ONLY: generates client code to call Haike SAAS APIs. NEVER generates any server-side code (no Controller, no handler, no notify receiver, no verifySign). ALL interfaces follow the same flow: build params → compute sign (NEVER copy doc example sign, NEVER verifySign) → POST to the confirmed request URL → handle response. EVERY generated code MUST include an HTTP client call. If a doc lacks a complete request URL, ask the user for the address — the rest of the flow stays the same. This SKILL has ZERO server-side code scenarios: all 162 APIs are client → SAAS calls. Config: URLs only; secrets via env. Demos only when user omits placement. Use when the user types /hk-saas-api or /hk-saas-update, or asks to integrate SAAS or 海科/机构对接 APIs in Java, Python, Go, TypeScript, C#, etc. /hk-saas-update is used to refresh local API document cache from online doc portal.

personAuthor: user_bc83285bhubcommunity

SAAS 平台接口对接(hk-saas-api)

⚠️ 本 skill 的唯一产出:客户端调用海科 SAAS 平台的对接代码。全部 162 个接口统一流程:组参 → 签名 → HTTP POST → 处理响应。绝不生成服务端代码。

⛔ 关键误判警告(必读,最高优先级)

正确推理链:所有接口文档都是服务商对接 SAAS 的参考材料 → 文档中的 notify_url 只是请求参数之一(值为服务商自己的通知地址),或文档描述的是 SAAS 将发给服务商的通知格式 → 生成的是服务商侧的客户端代码(组参→签名→调 SAAS API,或解析通知数据→调 SAAS 查询接口),不是服务端接收端点。

最常见的误判场景

| 文档特征 | ❌ 常见错误判断 | ✅ 正确理解 | |---------|-------------|---------| | 参数含 notify_url,值为 http://www.baidu.com 等示例 | 需要生成接收通知的服务端代码 | notify_url 只是请求参数,与其他参数无区别。服务商调用 SAAS 时传自己的通知地址,仍是 client→SAAS | | 文档写"通知地址为...notify_url",无固定 URL | 这个接口缺 URL,无法生成 HTTP 调用 | 该文档描述的是 SAAS 发给服务商的通知格式。代码应为客户端处理逻辑:解析通知数据 → 调 SAAS 查询接口确认 | | 文档名含"通知"(如支付成功异步通知) | 需要生成 HTTP 端点接收 SAAS 通知 | 文档是通知格式参考,生成的处理代码是客户端代码:入参为通知数据 → 签名校验(用 accesskey 计算 sign 比对,不是 verifySign)→ 调 SAAS 查询接口确认状态 |

一句话铁律本 skill 不生成任何HTTP 端点注册代码。 如果你生成的代码中出现了这些,说明你犯了方向错误。所有 162 个文档,产出物永远是客户端代码——能被 main 函数或业务方法直接调用的代码,不需要启动服务器就能运行。

通知类接口的正确产出示例(Java)——这是你应该生成的代码形态:

// ✅ 正确:客户端代码。入参为通知数据,内部做签名校验 + 调 SAAS 查询接口
// 注意:没有 @RestController / @PostMapping / @Service 等任何 Spring 注解
// 复制 doc/SignUtils.java 到项目 utils 包,不要自己写 SignUtil

public class MerchantNotifyDemo {

    /**
     * 处理 SAAS 发来的商户状态变更通知数据。
     * 此方法由你现有的 HTTP 框架调用(如何接收通知由你的框架决定,不在生成范围)。
     *
     * @param notifyData SAAS POST 过来的 JSON 解析为 Map
     * @param accesskey 签名密钥(来自环境变量/配置)
     * @param saasBaseUrl SAAS 平台地址,用于调查询接口二次确认
     */
    public static void handleMerchantStatusNotify(
            Map<String, Object> notifyData,
            String accesskey,
            String saasBaseUrl) {

        // 1. 客户端签名校验:自己算 sign
        Map<String, Object> params = new HashMap<>(notifyData);
        params.remove("sign");
        String computedSign = SignUtils.signParams(accesskey, params);

        // 2. 调接口
        params.put("sign", computedSign);
        String response = httpClient.post(saasBaseUrl + "/api/merchant/notify", params);

        // 3. 处理返回请求
        
    }
}

⛔ 强制生成流程(按序号执行,禁止跳步、禁止重排)

以下 6 步是硬性要求。任一步的条件不满足 → 停止,询问用户 → 确认后继续。跳过任一步直接生成代码 = 未按 SKILL 执行。

第 1 步:确认接口

  • doc/api-catalog.yaml 匹配接口,读取文档
  • 多个匹配 → 列出所有候选项,让用户选择;禁止自行挑一个
  • catalog 无匹配 → 告知用户,请用户提供接口名称或文档 URL
  • 未确认具体接口前,禁止进入下一步

第 2 步:确认请求 URL ⛔(最高频遗漏项)

  • 从接口文档中提取请求 URL
  • 以下情况视为缺 URL,必须询问用户提供完整地址
    • 仅有 path(如 /api/v1/xxx)无完整域名
    • 写"运营配置""需运营配置后提供"
    • 完全无地址信息
  • 特殊:文档写"通知地址为 notify_url":这不是缺 URL。该文档描述的是 SAAS 将发给服务商的通知数据格式。处理方式:生成客户端代码,入参为通知数据(Map/JSON),计算 sign 与通知中的 sign 比对(用 accesskey,不是 verifySign),然后调 SAAS 查询接口确认状态。不是生成 HTTP 端点去接收通知。注意:调 SAAS 查询接口需要 SAAS 的 base URL,若提示词/配置文件未提供 → 仍需询问用户。
  • URL 不完整 → 停止,询问用户 → 用户给出后才继续。禁止编造域名、禁止跳过 HTTP 调用

第 3 步:组装请求参数

  • 优先使用文档请求示例中的字段和值(sign 除外 — 见第 4 步)
  • 无请求示例 → 用参数表样例列;仍无 → 询问用户
  • 必填参数缺值 → 告知用户,列出缺失项
  • 禁止使用 "test""xxx""abc" 等自编占位值。参数值只能来自:文档示例 > 参数表样例 > 用户提供

第 4 步:获取 accesskey 并计算 sign

  • accesskey 来源:环境变量 > 项目配置 > 询问用户
  • sign 必须实时计算,禁止抄文档示例中的 sign 值
  • 签名算法以 reference/signing.md 为准:[过滤空值+sign/mac] → [按 key 字典序排序] → [拼成 k1=v1&k2=v2] → [末尾追加 accesskey] → [MD5 大写]
  • 禁止生成 verifySigncheckSign 等验签方法

第 5 步:发送 HTTP POST 请求

  • 向第 2 步确认的 URL 发 POST,Content-Type: application/json; charset=utf-8
  • sign 必须在第 4 步计算完成后才放入请求体
  • 最终代码必须包含 HTTP 客户端调用。只生成签名计算而无 HTTP 调用 = 方向错误

第 6 步:处理响应

  • 解析 HTTP 状态码 + 响应 body
  • 处理成功/失败分支,输出日志

⛔ 生成前强制自检(以下任一项为"否" → 禁止生成代码)

| # | 检查项 | 否 → 处理 | |---|--------|----------| | 1 | 接口已唯一确认? | 列出候选项让用户选 | | 2 | 完整请求 URL 已确认?(含协议+域名+路径) | 询问用户,禁止编造 | | 3 | accesskey 获取方式已确认? | 询问用户 | | 4 | 所有必填参数有值来源? | 列出缺失项,询问用户 | | 5 | 目标语言已明确? | 询问用户 | | 6 | 代码方向是客户端→SAAS(非服务端接收)?含"通知"关键词的接口也是客户端 API | 重新检查,参考顶部「关键误判警告」和「方向规则」 |


⛔ 生成后强制自检(以下任一项为"否" → 代码不合格,必须重写)

| # | 检查项 | |---|--------| | 1 | 代码中有 URL 变量或常量(HTTP 请求的目标地址)? | | 2 | 代码中有 HTTP 客户端 POST 调用? | | 3 | sign 来自签名方法返回值(非字符串常量)? | | 4 | 没有 verifySign / checkSign / handleNotify / receiveNotify? | | 5 | 参数值来自文档示例或用户提供(非 "test" / "xxx")? |


方向规则(客户端 → SAAS,非服务端)

| # | 规则 | 禁止 | |---|------|------| | 1 | 代码方向:客户端 → HTTP POST → SAAS 平台 | 禁止生成服务端接收端(Controller/handler) | | 2 | 签名:用 accesskey 计算 sign | 禁止验签(verifySign/checkSign) | | 3 | 必须包含 HTTP 客户端调用 | 禁止只生成签名计算而无 HTTP 请求 | | 4 | sign 实时计算 | 禁止抄文档示例 sign 值 |

反模式速查:类名含 Receiver/Handler/Listener → 错误;方法名含 handleNotify/receiveNotify → 错误;import 不存在的类(如 SaasConfig)→ 错误;看到"通知""回调"关键词就认为需要生成服务端接收代码 → 错误;说"这超出 skill 范围但我可以为你生成" → 错误(本 skill 无例外)


何时启用

用户在消息中使用 /hk-saas-api,或表达要对接 海科SAAS接口、实现 sign签名、按接口文档生成对接代码时,须按本 skill 流程执行。产出均为客户端代码(组参 → 签名 → HTTP 调平台);绝不生成任何服务端验签、接收通知 Controller 或平台下行处理逻辑。

用户在消息中使用 /hk-saas-update,或表达要更新接口文档时,须按 §7 流程执行。

自包含约束(必读)

本 skill 可单独复制到任意工程或工具目录使用。执行时只读本目录内资源:

| 路径 | 用途 | |------|------| | doc/api-catalog.yaml | 接口场景与在线文档 URL(唯一结构化目录,勿再找历史 txt);每个 API 含 local_doc 指向本地缓存 | | doc/docs/ | 本地接口文档缓存(Markdown 格式,从在线文档门户预下载并转换),manifest.json 记录下载时间与映射 | | doc/SignUtils.java | Java 可直接复制到目标工程工具包;其它语言勿直接拷贝,见 §5 | | reference/signing.md | Sign 算法、速查表、golden examples(规范与跨语言对照) | | reference/api-index.md | 场景 id与人类可读索引 | | reference/languages.md | 多语言检测与 HTTP 栈建议 | | doc/README.md(可选) | doc/ 目录说明 |

仅导入本文件夹即可:无论从何处复制(例如本仓库的 api-server/skills/hk-saas-api),目标环境只需要这一层目录内的全部文件与子目录;不必带上 hkrt_aiapi-server 或任何上级路径。Markdown/YAML 中的相对路径均以 hk-saas-api/根目录 为基准解析。

禁止引用本 skill 目录外的「原始 txt / 未整理附件」;禁止假设运行时代码仓库里一定存在名为 api-server/ 的目录(文中若出现仅作反面说明)。

签名 sign 与请求示例(必读,防误判)

接口文档「请求示例」里的 sign 仅为排版演示,与当前时刻、当前 accesskey、当前参数字典不保证一致,也不能代表你联调时的正确签名。

| 必须做 | 禁止做 | |--------|--------| | 用 accesskey + 待发送的完整业务参数字典(不含 sign),按 reference/signing.md 现算 sign,再 POST | 把请求示例里的 sign 原样写进代码或配置 | | 单元测试里用 signing.mdgolden examples 校验签名实现 | 用文档请求示例里的 sign 作为期望值,做 assertEquals / == / 或把「与文档 sign 一致」当作联调成功依据 | | 联调失败时对照「待签串、key 序、空值过滤」排查 | 认为「算出来的 sign 必须和文档示例一样」才算对 |

结论:文档示例中的 sign 不是合法联调凭据;唯一合法来源是:对本请求实际参数 + 本环境 accesskey 调用签名方法得到的值。

工作流(必须按序)

flowchart TD
  trigger[Trigger_slash_saas_or_intent]
  scene[Resolve_or_list_business_scenes]
  api[Resolve_or_list_APIs_under_scene]
  miss{Catalog_hit?}
  clarify[Confirm_API_name_or_user_doc_URL_or_paste]
  lang[Detect_or_ask_target_language]
  learn[Learn_project_conventions]
  fetch_online[Try_fetch_doc_url_online]
  online_ok{Online_fetch_ok?}
  fetch_local[Read_local_doc_cache]
  local_ok{Local_doc_exists?}
  ask_user[Ask_user_to_provide_doc]
  confirm[Confirm_uncertain_info_URL_params_values]
  confirm_ok{All_confirmed?}
  gen[Generate_client_sign_and_HTTP]
  check[Syntax_and_convention_check]
  trigger --> scene --> api --> miss
  miss -->|no| clarify --> lang --> learn --> fetch_online
  miss -->|yes| lang --> learn --> fetch_online
  fetch_online --> online_ok
  online_ok -->|yes| confirm
  online_ok -->|no| fetch_local --> local_ok
  local_ok -->|yes| confirm
  local_ok -->|no| ask_user --> confirm
  confirm --> confirm_ok
  confirm_ok -->|yes| gen --> check
  confirm_ok -->|no| ask_user --> confirm

进度清单:

- [ ] 业务场景已明确(或已从 api-catalog 的 scenario 列出并确认)
- [ ] 具体接口已明确(catalog 唯一命中,或多匹配时已列出候选并由用户选定具体接口,或用户已提供文档/URL)
- [ ] 若在 catalog 中未命中:已向用户说明无匹配项,并确认名称准确性或已取得文档/URL
- [ ] 目标语言已明确
- [ ] 已学习当前项目的开发规范(目录结构、命名风格、代码分层、依赖管理等)
- [ ] 已取得接口文档内容(在线抓取成功 / 本地缓存读取 / 用户提供)
- [ ] **完整请求 URL 已确认**:文档有完整 URL → 直接使用;文档缺 URL(仅 path / 运营配置 / 完全缺失等)→ 已询问用户并获得完整地址;文档为通知格式描述(url_status=notify_url)→ 按通知处理模式生成客户端代码(见第 2 步);**禁止**编造域名或因缺 URL 而跳过 HTTP 调用
- [ ] **accesskey 获取方式已确认**:环境变量 / 密钥管理 / 项目配置;若无法获取 → 已询问用户
- [ ] **参数值已确认**(请求示例存在且完整,或无示例时已告知用户并获取测试值;**`sign` 除外**——从不采用示例值,一律现算)
- [ ] **所有不确定信息已确认**(无未确认的地址、参数值、语言、落点等)
- [ ] **方向自检已通过**(对照顶部「方向规则」和「生成后强制自检」):代码方向为客户端→SAAS,包含 HTTP 调用,sign 为实时计算,无服务端验签/接收端逻辑
- [ ] 已在用户指定路径生成对接代码:包含 **完整客户端对接流程**(获取参数 → 现算 sign → HTTP 调用 → 处理响应);签名实现符合 `reference/signing.md`;**禁止**仅签名计算而无 HTTP 调用;**不含**任何服务端代码(验签/接收通知/Controller)
- [ ] 已对生成代码做语法检查与项目规范一致性校验

1. 业务场景检测

  • 读取 reference/api-index.md 中的场景表(与 api-catalog.yamlscenarios[].id 对应)。
  • 无法确定时:列出全部 title,用 AskQuestion 或对话映射到某个 id

2. 接口检测

  • 解析 doc/api-catalog.yaml:在用户已选或已推断的 scenarios[].id 下匹配 apis[].name;若用户未选场景,可在全部 scenarios 中按名称做模糊检索。
  • 唯一命中:展示该条的 name + doc_url,进入 §4。
  • 多个命中(必须确认,严禁全量生成):
    1. 停止生成,将匹配到的接口列表展示给用户(每项含 name + 所属场景),并询问用户具体需要对接哪个(或哪些)。
    2. 用户指定后才继续:在用户明确选出具体接口之前,不得生成任何对接代码。
    3. 例外:仅当用户明确说明「全部都要对接」或「上面列出的都生成」时,方可按列表逐接口生成。

未命中 catalog 时(必读,禁止硬编)

  1. 明确告知:当前 api-catalog.yaml没有与用户描述一致的接口条目(或无法唯一确定),不要猜测或捏造 doc_url、路径与参数字段。
  2. 询问用户:提供的接口名称是否准确(是否别名、简称、口误、是否属于别的产品线)。
  3. 名称不准确:请用户给出准确接口名称或从门户里复制的完整标题后,重新检索 catalog;在用户提供准确名称之前,不生成对接代码。
  4. 名称准确仍无条目(或用户直接选择自建流程):请用户任选其一提供材料,再进入 §4 / §5:
    • 接口文档正文(可粘贴):须至少包含测试/生产 请求 URL、参数表或请求示例、返回说明(能支撑签名与 HTTP 即可);
    • 接口文档地址:用户给出的 URL 与 catalog 里的 doc_url 同等对待——按 §4「快速提取法」抓取页面得到正文后再生成代码。
  5. 用户仅提供模糊需求且无法补齐名称或文档时:停止生成,保持对话直到材料足够;可建议用户到 SAAS 文档门户按关键词搜索后把页面链接或截图文字发回。

3. 目标语言检测(多语言)

reference/languages.md:优先用户明示 → 仓库文件信号 → 询问。

3.5 项目规范学习(必读,生成代码前必须执行)

本 skill 可能被导入不同的开发工具、不同的项目、使用不同的编程语言,因此生成代码前必须先了解当前项目的开发规范,确保生成的代码与项目风格一致。

学习步骤:

  1. 扫描项目结构:查看项目根目录及子目录的文件组织方式,识别:

    • 源码目录结构(如 src/main/javaapp/lib/ 等)
    • 配置文件位置(如 resources/config/.env 等)
    • 工具类/公共方法存放目录(如 utils/common/helpers/ 等)
    • 业务逻辑存放目录(如 service/controllers/api/ 等)
  2. 识别开发规范:检查项目中是否包含规范文件:

    • .editorconfig — 编辑器配置
    • eslint/ruff/checkstyle 等代码检查配置
    • README.md 中的开发规范章节
    • 项目已有的代码风格(命名约定、注释风格、异常处理模式等)
  3. 总结规范要点:将扫描到的规范整理为以下维度,作为代码生成的约束:

    • 目录规范:代码文件应放在哪个目录下(如公用方法放 common、工具类放 utils、业务逻辑放 service、配置放 config/resources
    • 命名规范:类名、方法名、变量名的命名风格(camelCase、snake_case、PascalCase)
    • 代码分层:controller 层避免过多业务逻辑、SQL 通过配置文件管理不嵌入代码
    • 依赖管理:新增依赖需同步更新打包部署文件
    • 代码复用:重复逻辑提取为公共方法
    • 方法长度:方法代码行数控制(如 50 行以内),复杂逻辑需拆分
  4. 规范冲突处理

    • 若项目规范与本 skill 默认建议冲突,以项目规范为准
    • 若项目无明确规范,则按 reference/languages.md 中该语言的通用最佳实践执行

4. 获取接口文档(三级回退,必读)

获取接口文档时必须按以下优先级逐级回退,确保在网络不稳定时仍能正常工作:

优先级 1:在线抓取 doc_url → 成功则使用
优先级 2:读取本地缓存 local_doc → 文件存在则使用
优先级 3:请用户提供文档 → 用户粘贴正文或提供新 URL

4.1 第一级:在线抓取(优先)

  • 文档来源可以是:catalog 中的 doc_url,或 用户在 §2 中提供的官方/自建文档 URL。对 URL:统一先做一次"快速抓取",目标是直接拿到接口页主体内容(避免工具长时间探索整个站点)。
  • 该文档站点页面通常包含 editormd/markdown-article-inner 等标记;主体内容一般在 HTML 的:
    • <article class="markdown-article-inner"> ... </article>(优先)
    • id="page-content" 所在区域

推荐的快速提取法(适用于 Mindoc/EditorMD 风格页面)

  1. 使用 Agent 的 WebFetch 能力抓取 doc_url 页面,获取 HTML 内容
  2. 从 HTML 中只提取 <article ...markdown-article-inner...> 的内部 HTML(剔除目录 TOC,如 markdown-toc div),再做 HTML→Markdown 的轻量转换
  3. 只要先拿到"接口名称、请求方法、路径、参数表、示例、返回字段",就可以开始生成代码;无需完整还原页面样式
  4. 在线抓取成功 → 直接使用抓取内容,跳过第二级和第三级

备选命令行方式(仅当 Agent 无 WebFetch 能力时使用):

  1. 用命令行先确认可访问(返回 200):curl -I <doc_url>
  2. 获取 HTML:curl -L <doc_url>
  3. 再按上述步骤 2-3 提取主体内容

4.2 第二级:本地缓存回退

若在线抓取失败(网络超时、连接拒绝、登录/动态渲染/反爬等),立即回退到本地缓存:

  1. api-catalog.yaml 中该 API 条目读取 local_doc 字段(如 docs/files_saas-1ebob0j33h3ed.md)。
  2. doc/ 目录为基准,拼接 local_doc 路径,读取本地 Markdown 文件。
  3. 本地 Markdown 已是从 HTML 转换后的格式,包含完整的接口参数表、请求示例、返回示例等,可直接读取使用。
  4. 本地文件存在且可读 → 使用本地缓存内容,跳过第三级。
  5. 本地文件不存在 → 进入第三级。

本地缓存说明

  • doc/docs/ 目录包含从文档门户预下载并转换为 Markdown 的全部接口文档(161 个文件)。
  • doc/docs/manifest.json 记录了下载时间、每个 API 的 doc_url 与本地文件的映射关系。
  • 可通过 doc/download_docs.py 脚本重新下载或更新本地缓存(自动将 HTML 转换为 Markdown)。
  • 本地缓存可能不是最新版本;若用户反馈文档内容过时,应优先尝试在线抓取。

4.3 第三级:请用户提供

若在线抓取失败且本地无缓存,必须请用户提供文档材料:

  1. 明确告知:在线文档抓取失败,本地也无该接口的缓存文档。
  2. 请用户任选其一提供材料:
    • 接口文档正文(可粘贴):须至少包含测试/生产 请求 URL、参数表或请求示例、返回说明(能支撑签名与 HTTP 即可);
    • 接口文档地址:用户给出的 URL → 按 §4.1「快速提取法」重新尝试抓取(用户提供的 URL 可能指向不同的文档站点)。
  3. 用户仅提供模糊需求且无法补齐文档时:停止生成,保持对话直到材料足够。

页面内出现的关联链接(如公共参数)按需再抓取;优先抓取与当前接口直接相关的链接,避免全站爬取。

实测提示(减少探索时间)

  • 该站点 doc_url 页面往往未显式标注 HTTP 方法,但请求示例为 JSON;默认按 POST + Content-Type: application/json; charset=utf-8 实现,若接口页另有说明则覆盖。
  • 请求示例中的 sign 通常是示例值;生成代码时应当忽略示例 sign并按 reference/signing.md 实时计算;禁止用示例 sign 做单元测试或「签名校验」的期望值(详见上文 「签名 sign 与请求示例」)。
  • 若接口参数说明包含"至少送一个"这类约束(例如:agent_apply_no、merch_no 至少送一个),生成代码时必须做显式校验并给出清晰错误提示,避免请求发出后才失败。
    • 若同一业务存在微信/支付宝等多渠道的"业务申请"接口,其必填字段通常不同(例如:微信 settle_id,支付宝 mcc/business_id)。生成代码时应:
      • 为不同渠道生成独立的 payload builder / 配置键(例如 wx_*ali_*),避免字段混用;
      • 依据文档参数表的 M/O(必传/非必传)做必填校验,并在报错中明确缺失的字段名。
    • Windows 终端可能不是 UTF-8,导致中文报错乱码;生成代码时建议在 README 加提示(如 chcp 65001PYTHONUTF8=1),且异常信息至少包含 field_name 等可读的 ASCII 关键字,便于定位。
    • 文档标题可能出现多余空格(例如 请求 URL:),仅用 grep 请求URL 可能漏检;提取测试地址时可搜 测试环境<a href="http://47.** 或页面内 第一个业务路径型 URL
    • 参数表 可空列均为 O,但说明里写 「二选一」(如 apply_nobusiness_code)时,应按说明做 OR 校验,不能误以为都可省略。
    • 部分接口请求 JSON 使用 camelCase 或与 agent_no 并存的 agentNo 等字段名;必须与文档示例完全一致后再参与签名(签名按 key 字典序拼接,大小写敏感)。
    • 页面 概要描述 偶发与真实接口不符(复制错误);以 请求 URL + 参数表 + 请求示例 为准;若 YAML 目录缺项,可抓取门户首页 HTML 搜索中文接口名得到 doc_url,并将条目补回 doc/api-catalog.yaml(保持 skill 自洽)。
    • api-catalog.yaml 未收录时:下载文档门户首页 HTML(如 doc_portal_base),用标题关键词检索 <a ... title="..."> 定位 doc_url;勿凭接口中文名猜路径。
    • 整页 HTML 常为一超长行rg/grep 在部分环境可能对「超长行」匹配不稳定;可搜 URL 路径片段(如 trade/limitquery-merchant-product),或对已保存的 HTML 用脚本/read_file 局部查看。
    • accessid 并非所有接口必传accessid 主要用于在平台侧获取 accesskey,而非所有接口的必传参数。若接口文档参数表中包含 accessid,则按文档要求传入并参与签名;若文档中无此字段,则无需配置和传入。生成代码时以接口文档的参数表 M/O 标注为准,但请求示例中包含的字段即使参数表未列出也应传入(参数表偶有遗漏,请求示例是实际可用的参考)。签名只需 accesskeyaccessid 仅当接口文档要求时才作为请求参数参与签名。但生成 Demo/测试代码时,若请求示例中出现 accessid,则 Demo 参数中也必须包含该字段(使用示例中的值),不得因"非必传"而自行省略。
    • 签名计算顺序至关重要:必须先组装业务参数(按文档参数表)→ 计算签名 → 放入 sign。若 sign 提前放入参数字典,签名必然失败。
    • 嵌套对象中的空值字段必须递归过滤:如 merchant_data.ledger_receive_flag=""product_data.wx.mcc="" 等字段,签名时必须跳过。Java 的 SignUtils.getToBeSign() 已实现递归过滤;其他语言实现时也必须对嵌套 dict/object 做同样的空值过滤。
    • 部分页面无 JSON 请求示例:仅有参数表时,按 M/C/O 与说明组装字典,样例列有值必须采用(勿编造或使用通用占位值如 "test"、"xxx");在代码注释中标明「无示例,来自参数表」。
    • 测试参数严禁编造:请求示例是测试参数的唯一合法来源,不得使用自编占位值。完整规则见 §5.0
    • 请求示例中包含但参数表未列出的字段也必须保留:部分接口文档的参数表可能不完整(如未列出 accessid,但请求示例明确包含且 API 实际要求),生成代码时请求示例中出现过的字段一律视为应传入字段,不得因"参数表未列"而省略。请求示例与参数表冲突时,以请求示例为准
    • 接口调用地址可能未在文档中明确展示:部分接口的请求 URL(如 https://xxx.xxx.com/xxx/xxx)需要由运营在后台配置后才能获取,文档中可能仅给出请求路径(如 /api/trade/pay)而无完整域名。禁止猜测或编造调用地址。若文档中未包含完整的测试/生产请求 URL,必须询问用户获取实际的接口调用地址后再生成代码;在代码中用占位符(如 {BASE_URL}/api/trade/pay)并加注释说明「请替换为运营提供的实际调用地址」。

4.5 不确定信息确认

在生成任何对接代码之前,必须逐一确认以下不确定信息。任何一项未确认时,禁止生成代码。

4.5.1 请求地址确认

凡无法在接口文档中确定「客户端本次 HTTP 请求应发往的完整地址(含协议与域名,如 https://api.example.com/path)」时,必须询问用户禁止猜测或编造域名

首先判断文档类型

| 文档特征 | 类型 | 处理方式 | |---------|------|---------| | 有明确的请求 URL(含 http://https://) | 标准客户端 API | 直接使用该 URL | | 有 path 但缺域名 / 写"运营配置" / 完全无地址 | 标准客户端 API,URL 待确认 | 询问用户提供完整地址 | | 写"通知地址为...notify_url" / url_status=notify_url / 文档名含"通知"且无请求 URL | 通知格式参考文档(描述 SAAS→服务商的通知数据格式) | 不询问 URL。按通知处理模式生成客户端代码(见下) |

通知格式参考文档的处理模式(url_status=notify_url 的接口):

这类文档描述的是 SAAS 将发送给服务商的通知数据格式(如支付成功通知、退款结果通知等),通知发往服务商此前在业务请求中上送的 notify_url。由于每个服务商的 notify_url 不同,文档不写固定地址。

生成的代码是服务商侧的客户端代码,不是服务端接收端点

  1. 生成一个方法/函数,入参为通知数据(Map<String, Object> / dict / JSON 字符串)
  2. 方法内:用 accesskey 计算通知数据的 sign,与通知中的 sign 比对(这是客户端签名校验,不是 verifySign 服务端验签)
  3. 根据需要调 SAAS 查询接口(如交易查询)确认状态
  4. 返回处理结果
  5. 不生成 @PostMapping/@app.route 等 HTTP 端点注册代码——通知如何到达这个方法由服务商自己的框架决定

缺 URL 的识别(标准客户端 API,从文档正文判断)

文档中出现以下任一特征时,视为缺 URL:

  • 仅有 path(如 /api/v1/xxx)而无 https://http:// 开头的完整地址
  • 写「运营配置」「运营配置地址」「需运营配置后提供」
  • 完全无任何地址信息
  • 协议、域名、端口任一缺失

也可从 api-catalog.yaml 预判:该 API 条目含 url_status 字段且值非 complete 时,按以下规则处理。url_status 值含义:

  • path_only:仅提供 path,缺 Base URL → 询问用户
  • operator_config:运营配置,无具体 URL → 询问用户
  • notify_url:通知格式参考文档,不是可调用的 SAAS API → 不询问 URL,按上述通知处理模式生成客户端代码
  • missing:完全无地址信息 → 询问用户

4.5.2 参数值确认

生成测试/Demo 代码时,参数值必须来自文档请求示例(见 §5.0 强制规则)。遇到以下情况时,必须明确告知用户并确认:

  1. 无请求示例:接口文档中完全没有请求示例 JSON 或表单。

    • 告知用户:"该接口文档中未提供请求示例。参数值将仅按参数表中的样例列生成(如有),或需要您手动提供测试值。请确认是否继续,或提供您期望的测试参数值。"
  2. 请求示例中缺少某些必填参数:请求示例 JSON 中未包含参数表中标注为必填(M)的字段。

    • 告知用户:"请求示例中缺少以下必填参数:xxxyyy。请提供这些参数的测试值,或确认这些参数在您的场景中是否确实需要。"
  3. 参数值具有业务特定性:如商户编号、订单号、金额等与具体业务场景强相关的参数。

    • 告知用户:"以下参数值与您的具体业务场景相关,请确认或提供实际值:merch_no(商户编号)、out_trade_no(订单号)等。"

4.5.3 其他不确定信息

  1. 目标语言未明确:用户未说明要生成哪种语言的代码,且无法从项目结构中推断。

    • 必须询问用户:"请指定要生成的目标语言(Java / Python / Go / TypeScript / C# 等)。"
  2. 代码落点未明确:用户未说明代码应该放在项目的哪个位置。

    • 可按 §5.1 的默认规则生成 Demo,但必须告知用户:"您未指定代码落点,已按默认规则生成 Demo 代码。如需集成到具体业务模块,请告知目标文件路径。"
  3. 多接口歧义:用户描述的接口名称在 catalog 中有多个匹配项。

    • 必须列出所有匹配项,让用户选择具体要对接哪个接口。禁止自行选择一个生成代码

4.5.4 确认流程与交互规范

必须明确列出不确定项,询问用户确认处理方式,生成代码后标注需补充的内容。

第一步:列出不确定信息清单

发现不确定信息时,必须先明确列出,让用户清楚知道哪些需要确认:

示例输出格式:

「检测到以下信息不确定,需要您确认:

1. **请求地址**:文档中未提供完整可请求的 URL(或仅有 path),需您提供实际调用的完整地址(含 `https://`)。
2. **参数 `merch_no`**:请求示例中未包含此必填参数,需要商户编号。
3. **参数 `out_trade_no`**:订单号需根据您的业务场景生成。

📌 请确认:您能否提供以上信息的实际值?若暂时无法提供,我先用示例值生成代码,并标注需要您后续替换的位置。」

第二步:等待用户确认

  • 用户提供了实际值 → 使用用户提供的值
  • 用户无法提供,但确认可以用示例值/空值 → 执行第三步
  • 用户未回复或回复不明确 → 再次询问:「是否可以用示例值/空值先完成代码生成?确认后我将标注哪些需要您后续修改。」

第三步:生成示例值/空值并标注

用户确认后,按以下规则生成:

| 不确定类型 | 示例值/空值规则 | 标注方式 | |-----------|----------------|---------| | 请求地址未定时 | {BASE_URL} 或用户提供的占位 URL | 代码注释「须替换为完整请求地址,已由用户/运营确认」 | | 商户编号 | "83300000001"(格式化示例) | 代码注释「示例值,需替换为实际商户编号」 | | 订单号 | "ORD20240101XXXXXX"(时间戳格式) | 代码注释「示例值,需替换为实际订单号」 | | 其他标识类参数 | "EXAMPLE_XXX" | 代码注释「示例值,需替换」 | | 无法推断的参数 | 空值 """待填写" | 代码注释「需填写实际值」 |

第四步:生成代码并输出补充清单

代码生成后,必须输出一份清单告知用户哪些需要后续补充修改:

示例输出格式:

「代码已生成。以下内容使用示例值/空值,需要您后续补充修改:

【需替换的请求地址】
- `{REQUEST_URL}` → 文档未写全或需运营配置时,由您提供的完整请求地址(如 `https://api.example.com/saas/xxx`)

【需替换的参数值】
- `merch_no: "83300000001"` → 实际商户编号
- `out_trade_no: "ORD20240101XXXXXX"` → 实际订单号

请在上传到生产环境前完成以上替换。」

注意:所有接口在本 skill 下的客户端对接交付物一致:组参 → 按 reference/signing.md 现算 signHTTP 客户端向已确认 URL 发起请求 → 解析响应。文档未写全 URL 时,须已完成 §4.5.1 询问并在代码中占位。本 skill 绝不生成任何服务端验签逻辑或接收通知 Controller。

禁止事项

  • 禁止编造真实商户名、真实手机号、真实身份证号
  • 禁止使用 "test""xxx""abc" 等无意义占位符(应使用格式化示例值)
  • 禁止在用户未确认的情况下直接生成代码(必须先询问确认)

核心原则明确列出不确定项 → 询问用户能否提供 → 用户确认后生成示例值 → 输出补充清单。不猜测,不隐瞒,让用户清楚知道哪些需要修改。

5. 生成对接代码

5.0 测试请求参数来源(强制规则 — 违反即未按 SKILL 执行)

本规则是 SKILL 内最高优先级规则,覆盖一切相悖的其他指引。

生成任何 Demo / 测试类 / build_xxx_params 的请求参数时:

  1. 先找请求示例:在接口文档中搜索 请求示例 标题,定位 JSON 或表单代码块。
  2. 逐字段原样复制:将请求示例中的每一个字段名和字段值sign 除外,见下条)原样复制到代码中。
  3. sign 唯一例外(与「复制示例」相反):从请求示例复制参数时,不得复制示例中的 sign 值;不得用该值做变量初值、常量、配置,也不得在客户端联调代码里把「与文档示例 sign 一致」当作成功条件。sign 必须且只能由:当前 Map 中的业务参数(仍不含 sign)+ accesskey,按 reference/signing.md 计算后写入。agent_noaccessid 等鉴权字段可用环境变量或配置项包装,但常量值必须来自请求示例(sign 不在此列)。
  4. 严禁编造绝对禁止使用 "test""xxx""abc123""your_value_here""value1"、AI 自行推测的姓名/手机号/金额等一切非文档来源的值。一个字都不准编。例外sign 不来自文档,而来自签名算法输出,见上条。)
  5. 仅无请求示例时可例外:当且仅当接口文档完全不存在请求示例时,才允许按参数表样例列构造参数值,且必须在代码注释中标注「无请求示例,数据来自参数表样例列」。
  6. 所有接口类型的 sign 规则一致:无论接口是否为异步通知、仅提供 path、运营配置地址等,请求示例中的 sign 均仅为排版演示,一律禁止抄用,必须用 accesskey + 当前参数字典按 reference/signing.md 现算。

执行流程:读取接口文档 → 定位请求示例 → 复制到代码 → 删除或未设置 sign → 用 accesskey 与参数字典按 signing.md 计算 sign 后写入 → 添加注释标注数据来源(可写「sign 由签名方法生成,非文档示例值」)。禁止在测试或业务代码中把计算结果与文档示例 sign 做相等断言。跳过「定位请求示例」这一步骤直接生成代码的,视为未按规范执行。

  • 输出路径仅按用户指定或询问后写入。
  • HTTP 客户端与风格见 languages.md
  • 用户指令优先(必读)
    • 若用户已说明 传参方式 / 数据来源 / 代码应落在哪个文件、类或函数,须 严格按用户要求 实现与落点。
    • 不要在用户已指定业务落点的情况下,再强行追加一套「仅含文档示例」的独立 Demo 或并行的 build_xxx_params,除非用户明确要求示例并存。
    • 仅当用户未说明 传参逻辑与代码位置时,才提供可运行的 Demo(参数来源见 §5.0 强制规则;并注明「生产请改为真实数据来源」)。

5.1 配置与代码分层(必读)

真实接入流程是:先在业务代码里准备好请求参数字典,再调用 SAAS;本 skill 会在不同项目、不同工具里执行,默认没有统一的「参数从哪张表来」的实现,因此生成代码时必须遵守:

| 层级 | 放什么 | 禁止 | |------|--------|------| | 配置文件(如 YAML) | 各环境的 请求 URL(可按接口分键,如 query_merchant_info_url)。注意:部分接口的调用地址需由运营配置,文档中可能无完整 URL;此时配置文件中放占位符(如 https://{BASE_URL}/api/xxx),并加注释说明「请替换为运营提供的实际调用地址」 | 不要把 merch_no、门店信息、费率等业务字段写进「接口配置文件」;禁止猜测或编造调用地址 | | 鉴权 | accesskey(签名必需)、agent_no 等:按目标工程使用 环境变量 / 密钥管理 / 独立凭据文件(勿提交真实密钥);accessid 仅当接口文档要求时才配置,主要用于在平台侧获取 accesskey;跨工具可复制示例名如 SAAS_ACCESSKEYSAAS_AGENT_NOSAAS_ACCESSID(可选) | 与大量业务键混在同一份「万能 YAML」里 | | 公用封装 | 一个「给定 URL + accesskey + 业务参数字典(不含 sign)→ 按 reference/signing.md 计算 signPOST application/json; charset=utf-8(以文档为准)→ 返回响应 body」的方法/类,全项目复用 | 每个接口各写一套散落的签名 + HTTP 拼接(除非用户项目已有统一客户端,则接入该客户端);禁止只有签名计算而无 HTTP 调用(强制规则,无论何种接口类型) | | 业务层 | 用户在提示词中指定的模块/函数内组装参数;未指定时再由 Agent 在合理位置实现或落 Demo | 与用户指定的文件路径、命名或调用链冲突 | | Demo(可选) | 仅当用户未说明传参逻辑与落点:可提供 build_xxx_params(参数来源见 §5.0)+ main/脚本入口,便于工具内快速验证签名与 HTTP | 用户已指定落点时仍默认再生成一套「仅示例」的并行入口(除非用户要) |

交付形态建议

  • 用户已指定传参与代码位置:只改/只增用户要求处,并接上既有或新建的 公用签名 + HTTP 调用;若用户说复用项目里已有 HTTP 客户端,则不要再新建一套并行封装。
  • 用户未指定:公用封装 +(可选)文档示例 build_xxx_params(参数来源见 §5.0)+ 简短可运行入口(入口内须包含一次发往配置 URL 的 HTTP 调用,URL 可占位)。

5.2 accesskey 与联调

  • accesskey 是签名计算的必需凭据,一般在服务商入网成功后下发,也可通过 agent_no 在平台侧查询/获取。
  • accessid 主要用于在平台侧获取 accesskey,并非所有接口的必传参数。仅当接口文档参数表中包含 accessid 时,才需将其作为请求参数传入并参与签名。
  • 生成代码时:优先用环境变量或项目既有密钥模块存放 accesskey不要把它和业务参数堆在同一配置文件中。accessid 仅在接口文档要求时才配置。
  • 若用户仅有 agent_no:提示向平台补全 accesskey 后再联调,避免在文档站无意义翻找。
  • 签名工具类落盘规则(必守)
    • Java:将本 skill 内 doc/SignUtils.java原样复制到用户项目工具类所在包路径下(仅修改 package 与必要时类名以符合项目规范);补全 pom.xml / build.gradlenet.sf.json(json-lib,注意需指定 jdk15 classifier)commons-codec 等与该类 import 一致的依赖。
    • 非 Java不得直接复制 SignUtils.java。须阅读 doc/SignUtils.javareference/signing.md,将同等逻辑用目标语言实现后,写入用户项目约定的 utils / helpers / common 等目录(与项目现有工具类组织方式一致);并用 signing.md §5 golden examples 做自测。
  • 签名语义始终以 reference/signing.md 为准;与平台单接口文档冲突时以接口文档为准。
  • 生成物须可编译、可测,勿留未解析依赖。

Java 签名调用模板(必读,防止签名错误)

生成 Java 对接代码时,签名与 HTTP 调用必须遵循以下模板(与 languages.md 中 HTTP 栈结合):

// 1. 组装业务参数(不要包含 sign 字段,按文档参数表组装)
Map<String, Object> params = new HashMap<>();
params.put("agent_no", agentNo);
params.put("agent_apply_no", applyNo);
// ... 其他业务参数(按文档参数表 M/O 标注添加)
// 若文档参数表包含 accessid,则添加(accessid 主要用于获取 accesskey,非所有接口必传):
// params.put("accessid", accessId);

// 2. 计算签名(只需 accesskey,SignUtils 会自动过滤 sign/mac 和空值)
String sign = SignUtils.signParams(accessKey, params);

// 3. 将 sign 放入请求体
params.put("sign", sign);

// 4. 发送请求
String response = httpClient.post(url, JSONObject.fromObject(params).toString());

关键注意事项

  • 签名只需 accesskeyaccesskey 是签名计算的必需凭据;accessid 主要用于获取 accesskey,仅当接口文档要求时才作为请求参数参与签名
  • 步骤 3 必须在步骤 2 之后sign 字段不能参与签名计算
  • 嵌套对象中的空值字段会自动被过滤:如 product_data.wx.mcc="" 不会出现在签名串中
  • 不要使用 JSONObject 直接遍历拼接JSONObject 键序不确定,必须通过 SignUtils.getToBeSign() 转为 TreeMap 后拼接

5.3 Java 参数类规范(必读)

生成 Java 请求参数类/DTO 时,必须使用 Lombok 注解,禁止手写 getter/setter/constructor 等样板代码。

强制规则

| 场景 | 必须使用 | 禁止 | |------|---------|------| | 请求参数类(DTO/Request/VO) | @Data | 手写 getXxx()/setXxx() | | 不可变参数类 | @Value | 手写 final 字段 + 全参构造器 + getter | | 链式构造参数类 | @Data + @Builder | 手写 Builder 模式 | | 嵌套参数对象 | @Data | 手写 getter/setter |

示例

// ✅ 正确:使用 @Data
@Data
public class CreateMerchantRequest {
    private String agentNo;
    private String merchName;
    private String contactPhone;
}

// ❌ 错误:手写 getter/setter(冗余,不符合规范)
public class CreateMerchantRequest {
    private String agentNo;
    public String getAgentNo() { return agentNo; }
    public void setAgentNo(String agentNo) { this.agentNo = agentNo; }
    // ...
}

Lombok 依赖(如项目未引入,生成代码时需提醒用户在 pom.xml 中添加):

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>

注意lombokscopeprovided,运行时由 IDE/编译器处理,不打包进最终 jar。

5.5 语法检查与规范校验(生成代码后必须执行)

代码生成完成后,必须进行以下检查,确保代码可正常运行且符合项目规范:

  1. 方向与流程检查(对照顶部「⛔ 强制生成流程」和「方向规则」,最高优先级):

    • 代码中是否有 URL 变量/常量(请求地址)?无 → 方向错误,必须添加
    • 代码中是否有 HTTP 客户端 POST 调用?无 → 方向错误,必须添加
    • 代码中是否有 verifySigncheckSignvalidateSign 等验签操作?有 → 必须删除
    • 代码中是否有 handleNotifyreceiveNotifyonNotify 等服务端接收方法?有 → 必须删除
    • 代码中是否有解析请求 body → 业务处理 → 构建响应(如 SUCCESS/return_code)的服务端逻辑?有 → 必须删除
    • 代码中的 sign 是否来自签名方法返回值(而非字符串常量)?否 → 必须重构
    • 是否生成了 import saas.notify.*SaasConfig.getInstance() 等目标项目不存在的依赖?有 → 使用标准库实现
  2. 语法检查

    • Java:检查 import 是否完整、类型是否匹配、方法签名是否正确、异常处理是否完善;参数类/DTO 是否使用 Lombok @Data(禁止手写 getter/setter)
    • Python:检查缩进是否一致、import 是否完整、类型注解是否正确
  3. 项目规范一致性校验(基于 §3.5 学习到的规范):

    • 代码文件是否放在正确的目录下(公用方法 → common,工具类 → utils,业务逻辑 → service,配置 → config/resources
    • 命名风格是否与项目一致(类名、方法名、变量名)
    • 方法长度是否在限制内(如 50 行以内),超长方法需拆分
    • controller 层是否避免了过多业务逻辑
    • SQL 语句是否通过配置文件管理,而非直接嵌入代码
    • 新增依赖是否已同步更新到打包部署文件
    • 是否存在重复逻辑应提取为公共方法
  4. 签名逻辑校验

    • 签名实现是否与 reference/signing.md 一致
    • 是否正确过滤了 sign/mac 字段和空值
    • 嵌套参数展开规则是否正确(对照 golden examples)
    • 密钥拼接方式是否与接口文档要求一致(直接拼接 vs &key= 前缀)
    • Java 特有检查
      • 是否使用了 SignUtils.signParams() 而非自行拼接签名串
      • accessid 仅在接口文档要求时才传入和参与签名,非文档要求时不应强行添加;accesskey 是签名必需凭据
      • sign 字段是否在签名计算之后才放入参数 Map
      • 嵌套对象中的空值字段(如 mcc="")是否被递归过滤
      • pom.xml 中 json-lib 是否指定了 jdk15 classifier
      • 是否编写了 golden examples 单元测试(见 signing.md §8.2)
      • Demo/测试参数是否符合 §5.0 强制规则(来自请求示例,非编造)
  5. 客户端对接流程完整性(对照顶部「⛔ 强制生成流程」):

    • 是否存在「获取参数 → 现算 sign → HTTP 客户端 POST → 处理响应」的完整调用链
    • 缺 URL 接口是否已按第 2 步询问用户,代码中用占位符 + 注释
    • 是否存在仅签名计算而无 HTTP 调用的生成代码(禁止,与顶部强制规则对齐)
    • 是否误生成了服务端验签 / 接收通知 Controller(本 SKILL 绝不生成任何服务端代码
    • 是否误用文档请求示例中的 sign:不得硬编码、不得作为断言期望值
  6. sign 生成逻辑(与 §5.0 对齐):

    • sign 是否通过 accesskey + 参数字典现算(而非抄用文档示例值)
    • sign 是否在签名计算后才放入参数字典
    • 嵌套参数展开规则是否正确(对照 golden examples)
    • 密钥拼接方式是否与接口文档要求一致(直接拼接 vs &key= 前缀)
  7. 依赖完整性检查

    • 新增的第三方库是否已在项目依赖文件中声明(pom.xmlrequirements.txtgo.modpackage.json 等)
    • 是否存在未解析的 import 或引用
  8. 问题处理

    • 发现语法错误 → 立即修复后重新检查
    • 发现规范不一致 → 调整代码以符合项目规范
    • 发现签名逻辑问题 → 对照 reference/signing.md 修正

6. 清理临时文件(生成后必须执行)

  • 若为"抓文档→生成代码"过程创建了临时文件(如 *.html*_doc.html、抓取缓存、解析中间产物),在代码生成完成后应自动删除,避免污染用户工程与提交历史。
  • 仅保留:最终对接代码、配置模板、必要的单元测试(如签名 golden tests)与简短 README。

详细参考

安装到各工具

复制整个 hk-saas-api 文件夹(含 doc/doc/docs/reference/SKILL.md)到对应 skills 目录。缺少 doc/api-catalog.yamldoc/docs/(本地文档缓存)、doc/SignUtils.java(Java 直拷用)或 reference/signing.md 则本 skill 不完整。

可通过 doc/download_docs.py 脚本重新下载或更新本地接口文档缓存(需网络连接到文档门户,仅当环境中安装了 Python 时可用)。

7. 更新接口文档(/hk-saas-update 命令)

用户使用 /hk-saas-update 命令时,按以下流程更新本地接口文档缓存。

重要:本 skill 支持 Java/Python 等多语言环境,不能假设运行环境已安装 Python。更新操作必须通过 Agent 自身能力(WebFetch 抓取页面 + 文件写入)完成,而非调用 Python 脚本。

命令格式

/hk-saas-update                    # 更新全部接口文档
/hk-saas-update {接口名称}         # 按接口名称模糊匹配,仅更新匹配的接口

示例

/hk-saas-update                    # 更新全部 161 个接口文档
/hk-saas-update 预下单             # 更新"预下单"接口文档
/hk-saas-update 商户入网           # 更新所有包含"商户入网"的接口文档
/hk-saas-update pre-pay            # 按英文标识(local_doc 文件名)匹配

执行步骤(由 Agent 直接执行,不依赖 Python):

  1. 解析过滤条件:从命令参数中提取接口名称关键词(支持中文名称和英文标识模糊匹配)
  2. 匹配接口:读取 doc/api-catalog.yaml,遍历所有 scenarios[].apis[],对 name(中文名称)和 local_doc(英文标识文件名)做模糊匹配
  3. 在线抓取:对匹配到的每个接口,使用 Agent 的 WebFetch 能力从 doc_url 抓取文档页面 HTML
  4. 提取主体内容:从 HTML 中提取 <article class="markdown-article-inner"> 区域的内容,剔除 TOC 目录(markdown-toc div),转换为 Markdown 格式
  5. 保存到本地:将 Markdown 内容写入 doc/{local_doc} 指定的文件路径(如 doc/docs/pre-pay.md),已有文件直接覆盖
  6. 更新清单:更新 doc/docs/manifest.json 中对应条目的下载时间和状态
  7. 输出结果:报告成功/失败数量,失败的接口输出名称和 URL

HTML 提取规则(与 doc/download_docs.py 一致):

  • 定位 <article class="markdown-article-inner"> 标签,提取其内部 HTML
  • 若无此标签,尝试 <article id="page-content">
  • 剔除 <div class="markdown-toc"> 目录导航区域
  • 剔除 <script><style> 标签
  • 将清理后的 HTML 转换为 Markdown 格式(保留表格、代码块、链接等结构)
  • 合并多余空行(3 个以上连续空行合并为 2 个)

备选方案:若环境中安装了 Python 及 yamlmarkdownify 依赖,也可直接运行脚本:

python doc/download_docs.py 预下单 订单查询    # 按名称过滤
python doc/download_docs.py                    # 更新全部

不得将此脚本作为唯一更新方式,Agent 必须能独立完成更新操作。