Files
ozon-seller-kit/docs/v2.1/api.md
T
2026-08-31 14:37:28 +08:00

9.7 KiB
Raw Blame History

V2.1 API 契约(新增 + 复用)

状态:前端服务层已按本文开发(Phase A);服务端 Phase B 按 本文实现。 通用:鉴权 Authorization: Bearer <JWT>(studio 走 axios 拦截器自动附带);错误统一 FastAPI detail。


1. 复用的现有接口(Phase A 即可用)

接口 用途(试算页)
GET /api/products/{id}、PATCH /api/products/{id} 商品详情 / 试算页自动保存(raw/pricing/copy/price/weight/... 全字段)
GET /api/products/{id}/assets 素材列表(分组/规格/状态/current stored_url、original_url、水印状态)
GET /api/products?stage&q&page&page_size 批量 CSV / 组合码导出的数据源
POST /api/materials/bytes 试算页「上传图片」(FormData:product_id, group_key=upload, file)→ {asset_id, status}
GET /api/fx 汇率 {rate, source, ts}
GET /api/ai/models、POST /api/ai/copy 俄文文案(模型白名单 / 生成)
POST /api/image/edit 智能修图页保留,不在试算页主链路

2. 套图规划 POST /api/suite/plan(Phase B)

Req

{
  "product_id": "uuid",            // 可选:便于日志与上下文缓存
  "texts": [ { "kind": "title|price|params|selling_point|desc|brand|sales|shop",
               "content": "…", "pairs": [ { "key": "…", "value": "…" } ] } ],
  "sku_variants": ["粉色", "蓝色"],
  "image_stats": { "main": 8, "sku": 6, "detail": 12 },
  "platform": "ozon",
  "requirements": "…|null"         // 用户强制要求,最高优先级
}

Res { "summary": "一句话方案说明", "items": [ { "kind": "white_bg", "title": "白底主图", "detail": "…", "prompt_hint": "…", "count": 2, "variant_name": "粉色|null" } ] }

实现要点:DeepSeek 单行紧凑 JSON;kind 白名单清洗;count 钳 0-3;幻觉 variant 丢弃绑定;总张数 AI 自主(建议 8 张左右;安全上限:默认 15,生图要求指定「N 张」时按 N、最大 24)。同步接口(数秒级)。

3. 一键生成 POST /api/suite/generate(Phase B)

Req

{
  "product_id": "uuid",
  "texts": [ …同上… ],
  "images": [ { "url": "…", "group_key": "main|sku|detail|upload", "variant_name": "粉色|null" } ],  // 勾选参考底图
  "style_set": 1,
  "style_prompt": "…|null",        // 用户改写的风格提示词,覆盖后端模板
  "requirements": "…|null",
  "plan": [ …PlanItem(count>0)… ],
  "platform": "ozon",
  "model": "gpt-image-2-vip",
  "watermark": { "enabled": true, "type": "image|text", "text": "xiongmaoyx", "opacity": 30 }  // 关闭时缺省
}

Res { "suite_id": "…" }

实现要点:方案按 count 展开为持久化逐图子任务;独立 Worker 领取子项并在完成后回写进度。Pcore、RightAPI 与通义万相的第三方任务 ID 会先写入数据库,重启后继续轮询同一个模型任务;完成后再水印、落 storage、追加 product_assets(group_key='generated')。

4. 任务查询 GET /api/suites/{id}(Phase B)

Res

{
  "id": "…", "status": "queued|running|done|partial|failed|cancelled",
  "style_set": 1, "platform": "ozon", "lang": "俄文", "ratio": "3:4", "provider": "rightapi",
  "total": 8, "completed": 3, "failed": 1,
  "images": [ { "type_id": "white_bg", "name": "白底主图-01.png", "url": "/media/suites/…png",
                "status": "queued|waiting_provider|running|done|failed|cancelled", "error": null } ],
  "error": null
}

前端采用“本次请求结束后再延迟下一次”的递归轮询(正常 3s、请求失败指数退避),并在切换任务、组件卸载时取消在途请求;done/partial/failed/cancelled 为终态。每条 images 项另含 item_id,用于按图重试。浏览器会暂存当前任务 ID,并从服务端查询商品的活动任务;Web 服务或 Worker 重启后仍可恢复任务状态。

辅助接口:GET /api/products/{product_id}/suites?active_only=true 恢复活动任务;POST /api/suites/{id}/cancel 取消任务;POST /api/suites/{id}/retry 重试全部失败子项;POST /api/suites/{id}/items/{item_id}/retry 只重试指定失败项。

5. 结果导出 GET /api/suites/{id}/zip(Phase B)

→ application/zip blob(按方案标题命名内部文件)。404/失败返回 detail JSON。

6. 单张 AI 生图 POST /api/suite/image-edit(Phase B)

Req

{
  "product_id": "uuid",
  "image_url": "…",               // stored_url 或 source_url(服务端代下绕防盗链)
  "prompt": "把背景换成纯白色摄影棚",  // 必填
  "model": "nano-banana-2",
  "append": true                   // true:结果追加 product_assets(generated)
}

Res { "suite_id": "…" }

