← 返回 Skill 列表
extension
分类: 营销与增长API Key 暂未确认

FlyLink商品上架

Publish a FlyLink product via XAILinker Skill OpenAPI. Supports product image flow, product link flow (WebFetch page extraction), and Excel/CSV batch file flow. Fetches store distribution defaults, forces USD pricing with user confirmation, and builds English SKU/spec payloads unless the user requests another language. Requires XAILinker API Key only; never FlyLink client_secret.

person作者: FlywayTThubModelScope

FlyLink 商品上架(图片 / 链接 / 文件 → 确认 → 发布)

定位: 飞来汇(Flyway)旗下 FlyLink 商品上架能力,由 XAILinker 提供 Skill OpenAPI 接入。
一句话使用: 把商品图片、链接或 Excel/CSV 文件丢过来,说「上架到 FlyLink」即可—— 「帮我把这张图上架到 FlyLink」「把这个链接上架到 FlyLink」「把这个 Excel 里的商品批量上架到 FlyLink」

术语: 文中「平台」一律指 XAILinker 平台(鉴权、额度、FlyLink developer 凭证绑定均在此完成)。

支持三种入口:

  • 商品图片:根据图片生成商品名称与描述,再调用 XAILinker Skill OpenAPI 上架到 FlyLink
  • 商品链接:使用 WebFetch 抓取已可访问的页面内容,由 agent 提取商品信息构建草稿(见 Step 1B;不保证任意链接完整提取)
  • Excel/CSV 文件(批量):读取文件内容,解析每一行为一个商品草稿,用表格汇总展示给用户确认后逐个走标准流程(见 Step 1A-2)

前置条件

  1. 用户已配置 XAILinker API Key(即 OpenAPI client_key,Skill 只持有这一项)
  2. 该用户已在 XAILinker 平台绑定 FlyLink developer 凭证(否则接口返回 4401 / FLYLINK_DEV_CREDENTIAL_MISSING)
  3. 用户提供以下任一输入:
    • 商品图片(本地路径)
    • 商品链接(可访问的 URL;走 WebFetch 抓取页面,agent 自行提取信息)
    • Excel/CSV 文件(本地路径,批量上品;文件格式不限,agent 读取后先展示表格供用户确认)
  4. 若提供的是商品链接 → 走 Step 1B(WebFetch 抓取页面,agent 自行提取信息)
  5. 若提供的是 Excel/CSV 文件 → 走 Step 1A-2(读取文件 → 表格展示确认 → 逐商品走标准流程)
  6. 另需:USD 售价(必须用户确认;币种仅允许 USD)

不支持范围

  • 不支持侵权、仿牌、盗图商品
  • 不支持受监管商品或禁售品
  • 不支持医疗、药品、武器、成人、金融等敏感品类
  • 不支持绕过目标网站访问限制抓取内容
  • 不保证从任意链接完整提取商品信息
  • 不保证 AI 生成内容可直接用于商业发布(须经用户确认后再建品)

审核责任边界

  • Skill 建品提交成功 ≠ FlyLink 审核通过
  • 审核结果以 FlyLink 后台为准;被拒需按规则修改后重新处理
  • Skill 仅辅助准备与提交资料,不能绕过 FlyLink 审核
  • 有 goods_id 但无上线 url:视为仍在审核或未通过,不得宣称「已审核通过」

硬性约束(必须遵守)

| 约束 | 说明 | |------|------| | 币种 | 仅允许 saleCurrency=USD(后端与 CLI 均强制校验) | | 价格确认 | 建品前每个 SKU 逐一确认 USD 售价与库存——单 SKU 确认一组,多 SKU 逐行列表示确认,禁止对多 SKU 静默填充统一价格/库存 | | SKU 语言 | 规格名/规格值默认用英文;第一步就提醒用户;仅当用户指定语言时才改 | | 描述展示 | goodsDesc 会直接展示在商品页,必须使用格式化可读内容(见下文模板) | | 分销 | Step 0C 拉取店铺分销设置(仅拉取);Step 1D-2(Step 1C 之后)向用户确认是否开分销及佣金比例 | | 标题长度 | goodsTitle ≤ 200 字符;超长截断到 197 + ... 或提示用户精简 | | 描述长度 | goodsDesc ≤ 6000 字符;超长时截断非关键段落或提示用户精简 | | 图片数量 | 每个商品 goodsImageList 1~10 张;超过 10 张时让用户选择最重要的 10 张 |

鉴权(运行前必做)

任何 API 调用之前,先确认 XAILINKER_API_KEY:

python scripts/skill_openapi_client.py check-auth

