首次提交:初始化后端、数据库结构与文档代码

This commit is contained in:
Peter
2026-03-23 16:10:29 +08:00
commit 86f384c2d3
95 changed files with 10090 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
-对于Java包更推荐使用Maven工具安装管理。
参照以下代码示例更新最新版本在Maven中直接引用即可并且请在settings.xml中引入有赞云maven仓库。
<dependency>
<groupId>com.youzan.cloud</groupId>
<artifactId>open-sdk-core</artifactId>
<version>1.0.28-RELEASE</version>
</dependency>
<dependency>
<groupId>com.youzan.cloud</groupId>
<artifactId>open-sdk-gen</artifactId>
<version>1.0.22.80701202109281055-RELEASE</version>
</dependency>
<mirrors>
<mirror>
<id>youzan-nexus-snapshot</id>
<name>Maven Repository Mirror running on maven.youzanyun.com</name>
<url>http://maven.youzanyun.com/repository/maven-public</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<profiles>
<profile>
<id>dev</id>
<repositories>
<repository>
<id>public</id>
<name>public repository</name>
<url>https://maven.youzanyun.com/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>public repository</name>
<url>https://maven.youzanyun.com/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>dev</activeProfile>
</activeProfiles>
【说明】
-SDK使用的是OkHttp3已经暴露了对应的配置方法可自行根据业务进行配置参考如下示例。
OkHttpClient.Builder builder = new OkHttpClient.Builder().readTimeout(5, TimeUnit.HOURS);
HttpConfig httpConfig = HttpConfig.builder().OkHttpClientBuilder(builder).build();
YouZanClient youZanClient = new DefaultYZClient(httpConfig);
-Java open SDK依赖包引入示例如下。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.12</version>
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>1.15.0</version>
</dependency>

View File

@@ -0,0 +1,97 @@
# 自用型应用获取和刷新 access_token
## 1. 接口说明
* **接口功能**:用于“自用型应用”获取及刷新调用有赞云 API 所需的身份验证凭证(`access_token`)。
* **前提条件**:已在有赞云控制台完成自用型应用的创建,并且完成了店铺授权。
* **业务注意**
1. 一个店铺只能授权给一个自用型应用,而一个自用型应用可以有多个店铺授权(多店授权需通过有赞云审核)。
2. 建议开发者在代码中全局捕获 Token 失效的错误码,并实现 `access_token` 失效时自动重新获取的逻辑。
---
## 2. 请求说明
* **请求地址**`https://open.youzanyun.com/auth/token`
* **请求方式**`POST`
* **请求头 (Header)**`Content-Type: application/json`
> ⚠️ **注意**:必须严格使用 `POST` 加上 `application/json` 的请求方式,否则会报错。
---
## 3. 请求参数
在请求的 BodyJSON格式中传入以下参数
| 参数名称 | 类型 | 是否必须 | 示例值 | 描述说明 |
| :--- | :--- | :---: | :--- | :--- |
| `client_id` | String | **是** | `239ec70db50cfd...` | 有赞云颁发给开发者的应用 ID [1] |
| `client_secret` | String | **是** | `9ea25ab4513b7f...` | 有赞云颁发给开发者的应用密钥 (AppSecret) [1] |
| `authorize_type` | String | **是** | `silent` | 授权方式。自用型应用固定为 `"silent"` [1] |
| `grant_id` | String | **是** | `123456` | 授权店铺ID`kdt_id`。如果是API接口对接传店铺ID如果是支付商户对接传 `mchId` [1] |
| `refresh` | Boolean | 否 | `false` | 是否需要返回 `refresh_token`。默认为 `false`。如需通过 `refresh_token` 刷新凭证,需传入 `true` [1] |
*(注:`client_id`、`client_secret` 和店铺ID `grant_id`,请前往有赞云控制台的应用详情和授权页面查看 [1]。)*
---
## 4. 响应参数
响应主体为 JSON 格式,核心数据包裹在 `data` 节点中:
| 参数名称 | 类型 | 描述说明 |
| :--- | :--- | :--- |
| `success` | Boolean | 请求是否成功 |
| `code` | Integer | HTTP 状态码,`200` 表示成功 |
| `data.access_token` | String | 用于调用业务 API 接口的有效凭证 |
| `data.expires_in` | Long | `access_token` 的有效时间(单位:秒,通常为 7 天 / 604800秒 |
| `data.authority_id` | String | 授权店铺的 ID`kdt_id` |
| `data.refresh_token` | String | 用于刷新 `access_token` 的凭证(仅在请求参数 `refresh``true` 时返回) |
---
## 5. 请求与响应示例
### 5.1 CURL 请求示例 [1]
```bash
curl -X POST https://open.youzanyun.com/auth/token \
-H 'content-type: application/json' \
-d '{
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"authorize_type": "silent",
"grant_id": "88888",
"refresh": false
}'
```
### 5.2 成功响应示例
```json
{
"success": true,
"code": 200,
"data": {
"access_token": "f59b1a6bb04f4eqweqd1c6af315d",
"expires_in": 604800,
"authority_id": "88888",
"refresh_token": "c3b21a6bb04f4eqweqd1c6af315d"
},
"message": null
}
```
---
## 6. 🔄 如何刷新 access_token
对于**自用型应用**,有赞云提供了两种刷新/重新获取 token 的策略:
### 方式一:直接静默重新获取(推荐做法)
因为自用型应用采用的是 `silent`(静默)授权模式,无需商家人工干预。因此当 `access_token` 过期时,**直接再次发送和首次获取时完全一样的 POST 请求**`authorize_type` 依然为 `silent`),即可直接生成并获取到一个全新的 `access_token`
### 方式二:通过 refresh_token 刷新
1. 在首次获取 token 时,必须将入参的 `refresh` 字段设置为 `true` [2],此时响应数据中会返回一个 `refresh_token`
2.`access_token` 过期后,可以改变请求参数来刷新 Token
*`authorize_type` 的值修改为 `"refresh_token"` [2]
* 增加传递 `"refresh_token": "你获取到的refresh_token字符串"` [2]
* 仍然携带 `client_id``client_secret` [2]
*(建议:业务中采取在 Redis / 本地缓存中托管 Token 及到期时间,在到期前提前 10-30 分钟使用方式一重新拉取即可。)*

View File

@@ -0,0 +1,26 @@
获取和刷新 access_token说明
access_token说明
1. 当请求 API 时access_token 提示失效或过期,请重新获取。
2. 若因网络等原因未能成功获取新的 access_token在 1 个小时内仍可重新获取,多次重复调用拿到的是同一个 access_token。
3. 开发者需要缓存 access_token不能频繁调用否则会受到调用频率限流请合理使用 access_token 的有效期。
4. 旧access_token 在有效期内,当 refresh=true 时生成新的token旧token会在一小时后失效;
- 旧access_token已过期当 refresh=true 时生成新的token
- 旧access_token 在有效期内,当 refresh=false 时返回旧的token不会生成新的token也不会给的旧token续期;
- 旧access_token已过期当 refresh=false 时生成新的token。
5. 当多个店铺授权给同一个应用时,每个应用对应的店铺的 access_token 是彼此独立的,所以缓存时需要区分店铺 id。
6. 一个店铺只能授权给一个自用型应用,而一个自用型应用可以有多个店铺授权(需要有赞云审核)。
7. 因授权实现业务需要,建议开发者应实现 access_token 失效时重新获取的逻辑正常情况下生成的token有7天有效期接口返回expires是失效时间
8. 开发者需要缓存 access_token不能频繁调用否则会受到调用频率限流请合理使用 access_token 的有效期。
前置条件
已完成应用的创建,并且完成店铺授权。
- 自用型、工具型应用类型的获取方式有区别;
- 有容器、无容器应用类型获取方式一致。
工具型与自用型区别
工具型
- 授权方式authorize_type=“authorization_code”需要店铺授权 code 参数。
- 通过返回的refresh_token进行access_token有效期刷新。
自用型
- 授权方式authorize_type=“silent”需要店铺 id。
- 通过参数refresh参数直接刷新。

View File