接口仅创建并提交统一图片任务,立即返回;前端通过 GET /api/suites/{suite_id} 查询状态和 images[0].url。完成后若 append=true,结果会回写为 product_assets(group_key='generated')。单张编辑优先级高于套图,提交模型后同样持久化第三方任务 ID;参考图 = 传入单图;Ozon 规格(俄文 3:4)。

7. 素材水印 POST /api/assets/watermark / POST /api/assets/watermark/remove

POST /api/assets/watermark 的请求体为 { "asset_ids": ["uuid"], "watermark": { "enabled": true, "type": "text|image", "text": "…", "opacity": 30 } },立即返回 { "job_id": "uuid", "total": n }。Worker 对选中的采集图或生成图逐张应用水印,前端经 GET /api/suites/{job_id} 查看逐图进度和错误;GET /api/products/{product_id}/watermark-jobs?active_only=true 用于页面刷新后恢复。

POST /api/assets/watermark/remove 的请求体为 { "asset_ids": ["uuid"] },将选中图片恢复为无水印原图。

POST /api/assets/watermark/remove 当前仍为短时同步操作,返回 { "updated_ids": [], "failed": [] }。两接口均只保留原图和当前展示版本:重新加水印会在数据库提交后删除旧水印文件;前端展示、单张下载与导出均使用 stored_url。

8. 商品轮播视频

  • POST /api/products/{product_id}/video-jobs:请求 { "asset_ids": ["uuid", "uuid"] },按传入顺序选择当前商品的 2–5 张已转存图片,立即返回 { "job_id": "uuid" }。服务端只接受素材 ID,不接受任意图片 URL。
  • GET /api/products/{product_id}/video-jobs、GET /api/video-jobs/{job_id}:读取任务和成片状态;POST /api/video-jobs/{job_id}/cancel 会取消并立即清理任务记录,POST /api/video-jobs/{job_id}/retry 重试失败任务,DELETE /api/video-jobs/{job_id} 删除成片及记录,GET /api/video-jobs/{job_id}/download 下载 MP4。
  • Worker 使用 FFmpeg 合成无音轨轮播视频:AI 生成图在前端选择器中优先展示;支持 2–5 张,按 4.5 / 3.5 / 3.0 / 2.8 秒单图停留并使用 0.35 秒淡入淡出。默认输出为 810×1080、30 fps、H.264、yuv420p、最大 45 MB,结果存入 products/{product_id}/videos/{job_id}/result.mp4。
  • 需要系统安装 ffmpeg 与 ffprobe(Ubuntu:apt install -y ffmpeg);路径和大小/超时限制可通过 VIDEO_* 环境变量覆盖。任务复用 background_jobs,无需新增视频业务表;进行中、失败和已完成成片可在刷新后继续查看,取消会立即移除任务及临时文件,不保留记录。

9. 导出与代理(Phase B / D)

接口 方法 Req Res
/api/export/images POST { "title": "…", "images": [{ "url", "groupName", "variantName", "key" }] } zip blob(分组建文件夹)
/api/proxy-image?url= GET 源站图片 URL 图片字节(带站点 Referer 代下,绕防盗链)
/api/export/trial-csv GET query:stage? csv blob(16 列,见 trial-page.md §7;Phase D 服务端化,替代前端拼装)

图片资源上限:默认单张上传/远程下载 20 MB;一次导出最多 50 张,ZIP 内源图片总量与成品 ZIP 均最多 200 MB。超过限制返回 HTTP 413 及可读错误提示;ZIP 超过 2 MB 自动写入临时磁盘,并以分块响应下载。

图片校验与元数据:图片上传、采集转存和 AI 生成图写入素材库时,服务端以实际字节识别 JPEG、PNG、WebP、GIF 或 BMP,不信任 URL 后缀和上传声明的 MIME。解码失败或不支持的格式返回/记录为失败;默认限制为 40,000,000 像素(IMAGE_MAX_PIXELS),并记录 product_assets.width、height。静态图片若带 EXIF 方向,会在落库前纠正并移除该方向标记;动画图不重编码,以避免丢帧。POST /api/materials/bytes 成功响应会额外返回 width、height,不合规图片返回 422。

远程图片安全规则:/api/proxy-image、采集图转存、AI 参考图及远程导出统一只请求公网 http(s) 地址;localhost、回环、内网、链路本地、多播和其他保留 IP 会返回 400。重定向不会自动跟随:服务端最多跟随 3 跳,并在每一跳重新解析和校验目标地址。已转存的本项目 /media/... 素材直接读取本地磁盘,不经过 HTTP 回环请求。下载仍受 IMAGE_DOWNLOAD_MAX_BYTES 限制,连接/读写/总超时与重定向次数可通过 IMAGE_DOWNLOAD_CONNECT_TIMEOUT、IMAGE_DOWNLOAD_READ_TIMEOUT、IMAGE_DOWNLOAD_TOTAL_TIMEOUT、IMAGE_DOWNLOAD_MAX_REDIRECTS 配置;下载超时返回 504。

10. 采集相关(Phase C 使用,均已实现)

  • POST /api/materials:插件上传采集结果;响应含 product_id(插件用于打开 /trial/{id})。
  • GET /api/collected?platform=&itemId=:采集前查重。

11. 冻结接口(不投入,保留代码)

/api/publish/*、/api/shops/*、/api/categories/*——Ozon API 直传链路(D1)。