Agent 检查流程

  1. 检查是否已有 Key

    • 优先读取环境变量 XAILINKER_API_KEY(由 WorkBuddy 等宿主注入)
    • 若环境变量缺失,则读取当前 skill 目录的 config.json
    • 可执行 check-auth --skip-ping 仅验证本地是否已配置 Key
    • 执行 check-auth(不带 --skip-ping)会请求 GET /flylink/categories 验证 Key 是否有效
  2. 缺失则引导用户获取并设置

    • 前往 https://xailinker.com/skill/login
    • 使用 飞来汇(Flyway)账户登录;新用户可在该页注册
    • 登录后在页面复制完整 OpenAPI Key
    • 用户把 Key 粘贴回来后,执行以下任一方式保存:
      python scripts/skill_openapi_client.py set-key --key <用户粘贴的 Key>
      
      或请 WorkBuddy 设置环境变量 XAILINKER_API_KEY(可选 XAILINKER_BASE_URL)
    • 保存后再执行 check-auth 验证
  3. Credit 余额检查(运行时感知)

    • check-auth 验证的是 Key 有效性,不检查 Credit 余额
    • Credit 余额不足会在后续 API 调用(upload / create 等)时才暴露
    • 当任何 API 返回含 credit / 余额不足 / insufficient credit 关键词,或错误码为 4020 / 4021 等余额相关错误时:
      • 立即停止当前操作,不要重试
      • 提醒用户:「您的 XAILinker 账户额度不足,本次操作未继续执行。请在 XAILinker 平台 账户中查看额度及处理。」
      • 用户处理额度后,重新执行失败的操作即可,无需重新鉴权

环境变量(由 WorkBuddy 设置):

| 变量 | 说明 | |------|------| | XAILINKER_BASE_URL | 默认 https://www.xailinker.com/api/v1 | | XAILINKER_API_KEY | Bearer:OpenAPI client_key 或 access_token |

config.json(保存/读取)

{
  "XAILINKER_API_KEY": ""
}

标准流程(严格按序)

确认鉴权
→ Step0 收集输入(提醒:SKU 默认英文;价格仅 USD)
→ Step 0C 拉取店铺分销默认值(仅拉取,不在此确认)
→ 获取商品草稿(看图 / WebFetch 链接抓取 / 文件解析)
→ 【若文件入口】表格展示全部商品信息 → 用户确认内容 → 逐商品走以下流程
→ 整理 SKU/规格 + 强制确认 USD 价格(Step 1C)
→ Step 1D-2 分销确认(使用 Step 0C 拉取的默认值,向用户确认是否开分销 + 佣金)
→ 上传图床 → 拉品类并匹配
→ 用户总确认 Step 1E(通用最终确认闸门,所有入口必经)
→ 建品 → 等待审核并查询上线链接

Step 0 — 收集输入(第一步就提醒语言与币种)

向用户确认并记下:

  • goods_id(可选:若已有,可跳过建品,只查上线链接)
  • 输入来源:图片路径、商品链接或 Excel/CSV 文件路径(三选一;无 goods_id 时必填)
  • 售价(USD):必须稍后再次确认;禁止使用 CNY 等其他币种;多 SKU 时必须逐 SKU 确认(见 Step 1C)

    若输入是文件,价格从文件中读取(Step 1A-2 表格确认),不再单独询问;但仍需 Step 1C 逐 SKU 确认

  • 库存:多 SKU 时每个 SKU 的库存也需分别确认;默认单 SKU 库存为 100

    若输入是文件,库存从文件中读取,不再单独询问;但仍需 Step 1C 逐 SKU 确认

  • SKU / 规格文案语言:默认英文。开场即提醒:

    「规格名与规格值将默认使用英文(如 Size / Color / M / L)。若需要中文或其他语言,请现在说明。」 「若有多个 SKU,稍后会逐项确认每个 SKU 的 USD 价格和库存,请留意。」

  • 可选:标题偏好、库存、是否多规格(仅当用户主动提到时再记;不要为此单独开一轮追问)

联系方式(默认跳过,勿主动询问):

  • 支持字段:contactEmail / contactMobile / contactWhatsApp / contactFaceBook / contactInstagram / contactSkype / contactTelegram / contactDiscord 等
  • 禁止在收集输入、确认清单或最终闸门中主动询问「要带联系方式吗?」
  • 仅当用户主动提供联系方式时再写入 payload;用户未提及时整组 contact* 字段一律不传
  • 不要从 config.json 里静默带出历史联系方式,除非用户本轮明确要求沿用

若输入是 URL → 走 Step 1B(WebFetch 抓取页面,agent 自行提取信息)

若输入是文件(后缀 .xlsx / .xls / .csv / .tsv):

  • 走 Step 1A-2(读取文件 → 解析 → 表格展示 → 用户确认 → 逐商品走标准流程)

缺必填项时先问齐,再继续。

Step 0B — 仅查询是否已上线(有 goods_id)

python scripts/skill_openapi_client.py wait-link-url --goods-id <goods_id> --initial-wait 5 --timeout 10
  • 有 url:发给用户
  • 无 url:仍在审核,提示稍后用同一 goods_id 复查

Step 0C — 拉取店铺分销设置(仅拉取,不在此处确认)

时机说明:此步骤仅调用 API 拉取分销默认值并记录,不向用户确认。 用户的分销确认(是否开分销 + 佣金比例)在 Step 1C 价格确认之后进行(见标准流程图)。 这样做的原因:用户需要先看到完整的 SKU 和价格信息,再决定是否开分销。