@@ -0,0 +1,115 @@
# 订单批量查询接口 (youzan.trades.sold.get.4.0.4)
## 1. 接口基本信息
* **API 名称**:订单批量查询接口
* **API 接口名**`youzan.trades.sold.get`
* **版本号**`4.0.4` 4.0.2 及以上版本共用同一套底层结构)
* **请求协议**HTTPS
* **请求方式**GET/POST (推荐 POST `application/json`)
## 2. 接口描述
用于按条件批量搜索和查询有赞店铺的订单列表数据。该版本接口已全面升级 `yz_open_id` 作为买家唯一标识,**目前不支持返回 `buyer_id`**。
### ⏱️ 核心查询与排序规则
支持基于订单的创建时间、更新时间和完成时间进行获取。
* **创建时间**:可以获取指定时间内所有的订单。
* **更新时间**:可以获取最新更新的订单,但是该范围内的订单是动态变化的。
* **完成时间**:可以获取指定时间内已完成的订单。
**接口内置排序规则(优先级)**
1. 只有创建时间 `start_created``end_created`,按 **创建时间** 排序。
2. 只有更新时间 `start_update``end_update`,按 **更新时间** 排序。
3. 只有完成时间 `start_success``end_success`,按 **完成时间** 排序。
4. 同时存在创建时间、更新时间,按 **更新时间** 排序。
5. 同时存在创建时间、完成时间,按 **完成时间** 排序。
6. 同时存在更新时间、完成时间,按 **完成时间** 排序。
7. 同时存在创建时间、更新时间、完成时间,按 **完成时间** 排序。
8. **重要提醒**:如创建或更新或完成时间的开始和结束时间不是**成对出现**,则该时间条件无效。
---
## 3. 请求地址
```http
https://open.youzanyun.com/api/youzan.trades.sold.get/4.0.4
```
---
## 4. 请求参数 (全量)
| 参数名称 | 参数类型 | 必填 | 示例值 | 参数说明 |
| :--- | :--- | :---: | :--- | :--- |
| `access_token` | String | **是** | `9b510e232c9...`| 鉴权凭证,用于请求 API |
| `type` | String | 否 | `NORMAL` | 订单类型。`NORMAL`: 普通订单; `PEERPAY`: 代付; `GIFT`: 我要送人; `GROUP`: 拼团; `HOTEL`: 酒店; `TAKE_AWAY`: 外卖; `CATERING_OFFLINE`: 堂食点餐; `CATERING_QRCODE`: 外卖买单; `KNOWLEDGE_PAY`: 知识付费 等 |
| `status` | String | 否 | `WAIT_SELLER...` | 订单状态(一次只能查一种状态)。<br>`WAIT_BUYER_PAY`: 待付款<br>`WAIT_SELLER_SEND_GOODS`: 待发货<br>`WAIT_BUYER_CONFIRM_GOODS`: 待确认收货<br>`TRADE_SUCCESS`: 订单完成<br>`TRADE_CLOSED`: 订单关闭<br>`TRADE_REFUND`: 退款中 |
| `start_created` | Date | 否 | `2023-10-01 00:00:00`| 创建开始时间 |
| `end_created` | Date | 否 | `2023-10-01 23:59:59`| 创建结束时间 |
| `start_update` | Date | 否 | `2023-10-01 00:00:00`| 更新开始时间 |
| `end_update` | Date | 否 | `2023-10-01 23:59:59`| 更新结束时间 |
| `start_success` | Date | 否 | `2023-10-01 00:00:00`| 交易完成开始时间 |
| `end_success` | Date | 否 | `2023-10-01 23:59:59`| 交易完成结束时间 |
| `delivery_start_time` | Date | 否 | `2023-10-01 00:00:00`| 发货/配送/自提 期望开始时间 |
| `delivery_end_time` | Date | 否 | `2023-10-01 23:59:59`| 发货/配送/自提 期望结束时间 |
| `page_no` | Integer| 否 | `1` | 页码,从 1 开始。**页码最大不能超过 100**,如需查询更多数据,必须按时间分段查询。 |
| `page_size` | Integer| 否 | `20` | 每页条数,默认 20 条,**最大不能超过 100**。 |
| `tid` | String | 否 | `E202310011...`| 有赞订单号(精确搜索查询) |
| `yz_open_id` | String | 否 | `V1abcdef123...` | 买家在有赞的唯一标识 ID |
| `receiver_name` | String | 否 | `张三` | 收件人姓名 |
| `receiver_phone` | String | 否 | `13800138000` | 收件人手机号 |
| `offline_id` | Long | 否 | `123456` | 门店/网点 ID传入后只查归属该网点的订单 |
| `node_kdt_id` | Long | 否 | `88888` | 连锁门店网点店铺 ID用于多网点/连锁总店拉取特定店单据场景) |
| `goods_id` | Long | 否 | `987654321` | 商品 ID筛选包含该商品的订单 |
| `goods_title` | String | 否 | `薯片` | 商品标题(模糊搜索包含该标题的订单) |
| `keywords` | String | 否 | `苹果` | 搜索关键字(模糊匹配商品名、订单号等) |
| `express_type` | String | 否 | `EXPRESS` | 物流类型。`EXPRESS`: 快递配送; `LOCAL_DELIVERY`: 同城送; `SELF_FETCH`: 自提 |
| `fans_id` | Long | 否 | `0` | 买家有赞粉丝 ID |
| `fans_type` | Integer| 否 | `1` | 买家粉丝类型 |
| `exclude_order_tag`| String | 否 | `xxx` | 排除包含特定标签的订单 |
| `need_order_url` | Boolean| 否 | `false` | 是否需要返回前端该订单详情的 H5 链接 |
| `star` | Integer| 否 | `1` | 卖家星标备注过滤1-5 对应标记的星级颜色) |
---
## 5. 响应参数 (全量展开)
返回主体内以 `data` 包裹,核心业务数据在 `full_order_info_list` 中以数组形式返回。
| 根级参数名称 | 参数类型 | 描述说明 |
| :--- | :--- | :--- |
| `total_results` | Integer | 搜索条件匹配到的订单总数 |
| `has_next` | Boolean | 是否还有下一页(用于辅助判定分页) |
| `full_order_info_list`| Array | 完整的订单信息列表集合 |
### 5.1 `full_order_info_list` 内部对象全量解构
列表内的每一项包裹了一个 `full_order_info` 对象,内部包含了关于这笔交易各个维度的子结构体:
| 子结构体名称 | 内部包含的核心全量字段与说明 |
| :--- | :--- |
| **`order_info`**<br>*(交易基础信息)* | `tid`(有赞订单号)<br>`status`(主订单状态枚举,如 `WAIT_SELLER_SEND_GOODS`)<br>`status_str`(状态中文描述文字)<br>`type`(主订单类型:`0`普通 `10`拼团 等)<br>`backstage_order_type`(后台订单类型标识,如 `NORMAL``CROSS_BORDER`)<br>`pay_type`(支付方式枚举值) |
| **`buyer_info`**<br>*(买家信息)* | `yz_open_id`(买家有赞唯一身份标识,**对账核心**)<br>`buyer_phone`(买家手机号,可能存在脱敏加密)<br>`fans_id`(粉丝ID)`fans_type`(粉丝类型)<br>`fans_nickname`(粉丝昵称)<br>`outer_user_id`(外部用户ID)<br>*(⚠️ 注:此接口文档明确不返回原版 `buyer_id`)* |
| **`pay_info`**<br>*(支付与金额信息)* | `total_fee`(订单总金额)`post_fee`(运费)<br>`payment`(实付总金额)`real_payment`(实际支付现金)<br>`deduction_pay`(虚拟抵扣金额,如积分/余额抵扣)<br>`deduction_real_pay`(实际抵扣金额)<br>*(注:金额类型字段为 String 格式,单位:**元**)* |
| **`address_info`**<br>*(收件与物流信息)* | `receiver_name`(收件人姓名)`receiver_tel`(收件人电话)<br>`delivery_province`(省份)`delivery_city`(城市)<br>`delivery_district`(区县)`delivery_address`(详细地址)<br>`delivery_postal_code`(邮编)<br>`address_extra`(JSON 格式的经纬度扩展,如 `{"lon":120.1,"lat":30.4}`)<br>`self_fetch_info`(自提点门店详情)<br>`delivery_start_time`/`delivery_end_time`(期望配送或提货时间) |
| **`remark_info`**<br>*(备注与评价信息)* | `buyer_message`(买家留言)<br>`trade_memo`(卖家内部备注)<br>`star`(订单星标等级 0~5) |
| **`orders`** (Array)<br>*(商品明细列表)* | **包裹在该订单内的所有独立商品 SKU 数组:**<br>`item_id`(商品ID)`sku_id`(规格ID)<br>`outer_item_id`(外部商品/SPU商家编码)<br>`outer_sku_id`(外部规格/SKU商家编码)<br>`title`(商品名称)`price`(单价,单位元)<br>`num`(购买数量)`discount_fee`(优惠分摊金额)<br>`payment`(该商品最终实付金额)`is_cross_border`(是否海淘商品) |
| **`child_info`**<br>*(子单信息)* | 包含 `child_orders` 数组。当出现订单因拆包或部分发货时会产生关联的子订单号(通常取自其内部的 `tid` 用于局部发货接口)。 |
| **`invoice_info`**<br>*(发票信息)* | `taxpayer_id`(买家填写的发票税号/抬头等) |
---
## 6. ⚠️ 开发者防坑指南与注意事项
1. **接口同步延时(非常重要)**
批量接口底层数据有一定的同步延时。**强烈建议在收到订单相关的交易消息推送Webhook间隔大于 30 秒再调用此接口查询**。如果是主动定时轮询拉取订单,同样建议将查询时间范围整体向后延迟 30 秒(例如当前是 10:00:00只查 09:59:30 之前的数据)。如果刚付款立刻查可能返回为空,遇到返回空可以实施重试机制。
2. **分页与深度翻页限制**
`page_no``page_size` 乘积代表查询深度,单页最大 100 条且**页码不能超过 100 页**。在系统对接进行大批量拉取时,必须采用**时间切片法**(如每 1 小时或每 30 分钟为一个区间,循环请求),不能单靠增加页码来拉取海量历史数据。
3. **退款订单的特殊性**
`start_success` (完成时间) 搜索,查到的是状态为“交易成功”的订单。如订单发生全额退款,其状态会变为 `TRADE_CLOSED`(交易关闭)。若需处理售后退单业务,须配合有赞退款 API`youzan.trade.refund.search`)或交易消息服务使用。
4. **老订单降级说明**
由于该版本数据架构调整,若需查询 **2020 年以前的极早期订单数据**,请降级调用 `youzan.trades.sold.get.4.0.0` 接口,新版接口无法查出早于 2020 年的历史数据。

