Files
atlas-seller-kit/docs/api/online-listings.md

105 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 在线商品镜像与同步 API
> 在线商品是平台 + 门店独有的外部事实镜像,一行对应一个 Ozon `product_id` / `offer_id` SKU。它包含 Atlas 发布商品和外部商品;不能跨店铺、跨平台复用,也不能当作采集箱 SPU。首期接口只读镜像和触发同步,不支持在此编辑、删除、下架、改价或设置库存。
## 1. 当前门店与镜像边界
所有接口要求 `X-Atlas-Platform-Id`。`store_id` 未传时服务端取当前工作空间该平台默认店铺;没有默认店铺返回 `422 DEFAULT_STORE_REQUIRED`。显式传入的 `store_id` 必须属于当前工作空间和 header 平台。
- 采集箱的“已上架”表示 Atlas 首次导入 SKU 的成功事实;它不由本模块的 `visible`、库存或审核状态推导。
- `platform_listings.visible` 是 Ozon 同步返回的实际可见性;`null` 表示尚未获取,不能当作 `false`。
- Atlas 发布 SKU 以 `store_id + offer_id` 和回填的 Ozon `product_id` 映射。外部同步商品 `source=external_sync`,没有 Atlas 草稿关联也必须显示。
- 同步失败始终保留上一轮成功镜像;不把失败、超时或尚未见到的条目直接解释为已下架。
## 2. 在线商品列表与详情
`GET /api/platform-listings?store_id={uuid}&cursor={opaque}&limit=20&q={keyword}&visibility={all|visible|invisible|unknown}&source={atlas_published|external_sync}&moderation_status={value}&include_archived=false`
默认按 `updated_at DESC, id DESC` 返回当前店铺镜像。`q` 匹配 `name`、`offer_id`、`remote_product_id`、`remote_sku`;`visibility=unknown` 只匹配 `visible=null`;`include_archived=false` 排除同步后标记已归档的历史镜像。
```json
{ "data": [{
"id": "uuid", "store_id": "uuid", "platform_id": "uuid",
"remote_product_id": "123456", "offer_id": "atlas-abc", "remote_sku": "987654",
"name": "商品标题", "currency_code": "RUB", "selling_price": "999.00", "list_price": "1110.00",
"visible": true, "remote_state": "processed", "moderation_status": "approved", "validation_status": "success",
"stock_summary": { "total": 0, "has_data": true },
"image": { "url": "https://platform-image-or-null", "width_px": null, "height_px": null },
"errors": [], "visibility_details": {},
"source": "atlas_published", "atlas_origin": { "collection_item_id": "uuid", "product_id": "uuid", "variant_id": "uuid" },
"last_synced_at": "2026-09-02T08:00:00Z", "missing_since": null, "archived_at": null
}], "meta": {
"next_cursor": null, "has_more": false,
"store": { "id": "uuid", "name": "Ozon 主店" },
"last_successful_sync_at": "2026-09-02T08:00:00Z", "last_sync_status": "succeeded"
} }
```
`image.url` 是 Ozon 返回的图片引用或 `null`,不是 Atlas `media_assets` 的永久地址;没有图片不意味着 Atlas 素材丢失。`errors` 仅返回页面可展示的结构化摘要,隐藏 Ozon 原始响应中可能存在的无关敏感字段。
`GET /api/platform-listings/{listing_id}`
返回单个 SKU 镜像的完整业务摘要、可见性详情、库存摘要、审核/失败原因、Atlas 来源链接和最近同步信息。它不返回 `raw_payload`;需要平台原始响应排障时仅由受控运营工具读取。
## 3. 手动触发同步
`POST /api/stores/{store_id}/platform-product-sync-runs`
Headers:`Idempotency-Key` 必填。Body 可省略,或为:
```json
{ "reason": "manual_refresh" }
```
服务端验证店铺连接处于可同步状态,然后创建一次**全量**同步 run 并投递 Worker:
```text
/v3/product/list(分页,最多每页 1000)
→ /v3/product/info/list(每批最多 100)
→ 按 store + remote_product_id / offer_id upsert 镜像
→ 完整成功后将本轮未见记录标记 missing_since / archived,不物理删除
```
返回 `202 Accepted`:
```json
{ "data": { "sync_run": {
"id": "uuid", "store_id": "uuid", "status": "queued", "trigger_source": "manual",
"listed_count": 0, "upserted_count": 0, "failed_count": 0, "created_at": "2026-09-02T08:00:00Z"
} } }
```
同一工作空间同一店铺只允许一个 `queued` / `running` 全量同步;正在同步时返回 `409 SYNC_ALREADY_RUNNING` 和现有 `sync_run_id`。无有效 Seller API 凭据时返回 `422 STORE_CREDENTIAL_UNAVAILABLE`,不尝试使用浏览器 Cookie。
## 4. 同步状态与历史
`GET /api/platform-product-sync-runs/{sync_run_id}`
返回当前/历史同步 run:
```json
{ "data": {
"id": "uuid", "store_id": "uuid", "status": "running", "trigger_source": "manual",
"cursor_started": null, "cursor_finished": null,
"listed_count": 1000, "upserted_count": 100, "failed_count": 0,
"started_at": "2026-09-02T08:00:10Z", "completed_at": null,
"error": null
} }
```
`GET /api/stores/{store_id}/platform-product-sync-runs?cursor={opaque}&limit=20`
按创建时间倒序返回该店铺同步历史。失败 run 的 `error` 是可展示摘要;前端应保留并标注上一轮成功同步时间,而不是清空在线列表。
Worker 只在完成所有分页和详情批次后把 run 标记 `succeeded`。部分请求失败时 run 为 `failed`,已成功 upsert 的记录仍保留,但不执行“未见记录归档”步骤,避免将网络错误放大为商品消失。
## 5. 明确不在首期接口中的操作
- 从在线商品编辑 Ozon 商品、重新发布或更新已导入 SKU;
- 设置库存、仓库、可见性或下架;
- 认领/导入外部同步商品到采集箱;
- 自动同步的频率、手动同步冷却时间和多店并发策略;
- 运营人员查看完整 Ozon 原始 payload。
这些操作均需要单独定义 Ozon 可修改字段、审核/重试边界和审计规则,不能借用采集箱“首次上架”接口。