python scripts/skill_openapi_client.py distribution-settings

或 GET /skill-openapi/flylink/distribution/settings。

关注字段(API 返回 snake_case):

| 字段 | 含义 | |------|------| | enable_distribution | 店铺是否开启分销:1 开 / 0 关 | | goods_default_commission_rate | 默认商品分销佣金比例(如 "0.1500") |

规则(仅记录,不确认):

  1. 若 enable_distribution == 1:
    • 记录默认佣金比例 goods_default_commission_rate,待 Step 1C 之后向用户确认
    • 批量入口(文件):只拉取一次分销设置,稍后统一确认一次(如「以下分销设置将适用于全部 N 个商品:开启分销,佣金 15%」),用户确认后对所有商品统一适用
  2. 若 enable_distribution == 0:
    • 记录为 enableDistribution=0,Step 1C 之后可顺便询问用户是否要开(一般保持关闭即可)

Step 1D-2 — 分销确认(Step 1C 价格确认之后、上传图片之前)

此步骤在 Step 1C 逐 SKU 确认价格之后执行,使用 Step 0C 拉取的分销设置。

  1. 若 Step 0C 拉取到 enable_distribution == 1:
    • 向用户展示默认值,并确认:
      • 本商品是否开启分销?(默认建议:开启)
      • 分销比例 commissionRate?(默认:Step 0C 拉取的 goods_default_commission_rate)
    • 用户确认开启 → payload:enableDistribution=1,commissionRate=<确认值>
    • commissionRate 格式:字符串,4 位小数,值域 "0.0000" ~ "1.0000"。用户说 "10%" → "0.1000";说 "15%" → "0.1500"。始终格式化为 4 位小数
    • 用户选择关闭 → enableDistribution=0,不传 commissionRate
    • 批量入口(文件):统一确认一次,适用全部商品,不再逐个询问
  2. 若 Step 0C 拉取到 enable_distribution == 0:
    • 默认 enableDistribution=0
    • 仍可询问用户是否要开(一般保持关闭即可)

Step 1A — 图片入口:生成商品信息(本地,不调 API)

生成:

  • goodsTitle:≤200 字。超长时优先截断到 197 字加 ...,或提示用户自行精简
  • goodsDesc:≤6000 字符的页面可读格式化描述(见下方模板);生成后检查长度,超 6000 时截断非关键段落(如 Notes)或精简 Highlights 列表
  • 品类关键词
  • 建议 USD 售价(仅作默认值,必须再确认)

Step 1A-2 — 文件入口(Excel/CSV):读取 → 表格确认 → 逐商品走标准流程

当用户提供 Excel/CSV 文件时,文件格式不固定——列名和列顺序可能千差万别。Agent 需先读取文件、智能推断列含义、用表格展示给用户确认,确认后再逐个商品走标准流程。

1. 读取文件

  • .csv / .tsv → 使用 Read 工具直接读取文本内容
  • .xlsx / .xls → 使用 Python 解析:
    python -c "
    import openpyxl, json, sys
    wb = openpyxl.load_workbook(sys.argv[1], read_only=True)
    ws = wb.active
    rows = list(ws.iter_rows(values_only=True))
    print(json.dumps(rows, ensure_ascii=False, default=str))
    " "<文件路径>"
    

    ⚠️ Windows 路径含空格时必须用双引号包裹(如 "C:\Users\My Photos\products.xlsx"),否则 shell 会将路径拆成多个参数。 若 openpyxl 未安装:pip install openpyxl(在隔离 venv 中安装,详见运行时隔离规则)

2. 智能推断列含义

文件格式不固定,Agent 需根据列名(或首行内容)推断每列对应的商品字段:

| 可能的列名(中/英) | 推断为 | 说明 | |---------------------|--------|------| | 标题 / title / name / 商品名 / 产品名 | goodsTitle | 商品标题 | | 描述 / description / desc / 详情 / 卖点 | goodsDesc | 商品描述(若多列则合并) | | 价格 / price / 售价 / 单价 / price(USD) / 美元价 | salePrice | 参考价格,仅参考,必须 Step 1C 确认 | | 原价 / origPrice / 划线价 / 原始价 | origPrice | 原价 | | 库存 / stock / 数量 / quantity / qty | stock | 参考库存,仅参考,必须 Step 1C 确认 | | 图片 / image / 图片路径 / 图片链接 / image_url / 主图 | images | 本地路径或 URL(分别处理) | | 规格 / spec / SKU / 尺码 / 颜色 / size / color | specList | 规格维度(可能多列) | | 品类 / 分类 / category / 类目 | category | 品类提示词 | | 品牌 / brand | brand | 品牌信息 |

推断规则:

  • 先看首行(表头),匹配上表的列名(支持中英文、忽略大小写、忽略空格)
  • 若无表头(首行直接是数据),根据内容特征推断(如含 $ 或纯数字 → 价格,含路径或 http → 图片)
  • 无法确定的列:保留原始列名,在表格中标注「❓ 未识别」,请用户说明
  • 不要静默丢弃任何列——即使无法推断也要展示给用户