View File

@@ -0,0 +1,206 @@
# 分页查询微商城销售中和已售罄商品列表 (youzan.item.search.3.0.0)
## 1. 接口基本信息
* **API 名称**:分页查询微商城销售中和已售罄商品列表
* **API 接口名**`youzan.item.search`
* **版本号**`3.0.0`
* **计费规则**:基础接口,调用计费(具体以控制台能力包购买为准)。
* **接口描述**:用于分页综合查询处于“**销售中**”和“**已售罄**”状态的商品列表。支持按关键字、分组、品牌、类目、更新时间等多种维度组合筛选。
* **⚠️ 注意**:此接口**无法查询到“仓库中”的商品**(如下架商品),若需查询下架或仓库中商品需调用 `youzan.items.inventory.get`
---
## 2. 请求说明
* **请求协议**HTTPS
* **请求方式**GET/POST (推荐 POST `application/json`)
* **请求地址**
```http
https://open.youzanyun.com/api/youzan.item.search/3.0.0
```
---
## 3. 请求参数 (全量)
| 参数名称 | 类型 | 是否必须 | 示例值 | 参数说明 |
| :--- | :--- | :---: | :--- | :--- |
| `access_token` | String | **是** | `9b510e232c9...` | 有赞云 API 鉴权凭证 |
| `q` | String | 否 | `薯片` | 搜索字段,支持搜索:商品名(模糊匹配) |
| `item_ids` | String | 否 | `457692126,45745...` | 作为查询条件的商品 ID 列表,以逗号分隔,用于精确筛选 |
| `page_no` | Integer | 否 | `1` | 页码,从 1~100 开始,分页数不能超过 100 页。`page_size` 和 `page_no` 相乘总条数不能大于 4000 条 |
| `page_size` | Integer | 否 | `20` | 每页数量,要求小于 50默认 20 |
| `order_by` | String | 否 | `update_time:desc` | 排序方式,格式为 `字段名:升降序`。<br>支持:`created_time`(创建时间)、`update_time`(更新时间)、`price`(价格)、`sold_num`(销量) |
| `update_time_start`| Long | 否 | `1563379200000` | 更新时间**起始**Unix时间戳**时间单位ms毫秒** |
| `update_time_end` | Long | 否 | `1563465600000` | 更新时间**截止**Unix时间戳**时间单位ms毫秒** |
| `show_sold_out` | Integer | 否 | `0` | 是否在售:`0`—在售,`1`—售罄或部分售罄,`2`—全部 |
| `tag_ids` | String | 否 | `106590,106593` | 作为查询的分组(标签) ID 列表,以逗号分隔 |
| `brand_ids` | String | 否 | `1254378,86662` | 作为查询的品牌 ID 列表,以逗号分隔 |
| `category_ids` | String | 否 | `67263,71822` | 作为查询的分类 ID 列表,以逗号分隔 |
| `leaf_category_id` | Long | 否 | `9723123` | 新版商品类目V4版本叶子类目 ID |
| `shop_org_ids` | List<Long>| 否 | `[123, 234]` | 店内组织末级节点 ID 列表,最大不能超过 200 |
| `node_kdt_id` | Long | 否 | `54731007` | 有赞连锁网店店铺 ID仅供连锁场景使用判断信息归属网店 |
| `search_code_type` | Integer | 否 | `3` | 编码查询类型:`1` 编码,`2` 条码,`3` 规格编码,`4` 规格条码 |
| `search_code_list` | List<String>| 否 | `["BM111","BM222"]` | 对应上述类型的编码数组,限制 100 个 |
| `item_source` | Integer | 否 | `0` | 商品创建类型:`0` 普通;`1` 网店自建 (仅支持连锁分店) |
| `offline_id` | Long | 否 | `58853441` | 多网点 ID |
| `channel` | Integer | 否 | `0` | 店铺渠道类型:`-1`:全部渠道;`0`:网店; `1`:门店。默认网店。 |
---
## 4. 响应参数
响应结果主体以 `data` 包裹,主要包含商品总数 `count` 和商品对象列表 `items`。
| 根级参数名称 | 类型 | 描述说明 |
| :--- | :--- | :--- |
| `success` | Boolean | 业务请求是否成功 (`true`/`false`) |
| `code` | Integer | 状态码,`200` 为成功 |
| `message` | String | 成功或错误的提示消息 |
| `data.count` | Integer | 搜索到的符合条件的商品总数量(用于前端计算总页数) |
| `data.items` | Array | 商品详细信息集合 |
### 4.1 `items` 数组内商品基础字段
| 字段名 | 类型 | 字段说明 |
| :--- | :--- | :--- |
| `item_id` | Long | 商品唯一标识(有赞内部商品 ID |
| `alias` | String | 商品别名,可用于拼接商品前端 H5/小程序详情页链接 |
| `title` | String | 商品名称/标题 |
| `sub_title` | String | 商品分享描述 / 副标题 |
| `price` | Long | 商品当前售卖价(单位:**分**,如 100 代表 1元 |
| `origin` | String | 划线价(单位:**元** |
| `item_no` | String | 商家自行填写的商品编码(支持英文和数字组合) |
| `quantity` | Long | 库存数量(注:门店渠道下会被放大 1000 倍展示) |
| `actual_quantity` | String | 实际总库存(自动处理门店渠道放大 1000 倍的转换问题,建议以该字段为准) |
| `item_type` | Integer | 商品类型:`0`普通 `3`降价拍 `5`外卖 `10`分销 `20`会员卡 `60`虚拟 `61`电子卡券等 |
| `channel` | Integer | 归属渠道类型:`0`网店 `1`门店 |
| `post_type` | Integer | 运费类型:`1`—统一运费,`2`—运费模板 |
| `post_fee` | Long | 统一运费的费用(单位:分) |
| `created_time` | String | 创建时间,格式 `"yyyy-MM-dd HH:mm:ss"` |
| `update_time` | String | 最后更新时间,格式 `"yyyy-MM-dd HH:mm:ss"` |
| `has_multi_sku` | Boolean | 是否包含多规格(多 SKU商品 |
| `tag_ids` | List<Long> | 商品分组(标签) ID 列表包含1、2级分组 |
| `group_names` | List<String>| 分组名称列表,如 `["全部分组", "T恤"]` |
| *(其他链接类)* | String | `image` (主图链接), `page_url` (小程序路径), `detail_url` (H5链接) |
### 4.2 `items` 内嵌复杂对象 (图片、运费、属性等)
在每个商品对象中,还包含以下级联对象,用于描述商品更立体的属性:
| 对象/数组名称 | 内部核心字段说明 |
| :--- | :--- |
| **`delivery_template`**<br>*(运费模板)* | `delivery_template_id`(模板ID), `delivery_template_name`(名称), `delivery_template_fee`(运费范围,单位:**元**), `delivery_template_valuation_type`(计费类型 `1`按件 `2`按重量 `3`体积) |
| **`item_imgs`**<br>*(图片列表)* | 包含商品轮播图等:`id`(图片ID), `url`(原图链接), `thumbnail`(缩略图), `medium`(中图), `created`(创建时间) |
| **`sku_extension_attributes`**<br>*(SKU扩展属性)* | `sku_id`(规格ID), `cost_price`(成本价) |
| **`meas_prop`**<br>*(重量与计量)* | 内部包裹 `meas` 数组。包含:`sku_id`(商品规格ID), `weight`(规格维度重量,单位:**克**) |
| **`properties`**<br>*(类目相关属性)* | 分为 `publics` (公域属性,如品牌、材质) 和 `privates` (私域属性,如商家自定义的颜色、尺码)。内含 `pro_name`(属性名) 和 `val_names`(属性值名称列表) |
*(注:如果需要对多规格商品进行深度的库存或价格修改,建议结合 `youzan.item.detail.get` 获取完整的 SKU 明细节点。)*
---
## 5. 请求与响应示例
### 5.1 Java SDK 调用示例
```java
YZClient client = new DefaultYZClient(new Token("YOUR_ACCESS_TOKEN"));
YouzanItemSearchParams youzanItemSearchParams = new YouzanItemSearchParams();
// 搜索关键字
youzanItemSearchParams.setQ("薯片");
// 设置按更新时间降序排列
youzanItemSearchParams.setOrderBy("update_time:desc");
// 仅查询在售商品
youzanItemSearchParams.setShowSoldOut(0);
// 设置页码和每页数量
youzanItemSearchParams.setPageNo(1);
youzanItemSearchParams.setPageSize(20);
YouzanItemSearch youzanItemSearch = new YouzanItemSearch();
youzanItemSearch.setAPIParams(youzanItemSearchParams);
YouzanItemSearchResult result = client.invoke(youzanItemSearch);
```
### 5.2 响应示例 (JSON - 全量结构截取)
```json
{
"success": true,
"code": 200,
"message": "successful",
"data": {
"count": 18,
"items":[
{
"item_id": 365112687,
"alias": "2x9272j7pmw9q",
"title": "一袋薯片",
"price": 1000,
"origin": "15.00",
"item_no": "spbm001",
"quantity": 66,
"actual_quantity": "66",
"item_type": 0,
"channel": 0,
"post_type": 2,
"post_fee": 0,
"created_time": "2019-03-24 11:04:24",
"update_time": "2019-03-25 11:04:24",
"has_multi_sku": false,
"group_names":["零食", "全部分组"],
"image": "https://img.yzcdn.cn/upload_files/2019/03/08/Foya.jpg",
"page_url": "packages/goods/detail/index",
"delivery_template": {
"delivery_template_id": 658289,
"delivery_template_name": "杭州市按件计费",
"delivery_template_fee": "16.00",
"delivery_template_valuation_type": 1
},
"item_imgs":[
{
"id": 365112687,
"url": "https://img.yzcdn.cn/upload_files/2019/03/08/Foya.jpg",
"thumbnail": "https://img.yzcdn.cn/upload_files/2019/03/08/Foya.jpg?imageView2/2/w/290/h/290"
}
],
"properties": {
"publics":[
{
"pro_id": 123,
"pro_name": "品牌",
"val_names": ["乐事"]
}
],
"privates":[
{
"pro_id": 124,
"pro_name": "口味",
"val_names": ["番茄味"]
}
]
}
}
]
}
}
```
---
## 6. ⚠️ 常见使用问题与避坑指南
1. **接口查询状态限制(无法查全库)**
注意:此接口只能查到状态为 **“销售中”** 以及 **“已售罄”** 的商品。它**不支持**查询“仓库中”的商品。若需对全店商品库对账,需搭配 `youzan.items.inventory.get` 使用;如果是连锁总部的商品库,需使用 `youzan.item.common.search`。
2. **库存数量的陷阱 (`quantity` vs `actual_quantity`)**
当您的店铺属于“门店渠道”(`channel = 1`) 时,旧版的 `quantity` 字段因为单位换算问题,会被强制放大 **1000倍**(如实际库存 66 个会返回 66000。**强烈建议开发者在业务逻辑中直接取用 `actual_quantity` 字段**,该字段官方已自动处理好了单位转换,始终代表真实的物理库存数量。
3. **分页与查询深度的限制**
接口严格限制 `page_size * page_no <= 4000` 条。如果店铺内商品总数超过 4000 个,无法仅通过增加页码拉取全量数据。**解决方案**:利用 `update_time_start``update_time_end` 进行时间切片例如每次查询1个月内的更新记录循环遍历全量数据。
4. **时间戳单位是“毫秒”**
请仔细核对您的入参。`update_time_start``update_time_end` 必须传递 **13 位毫秒级时间戳**,如果后端语言默认生成的是 10 位秒级时间戳,会导致无法匹配数据返回空。
5. **增量更新推荐WebHook 推送**
如果您需要对店铺内的商品信息进行双向准实时同步,官方不推荐使用本接口进行“定时高频死循环轮询”。正确的姿势是:订阅有赞云商品变更消息推送(如 `ITEM_UPDATE``ITEM_CREATE`),在接收到商品变更的 `item_id` 后,再针对该单品去调用接口更新本地数据库。

View File

@@ -0,0 +1,69 @@
# 查询客户详细信息 (youzan.scrm.customer.detail.get.1.0.1)
## 1. 接口基本信息
* **API 名称**:查询客户详细信息
* **API 接口名**`youzan.scrm.customer.detail.get`
* **版本号**`1.0.1`
* **接口描述**:用于精确查询单个客户在店铺/网点内的详细视图数据。通过指定查询模块,可以一次性获取客户的基础资料、标签、积分、会员等级、储值、权益卡以及自定义属性等全方位数据。
---
## 2. 请求说明
* **请求协议**HTTPS
* **请求方式****POST** (严格要求,推荐 `application/json` 格式)
* **请求地址**
```http
https://open.youzanyun.com/api/youzan.scrm.customer.detail.get/1.0.1
```
---
## 3. 请求参数
在请求的 Body 中传入以下 JSON 数据参数:
| 参数名称 | 类型 | 是否必填 | 示例值 | 参数说明 |
| :--- | :--- | :---: | :--- | :--- |
| `access_token` | String | **是** | `9b510e232...` | 有赞云 API 鉴权凭证 |
| `yz_open_id` | String | 否 | `hijaMaXo65...` | 客户在有赞体系内的唯一身份标识。**(推荐使用,与 `account_info` 至少二选一)** |
| `account_info` | Object | 否 | - | 账户信息对象(如果不传 `yz_open_id`,可通过此字段检索如手机号匹配的客户) |
| `└─ account_id` | String | 否 | `13800138000` | 账号标识,如具体的手机号码 |
| `└─ account_type`| Integer| 否 | `2` | 账号类型,`2` 代表国内手机号 |
| `fields` | String | 否 | `user_base,credit` | **指定需要返回的客户信息模块**,多个用英文逗号分隔。<br>支持:`user_base`(基础资料), `tags`(标签), `benefit_cards`(权益卡), `benefit_level`(会员等级), `benefit_rights`(权益), `credit`(积分), `behavior`(行为数据), `giftcard`(礼品卡), `prepaid`(储值), `coupon`(优惠券), `level`(成长值/等级), `auth_info`(授权信息), `customer_attrInfos`(自定义属性) |
| `is_do_ext_point`| Boolean| 否 | `false` | 是否触发外部积分扩展点查询校验,默认为 `false` |
---
## 4. 响应参数
响应主体包裹在 `data` 中。因为该接口是**按需返回**的(基于 `fields` 传入的模块名),以下整理全量核心业务模块的响应结构:
| 根级参数名称 | 类型 | 描述说明 |
| :--- | :--- | :--- |
| `success` | Boolean | 请求是否成功 (`true`/`false`) |
| `code` | Integer | 状态码,`200` 表示成功 |
| `message` | String | 成功或错误提示信息 |
| `data` | Object | **客户详情数据总包**(内含根据 fields 指定返回的各个业务模块数据) |
### 4.1 `data` 内部核心业务模块解构
| 内部模块结构 / 数组 | 核心包含内容与说明 |
| :--- | :--- |
| **`user_base`**<br>*(基础资料)* | 客户的核心基础信息。<br>`yz_open_id`(有赞唯一标识); `name`(客户姓名/昵称); `gender`(性别:0未知,1男,2女); `birthday`(生日); `mobile` / `phone`(手机号,通常含脱敏星号); `remark`(商家后台备注); `created_at`(成为本店客户的时间); `ascription_kdt_id`(归属店铺/网点ID) |
| **`tags`** (Array)<br>*(标签信息)* | 客户被打上的标签列表。<br>`tag_id`(标签ID); `tag_name`(标签名称) |
| **`level_infos`** (Array)<br>*(等级信息)* | 从 `level` 或 `benefit_level` 调取出的客户当前等级情况。<br>`level_alias`(等级名称,如白银会员); `level_type`(等级类型:免费/付费等) |
| **`cards`** (Array)<br>*(权益卡/礼品卡)*| 返回客户名下持有的卡信息。<br>`card_alias_no`(卡号); `card_type`(卡类型); `name`(卡名称) |
| **`rights`** (Array)<br>*(会员权益)* | 包含客户享有的具体权益ID、权益名称如包邮、专享折扣等细则项 |
| **`credit`**<br>*(积分信息)* | `current_credit`(客户当前可用积分余额); `total_credit`(历史累计总积分) |
| **`behavior`**<br>*(行为/交易数据)*| `trade_count`(客户本店累计交易笔数); `trade_amount`(累计交易总金额); `last_trade_time`(最近一次交易时间) |
| **`customer_attrInfos`** (Array)<br>*(自定义属性)* | 商家在后台为客户模板设置的自定义扩展项。<br>`attr_id`(属性项ID); `attr_name`(属性项名称); `attr_value`(属性值) |
---
## 5. ⚠️ 开发者防坑指南与注意事项
1. **请求方式的陷阱(必需 POST**
虽然 API 接口命名是以 `.get` 结尾(`youzan.scrm.customer.detail.get`),但是该接口**严格要求使用 HTTP POST** 并在 Body 中传递 JSON。如果错误地使用了 GET 方法且在 URL 后拼接参数,接口会报错 `invalid params` 或导致返回的数组模块全部为空(如 `"tags":

View File

@@ -0,0 +1,111 @@
# 分页查询库存模式 (youzan.retail.open.stock.mode.query.1.0.0)
## 1. 接口基本信息
* **API 名称**:分页查询库存模式
* **API 接口名**`youzan.retail.open.stock.mode.query`
* **版本号**`1.0.0`
* **计费规则**:基础接口,调用计费
* **接口描述**:用于连锁总部或单店商家,分页查询旗下各个店铺/门店kdt_id对应的“库存管理模式”。帮助开发者判断门店是使用独立销售库存还是共享总部/仓储的库存,以及是否开启了单据管理库存。
---
## 2. 请求说明
* **请求协议**HTTPS
* **请求方式**POST (请求体传参,推荐 `application/json` 格式)
* **请求地址**
```http
https://open.youzanyun.com/api/youzan.retail.open.stock.mode.query/1.0.0
```
---
## 3. 请求参数
在请求的 Body 中传入以下 JSON 参数:
| 参数名称 | 类型 | 是否必填 | 示例值 | 参数说明 |
| :--- | :--- | :---: | :--- | :--- |
| `access_token` | String | **是** | `9b510e23...` | 鉴权凭证,用于请求 API |
| `retail_source` | String | **是** | `YOUZAN` | 零售调用来源(调用方和有赞约定的值,通常为接入应用标识,必填字段) |
| `node_kdt_id` | Long | 否 | `18938611` | 连锁场景下查询指定分店的 `kdt_id`。查总部下全部店铺则不用传;单店场景不用传。 |
| `stock_mode` | Integer | 否 | `2` | 按特定库存模式筛选。不传则查全部模式。<br>`1`-独立销售库存;`2`-共享总部库存;`3`-共享门店仓库存库;`4`-进出存单据管理。 |
| `page_no` | Integer | 否 | `1` | 页码,默认从 1 开始 |
| `page_size` | Integer | 否 | `20` | 分页大小,默认每页 20 条数据 |
---
## 4. 响应参数
响应主体包裹在 `data` 中,返回门店库存模式列表与分页信息。
| 根级参数名称 | 类型 | 描述说明 |
| :--- | :--- | :--- |
| `success` | Boolean | 请求是否成功 (`true`/`false`) |
| `code` | Integer | 状态码,`200` 表示成功,`-100` 表示系统错误 |
| `message` | String | 成功或错误提示信息 |
| `request_id` | String | 请求 ID官方标注已作废 |
| `data` | Object | **查询结果总包** |
### 4.1 `data` 内部核心业务字段解构
| 内部模块结构 / 数组 | 类型 | 核心包含内容与说明 |
| :--- | :--- | :--- |
| **`open_stock_mode_search_d_t_o`** | List | **库存模式明细列表** |
| └─ `kdt_id` | Long | 店铺/门店底层 ID 标识 |
| └─ `team_name` | String | 店铺/门店名称(如:测试门店) |
| └─ `shop_role` | Integer | 店铺类型。`2`-门店;`3`-独立仓;`6`-分销供货商店铺;`7`-前置仓 |
| └─ `stock_mode` | Integer | **库存模式**。<br>`1`-独立销售库存<br>`2`-共享总部库存<br>`3`-共享门店仓库存库<br>`4`-进出存单据管理 |
| └─ `order_manager_stock` | Integer | 单据管理库存开关(门店专用)。`1`-开启,`0`-关闭 |
| **`paginator`** | Object | **分页信息对象** |
| └─ `page` | Integer | 当前页码 |
| └─ `page_size` | Integer | 当前页大小 |
| └─ `total_count` | Integer | 匹配到的总条数(用于前端计算总页数) |
---
## 5. 响应示例 (JSON)
### 5.1 成功响应示例
```json
{
"trace_id": "yz7-0ae82d0e-1677750929750-364981",
"code": 200,
"success": true,
"message": "successful",
"data": {
"open_stock_mode_search_d_t_o":[
{
"kdt_id": 18938611,
"team_name": "YZ-零售单店(别改名字)鄧",
"shop_role": 0,
"stock_mode": 3,
"order_manager_stock": 1
}
],
"paginator": {
"total_count": 1,
"page": 1,
"page_size": 20
}
}
}
```
---
## 6. ⚠️ 开发者防坑指南与注意事项(核心排错)
1. **必传参数 `retail_source` 遗漏阻断**
有赞零售Retail体系的接口有部分老业务逻辑强依赖 `retail_source`(零售调用来源)。此字段在文档中明确标注为**必填(是)**。如果不传,接口会直接报错拦截。如果您是常规自用型应用对接,通常约定传 `"YOUZAN"` 或咨询有赞服务小二获取专属标识。
2. **错误码 `-100` 的核心排查方向Token 权限越界)**
如果接口返回 `{"code": -100, "message": "服务器错误"}`,除了检查必填参数外,**最常见的原因是 `access_token` 的授权主体不匹配**。
* **排查建议**:请检查申请 Token 的授权 ID 是否是连锁“总部”、“单店”或“合伙人”级别的 ID。例如用一个无下属门店的普通微商城 Token 试图去拉取总部结构,就会触发越界报错。
3. **`node_kdt_id` 与网点架构关系**
* **单店系统**:不要传 `node_kdt_id`。
* **连锁总部系统**:如果需要一次性获取旗下所有门店的模式(常用于 ERP 系统初始化对账),不传此参数即可查全部;如果由于业务变动需要校验某一家具体分店是否切换了共享仓,传入该分店的 `kdt_id` 精确点查,效率最高。
4. **`stock_mode` 共享库存拦截提醒**
当 `stock_mode` 返回值为 `2`(共享总部库存)时,意味着该门店没有独立的实物库存管理权限。此时如果您通过代码强行调用门店库存扣减/入库的 API有赞底层会报错拦截。业务逻辑上必须将库存扣减的指令路由指向其**共享总部**的店铺 ID 或总仓。

View File

@@ -0,0 +1,76 @@
# 查询仓库商品库存 (youzan.retail.open.query.warehousestock.1.0.0)
## 1. 接口基本信息
* **API 名称**:查询仓库商品库存
* **API 接口名**`youzan.retail.open.query.warehousestock`
* **版本号**`1.0.0`
* **接口描述**用于精确查询指定仓库或线下门店下特定商品规格SKU的各项详细库存数据。支持实时拉取实物库存、在途库存、计划库存及各维度的占用库存。
---
## 2. 请求说明
* **请求协议**HTTPS
* **请求方式**POST (严格要求,推荐 `application/json` 格式)
* **请求地址**
```http
https://open.youzanyun.com/api/youzan.retail.open.query.warehousestock/1.0.0
```
---
## 3. 请求参数
在请求的 Body 中传入以下 JSON 参数:
| 参数名称 | 类型 | 是否必填 | 示例值 | 参数说明 |
| :--- | :--- | :---: | :--- | :--- |
| `access_token` | String | **是** | `9b510e232...` | 有赞云 API 鉴权凭证 |
| `warehouse_code` | String | **是** | `MD00021` | 仓库/门店编码。必须传递有赞底层生成的仓编码(由 `youzan.retail.open.warehouse.query` 接口获取)。 |
| `sku_codes` | Array (String) | **是** | `["SKU001", "SKU002"]` | 商品规格编码SKU数组。**注意:每次请求最多传入 20 个 SKU 编码。** |
---
## 4. 响应参数
响应主体包裹在 `data` 中,以数组列表形式返回请求中对应 SKU 的多维度库存详情。
| 根级参数名称 | 类型 | 描述说明 |
| :--- | :--- | :--- |
| `success` | Boolean | 请求是否成功 (`true`/`false`) |
| `code` | Integer | 状态码,`200` 表示成功 |
| `message` | String | 成功或错误提示信息 |
| `data` | Array | **库存结果列表集合** |
### 4.1 `data` 数组内核心业务字段解构
| 内部参数名称 | 类型 | 核心说明 |
| :--- | :--- | :--- |
| `sku_code` | String | 商品规格编码(对应入参检索的 SKU。 |
| `warehouse_code`| String | 当前查询返回的仓库编码。 |
| `stock_num` | String/Decimal| **实物库存数量**。当前仓库中真实存在的物理库存总数。(注:该接口返回的库存数值精确到小数点后两位,如 `100.00` |
| `freeze_num` | String/Decimal| **实物库存占用**。已被订单锁定、但尚未真实扣减出库的物理库存数量。 |
| `plan_num` | String/Decimal| **计划库存数量**。多用于门店预售或外部系统的虚拟分配库存。 |
| `plan_freeze_num`| String/Decimal| **计划库存占用**。计划库存中已被锁定的数量。 |
| `road_num` | String/Decimal| **在途库存**。处于采购在途、调拨在途的预计入库商品数量。 |
---
## 5. ⚠️ 开发者防坑指南与注意事项(核心高频报错提醒)
1. **极其高频的报错:`234000003 - 仓库信息不存在`**
如果您在调用该接口时收到此错误,**99% 的原因是您在 `warehouse_code` 字段里错误地传入了门店的店铺 ID`kdt_id`**。
* **避坑必看**:此接口不认网点 ID。请务必先调用 `youzan.retail.open.warehouse.query`(查询总部下门店和仓库信息),拿到类似 `MD00021` 或 `TEST001` 的真正**仓库编码**,再传入本接口使用。
2. **如何计算“当前可用库存”?**
本接口不会直接吐出一个叫“可用库存”的字段。如果您正在对接前端商城的剩余可售数量计算,请按照公式自行相减:
`可用库存 = 实物库存 (stock_num) - 实物库存占用 (freeze_num)`
3. **参数数量超限限制**
入参的 `sku_codes` 数组**严格限制最大长度为 20**。如果您需要进行全店全量商品的库存对账或初始化同步,请不要用该接口循环遍历(极易触发限流告警),建议使用对应的“分页查询库存”专用接口。此接口更适合购物车结算前或单品详情页的**点对点实时余量校验**。
4. **精度格式说明**
有赞新零售体系内的库存不仅支持整数,也支持散装/称重商品(如按斤、米售卖)。因此返回的 `stock_num` 等数量字段可能为带有两位小数的数值型字符串(如 `"5.50"`),在强类型语言(如 Java、Go解析时需注意浮点数/高精度类的映射处理。

View File

@@ -0,0 +1,76 @@
# 查询总部下门店和仓库信息 (youzan.retail.open.warehouse.query.3.0.0)
## 1. 接口基本信息
* **API 名称**:查询总部下门店和仓库信息
* **API 接口名**`youzan.retail.open.warehouse.query`
* **版本号**`3.0.0`
* **接口描述**:用于连锁总部或多网点商家,批量查询其底下的所有真实仓库以及具有仓库属性的“线下门店”信息。获取到的 `warehouse_code` 是后续调用库存调整、盘点、调拨等单据接口的**必传核心参数**。
---
## 2. 请求说明
* **请求协议**HTTPS
* **请求方式**POST (推荐 `application/json` 格式)
* **请求地址**
```http
https://open.youzanyun.com/api/youzan.retail.open.warehouse.query/3.0.0
```
---
## 3. 请求参数
在请求的 Body 中传入以下 JSON 参数:
| 参数名称 | 类型 | 是否必填 | 示例值 | 参数说明 |
| :--- | :--- | :---: | :--- | :--- |
| `access_token` | String | **是** | `9b510e232...` | 有赞云 API 鉴权凭证(请使用连锁总店的 Token 授权) |
| `page_no` | Integer | 否 | `1` | 页码,默认从 1 开始 |
| `page_size` | Integer | 否 | `20` | 每页返回的数量,建议默认 20最大通常不超过 100 |
| `warehouse_name` | String | 否 | `北京一号仓` | 仓库或门店名称(支持模糊搜索筛选) |
| `retail_source` | String | 否 | `YOUZAN` | 零售调用来源。*(注:该字段官方已于 2021-04-26 废弃取消强校验,新接入开发者无需传值,不影响调用)* |
---
## 4. 响应参数
响应主体包裹在 `data` 中,主要返回门店与仓库的映射列表信息。
| 根级参数名称 | 类型 | 描述说明 |
| :--- | :--- | :--- |
| `success` | Boolean | 请求是否成功 (`true`/`false`) |
| `code` | Integer | 状态码,`200` 表示成功 |
| `message` | String | 成功或错误提示信息 |
| `data` | Object | **查询结果总包** |
| └─ `count` | Integer | 匹配到的总条数(用于计算分页) |
| └─ `items` | Array | **仓库/门店信息列表集合** |
### 4.1 `items` 数组内核心业务字段解构
| 内部参数名称 | 类型 | 核心说明 |
| :--- | :--- | :--- |
| `warehouse_code` | String | **仓库/门店编码(核心参数)**。有赞系统内部生成的唯一编码(如 `MD00021` 或 `TEST001`)。 |
| `warehouse_name` | String | 仓库或门店的名称。 |
| `warehouse_type` | Integer | 仓库属性类型。区分该主体是“普通大仓”还是“线下实体门店”。 |
| `kdt_id` | Long | 绑定的对应店铺/网点的底层 ID。如果该仓是独立门店则返回对应门店的 kdt_id |
| `status` | Integer | 仓库状态。例如正常营业、停用等。 |
| `address` | String | 仓库或门店的详细物理地址。 |
---
## 5. ⚠️ 开发者防坑指南与注意事项(核心高频报错提醒)
1. **极其容易混淆的 `warehouse_code` 与 `kdt_id`(错误码 `234000003`**
在有赞新零售/连锁系统中,“线下门店”本身也被视作一个“仓库”。很多开发者在调用“查询/调整门店商品库存”接口(如 `youzan.retail.open.query.warehousestock` 或 `youzan.retail.open.stock.adjust`)时,**错误地将门店的底层店铺ID`kdt_id`)当作仓库编码传了进去**,这会导致接口直接报错:`{"code": 234000003, "message": "仓库信息不存在"}`。
**正确做法**:必须先调用本接口(`youzan.retail.open.warehouse.query`),拿到门店对应的真实 `warehouse_code`(类似 `MD00021`),再用这个编码去调用库存接口。
2. **ERP 映射关系的建立(库存对接必读)**
如果您正在对接第三方 ERP 系统的网店/门店库存同步,正确的初始化流必须是:
在第三方系统中建立映射表 → 调用本接口全量拉取有赞的 `warehouse_code` → 与 ERP 系统里的仓库编码(或者门店编号)进行 `1:1` 的绑定映射。
3. **连锁授权架构提示**
本接口属于“零售连锁/多网点”场景下的专属 API。调用时使用的 `access_token` 必须是由**总部(总店)**授权产生的。如果使用单店或无多网点权限的微商城 Token 请求,可能会拉取为空或提示权限不足。

View File

@@ -0,0 +1,105 @@
# 查询门店商品信息 (youzan.retail.open.offline.spu.query.3.0.0)
## 1. 接口基本信息
* **API 名称**:查询门店商品信息
* **API 接口名**`youzan.retail.open.offline.spu.query`
* **版本号**`3.0.0`
* **计费规则**:基础接口,调用计费
* **接口描述**:查询门店商品信息。**注意:系统有严格的查询深度限制,`page_no * page_size` 的乘积不能大于 3300。**
---
## 2. 请求说明
* **请求协议**HTTPS
* **请求方式**POST (请求体传参,`application/json` 格式)
* **请求地址**
```http
https://open.youzanyun.com/api/youzan.retail.open.offline.spu.query/3.0.0
```
---
## 3. 请求参数
| 参数名称 | 类型 | 是否必填 | 示例值 | 参数说明 |
| :--- | :--- | :---: | :--- | :--- |
| `access_token` | String | **是** | `9b510e232...` | 鉴权凭证,用于请求 API |
| `retail_source` | String | **是** | `YOUZAN` | 零售调用来源。*(注该字段已于2021-04-26号废弃取消校验新接入开发者无需传值已对接开发者不受影响)* |
| `warehouse_code` | String | 否 | `TEST001` | **仓库编码**。可通过 `youzan.retail.open.warehouse.query` 接口获取;**如果不填,默认查总部商品库商品** |
| `show_display` | Integer | 否 | `0` | 销售状态。`0`:已售罄;`1`:销售中;`2`:在库中。**不传值默认查询“销售中”状态** |
| `page_no` | Integer | 否 | `1` | 页码,从 1~300 开始的正整数。(`page_no * page_size` 总数不超过3300) |
| `page_size` | Integer | 否 | `20` | 每页条数,默认 20 条。(`page_no * page_size` 总数不超过3300) |
| `name_or_sku_no` | String | 否 | `商品1` | 搜索条件:商品名称 / 商品条码 |
| `item_ids` | List<Long> | 否 | `[12312321]` | 商品 Id 列表(适用于首次通过该接口批量获取存入数据库,后续查询时取出导入的场景) |
---
## 4. 响应参数
响应主体包裹在 `data` 中,主要分为 `paginator` (分页信息) 和 `offline_spus` (门店商品明细)。
| 根级参数名称 | 类型 | 描述说明 |
| :--- | :--- | :--- |
| `success` | Boolean | 表示本次请求是否成功 (`true`/`false`) |
| `code` | Integer | 网关返回码,`200` 表示成功 |
| `message` | String | 网关返回码描述 |
| `data` | Object | **响应参数总包** |
| └─ `paginator` | Object | **分页数据对象** |
| &nbsp;&nbsp;&nbsp;&nbsp;├─ `page` | Integer | 页码,从 1 开始正整数 |
| &nbsp;&nbsp;&nbsp;&nbsp;├─ `page_size` | Integer | 每页条数。默认 20 条 |
| &nbsp;&nbsp;&nbsp;&nbsp;└─ `total_count` | Integer | 匹配到的总条数 |
| └─ `offline_spus`| List | **门店商品 (SPU) 信息列表** |
### 4.1 `offline_spus` (门店商品明细) 与 `sku_models` (规格明细) 结构解构
| 内部参数名称 | 类型 | 核心说明 |
| :--- | :--- | :--- |
| `item_id` | Long | 门店商品 Id有赞生成的店铺下商品唯一 Id |
| `title` | String | 商品名称 |
| `spu_no` | String | 商品条码 |
| `price` | String | 零售价 |
| `max_guide_price`| String | 最大建议零售价(单位:元) |
| `min_guide_price`| String | 最小建议零售价(单位:元) |
| `unit` | String | 单位(如:件) |
| `sell_stock_count`| String | 销售库存 |
| `sold_num` | String | 总销量 |
| `created_at` | String | 创建时间 |
| `is_display` | Integer | 是否上架:`1` (上架)`0` (未上架) |
| `measurement` | Integer | 称重非称重商品标识:`0` (非称重)`10` (称重) |
| `has_multi_sku` | Boolean | 是否多规格:`true` (是)`false` (否) |
| `is_non_spec` | Boolean | 是否无规格:`true` (是)`false` (否) |
| `category_name` | String | 商品分组名称 |
| `specifications` | String | 规格信息(如:`"XL"` |
| `tax_code` | String | 税收分类编码(商家配置开具电子发票时自定义填写) |
| `plu_code` | String | PLU 码 |
| `biz_mark_code` | String | 商品标编码(如 `"010000000002"` |
| `biz_mark_name` | String | 商品标名称。枚举对应:<br>`"010000000002"`:预售商品<br>`"020000000001"`:零售连锁<br>`"000000000041"`:餐饮商品<br>`"010000000042"`:生鲜果蔬商品<br>`"010000000043"`:海淘跨境商品 |
| **`sku_models`** | List | **门店商品 SKU (规格) 信息列表** |
| &nbsp;&nbsp;├─ `sku_id` | Long | 规格 Id有赞生成的店铺下商品规格唯一 Id |
| &nbsp;&nbsp;├─ `sku_no` | String | 规格条码(支持商家自定义,英文数字组合,店铺下唯一) |
| &nbsp;&nbsp;├─ `specs` | String | 规格信息(如:`"红色XL"` |
| &nbsp;&nbsp;├─ `price` | String | 价格 |
| &nbsp;&nbsp;├─ `max_guide_price`| String | 最大建议零售价 |
| &nbsp;&nbsp;├─ `min_guide_price`| String | 最小建议零售价 |
| &nbsp;&nbsp;├─ `plu_code` | String | PLU 码 |
| &nbsp;&nbsp;└─ `unit` | String | 单位 |
---
## 5. ⚠️ 开发者防坑指南与注意事项(基于官方文档)
1. **严格的深度查询限制 (`3300` 限制)**
文档特别强调了 Elasticsearch 的搜索深度约束:`page_no * page_size` 的**乘积绝对不能超过 3300**。例如当 `page_size` 为默认的 20 时,最多只能翻到第 165 页。如果要查询的数据量庞大,切忌无脑通过递增页码扫库,以免触发限制报错。
2. **`warehouse_code`(仓库编码)的归属逻辑**
* 如果您**不传**此参数:接口默认只去查询“总部商品库”的商品信息。
* 如果您想要查询某家特定门店的下发商品与价格信息,必须传入正确的、通过 `youzan.retail.open.warehouse.query` 获取到的特定门店仓库编码(如 `TEST001`)。
* **报错预警:**如果传入了错误或不存在的编码,系统将返回错误码 `234007003` (不合法的仓库编码)。
3. **`show_display` 默认行为过滤**
请注意,如果请求时不传 `show_display` 参数,接口底层会自动帮您**过滤掉**下架在库和已售罄的商品,**只返回状态为“1销售中”的商品**。如果有盘库需求,需要找回仓库里的下架商品,请务必显式传入对应的状态值。
4. **废弃的 `retail_source` 字段**
官方已明确声明该字段自 2021-04-26 起已取消校验。新接入的开发者无需关心或给该参数传值,不会影响接口的正常调用。
5. **查询结果为空处理 (`234002001` 错误码)**
如果在传入 `name_or_sku_no` 后没有匹配到任何结果,接口会返回错误码 `234002001`(无商品信息)。在代码侧编写逻辑时,需对此错误码做特殊的“无数据”放行处理,而不是作为异常直接抛出。

View File

@@ -0,0 +1,109 @@
# 查询售后单列表 (youzan.trade.refund.search.3.0.1)
## 1. 接口基本信息
* **API 名称**:查询售后单列表
* **API 接口名**`youzan.trade.refund.search`
* **版本号**`3.0.1`
* **计费规则**:基础接口,调用计费
* **接口描述**:用于按条件(如时间范围、订单号、状态等)分页查询店铺内的退款及售后单据列表。**注意:如果入参没有设置查询时间范围,接口默认查询创建时间为近 3 个月的单据。**
---
## 2. 请求说明
* **请求协议**HTTPS
* **请求方式**POST (请求体传参,`application/json` 格式)
* **请求地址**
```http
https://open.youzanyun.com/api/youzan.trade.refund.search/3.0.1
```
---
## 3. 请求参数
在请求体Body中传入以下 JSON 参数:
| 参数名称 | 类型 | 是否必填 | 参数说明 |
| :--- | :--- | :---: | :--- |
| `access_token` | String | **是** | 鉴权凭证,用于请求 API |
| `tid` | String | 否 | 有赞订单号E开头+年月日时分秒+随机数长24位 |
| `refund_id` | String | 否 | 售后退款单号 |
| `yz_open_id` | String | 否 | **(3.0.1新增)** 有赞用户 ID买家在有赞的唯一身份标识 |
| `create_time_start`| Long | 否 | 创建起始时间,**Unix时间戳单位**。不传则默认近3个月 |
| `create_time_end` | Long | 否 | 创建截止时间,**Unix时间戳单位** |
| `update_time_start`| Long | 否 | 更新起始时间,**Unix时间戳单位** |
| `update_time_end` | Long | 否 | 更新截止时间,**Unix时间戳单位** |
| `page_no` | Integer | 否 | 分页数,**`page_no > 100` 会报错“查询页数超过100”** |
| `page_size` | Integer | 否 | 每页显示个数,**`page_no * page_size > 3000` 会报错“超过ES搜索最大深度”** |
| `status` | String | 否 | 退款状态:<br>`WAIT_SELLER_AGREE`: 等待卖家同意<br>`WAIT_BUYER_RETURN_GOODS`: 等待买家退货<br>`WAIT_SELLER_CONFIRM_GOODS`: 等待卖家确认收货<br>`SELLER_REFUSE_BUYER`: 卖家拒绝退款<br>`CLOSED`: 退款关闭<br>`SUCCESS`: 退款成功<br>`CUSTOMER_SERVICE_IN`: 客满介入<br>`SELLER_REFUSE_BUYER_RETURN_GOODS`: 卖家拒绝收货,待买家处理<br>`SELLER_RETURN_GOODS`: 商家确认收货并发送换货 |
| `type` | Integer | 否 | 退款流程类型:`1`(买家申请退款), `2`(商家主动退款), `3`(一键退款), `4`(零售门店换货), `5`(微商城换货) |
| `demand` | Integer | 否 | 退款诉求:`1`(仅退款), `2`(退货退款), `3`(换货) |
| `phase` | Integer | 否 | 退款阶段:`1`(售中), `2`(售后) |
| `refund_mode` | Integer | 否 | 退款资金类型:`0`(原路退), `1`(现金退), `2`(标记退) |
| `search_tag` | Integer | 否 | 退款单列表查询 Tag`0`(待商家处理), `1`(待买家处理), `2`(客服介入中) |
| `delivery_status` | Integer | 否 | 发货状态:`1`(未发货), `2`(已发货) |
| `sku_no` | String | 否 | 商品规格编码 |
| `goods_title` | String | 否 | 商品名称(支持模糊搜索) |
| `delivery_no` | String | 否 | 物流单号 |
| `node_kdt_id` | Long | 否 | 分店店铺 ID连锁场景使用 |
| `sale_way` | Integer | 否 | 销售渠道:`1`(门店), `2`(网店) |
| `return_stock_status`| Integer | 否 | 退货归还库存状态:`0`(无需入库), `10`(待入库), `20`(归还库存成功) |
| `cs_status` | Integer | 否 | 客服介入状态:`1`(不需要), `2`(需要), `3`(介入结束) |
| `buyer_phone` | String | 否 | 买家电话 |
| `invalid` | Integer | 否 | 是否为无效的退款单:`1`(true无效), `0`(false有效) |
| `pay_type` / `pay_way` | Integer | 否 | 支付类型与支付渠道(如微信、支付宝、储值卡等细分枚举,详见官方码表) |
---
## 4. 响应参数
响应主体包裹在 `data` 中,返回当前搜索条件下的退款单总数和详情列表。
| 根级参数名称 | 类型 | 描述说明 |
| :--- | :--- | :--- |
| `success` | Boolean | 请求是否成功 (`true`/`false`) |
| `code` | String / Int | 成功失败状态码,`200` 表示成功 |
| `message` | String | 成功或错误提示信息 |
| `data` | Object | **查询结果总包** |
| └─ `total` | Integer | 匹配到的单据总数 |
| └─ `refunds` | Array | **退款信息明细列表** |
### 4.1 `refunds` 数组内核心业务字段解构
| 内部参数名称 | 类型 | 核心说明 |
| :--- | :--- | :--- |
| `refund_id` | String | 退款 ID / 售后单号 |
| `tid` | String | 关联的有赞订单号 |
| `kdt_id` | Long | 产生该单据的店铺 ID |
| `node_kdt_id` | Long | 产生该单据的子店/网点 ID |
| `status` | String | 退款状态。枚举同请求入参 `status` |
| `return_goods` | Boolean | 是否退货 |
| `refund_fee` | String | 申请退款的金额(如 `"0.01"` 元) |
| `reason` | Integer | 退款原因代码。<br>常见:`54`(未按约定时间发货), `11`(质量问题), `104`(拍错/不喜欢) 等。系统退款:`204`(订单关闭), `208`(拼团未成团) 等。 |
| `created` | String | 退款申请创建时间(格式 `"yyyy-MM-dd HH:mm:ss"` |
| `modified` | String | 退款申请最后修改时间(格式 `"yyyy-MM-dd HH:mm:ss"` |
| `cs_status` | Integer | 客满介入状态:`1`(客满未介入)`2`(客满介入中) |
| `delivery_status` | Integer | 发货状态:`1`(未发货)`2`(已发货) |
---
## 5. ⚠️ 开发者防坑指南与注意事项(核心对账与排错必看)
1. **版本升级核心变化 (`yz_open_id` 替代 `buyer_id`)**
`3.0.1` 最新版本中,废弃了原有的 `buyer_id`,全面拥抱 **`yz_open_id`** 作为用户的全网唯一标识。在进行 CRM 对账或跨接口(如用户详情查询接口)数据互通时,必须使用 `yz_open_id`
2. **时间戳参数单位陷阱(必须是秒)**
有赞的大多数接口时间戳为 13位毫秒级但是**该版本接口明确标注 `create_time_start` / `update_time_end` 等字段的单位为10位**
如果错误传入了 13 位时间戳,会导致报错或过滤结果为空。
3. **ES 搜索引擎的深度翻页限制(报错码 53002**
受限于底层 Elasticsearch 架构,请严格遵守以下分页限制,否则会报错 `page_size type error` 或导致接口熔断:
* **`page_no` 不能大于 100**。
* **`page_no * page_size` 乘积不能超过 3000**。
* **排错方案**:大店单据多时,**绝不可用大分页数无脑遍历**。请按更新时间将范围切分得更细(如每次只查 1 小时的数据),来保持总条数低于限制阈值。
4. **单据默认时间范围3 个月内)**
如果您在请求时不加任何时间限制直接查询,系统会自动添加默认过滤条件,仅返回最近 3 个月创建的退款单。对于旧账对账或初始化历史数据同步,务必显式传入准确的时间范围边界。
5. **网点/门店单据的隔离(`node_kdt_id`**
如果是连锁商家总部进行数据拉取,通过总部的 Token 默认只能拉取总部的单据。必须通过循环传递 `node_kdt_id` 才能精准拉取到各分店发生的维权与退款记录,切勿遗漏导致财务对账不平。