Appearance
V1 已上架商品 SKU 更新 API
本模块用于直接更新当前已上架多规格商品的 SKU 状态、自有料号、售价和库存。公开接口以 Sugumart 商品 UUID 定位商品,并允许每个 SKU 通过 Sugumart SKU UUID id 或露天 spec_id 定位。请求成功时,本地资料已经保存,并且需要同步的渠道资料已经提交露天。
Base Path: /openapi/v1/products/{id}/skus
所有接口都需要 Access Token,通过 Authorization: Bearer <access_token> 传递,并按 Token 绑定的卖家租户隔离。
通用定位与更新语义
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string(uuid) | 二选一 | Sugumart SKU UUID;与 spec_id 必须且只能提供一个 |
spec_id | string | 二选一 | 露天规格 ID;与 id 必须且只能提供一个,且必须属于路径商品 |
- 每次请求的
skus为 1–450 项;不得通过不同定位方式重复指向同一 SKU。 - 只保存实际发生变化的本地字段。请求值与本地当前值相同时不会重复提交露天,也不会改写
ruten_synced_at。 - 本地修改先保存,再提交露天。露天失败时返回
502 ruten_sku_update_failed,本地修改不会回滚;调用方应重新查询商品后再决定是否重试。 - 三个拆分接口与文末的合并接口均为正式支持能力。
更新 SKU 状态和自有料号
POST /openapi/v1/products/{id}/skus/spec-info
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
skus | SkuSpecInfoUpdate[] | 是 | 需要更新的 SKU,1–450 项 |
SkuSpecInfoUpdate 除通用定位字段外支持:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
status | boolean | 条件必填 | true 启用 SKU,false 停用 SKU |
custom_no | string | null | 条件必填 | 露天卖家自有料号;非空时为 1–100 个 ASCII 可见字符,null 表示清空 |
status、custom_no 至少提供一个。只要其中任一字段确实变化,平台提交露天 /api/v1/product/item/spec/info 时都会为该 SKU 补齐完整的 spec_id、最终 status 和最终 custom_no;请求未提供的值从本地数据库取得。更新后至少保留一个启用 SKU。
json
{
"skus": [
{ "id": "0e95a8db-9161-4b39-b77a-2bd796f27715", "status": false },
{ "spec_id": "22408041234567-2", "custom_no": "SKU-002" }
]
}更新 SKU 售价
POST /openapi/v1/products/{id}/skus/price
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
skus | SkuPriceUpdate[] | 是 | 需要更新的 SKU,1–450 项 |
SkuPriceUpdate 除通用定位字段外必须提供:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
taiwan_sale_price | string | 是 | TWD 主单位 decimal string,固定 2 位且必须为正整数金额,例如 1280.00;本地以 numeric(20,2) 保存,提交露天时转换为整数 |
json
{
"skus": [
{ "spec_id": "22408041234567-2", "taiwan_sale_price": "1280.00" }
]
}更新 SKU 库存
POST /openapi/v1/products/{id}/skus/stock
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
skus | SkuStockUpdate[] | 是 | 需要更新的 SKU,1–450 项 |
SkuStockUpdate 除通用定位字段外必须提供:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
qty | number | 是 | 可售库存,0–99,999 的整数;0 表示售罄 |
json
{
"skus": [
{ "id": "0e95a8db-9161-4b39-b77a-2bd796f27715", "qty": 30 }
]
}合并更新 SKU 价格、库存与状态
POST /openapi/v1/products/{id}/skus/update-price-quantity-and-status
本接口继续正式支持。一次请求可为每个 SKU 同时提交 taiwan_sale_price、qty、status、custom_no 中的一个或多个字段,字段规则与三个拆分接口相同。平台按实际变化分别调用露天规格资讯、价格和库存接口,不会因为一般价格、库存、状态或料号变化调用规格选项覆盖接口。
json
{
"skus": [
{
"id": "0e95a8db-9161-4b39-b77a-2bd796f27715",
"taiwan_sale_price": "1280.00",
"status": true,
"custom_no": "SKU-001"
},
{ "spec_id": "22408041234567-2", "qty": 30 }
]
}成功响应
四个接口使用相同响应结构。updated_skus 顺序与请求一致;无变化的目标也会返回最终状态。
| 字段 | 类型 | 说明 |
|---|---|---|
product | Product | 更新后的完整商品 |
updated_skus | UpdatedSku[] | 本次请求定位的 SKU |
UpdatedSku:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string(uuid) | Sugumart SKU UUID |
spec_id | string | 露天规格 ID |
taiwan_sale_price | string | 最终售价;TWD 主单位,固定 2 位小数 |
qty | number | 最终可售库存 |
status | boolean | 最终启用状态 |
custom_no | string | null | 最终露天卖家自有料号 |
json
{
"success": true,
"data": {
"product": {
"id": "a7b3c8df-bb08-46f0-9ca2-5597a32e0404",
"status": "migrated",
"total_quantity": 55,
"active_sku_count": 2,
"updated_at": "2026-09-02T08:30:00.000Z"
},
"updated_skus": [
{
"id": "0e95a8db-9161-4b39-b77a-2bd796f27715",
"spec_id": "22408041234567-1",
"taiwan_sale_price": "1280.00",
"qty": 25,
"status": true,
"custom_no": "SKU-001"
}
]
}
}Error Responses
| Status | message | code | 说明 |
|---|---|---|---|
| 400 | Invalid SKU update data | validation_error | 请求结构、金额、库存、定位二选一或必填修改字段不合法 |
| 400 | Product is not online | invalid_state | 商品当前不是已发布的多规格商品 |
| 400 | At least one active SKU is required | at_least_one_active_sku_required | 更新后没有任何启用 SKU |
| 400 | SKU has not been published to Ruten | sku_not_published | 目标 SKU 没有露天 spec_id |
| 400 | Duplicate SKU target | duplicate_sku_target | 多个请求项解析后指向同一 SKU |
| 401 | Invalid or expired token | invalid_token | Access Token 无效或已过期 |
| 404 | Product not found | not_found | 商品不存在或不属于当前租户 |
| 404 | SKU not found | sku_not_found | id 或 spec_id 不属于路径商品 |
| 409 | Ruten SKU structure conflict | ruten_sku_structure_conflict | 审核同步发现露天规格结构出现非本地变更,平台不会自动覆盖 |
| 502 | Ruten SKU update failed | ruten_sku_update_failed | 本地已经保存,但露天渠道同步失败;先查询商品状态再决定是否重试 |
| 503 | Product service is temporarily unavailable | backend_unavailable | 商品服务暂时不可用,尚未确认写入结果 |
json
{
"success": false,
"code": "ruten_sku_update_failed",
"message": "Ruten SKU update failed",
"data": {
"local_updated": true,
"updated_sku_ids": ["0e95a8db-9161-4b39-b77a-2bd796f27715"],
"failed_step": "price",
"completed_steps": []
}
}