3. 表格展示(核心步骤)

将解析出的所有商品信息用表格汇总展示给用户,这一步只做内容确认,不涉及上架:

我从文件中读取到了以下商品信息,请确认:

| # | 标题 | 描述 | 价格(USD) | 库存 | 图片 | 规格 | 品牌 | 品类 |
|---|------|------|-----------|------|------|------|------|------|
| 1 | ... | ...  | 9.99      | 100  | C:\photos\a.jpg | Size: S/M/L | ... | ... |
| 2 | ... | ...  | 14.99     | 50   | https://...     | Color: Red/Blue | ... | ... |
| 3 | ... | ...  | ❓未识别  | 100  | C:\photos\c.jpg | ❓未识别        | ... | ... |

⚠️ 以上内容来自文件自动解析,列含义已自动推断:
- 「价格」列 → 参考售价(稍后逐 SKU 确认,不会直接使用)
- 「库存」列 → 参考库存(稍后逐 SKU 确认)
- 标 ❓ 的列未能自动识别,请说明对应含义
- 标 ❓ 的价格为空,请补充

请确认:
1. 表格内容是否正确?有需要修正的地方吗?
2. 标 ❓ 的列是什么含义?
3. 每个商品是否都需要上架?如有不需要的行请告知行号。

4. 用户确认后,逐商品走标准流程

用户确认表格内容后,逐个商品走以下流程(串行执行,逐个反馈进度):

商品 1/3:{goodsTitle}
→ Step 1C 逐 SKU 确认价格与库存
→ Step 1D-2 分销确认(批量入口统一确认一次,适用全部商品)
→ 上传图片(若图片为本地路径直接 upload;若为 URL 先下载再 upload)
→ 品类匹配
→ Step 1E 最终确认闸门
→ 建品

商品 2/3:{goodsTitle}
→ ...

商品 3/3:{goodsTitle}
→ ...

⚠️ 文件入口的约束

  • 文件格式不固定——不要假设固定列名或固定列顺序,必须根据实际内容推断
  • 图片列可能是本地路径也可能是 URL——本地路径直接 upload,URL 先下载再 upload,禁止直接用外链 URL
  • 每个商品最多 10 张图片——若图片列有多个值(逗号分隔等),取前 10 张或让用户选择
  • 标题 ≤200 字符、描述 ≤6000 字符——文件中的标题/描述可能超长,生成 payload 前检查并截断或提示用户精简
  • 价格和库存仅为参考值——文件中写的价格不会直接用于建品,仍需 Step 1C 逐 SKU 确认
  • 表格展示是必经步骤——不要跳过直接开始上架,用户可能需要修正内容或排除某些行
  • 逐商品串行执行——不要并行建品,避免 API 限流;每个商品完成后反馈进度(如「✅ 商品 1/3 已上架」)
  • 若文件中某行关键信息缺失(如无标题、无图片),标注后跳过该行,继续处理后续行

批量上架的行数上限与分批

  • 建议上限:20 行/批。超过 20 行时,向用户建议分批处理(如「文件中有 50 行,建议分 3 批处理,每批约 17 行」)
  • 用户确认分批后,按批处理,每批完成后汇总反馈
  • 若用户坚持一次性处理全部,可以执行但需提前提醒「这将花费较长时间」

批量上架的错误恢复策略

逐商品串行处理时,若某个商品建品失败:

  1. 记录失败商品:行号、标题、失败原因(422 参数错误 / 网络超时 / API 500 等)
  2. 不要停止整个批次——跳过失败商品,继续处理后续商品
  3. 每个商品完成后反馈进度(如「✅ 商品 1/3 已提交建品」「❌ 商品 2/3 失败:422 参数错误,原因:缺少 categoryName」)
  4. 全部处理完毕后,汇总:
    • 成功列表(含 goods_id 和上线链接)
    • 失败列表(含行号、标题、失败原因),建议用户修正后重试

API 调用失败时的重试指引

| 失败类型 | 重试策略 | |----------|----------| | 网络超时(upload/create) | 等待 3 秒后重试 1 次;仍失败则跳过该商品,记录超时 | | API 500 / 502 / 503 | 等待 5 秒后重试 1 次;仍失败则跳过,记录服务端错误 | | API 422 / 4000(参数错误) | 不重试——逐项自查错误处理表中的清单,修正后重试 | | API 401 | 不重试——Key 过期,需重新鉴权 | | Credit 余额不足(code 4020/4021 或返回含 credit/余额不足 关键词) | 不重试——提醒:「您的 XAILinker 账户额度不足,本次操作未继续执行。请在 XAILinker 平台 账户中查看额度及处理。」处理后再重试 | | API 429(限流) | 等待 10 秒后重试;连续限流则降低批量并发

Step 1B — 链接入口:WebFetch 抓取

当用户提供商品链接时,用 WebFetch 工具 抓取页面内容,由 agent 自行提取商品信息。

