797 lines
26 KiB
Markdown
797 lines
26 KiB
Markdown
# 第三方订单对接文档
|
||
|
||
版本:v1.3
|
||
更新日期:2026-06-18
|
||
|
||
## 1. 对接说明
|
||
|
||
本文档用于第三方系统对接安心验开放接口。第三方推送订单时,最小只需要提供第三方自己的订单号 `external_order_no`。如第三方已具备服务套餐、物品信息、寄回地址、鉴定资料或寄入物流,也可以在创建订单时一并传入,平台会直接落入订单资料,减少后续人工补录。
|
||
|
||
接口域名以实际环境为准,本文统一使用:
|
||
|
||
```text
|
||
https://{api-domain}
|
||
```
|
||
|
||
## 2. 凭证与安全
|
||
|
||
平台会为每个对接方分配:
|
||
|
||
| 参数 | 说明 |
|
||
| --- | --- |
|
||
| `app_key` | 调用方身份标识 |
|
||
| `app_secret` | 签名密钥,请妥善保管,不要传给前端或泄露到日志中 |
|
||
|
||
所有开放接口都需要签名。请求必须使用 HTTPS,并携带以下请求头:
|
||
|
||
| Header | 必填 | 说明 |
|
||
| --- | --- | --- |
|
||
| `Content-Type` | 是 | 固定为 `application/json` |
|
||
| `X-AXY-App-Key` | 是 | 平台分配的 `app_key` |
|
||
| `X-AXY-Timestamp` | 是 | Unix 秒级时间戳,有效期 300 秒 |
|
||
| `X-AXY-Nonce` | 是 | 随机字符串,同一个 `app_key` 下不可重复使用 |
|
||
| `X-AXY-Signature` | 是 | 请求签名 |
|
||
|
||
### 2.1 签名算法
|
||
|
||
签名使用 HMAC-SHA256,小写十六进制输出。
|
||
|
||
```text
|
||
body_hash = sha256(raw_body)
|
||
base = UPPERCASE_HTTP_METHOD + path_with_query + timestamp + nonce + body_hash
|
||
signature = hex_hmac_sha256(base, app_secret)
|
||
```
|
||
|
||
字段说明:
|
||
|
||
| 字段 | 说明 |
|
||
| --- | --- |
|
||
| `raw_body` | 原始请求体字符串。GET 请求没有请求体时为空字符串 |
|
||
| `path_with_query` | 请求路径加查询字符串,例如 `/api/open/v1/orders?external_order_no=T202605080001` |
|
||
| `timestamp` | 与 `X-AXY-Timestamp` 完全一致 |
|
||
| `nonce` | 与 `X-AXY-Nonce` 完全一致 |
|
||
|
||
注意事项:
|
||
|
||
- `path_with_query` 必须与实际请求完全一致,包括查询参数顺序和 URL 编码。
|
||
- POST 请求签名时使用实际发送的 JSON 字符串,不要签名一个格式化版本、发送另一个压缩版本。
|
||
- GET 请求的 `body_hash` 为 `sha256("")`。
|
||
- `nonce` 会做防重放校验,重试请求需要重新生成 `nonce` 和签名。
|
||
|
||
### 2.2 Node.js 签名示例
|
||
|
||
```js
|
||
import crypto from 'node:crypto';
|
||
|
||
function sign({ method, pathWithQuery, body = '', timestamp, nonce, appSecret }) {
|
||
const bodyHash = crypto.createHash('sha256').update(body).digest('hex');
|
||
const base = method.toUpperCase() + pathWithQuery + timestamp + nonce + bodyHash;
|
||
return crypto.createHmac('sha256', appSecret).update(base).digest('hex');
|
||
}
|
||
```
|
||
|
||
### 2.3 PHP 签名示例
|
||
|
||
```php
|
||
function sign_request(string $method, string $pathWithQuery, string $body, string $timestamp, string $nonce, string $appSecret): string
|
||
{
|
||
$bodyHash = hash('sha256', $body);
|
||
$base = strtoupper($method) . $pathWithQuery . $timestamp . $nonce . $bodyHash;
|
||
return hash_hmac('sha256', $base, $appSecret);
|
||
}
|
||
```
|
||
|
||
## 3. 通用响应格式
|
||
|
||
成功响应:
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "ok",
|
||
"data": {}
|
||
}
|
||
```
|
||
|
||
失败响应:
|
||
|
||
```json
|
||
{
|
||
"code": 422,
|
||
"message": "external_order_no 不能为空",
|
||
"data": {}
|
||
}
|
||
```
|
||
|
||
常见错误码:
|
||
|
||
| code | 说明 |
|
||
| --- | --- |
|
||
| `401` | 鉴权失败、签名错误、时间戳过期、`nonce` 重复 |
|
||
| `404` | 订单不存在 |
|
||
| `409` | 幂等冲突,例如同一个 `external_order_no` 请求内容不一致 |
|
||
| `422` | 请求参数不合法 |
|
||
| `500` | 服务端处理失败 |
|
||
|
||
## 4. 套餐获取
|
||
|
||
第三方创建订单前,可以先调用本接口获取当前可用服务套餐和价格,再将返回的 `price_package_code` 传入创建订单接口。
|
||
|
||
```text
|
||
GET /api/open/v1/service-price-packages
|
||
```
|
||
|
||
### 4.1 查询参数
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `service_provider` | string | 否 | 服务方,可选 `anxinyan`、`zhongjian`;不传返回全部服务方启用套餐 |
|
||
|
||
### 4.2 cURL 示例
|
||
|
||
```bash
|
||
curl -X GET 'https://{api-domain}/api/open/v1/service-price-packages?service_provider=anxinyan' \
|
||
-H 'Content-Type: application/json' \
|
||
-H 'X-AXY-App-Key: your_app_key' \
|
||
-H 'X-AXY-Timestamp: 1715155200' \
|
||
-H 'X-AXY-Nonce: random_nonce' \
|
||
-H 'X-AXY-Signature: calculated_signature'
|
||
```
|
||
|
||
GET 请求参与签名的 `raw_body` 为空字符串,`path_with_query` 需要包含实际查询字符串。
|
||
|
||
### 4.3 成功响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "ok",
|
||
"data": {
|
||
"service_providers": [
|
||
{
|
||
"service_provider": "anxinyan",
|
||
"service_provider_text": "安心验鉴定",
|
||
"sla_hours": 48,
|
||
"default_price_package_code": "anxinyan_basic",
|
||
"packages": [
|
||
{
|
||
"service_provider": "anxinyan",
|
||
"service_provider_text": "安心验鉴定",
|
||
"price_package_name": "安心验基础套餐",
|
||
"price_package_code": "anxinyan_basic",
|
||
"price_package_price": 99,
|
||
"description": "默认服务价格套餐",
|
||
"is_default": true,
|
||
"sla_hours": 48
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.4 响应说明
|
||
|
||
- 接口只返回启用套餐,不返回停用套餐。
|
||
- `price_package_code` 可直接作为创建订单接口的 `price_package_code` 参数。
|
||
- `default_price_package_code` 表示该服务方当前默认套餐;创建订单不传 `price_package_code` 时,平台会使用当前服务方默认启用套餐。
|
||
|
||
## 5. 仓库地址列表
|
||
|
||
第三方创建订单或通知寄入物流前,可以调用本接口获取当前可寄送的安心验仓库地址列表。
|
||
|
||
```text
|
||
GET /api/open/v1/warehouses
|
||
```
|
||
|
||
### 5.1 查询参数
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `service_provider` | string | 否 | 服务方,可选 `anxinyan`、`zhongjian`;不传返回全部启用仓库 |
|
||
|
||
### 5.2 cURL 示例
|
||
|
||
```bash
|
||
curl -X GET 'https://{api-domain}/api/open/v1/warehouses?service_provider=anxinyan' \
|
||
-H 'Content-Type: application/json' \
|
||
-H 'X-AXY-App-Key: your_app_key' \
|
||
-H 'X-AXY-Timestamp: 1778227200' \
|
||
-H 'X-AXY-Nonce: random_nonce' \
|
||
-H 'X-AXY-Signature: calculated_signature'
|
||
```
|
||
|
||
GET 请求参与签名的 `raw_body` 为空字符串,`path_with_query` 需要包含实际查询字符串。
|
||
|
||
### 5.3 成功响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "ok",
|
||
"data": {
|
||
"warehouses": [
|
||
{
|
||
"id": 1,
|
||
"warehouse_name": "安心验鉴定中心",
|
||
"warehouse_code": "AXY-WH-DEFAULT",
|
||
"service_provider": "anxinyan",
|
||
"service_provider_text": "实物鉴定",
|
||
"receiver_name": "安心验鉴定中心",
|
||
"receiver_mobile": "400-800-1314",
|
||
"province": "广东省",
|
||
"city": "深圳市",
|
||
"district": "南山区",
|
||
"detail_address": "科技园鉴定路 88 号 安心验收件中心",
|
||
"full_address": "广东省深圳市南山区科技园鉴定路 88 号 安心验收件中心",
|
||
"service_time": "周一至周日 09:30-18:30",
|
||
"notice": "寄送前请确认订单信息完整,包裹内附上订单号可提升签收后的处理效率。",
|
||
"supported_category_ids": [],
|
||
"supported_category_names": [],
|
||
"service_area_provinces": [],
|
||
"service_area_cities": [],
|
||
"is_default": true,
|
||
"sort_order": 1
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 5.4 响应说明
|
||
|
||
- 接口只返回启用仓库,不返回停用仓库。
|
||
- `warehouse_code` 可用于第三方系统识别仓库;寄件时请以接口返回的收件人、手机号和地址为准。
|
||
- `supported_category_ids`、`service_area_provinces`、`service_area_cities` 为空数组时表示不限制对应条件。
|
||
- 响应不包含后台备注、启停状态和创建更新时间等内部管理字段。
|
||
|
||
## 6. 创建订单
|
||
|
||
```text
|
||
POST /api/open/v1/orders
|
||
```
|
||
|
||
第三方创建订单时,最小只需要传 `external_order_no`。平台会创建一笔待寄送商品订单;如请求中包含套餐、物品、地址、资料或寄入物流,平台会同步写入订单主表、商品资料、寄回地址、初始鉴定资料和寄入物流记录。
|
||
|
||
### 6.1 请求参数
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `external_order_no` | string | 是 | 第三方订单号。同一对接客户下必须唯一 |
|
||
| `service_provider` | string | 否 | 服务方,可选 `anxinyan`、`zhongjian`,默认 `anxinyan` |
|
||
| `price_package_code` | string | 否 | 服务价格套餐编码,可通过套餐获取接口取得;不传时使用当前服务方的默认启用套餐;传入无效或已停用编码时返回 `422` |
|
||
| `product_info` | object | 否 | 物品信息。不传时订单会保留待完善物品信息 |
|
||
| `materials` | array | 否 | 鉴定资料图片 URL 列表或资料对象列表。不传时不会生成初始资料文件 |
|
||
| `return_address` | object | 否 | 寄回地址。不传时后续由平台或用户补充;如传任一地址字段,则必填完整地址 |
|
||
| `inbound_logistics` | object | 否 | 寄入物流信息。不传时后续可由入库台按订单号、鉴定单号或外部订单号匹配入库 |
|
||
| `express_company` | string | 否 | 寄入快递公司,可替代 `inbound_logistics.express_company` |
|
||
| `tracking_no` | string | 否 | 寄入运单号,可替代 `inbound_logistics.tracking_no` |
|
||
| `extra_info` | object | 否 | 购买、成色、附件、备注等扩展信息 |
|
||
|
||
### 6.2 单独设置寄回地址
|
||
|
||
```text
|
||
POST /api/open/v1/orders/return-address
|
||
```
|
||
|
||
第三方可以在建单后单独补录或更新寄回地址。订单已生成回寄运单后,不允许再修改。
|
||
|
||
### 6.3 请求参数
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `external_order_no` | string | 是 | 第三方订单号 |
|
||
| `return_address` | object | 是 | 寄回地址,字段要求同创建订单接口 |
|
||
|
||
### 6.4 请求示例
|
||
|
||
```json
|
||
{
|
||
"external_order_no": "THIRD202605080001",
|
||
"return_address": {
|
||
"consignee": "张三",
|
||
"mobile": "13800138000",
|
||
"province": "浙江省",
|
||
"city": "杭州市",
|
||
"district": "西湖区",
|
||
"detail_address": "文三路 1 号"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.5 可选对象字段
|
||
|
||
`product_info` 支持:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `category_id` | integer | 否 | 平台品类 ID。第三方无法确定 ID 时可不传 |
|
||
| `category_name` | string | 否 | 品类名称 |
|
||
| `brand_id` | integer | 否 | 平台品牌 ID。第三方无法确定 ID 时可不传 |
|
||
| `brand_name` | string | 否 | 品牌名称 |
|
||
| `product_name` | string | 否 | 商品名称;不传时平台会尝试用品牌和品类拼接展示 |
|
||
| `color` | string | 否 | 颜色 |
|
||
| `size_spec` | string | 否 | 规格或尺寸 |
|
||
| `serial_no` | string | 否 | 序列号、刻印号或其他唯一标识 |
|
||
|
||
`return_address` 支持:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `consignee` | string | 条件必填 | 收件人 |
|
||
| `mobile` | string | 条件必填 | 手机号 |
|
||
| `province` | string | 条件必填 | 省份 |
|
||
| `city` | string | 条件必填 | 城市 |
|
||
| `district` | string | 条件必填 | 区县 |
|
||
| `detail_address` | string | 条件必填 | 详细地址 |
|
||
|
||
只要 `return_address` 中任意字段有值,上述字段都必须完整填写。
|
||
|
||
`materials` 支持两种格式:
|
||
|
||
```json
|
||
[
|
||
"https://example.com/item-front.jpg",
|
||
{
|
||
"item_code": "front",
|
||
"item_name": "商品正面图",
|
||
"file_url": "https://example.com/item-front.jpg",
|
||
"thumbnail_url": "https://example.com/item-front-thumb.jpg",
|
||
"is_required": true
|
||
}
|
||
]
|
||
```
|
||
|
||
资料文件当前只支持 `http` 或 `https` 图片 URL。对象格式中 `file_url` 与 `url` 等价;`thumbnail_url` 不传时默认使用原图 URL。
|
||
|
||
`extra_info` 支持:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `purchase_channel` | string | 否 | 购买渠道 |
|
||
| `purchase_price` | number | 否 | 购买价格 |
|
||
| `purchase_date` | string | 否 | 购买日期,建议格式 `YYYY-MM-DD` |
|
||
| `usage_status` | string | 否 | 使用状态 |
|
||
| `condition_desc` | string | 否 | 成色描述 |
|
||
| `has_accessories` | boolean | 否 | 是否有附件 |
|
||
| `accessories` | array | 否 | 附件列表 |
|
||
| `remark` | string | 否 | 备注 |
|
||
|
||
`inbound_logistics` 支持:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `express_company` | string | 成对填写 | 寄入快递公司 |
|
||
| `tracking_no` | string | 成对填写 | 寄入运单号 |
|
||
|
||
如果希望创建订单时同步写入寄入物流,需要同时提供快递公司和运单号。也可以直接使用顶层 `express_company` 和 `tracking_no`,含义与 `inbound_logistics` 内字段一致。
|
||
|
||
### 6.6 最小请求示例
|
||
|
||
```json
|
||
{
|
||
"external_order_no": "THIRD202605080001"
|
||
}
|
||
```
|
||
|
||
### 6.7 带可选字段请求示例
|
||
|
||
```json
|
||
{
|
||
"external_order_no": "THIRD202605080002",
|
||
"service_provider": "anxinyan",
|
||
"price_package_code": "anxinyan_basic",
|
||
"product_info": {
|
||
"category_name": "箱包",
|
||
"brand_name": "CHANEL",
|
||
"product_name": "Classic Flap 手袋",
|
||
"color": "黑色",
|
||
"size_spec": "中号",
|
||
"serial_no": "A12345678"
|
||
},
|
||
"inbound_logistics": {
|
||
"express_company": "顺丰速运",
|
||
"tracking_no": "SF1234567890"
|
||
},
|
||
"return_address": {
|
||
"consignee": "张三",
|
||
"mobile": "13800138000",
|
||
"province": "浙江省",
|
||
"city": "杭州市",
|
||
"district": "西湖区",
|
||
"detail_address": "文三路 1 号"
|
||
},
|
||
"materials": [
|
||
{
|
||
"item_code": "front",
|
||
"item_name": "商品正面图",
|
||
"file_url": "https://example.com/materials/front.jpg",
|
||
"thumbnail_url": "https://example.com/materials/front-thumb.jpg",
|
||
"is_required": true
|
||
}
|
||
],
|
||
"extra_info": {
|
||
"purchase_channel": "专柜",
|
||
"purchase_price": 68000,
|
||
"purchase_date": "2026-06-01",
|
||
"usage_status": "轻微使用",
|
||
"condition_desc": "外观轻微使用痕迹",
|
||
"has_accessories": true,
|
||
"accessories": ["防尘袋", "盒子"],
|
||
"remark": "第三方同步订单"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.8 cURL 示例
|
||
|
||
```bash
|
||
curl -X POST 'https://{api-domain}/api/open/v1/orders' \
|
||
-H 'Content-Type: application/json' \
|
||
-H 'X-AXY-App-Key: your_app_key' \
|
||
-H 'X-AXY-Timestamp: 1778227200' \
|
||
-H 'X-AXY-Nonce: 7b7b2a2f9c9e4d1f' \
|
||
-H 'X-AXY-Signature: calculated_signature' \
|
||
-d '{"external_order_no":"THIRD202605080001"}'
|
||
```
|
||
|
||
### 6.9 成功响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "订单已创建",
|
||
"data": {
|
||
"idempotent": false,
|
||
"order": {
|
||
"customer_id": "CUST001",
|
||
"customer_code": "CUST001",
|
||
"external_order_no": "THIRD202605080001",
|
||
"order_id": 123,
|
||
"order_no": "AXY20260508120000123",
|
||
"appraisal_no": "AXY-APP-20260508-1001",
|
||
"order_status": "pending_shipping",
|
||
"display_status": "待寄送商品",
|
||
"payment_status": "paid",
|
||
"price_package_name": "安心验基础套餐",
|
||
"price_package_code": "anxinyan_basic",
|
||
"price_package_price": 99,
|
||
"pay_amount": 99,
|
||
"estimated_finish_time": "2026-05-09 12:00:00",
|
||
"created_at": "2026-05-08 12:00:00",
|
||
"timeline": [
|
||
{
|
||
"node_code": "created",
|
||
"node_text": "下单成功",
|
||
"node_desc": "大客户订单已推送并创建成功",
|
||
"occurred_at": "2026-05-08 12:00:00"
|
||
},
|
||
{
|
||
"node_code": "pending_shipping",
|
||
"node_text": "待寄送商品",
|
||
"node_desc": "请将商品寄送至鉴定中心",
|
||
"occurred_at": "2026-05-08 12:00:00"
|
||
}
|
||
],
|
||
"inbound_logistics": null,
|
||
"return_logistics": null,
|
||
"report_summary": null
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.10 幂等规则
|
||
|
||
同一个对接客户下,`external_order_no` 作为幂等键:
|
||
|
||
- 第一次请求会创建订单。
|
||
- 后续使用相同 `external_order_no` 且请求内容一致时,不会重复创建订单,会返回已有订单,`data.idempotent` 为 `true`。
|
||
- 后续使用相同 `external_order_no` 但请求内容不一致时,返回 `409`。
|
||
- 如第一次只传最小字段,后续不能再用同一个 `external_order_no` 重推补充字段;如需补充资料,应走平台补录、入库或补料流程。
|
||
|
||
建议第三方重试创建订单时保持请求 JSON 内容一致,仅重新生成 `timestamp`、`nonce` 和 `signature`。
|
||
|
||
## 7. 查询订单
|
||
|
||
支持按第三方订单号或平台订单号查询订单进度。
|
||
|
||
### 7.1 按第三方订单号查询
|
||
|
||
```text
|
||
GET /api/open/v1/orders/{external_order_no}
|
||
```
|
||
|
||
示例:
|
||
|
||
```bash
|
||
curl -X GET 'https://{api-domain}/api/open/v1/orders/THIRD202605080001' \
|
||
-H 'Content-Type: application/json' \
|
||
-H 'X-AXY-App-Key: your_app_key' \
|
||
-H 'X-AXY-Timestamp: 1778227200' \
|
||
-H 'X-AXY-Nonce: f0f74a6baf764d8f' \
|
||
-H 'X-AXY-Signature: calculated_signature'
|
||
```
|
||
|
||
### 7.2 通过查询参数查询
|
||
|
||
```text
|
||
GET /api/open/v1/orders?external_order_no=THIRD202605080001
|
||
GET /api/open/v1/orders?order_no=AXY20260508120000123
|
||
```
|
||
|
||
### 7.3 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "ok",
|
||
"data": {
|
||
"order": {
|
||
"customer_id": "CUST001",
|
||
"customer_code": "CUST001",
|
||
"external_order_no": "THIRD202605080001",
|
||
"order_id": 123,
|
||
"order_no": "AXY20260508120000123",
|
||
"appraisal_no": "AXY-APP-20260508-1001",
|
||
"order_status": "report_published",
|
||
"display_status": "报告已发布",
|
||
"payment_status": "paid",
|
||
"price_package_name": "安心验基础套餐",
|
||
"price_package_code": "anxinyan_basic",
|
||
"price_package_price": 99,
|
||
"pay_amount": 99,
|
||
"estimated_finish_time": "2026-05-09 12:00:00",
|
||
"created_at": "2026-05-08 12:00:00",
|
||
"timeline": [],
|
||
"inbound_logistics": {
|
||
"express_company": "顺丰速运",
|
||
"tracking_no": "SF1234567890",
|
||
"tracking_status": "submitted",
|
||
"latest_desc": "客户已提交寄送运单:顺丰速运 SF1234567890,等待鉴定中心签收。",
|
||
"latest_time": "2026-05-08 12:00:00"
|
||
},
|
||
"return_address": {
|
||
"consignee": "张三",
|
||
"mobile": "13800138000",
|
||
"province": "浙江省",
|
||
"city": "杭州市",
|
||
"district": "西湖区",
|
||
"detail_address": "文三路 1 号",
|
||
"full_address": "浙江省杭州市西湖区文三路 1 号"
|
||
},
|
||
"return_logistics": null,
|
||
"report_summary": {
|
||
"report_no": "R202605080001",
|
||
"report_title": "鉴定报告",
|
||
"report_status": "published",
|
||
"publish_time": "2026-05-08 18:00:00",
|
||
"verify_url": "https://{h5-domain}/verify?id=xxx",
|
||
"report_page_url": "https://{h5-domain}/report/xxx",
|
||
"verify_status": "valid"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 8. 取消订单
|
||
|
||
第三方订单尚未寄送前,可以调用本接口取消订单。取消成功后订单状态变为 `cancelled`,后台待处理鉴定任务会同步移除。
|
||
|
||
```text
|
||
POST /api/open/v1/orders/cancel
|
||
```
|
||
|
||
### 8.1 请求参数
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `external_order_no` | string | 是 | 第三方订单号。只能取消当前 `app_key` 所属客户下的订单 |
|
||
| `cancel_reason` | string | 否 | 取消原因,最长 255 个字符 |
|
||
|
||
### 8.2 请求示例
|
||
|
||
```json
|
||
{
|
||
"external_order_no": "THIRD202606160001",
|
||
"cancel_reason": "客户取消鉴定"
|
||
}
|
||
```
|
||
|
||
### 8.3 成功响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "订单已取消",
|
||
"data": {
|
||
"cancelled": true,
|
||
"order": {
|
||
"customer_id": "CUST001",
|
||
"customer_code": "CUST001",
|
||
"external_order_no": "THIRD202606160001",
|
||
"order_no": "AXY20260616120000123",
|
||
"order_status": "cancelled",
|
||
"display_status": "已取消",
|
||
"payment_status": "paid",
|
||
"timeline": [
|
||
{
|
||
"node_code": "cancelled",
|
||
"node_text": "订单已取消",
|
||
"node_desc": "第三方客户取消订单:客户取消鉴定",
|
||
"occurred_at": "2026-06-16 12:00:00"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 8.4 取消规则
|
||
|
||
- 仅 `pending_shipping` 且尚未提交寄入运单的订单允许取消。
|
||
- 创建订单时已传 `inbound_logistics`,或已调用发货通知接口提交 `express_company`、`tracking_no` 的订单不允许取消,返回 `422`。
|
||
- 已到仓、鉴定中、补料中、已出报告、已完成等状态不允许取消,返回 `422`。
|
||
- 找不到当前客户下的 `external_order_no` 时返回 `404`。
|
||
- 重复取消已取消订单会返回成功,`data.cancelled` 为 `false`,不会重复写入取消时间线。
|
||
- 取消接口不触发 webhook 回调;调用方以接口响应或订单查询结果为准。
|
||
|
||
## 9. 发货通知
|
||
|
||
第三方在商品实际寄出后,可以调用本接口通知平台写入寄入物流。创建订单接口中的 `inbound_logistics` 仍然可用;但如果订单创建和商品寄出不是同一时点,建议创建订单时只建单,实际寄出后再调用本接口提交快递信息。
|
||
|
||
```text
|
||
POST /api/open/v1/orders/shipping
|
||
```
|
||
|
||
### 9.1 请求参数
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `external_order_no` | string | 是 | 第三方订单号。只能提交当前 `app_key` 所属客户下的订单 |
|
||
| `express_company` | string | 是 | 寄入快递公司 |
|
||
| `tracking_no` | string | 是 | 寄入运单号 |
|
||
|
||
### 9.2 请求示例
|
||
|
||
```json
|
||
{
|
||
"external_order_no": "THIRD202606110001",
|
||
"express_company": "顺丰速运",
|
||
"tracking_no": "SF1234567890"
|
||
}
|
||
```
|
||
|
||
### 9.3 成功响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "运单已提交",
|
||
"data": {
|
||
"idempotent": false,
|
||
"updated": false,
|
||
"logistics": {
|
||
"express_company": "顺丰速运",
|
||
"tracking_no": "SF1234567890",
|
||
"tracking_status": "submitted",
|
||
"latest_desc": "客户已提交寄送运单:顺丰速运 SF1234567890,等待鉴定中心签收。",
|
||
"latest_time": "2026-06-11 12:00:00"
|
||
},
|
||
"order": {
|
||
"customer_id": "CUST001",
|
||
"customer_code": "CUST001",
|
||
"external_order_no": "THIRD202606110001",
|
||
"order_no": "AXY20260611120000123",
|
||
"order_status": "pending_shipping",
|
||
"display_status": "已提交运单",
|
||
"inbound_logistics": {
|
||
"express_company": "顺丰速运",
|
||
"tracking_no": "SF1234567890",
|
||
"tracking_status": "submitted",
|
||
"latest_desc": "客户已提交寄送运单:顺丰速运 SF1234567890,等待鉴定中心签收。",
|
||
"latest_time": "2026-06-11 12:00:00"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 9.4 重复提交规则
|
||
|
||
- 相同 `external_order_no`、`express_company`、`tracking_no` 重复提交时,接口返回成功,`idempotent` 为 `true`,不会重复写物流节点或订单时间线。
|
||
- 同一订单在 `pending_shipping` 状态下提交不同快递公司或运单号时,会更新最新一条寄入物流,`updated` 为 `true`,并追加“已更新运单”时间线。
|
||
- 非 `pending_shipping` 状态的订单不允许提交或更新寄入运单,返回 `422`。
|
||
- 找不到当前客户下的 `external_order_no` 时返回 `404`。
|
||
|
||
## 10. 订单状态
|
||
|
||
常见订单状态如下,最终以接口返回的 `order_status` 和 `display_status` 为准。
|
||
|
||
| order_status | display_status | 说明 |
|
||
| --- | --- | --- |
|
||
| `pending_shipping` | 待寄送商品 / 已提交运单 | 订单已创建,等待物品到仓或人工确认收货 |
|
||
| `received` | 鉴定中心已收货 | 物品已到仓 |
|
||
| `appraising` | 物品鉴定中 | 鉴定师正在鉴定 |
|
||
| `generating_report` | 物品鉴定完成 | 鉴定完成,报告生成中 |
|
||
| `report_published` | 报告已发布 | 报告已发布,可查看报告摘要 |
|
||
| `return_shipped` | 物品已寄回 | 物品已退回寄出 |
|
||
| `completed` | 已完成 | 订单完成 |
|
||
| `pending_supplement` | 需要补充资料 | 需要补充资料 |
|
||
| `cancelled` | 已取消 | 订单已取消 |
|
||
|
||
## 11. Webhook 事件回调
|
||
|
||
如需接收订单状态变化通知,第三方需向平台提供可公网访问的 `webhook_url`,并由平台开启回调。
|
||
|
||
平台会以 POST JSON 方式推送事件:
|
||
|
||
| Header | 说明 |
|
||
| --- | --- |
|
||
| `Content-Type` | `application/json` |
|
||
| `X-AXY-App-Key` | 平台分配给该客户的 `app_key` |
|
||
|
||
当前 webhook 仅携带 `X-AXY-App-Key`,暂未实现回调签名。如第三方需要回调验签,可与平台另行约定后升级。
|
||
|
||
回调超时时间:
|
||
|
||
| 项目 | 值 |
|
||
| --- | --- |
|
||
| 连接超时 | 3 秒 |
|
||
| 总超时 | 6 秒 |
|
||
| 成功判定 | HTTP 状态码为 2xx 且无网络错误 |
|
||
|
||
### 11.1 回调报文
|
||
|
||
```json
|
||
{
|
||
"event_code": "order_created",
|
||
"event_text": "订单创建",
|
||
"customer_id": "CUST001",
|
||
"customer_code": "CUST001",
|
||
"external_order_no": "THIRD202605080001",
|
||
"order_no": "AXY20260508120000123",
|
||
"appraisal_no": "AXY-APP-20260508-1001",
|
||
"status_code": "pending_shipping",
|
||
"status_text": "待寄送商品",
|
||
"occurred_at": "2026-05-08 12:00:00",
|
||
"data": {},
|
||
"event_id": 1
|
||
}
|
||
```
|
||
|
||
### 11.2 事件类型
|
||
|
||
| event_code | event_text | status_code | status_text |
|
||
| --- | --- | --- | --- |
|
||
| `order_created` | 订单创建 | `pending_shipping` | 待寄送商品 |
|
||
| `inbound_received` | 快递已到仓 | `received` | 鉴定中心已收货 |
|
||
| `appraising` | 物品鉴定中 | `appraising` | 物品鉴定中 |
|
||
| `appraisal_finished` | 物品鉴定完成 | `generating_report` | 物品鉴定完成 |
|
||
| `report_published` | 报告已发布 | `report_published` | 报告已发布 |
|
||
| `return_shipped` | 物品已寄回 | `return_shipped` | 物品已寄回 |
|
||
| `completed` | 订单已完成 | `completed` | 已完成 |
|
||
| `supplement_required` | 需要补充资料 | `pending_supplement` | 需要补充资料 |
|
||
|
||
### 11.3 回调接收建议
|
||
|
||
第三方接收 webhook 时建议:
|
||
|
||
- 使用 `event_id` 做事件幂等,避免重复处理。
|
||
- 收到事件后返回 HTTP 2xx。
|
||
- 如需强一致的最新状态,可以收到 webhook 后再调用订单查询接口确认。
|
||
|
||
## 12. 对接流程建议
|
||
|
||
1. 平台分配 `app_key` 和 `app_secret`。
|
||
2. 第三方完成签名调试。
|
||
3. 第三方调用套餐获取接口,确认可用套餐和 `price_package_code`。
|
||
4. 第三方调用创建订单接口。最小只传 `external_order_no` 即可;如需要减少后续人工补录,建议同步传 `price_package_code`、`product_info`、`return_address`、`materials` 和 `inbound_logistics`。
|
||
5. 如订单尚未寄送且需要取消,可调用取消订单接口;已提交寄入物流后不再支持取消。
|
||
6. 如建单时未提供寄回地址,或后续需要变更,可调用寄回地址接口补录或更新 `return_address`。
|
||
7. 商品实际寄出后,第三方调用发货通知接口提交 `express_company` 和 `tracking_no`。
|
||
8. 第三方可通过查询接口主动查询订单状态,并核对 `return_address`、物流和报告结果。
|
||
9. 如启用 webhook,平台在订单状态变化时主动通知第三方。
|