Files
ozon-seller-kit/docs/v2/ozon-publish.md
T

8.9 KiB
Raw Blame History

V2 Ozon 发布集成

状态:方案设计(待确认) 上游:V2 总览 · V2 架构 · 数据库 · API 官方文档:Ozon Seller API(中文)


1. 鉴权与店铺凭证

Ozon Seller API 用 两个请求头 鉴权(不是 OAuth):

Client-Id: <你的 Client ID>
Api-Key:   <你的 API Key>
  • 获取:Ozon 卖家后台 → 设置 → Seller API → 生成 Key(可选权限级别)。
  • 凭证归属店铺V2 里每店铺一条 shops 记录,client_id/api_key 加密落库,调用时解密拼头。
  • 连通性校验POST /api/shops/:id/test/v1/roles(返回该 key 的角色与可用方法),既验证凭证又看权限范围,零成本。

服务端封装 services/ozon_client.py:统一 base URLhttps://api-seller.ozon.ru)、拼头、超时、错误映射(400/403/409/500 → 语义化 detail)、限流退避。


2. 核心接口(本项目用到)

用途 方法 说明
类目树 POST /v1/description-category/tree 返回 description_category_id / type_id / category_name / type_name / disabled / children只有末级类目可建品
类目属性 POST /v1/description-category/attribute 入参 description_category_id + type_id;返回属性含 is_required / is_aspect / is_collection / dictionary_id / type / max_value_count
属性值字典 POST /v1/description-category/attribute/values 入参 attribute_id + category_id + type_id + limit(≤2000) + last_value_id(分页)
属性值搜索 POST /v1/description-category/attribute/values/search value 模糊匹配参考值(≥2 字符,limit≤100)
发布/更新商品 POST /v3/product/import 一次 ≤100 个 item;返回 task_id
发布状态 POST /v1/product/import/info 入参 task_id;返回 items[{offer_id, product_id, status, errors[]}]
商品列表/回填 POST /v3/product/list offer_id/product_id 过滤取 product_id,或分页拉全部
跟卖复制 PDP POST /v1/product/import-by-sku 入参 sku + name + offer_id + price...;返回 task_id + unmatched_sku_list
图片更新 POST /v1/product/pictures/import product_id 覆盖 images/images360/color_image
商品详情(含图片/审核错误) POST /v3/product/info/list 回读已发布商品的图片/状态/错误

3. 类目与属性字典(采集属性 → Ozon 属性的关键)

3.1 数据流