流程

  1. 告知用户:

    「我将尝试自动抓取页面信息。提取结果可能不完整,稍后会让你逐项核实。」

  2. 调用 WebFetch 抓取页面:

    • 使用 WebFetch(url, prompt) 抓取页面内容
    • prompt 示例:「请提取此商品页面的以下信息:1. 商品标题 2. 商品描述/卖点 3. 所有商品图片 URL 4. 价格 5. SKU/规格信息(尺码、颜色等)6. 品牌 7. 品类。以 JSON 格式返回。」
  3. 从抓取结果中提取信息:

    • goodsTitle:页面标题或商品名,翻译为英文(≤200 字符)
    • goodsDesc:根据描述/卖点生成格式化 HTML(见 Step 1D 模板,≤6000 字符)
    • 图片 URL 列表:提取页面中的商品图片 URL(每个商品最多取 10 张)
    • 参考价格:页面显示的价格(仅参考,必须用户确认;若非 USD 需换算并标注汇率来源)
    • 规格/SKU 信息:尽量提取尺寸、颜色等规格维度
  4. 图片处理:

    • 提取到的图片 URL 是外链 → 下载到本地 → 逐一 upload → 得到 FlyLink CDN 路径
    • 禁止直接用外链 URL 作为 imageUrl 或 skuImage
  5. 生成商品草稿并明确标注来源:

    • 向用户展示提取到的信息时,每项标注「⚠️ 来自页面自动提取,请核实」
    • 特别标注:标题、价格、规格是否完整提取
  6. 进入 Step 1C 逐 SKU 确认价格与库存(与图片入口一致,不因来源是 WebFetch 就放宽确认)

⚠️ WebFetch 链接入口的约束

  • 提取的信息质量不可控——取决于目标网站结构、反爬机制、是否 SPA 等
  • 如果 WebFetch 返回的内容明显为空或无法提取有效商品信息(如只有导航栏/页脚),明确告知用户抓取失败,建议改走图片流程
  • WebFetch 提取的价格绝对不能直接用于建品——必须经 Step 1C 用户逐 SKU 确认
  • WebFetch 可能拿不到图片 URL(如懒加载图片),此时向用户索要商品图片
  • 提取到的规格信息可能不完整——缺失时向用户补充确认

Step 1C — SKU 与价格确认(强制)

情况 A:用户未提供多规格 / 只有单一售价

  1. 向用户确认:USD 售价、库存(默认 100)
  2. 生成最小 skuList(规格文案用英文,除非用户另指定语言):
{
  "specList": [
    {
      "specName": "Spec",
      "specItemList": [{ "itemName": "Default" }]
    }
  ],
  "skuList": [
    {
      "specSetName": "Default",
      "specSetNameForParent": "Default",
      "specSetNameForChild": "",
      "specData": "{\"Spec\":\"Default\"}",
      "salePrice": "29.90",
      "saleCurrency": "USD",
      "stock": 100
    }
  ]
}

origPrice 可选,仅在有划线价需求时设置(见 Step 4)。上例中不传 origPrice。

情况 B:用户提供了多 SKU / 规格(逐 SKU 确认,禁止静默填充)

当有 2 个及以上 SKU(多尺码/多颜色/多规格组合),必须逐项列出并确认每个 SKU 的价格和库存,不允许假设所有 SKU 同价同库存。

逐 SKU 确认流程:

  1. 先生成规格清单(specList),向用户确认规格维度与值
  2. 将规格展开为完整 SKU 矩阵,用表格逐行展示给用户填写确认:
| SKU    | Size | Color | salePrice(USD) | origPrice | stock |
|--------|------|-------|----------------|-----------|-------|
| S      | S    | —     |                |           |       |
| M      | M    | —     |                |           |       |
| L      | L    | —     |                |           |       |
| XL     | XL   | —     |                |           |       |
  1. 关键规则:

    • 禁止在用户未逐行确认价格/库存时静默填充默认值
    • 禁止假设所有 SKU 价格一致、库存一致
    • 用户可以用「全部统一 $X,库存各 Y」简化答复,但必须用户主动说出这句话才算确认,agent 不能默认
    • 确认完成后生成 skuList,确保 specData 与 specSetName 对齐(见 references/api.md 多规格示例)
  2. 其他字段:

    • 规格维度名(英文默认,如 Size / Color)
    • specList + skuList 字段对齐

多维度 SKU 组合(如 Color × Size)

当规格有两个及以上维度时(如 3 色 × 4 码),specList 和 skuList 结构如下:

  1. specList 包含每个维度,并生成 specIdForGroup(唯一分组 ID,取毫秒时间戳或自增整数):

⚠️ specIdForGroup 位于建品 payload 的根级别,与 specList、skuList、goodsTitle 同级。不是 specList 内部的字段。详见 references/api.md 多维度完整示例。

