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)
前置条件
- 用户已配置 XAILinker API Key(即 OpenAPI
client_key,Skill 只持有这一项) - 该用户已在 XAILinker 平台绑定 FlyLink developer 凭证(否则接口返回
4401/FLYLINK_DEV_CREDENTIAL_MISSING) - 用户提供以下任一输入:
- 商品图片(本地路径)
- 商品链接(可访问的 URL;走 WebFetch 抓取页面,agent 自行提取信息)
- Excel/CSV 文件(本地路径,批量上品;文件格式不限,agent 读取后先展示表格供用户确认)
- 若提供的是商品链接 → 走 Step 1B(WebFetch 抓取页面,agent 自行提取信息)
- 若提供的是 Excel/CSV 文件 → 走 Step 1A-2(读取文件 → 表格展示确认 → 逐商品走标准流程)
- 另需: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 检查流程
-
检查是否已有 Key
- 优先读取环境变量
XAILINKER_API_KEY(由 WorkBuddy 等宿主注入) - 若环境变量缺失,则读取当前 skill 目录的
config.json - 可执行
check-auth --skip-ping仅验证本地是否已配置 Key - 执行
check-auth(不带--skip-ping)会请求GET /flylink/categories验证 Key 是否有效
- 优先读取环境变量
-
缺失则引导用户获取并设置
- 前往 https://xailinker.com/skill/login
- 使用 飞来汇(Flyway)账户登录;新用户可在该页注册
- 登录后在页面复制完整 OpenAPI Key
- 用户把 Key 粘贴回来后,执行以下任一方式保存:
或请 WorkBuddy 设置环境变量python scripts/skill_openapi_client.py set-key --key <用户粘贴的 Key>XAILINKER_API_KEY(可选XAILINKER_BASE_URL) - 保存后再执行
check-auth验证
-
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") |
规则(仅记录,不确认):
- 若
enable_distribution == 1:- 记录默认佣金比例
goods_default_commission_rate,待 Step 1C 之后向用户确认 - 批量入口(文件):只拉取一次分销设置,稍后统一确认一次(如「以下分销设置将适用于全部 N 个商品:开启分销,佣金 15%」),用户确认后对所有商品统一适用
- 记录默认佣金比例
- 若
enable_distribution == 0:- 记录为
enableDistribution=0,Step 1C 之后可顺便询问用户是否要开(一般保持关闭即可)
- 记录为
Step 1D-2 — 分销确认(Step 1C 价格确认之后、上传图片之前)
此步骤在 Step 1C 逐 SKU 确认价格之后执行,使用 Step 0C 拉取的分销设置。
- 若 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 - 批量入口(文件):统一确认一次,适用全部商品,不再逐个询问
- 向用户展示默认值,并确认:
- 若 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 行」)
- 用户确认分批后,按批处理,每批完成后汇总反馈
- 若用户坚持一次性处理全部,可以执行但需提前提醒「这将花费较长时间」
批量上架的错误恢复策略
逐商品串行处理时,若某个商品建品失败:
- 记录失败商品:行号、标题、失败原因(422 参数错误 / 网络超时 / API 500 等)
- 不要停止整个批次——跳过失败商品,继续处理后续商品
- 每个商品完成后反馈进度(如「✅ 商品 1/3 已提交建品」「❌ 商品 2/3 失败:422 参数错误,原因:缺少 categoryName」)
- 全部处理完毕后,汇总:
- 成功列表(含 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 自行提取商品信息。
流程
-
告知用户:
「我将尝试自动抓取页面信息。提取结果可能不完整,稍后会让你逐项核实。」
-
调用 WebFetch 抓取页面:
- 使用
WebFetch(url, prompt)抓取页面内容 - prompt 示例:「请提取此商品页面的以下信息:1. 商品标题 2. 商品描述/卖点 3. 所有商品图片 URL 4. 价格 5. SKU/规格信息(尺码、颜色等)6. 品牌 7. 品类。以 JSON 格式返回。」
- 使用
-
从抓取结果中提取信息:
goodsTitle:页面标题或商品名,翻译为英文(≤200 字符)goodsDesc:根据描述/卖点生成格式化 HTML(见 Step 1D 模板,≤6000 字符)- 图片 URL 列表:提取页面中的商品图片 URL(每个商品最多取 10 张)
- 参考价格:页面显示的价格(仅参考,必须用户确认;若非 USD 需换算并标注汇率来源)
- 规格/SKU 信息:尽量提取尺寸、颜色等规格维度
-
图片处理:
- 提取到的图片 URL 是外链 → 下载到本地 → 逐一
upload→ 得到 FlyLink CDN 路径 - 禁止直接用外链 URL 作为
imageUrl或skuImage
- 提取到的图片 URL 是外链 → 下载到本地 → 逐一
-
生成商品草稿并明确标注来源:
- 向用户展示提取到的信息时,每项标注「⚠️ 来自页面自动提取,请核实」
- 特别标注:标题、价格、规格是否完整提取
-
进入 Step 1C 逐 SKU 确认价格与库存(与图片入口一致,不因来源是 WebFetch 就放宽确认)
⚠️ WebFetch 链接入口的约束
- 提取的信息质量不可控——取决于目标网站结构、反爬机制、是否 SPA 等
- 如果 WebFetch 返回的内容明显为空或无法提取有效商品信息(如只有导航栏/页脚),明确告知用户抓取失败,建议改走图片流程
- WebFetch 提取的价格绝对不能直接用于建品——必须经 Step 1C 用户逐 SKU 确认
- WebFetch 可能拿不到图片 URL(如懒加载图片),此时向用户索要商品图片
- 提取到的规格信息可能不完整——缺失时向用户补充确认
Step 1C — SKU 与价格确认(强制)
情况 A:用户未提供多规格 / 只有单一售价
- 向用户确认:USD 售价、库存(默认 100)
- 生成最小
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 确认流程:
- 先生成规格清单(
specList),向用户确认规格维度与值 - 将规格展开为完整 SKU 矩阵,用表格逐行展示给用户填写确认:
| SKU | Size | Color | salePrice(USD) | origPrice | stock |
|--------|------|-------|----------------|-----------|-------|
| S | S | — | | | |
| M | M | — | | | |
| L | L | — | | | |
| XL | XL | — | | | |
-
关键规则:
- 禁止在用户未逐行确认价格/库存时静默填充默认值
- 禁止假设所有 SKU 价格一致、库存一致
- 用户可以用「全部统一 $X,库存各 Y」简化答复,但必须用户主动说出这句话才算确认,agent 不能默认
- 确认完成后生成
skuList,确保specData与specSetName对齐(见references/api.md多规格示例)
-
其他字段:
- 规格维度名(英文默认,如
Size/Color) specList+skuList字段对齐
- 规格维度名(英文默认,如
多维度 SKU 组合(如 Color × Size)
当规格有两个及以上维度时(如 3 色 × 4 码),specList 和 skuList 结构如下:
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"}] }
]
}
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。无独立图片则不传。
- 多维度确认表格改为:
| SKU | Color | Size | salePrice(USD) | stock |
|----------|-------|------|----------------|-------|
| Blue/S | Blue | S | | |
| Blue/M | Blue | M | | |
| Gray/S | Gray | S | | |
| Gray/M | Gray | M | | |
- 多维度时禁止让用户分别确认每个维度再自己组合——必须直接列出笛卡尔积全表让用户逐行确认
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 审核通过
- 禁止尝试绕过目标网站访问限制抓取内容
Scan to join WeChat group