类目树(全局缓存)
   └─ 用户选类目 → 得 description_category_id + type_id
        └─ 拉该类目属性(按 category+type 缓存)
             └─ 对每个「有字典」的属性,按需拉值(/values 或 /values/search
  • 类目树全局缓存:与店铺无关(虽然接口要凭证),服务端拉一次存 category_tree 表 + 内存 LRUTTL 24h。
  • 属性按类目缓存category_attributes 表,按 (category_id, type_id) 缓存。
  • 属性值按需拉取:值目录可能非常大,只在用户映射到某个属性时才拉,且用 /values/search(按关键词搜)而非全量拉。

3.2 属性映射(采集的 raw.params → Ozon attributes[]

这是发布链路最重的工作。流程:

采集 raw.params: [{key:"Материал", value:"Нержавеющая сталь"}, …]
        │  ① 自动匹配:key 与属性 name 模糊匹配(归一化 + 词干)
        │  ② 有字典的属性:value 去 /values/search 找 dictionary_value_id
        ▼
属性映射 UI:自动匹配结果 + 人工确认未匹配项 + 必填项高亮
        ▼
products.attributes = [{complex_id:0, id, values:[{dictionary_value_id, value}]}]

必填项校验:服务端在「ready 校验」和「发布前」两次校验:category_attributesis_required=true 的属性必须已映射,否则阻断发布并指出缺哪些。


4. 发布请求体组装(对齐 ImportProductsV3

items[0] 字段(已核对官方示例):

字段 来源 说明
offer_id products.offer_id 自己的货号,跟卖不能用竞品的
name / description products.name/description(俄文)
description_category_id / type_id products.* 从类目树选
price / old_price / currency_code / vat products.* currency 须与店铺设置一致(默认 RUB)
depth/width/height/dimension_unit/weight/weight_unit products.* 必填且不能为 0(官方硬约束)
barcode products.barcode 可选
images products.images(七牛 URL,≤15 顺序即展示顺序;首张为主图。必须 https 直链(实测 Ozon 不接受 http,见 §7
primary_image products.primary_image 用 primary_image 则 images ≤14
images360 / color_image products.* 可选
attributes products.attributes 映射结果
complex_attributes products.complex_attributes 视频/尺码表等
pdf_list / promotions 可选 一般留空

跟卖场景可选优化:若竞品允许复制 PDP,走 /v1/product/import-by-sku(只需 sku + 基本信息),更快且继承竞品详情——但受「卖家是否允许复制」限制,且不能更新,故作为可选快捷路径,主路径仍是 import


5. 发布状态机与轮询

/v3/product/import 是异步的,返回 task_id。流程:

POST /v3/product/import  → { task_id }
        │  建 publish_tasks(status=pending, ozon_task_id)
        ▼
后台协程轮询 POST /v1/product/import/info { task_id }
        │  items[0].status ∈ imported | moderation | failed(+errors[])
        ▼
imported   → products.stage=published, ozon_product_id=items[0].product_id
moderation → products.stage=publishing(继续轮询,通常 <1 天)
failed     → products.stage=failed, publish_tasks.errors=items[0].errors
  • 轮询间隔:先 5s,退避到 30smoderation 状态降低频率到分钟级。
  • /v3/product/listfilter by offer_id)回读 product_id 兜底(轮询遗漏时)。
  • 上架还需设置库存import 成功后商品进入后台但不自动上架(architecture.md 与官方文档均明确「只有设置库存后才开售」)。V2 一期发布到「已创建/审核」即可,库存设置(/v2/products/stocks)作为二期可选,或提示用户去后台补库存。

6. CSV 导出字段

服务端 GET /api/export/products.csv,带 BOM 的 UTF-8,Excel 直接打开不乱码。字段:

offer_id, product_id, name, description_category_id, type_id,
price, old_price, currency_code, vat,
weight, weight_unit, depth, width, height, dimension_unit,
barcode, primary_image, images, source_platform, source_item_id, source_url,
stage, published_at, created_at, updated_at
  • images| 拼接七牛 URL。
  • 未发布商品 product_id 为空。
  • 支持筛选 stagecollected/ready/published/failed/全部)与 ids(勾选导出)。

对齐 V1v1 登记表导出的 sku + 卢布预留价 组合码,V2 里 offer_id + price(卢布)即等价物;若要完全兼容 v1 组合码,可加一列 combooffer_id + 卢布预留价)。


7. 错误处理与限流

Ozon 错误 含义 处理
400 Invalid parameter 参数错误 把 detail 透传前端,定位字段
403 Access denied 权限不足 提示检查 Api-Key 权限级别
409 Request conflict 冲突(如 offer_id 重复) 提示改 offer_id 或走更新
429 / 限流 频率超限 指数退避重试
item_limit_exceeded 超过当日建/更新商品限额 提示限额,可查 /v4/product/info/limit

publish_tasks.errors 完整保存 Ozon 返回的 errors 数组,前端发布结果页展示中文解读。


8. 店铺绑定交互

  1. 店铺管理页「新增店铺」:填 名称 + Client ID + API Key + 结算币种
  2. 点「测试连接」→ /api/shops/:id/test → 调 /v1/roles → 显示 ok 与角色列表,或失败原因(凭证错/权限不足/网络)。
  3. 保存后 client_id 只显示尾号打码(如 …1234),key 永不回显。
  4. 发布时从店铺下拉选择目标店铺。

9. 一期范围 vs 二期

能力 一期 二期
店铺绑定 + 连通性校验
类目树 + 属性 + 值字典(缓存)
属性映射 UI(自动 + 人工) 基础版 智能匹配优化
/v3/product/import 发布 + 轮询回填
/v1/product/import-by-sku 跟卖复制 🟡 可选
库存设置(上架) (提示去后台) /v2/products/stocks
价格/库存批量更新 /v1/product/import/prices/v2/products/stocks
图片更新(换图) /v1/product/pictures/import