{
  "specIdForGroup": 1783576121897,
  "specList": [
    { "specName": "Color", "specItemList": [{"itemName": "Blue"}, {"itemName": "Gray"}] },
    { "specName": "Size",  "specItemList": [{"itemName": "S"}, {"itemName": "M"}] }
  ]
}
  1. skuList 为笛卡尔积(2 色 × 2 码 = 4 个 SKU):
    • specSetName:父/子用 / 分隔,不要加空格(如 Blue/S 而非 Blue / S)
    • specSetNameForParent:第一个维度(父)的值
    • specSetNameForChild:第二个维度(子)的值
    • skuImage:可选,每个 SKU 可配独立图片(如不同颜色用不同图);不填则继承主图
[
  {
    "skuImage": "flylink/xxx_blue.jpg",
    "specSetName": "Blue/S",
    "specSetNameForParent": "Blue",
    "specSetNameForChild": "S",
    "specData": "{\"Color\":\"Blue\",\"Size\":\"S\"}",
    "salePrice": "200", "saleCurrency": "USD", "stock": 25
  },
  {
    "skuImage": "flylink/xxx_blue.jpg",
    "specSetName": "Blue/M",
    "specSetNameForParent": "Blue",
    "specSetNameForChild": "M",
    "specData": "{\"Color\":\"Blue\",\"Size\":\"M\"}",
    "salePrice": "200", "saleCurrency": "USD", "stock": 25
  },
  {
    "skuImage": "flylink/xxx_gray.jpg",
    "specSetName": "Gray/S",
    "specSetNameForParent": "Gray",
    "specSetNameForChild": "S",
    "specData": "{\"Color\":\"Gray\",\"Size\":\"S\"}",
    "salePrice": "200", "saleCurrency": "USD", "stock": 25
  },
  {
    "skuImage": "flylink/xxx_gray.jpg",
    "specSetName": "Gray/M",
    "specSetNameForParent": "Gray",
    "specSetNameForChild": "M",
    "specData": "{\"Color\":\"Gray\",\"Size\":\"M\"}",
    "salePrice": "200", "saleCurrency": "USD", "stock": 25
  }
]

specIdForGroup 生成规则:使用毫秒时间戳。获取方式(跨平台):

python -c "import time; print(int(time.time() * 1000))"

⚠️ 不要使用 date +%s%3N——Windows 的 Git Bash 不支持 %3N,会输出字面量 3N 而非毫秒数。

若建品脚本支持自动生成,则传 0 或省略让服务端处理。

skuImage 规则:如果不同颜色/款式各有独立图片,分别 upload 后填入各 SKU;同维度不同值(如 Blue 的 S/M 共享 Blue 图)可复用同一 URL。无独立图片则不传。

  1. 多维度确认表格改为:
| SKU      | Color | Size | salePrice(USD) | stock |
|----------|-------|------|----------------|-------|
| Blue/S   | Blue  | S    |                |       |
| Blue/M   | Blue  | M    |                |       |
| Gray/S   | Gray  | S    |                |       |
| Gray/M   | Gray  | M    |                |       |
  1. 多维度时禁止让用户分别确认每个维度再自己组合——必须直接列出笛卡尔积全表让用户逐行确认

Step 1D — goodsDesc 格式化(页面直接展示)

goodsDesc 会直接显示在商品详情页,禁止堆成一团无换行的长文本。使用以下结构(HTML 优先,便于页面渲染):

⚠️ 总长度 ≤ 6000 字符。生成后检查长度,超限时截断非关键段落(优先保留 Highlights)或精简内容。

<h3>Highlights</h3>
<ul>
  <li>...</li>
  <li>...</li>
</ul>
<h3>Specifications</h3>
<p>...</p>
<h3>How to Use</h3>
<p>...</p>
<h3>Notes</h3>
<p>...</p>

具体示例(基于转化结果中的 spu.attrs):

假设 spu.attrs = {"材质": "聚酯纤维", "面料功能": "速干", "适用季节": "夏季", "帽围": "56-58cm"}:

<h3>Highlights</h3>
<ul>
  <li>Quick-drying polyester fabric</li>
  <li>Breathable mesh design for summer</li>
  <li>Adjustable fit: 56-58cm head circumference</li>
</ul>
<h3>Specifications</h3>
<p>Material: Polyester | Feature: Quick-dry | Season: Summer | Size: 56-58cm</p>
<h3>Notes</h3>
<p>Hand wash recommended. Do not bleach.</p>

若用户指定非英文页面语言,标题/描述可用该语言,但 SKU 规格名仍默认英文(除非用户明确要求规格也改语言)。

Step 1E — 通用最终确认闸门(所有入口必经)

铁律:无论商品信息来自哪个入口(图片 / WebFetch 链接抓取 / Excel/CSV 文件),调用 create / publish 之前,必须通过此闸门,用户明确同意后才能建品。

至少展示并确认:

  • goodsTitle
  • 格式化后的 goodsDesc
  • 主图 / 图片数量
  • 品类(categoryId / categoryName)
  • 完整 specList + skuList(多 SKU 时必须逐行展示每个 SKU 的 price/stock,禁止只汇总说「4 个 SKU 各 $X」)
  • enableDistribution + commissionRate(若开启)

确认清单格式(必须逐项展示):

【最终确认清单】
□ 商品标题:{goodsTitle}({len} 字符,≤200)
□ 商品描述:{goodsDesc 摘要}({len} 字符,≤6000)
□ 商品图片:{N} 张(每个商品 ≤10 张)(首图 URL: ...)
□ 品类:{categoryName} (ID: {categoryId})
□ SKU 明细:
  | # | 规格组合 | salePrice(USD) | stock |
  |---|---------|----------------|-------|
  | 1 | ...     | $ X.XX         | N     |
  | 2 | ...     | $ X.XX         | N     |
□ 分销:{已开启, 佣金 X%} 或 {未开启}
□ 联系方式:仅当用户本轮主动提供时展示;未提供则**整行省略**,不要写「非必填 / 要带吗?」
  • 用户明确回复「确认发布 / 可以上架」后才能建品
  • 禁止在确认清单中省略任何 SKU 的价格或库存
  • 禁止用「全部统一」代替逐行展示(即使用户之前说过统一价格,最终清单仍需逐行列出以供确认)
  • 禁止跳过此闸门——无论信息来自图片识别、WebFetch 链接抓取还是文件解析,都必须走这一步
  • 禁止因联系方式可选就主动询问;未提供联系方式时直接建品即可

Step 2 — 上传图片

python scripts/skill_openapi_client.py upload --file <本地图片路径>

图片格式与限制:

| 项目 | 说明 | |------|------| | 支持格式 | .jpg / .jpeg / .png / .webp / .gif | | 图片数量 | 每个商品 1~10 张(goodsImageList 字段限制,非 API 接口限制) | | 建议尺寸 | 宽 ≥ 500px,长宽比 1:1 或 4:3(主图建议正方形) | | 建议大小 | 单张 ≤ 5MB;超大文件上传慢且可能被拒 | | 不支持 | .bmp / .tiff / .svg / .heic 等 |

建品 goodsImageList[].imageUrl 必须用上传返回的 URL。链接抓取得到的外链图片需先下载再 upload。

下载外链图片到本地:

curl -L -o "<本地保存路径>" "<外链图片URL>"
# 示例:
curl -L -o "D:/photos/product_1.jpg" "https://img.alicdn.com/imgextra/xxx.jpg"

下载后检查文件是否有效(非 0 字节、非 HTML 错误页)。若下载失败(403/404/超时),告知用户并请其手动提供图片。

多图场景:

  • 每个商品最多 10 张图片——goodsImageList 字段限制(非 API 接口限制);超过时让用户选择最重要的 10 张
  • 每张图片分别 upload,得到独立 URL
  • goodsImageList 中第一张设置 firstImage=1,其余 firstImage=0
  • 多图时主动询问用户:「是否需要多角度展示?如正面/背面/细节,我可以一并上传。」
  • 建议顺序:正面 → 背面 → 细节 → 标签/包装
  • SKU 独立配图(skuImage):多颜色/款式时,不同 SKU 可配独立图片。将各颜色/款式图片分别 upload,在 skuList 中逐 SKU 填入 skuImage 字段。同一颜色不同尺码可复用同一图片 URL。

Step 3 — 品类匹配

python scripts/skill_openapi_client.py categories

匹配叶子节点;不确定时列出候选让用户选。

Step 4 — 创建商品

python scripts/skill_openapi_client.py create --payload product.json

字段要点详见 references/api.md §5「字段要点」表。以下为流程特化规则(api.md 未覆盖的约束):

  • saleCurrency 仅允许 USD(脚本内置校验)
  • origPrice 可选,只在有划线价需求时设置(origPrice > salePrice 表示原价,无折扣时可等值或不传)
  • needMarketing 默认 0
  • 不要传 relateId
  • enableDistribution / commissionRate 按 Step 1D-2 用户确认结果填写

成功:回报 goods_id、relate_id。
注意: 此处「成功」仅表示 已提交建品,不代表 FlyLink 审核通过。

Step 5 — 等待审核并查链接

python scripts/skill_openapi_client.py wait-link-url --goods-id <goods_id> --initial-wait 5 --timeout 10
  • 若返回有效 url:可告知用户商品已上线(审核侧已给出可访问链接)
  • 若无 url:说明仍在审核或未通过,禁止使用「已审核通过」话术;提示稍后用同一 goods_id 复查,或以 FlyLink 后台为准

仅在拿到有效 link_url 时,用以下格式输出总结:

## ✅ 商品已提交并获取到上线链接

| 项目 | 内容 |
|------|------|
| 商品标题 | {goodsTitle} |
| 商品 ID | {goods_id} |
| 上线链接 | {link_url} |
| SKU | 逐行列出,每行格式:`{specSetName} — $ {salePrice} / {stock} 件`(单 SKU 则 `Default — $ {salePrice} / {stock} 件`) |
| 分销 | 已开启,佣金 {commissionRate%}(或"未开启") |
| 说明 | 建品提交成功 ≠ 审核结论本身;若链接失效或后台显示驳回,以 FlyLink 后台为准 |

若仅有 goods_id、尚无链接:

## ⏳ 商品已提交,等待 FlyLink 审核

| 项目 | 内容 |
|------|------|
| 商品标题 | {goodsTitle} |
| 商品 ID | {goods_id} |
| 状态 | 审核中或尚未返回上线链接;Skill 不能绕过平台审核 |

格式规则:

  • SKU 价格必须带 $ 前缀(如 $ 2.22),禁止裸数字
  • SKU 列表每行一个,用 ⋅ 或换行分隔
  • 若有品类信息可在标题下方单列一行

错误处理

| 现象 | 处理 | |------|------| | 缺少 XAILINKER_API_KEY | 引导 skill/login → set-key → check-auth | | 4401 / FLYLINK_DEV_CREDENTIAL_MISSING | 引导用户前往 XAILinker 平台绑定 FlyLink 开发者凭证 | | 4003 | 商户未绑定用户或用户非 ACTIVE 状态;引导用户检查 XAILinker 商户绑定 | | 401 | 检查 Key / Base URL | | saleCurrency 非 USD | 改为 USD,重新确认价格后重试 | | enableDistribution=1 缺 commissionRate | 用店铺默认比例补齐并请用户确认 | | 建品失败(422 / 4000) | 逐项自查以下清单,确认后重试:<br>① 是否缺 categoryName?(categoryId 和 categoryName 必须同时提供)<br>② imageUrl 是否来自 upload 命令返回的 URL?(禁止用外链图片)<br>③ 是否错误传了 relateId?(禁止传此字段)<br>④ specData JSON 字符串是否与 specSetName 对齐?多规格时 specData 中的 key 必须匹配 specList 的 specName<br>⑤ saleCurrency 值是否为 "USD"?(大小写敏感,必须全大写)<br>⑥ 开分销(enableDistribution=1)时是否传了 commissionRate?<br>⑦ 叶子 categoryId 是否正确?(非叶子节点会被 422 拒绝)<br>⑧ 多维度时 specSetName 是否用 / 分隔无空格(如 Blue/S)?specSetNameForParent 是否为父维度值、specSetNameForChild 是否为子维度值?<br>⑨ 多维度时顶层是否传了 specIdForGroup?<br>⑩ goodsTitle 是否 ≤200 字符?<br>⑪ goodsDesc 是否 ≤6000 字符?<br>⑫ goodsImageList 是否每个商品 ≤10 张? | | 审核中无 url | wait-link-url 再轮询 | | 链接抓取失败 | 走 Step 1B WebFetch;若仍无法提取有效信息,再建议图片流程 | | Excel/CSV 文件无法解析 | 检查文件格式是否正确(.xlsx/.xls/.csv/.tsv);若 openpyxl 未安装则在隔离 venv 中 pip install openpyxl 后重试 | | 文件列无法识别 | 在表格中标注「❓ 未识别」,请用户说明列含义;不要静默丢弃或猜测 | | Credit 余额不足(API 返回含 credit / 余额不足 / insufficient credit 等关键词,或 code 为 4020 / 4021 等余额相关错误码) | 立即停止当前操作,不要重试。向用户提醒:<br>「您的 XAILinker 账户额度不足,本次操作未继续执行。请在 XAILinker 平台 账户中查看额度及处理。」<br>处理后再重新执行失败操作即可,无需重新鉴权。 | | 用户输入属于不支持范围(侵权/禁售/敏感品类等) | 拒绝继续建品,说明不支持范围,引导更换合规商品 |

资源

| 路径 | 用途 | |------|------| | scripts/skill_openapi_client.py | set-key / check-auth / distribution-settings / upload / categories / create 等 | | references/api.md | 接口契约与 JSON 示例 |

禁止事项

  • 禁止在 Skill 配置或日志中写入 FlyLink client_secret
  • 禁止跳过 common/files、把任意外链当 imageUrl
  • 禁止伪造 relateId
  • 禁止使用非 USD 币种上架
  • 禁止未确认价格就建品
  • 禁止多 SKU 时静默假设所有 SKU 同价同库存——必须逐行展示表格让用户逐一确认
  • 禁止在店铺已开分销且用户同意开分销时,漏传 commissionRate
  • 禁止跳过 Step 1E 最终确认闸门——无论输入来源如何,建品前必须展示完整确认清单并获用户明确同意
  • 禁止将 WebFetch 提取的信息直接用于建品——必须经 Step 1C 逐 SKU 确认 + Step 1E 最终确认
  • 禁止跳过文件入口的表格确认步骤——文件内容自动解析后必须先展示给用户确认,不能直接开始上架
  • 禁止将文件中的价格/库存直接用于建品——文件中的值仅为参考,仍需 Step 1C 逐 SKU 确认
  • 禁止主动询问联系方式(邮箱/手机/WhatsApp 等)——联系方式完全可选;用户未主动提供时不传任何 contact* 字段,也不要在确认表里追问
  • 禁止对不支持范围内的商品继续建品(侵权/仿牌/盗图、禁售与敏感品类等)
  • 禁止在未拿到上线链接时宣称「已审核通过」——建品提交成功 ≠ FlyLink 审核通过
  • 禁止尝试绕过目标网站访问限制抓取内容