21 KiB
第三方订单对接文档
版本:v1.1 更新日期:2026-06-11
1. 对接说明
本文档用于第三方系统对接安心验开放接口。第三方推送订单时,最小只需要提供第三方自己的订单号 external_order_no。如第三方已具备服务套餐、物品信息、寄回地址、鉴定资料或寄入物流,也可以在创建订单时一并传入,平台会直接落入订单资料,减少后续人工补录。
接口域名以实际环境为准,本文统一使用:
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,小写十六进制输出。
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 签名示例
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 签名示例
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. 通用响应格式
成功响应:
{
"code": 0,
"message": "ok",
"data": {}
}
失败响应:
{
"code": 422,
"message": "external_order_no 不能为空",
"data": {}
}
常见错误码:
| code | 说明 |
|---|---|
401 |
鉴权失败、签名错误、时间戳过期、nonce 重复 |
404 |
订单不存在 |
409 |
幂等冲突,例如同一个 external_order_no 请求内容不一致 |
422 |
请求参数不合法 |
500 |
服务端处理失败 |
4. 套餐获取
第三方创建订单前,可以先调用本接口获取当前可用服务套餐和价格,再将返回的 price_package_code 传入创建订单接口。
GET /api/open/v1/service-price-packages
4.1 查询参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
service_provider |
string | 否 | 服务方,可选 anxinyan、zhongjian;不传返回全部服务方启用套餐 |
4.2 cURL 示例
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 成功响应示例
{
"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. 创建订单
POST /api/open/v1/orders
第三方创建订单时,最小只需要传 external_order_no。平台会创建一笔待寄送商品订单;如请求中包含套餐、物品、地址、资料或寄入物流,平台会同步写入订单主表、商品资料、寄回地址、初始鉴定资料和寄入物流记录。
5.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 | 否 | 购买、成色、附件、备注等扩展信息 |
5.2 可选对象字段
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 支持两种格式:
[
"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 内字段一致。
5.3 最小请求示例
{
"external_order_no": "THIRD202605080001"
}
5.4 带可选字段请求示例
{
"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": "第三方同步订单"
}
}
5.5 cURL 示例
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"}'
5.6 成功响应示例
{
"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
}
}
}
5.7 幂等规则
同一个对接客户下,external_order_no 作为幂等键:
- 第一次请求会创建订单。
- 后续使用相同
external_order_no且请求内容一致时,不会重复创建订单,会返回已有订单,data.idempotent为true。 - 后续使用相同
external_order_no但请求内容不一致时,返回409。 - 如第一次只传最小字段,后续不能再用同一个
external_order_no重推补充字段;如需补充资料,应走平台补录、入库或补料流程。
建议第三方重试创建订单时保持请求 JSON 内容一致,仅重新生成 timestamp、nonce 和 signature。
6. 查询订单
支持按第三方订单号或平台订单号查询订单进度。
6.1 按第三方订单号查询
GET /api/open/v1/orders/{external_order_no}
示例:
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'
6.2 通过查询参数查询
GET /api/open/v1/orders?external_order_no=THIRD202605080001
GET /api/open/v1/orders?order_no=AXY20260508120000123
6.3 响应示例
{
"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_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"
}
}
}
}
7. 发货通知
第三方在商品实际寄出后,可以调用本接口通知平台写入寄入物流。创建订单接口中的 inbound_logistics 仍然可用;但如果订单创建和商品寄出不是同一时点,建议创建订单时只建单,实际寄出后再调用本接口提交快递信息。
POST /api/open/v1/orders/shipping
7.1 请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
external_order_no |
string | 是 | 第三方订单号。只能提交当前 app_key 所属客户下的订单 |
express_company |
string | 是 | 寄入快递公司 |
tracking_no |
string | 是 | 寄入运单号 |
7.2 请求示例
{
"external_order_no": "THIRD202606110001",
"express_company": "顺丰速运",
"tracking_no": "SF1234567890"
}
7.3 成功响应示例
{
"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"
}
}
}
}
7.4 重复提交规则
- 相同
external_order_no、express_company、tracking_no重复提交时,接口返回成功,idempotent为true,不会重复写物流节点或订单时间线。 - 同一订单在
pending_shipping状态下提交不同快递公司或运单号时,会更新最新一条寄入物流,updated为true,并追加“已更新运单”时间线。 - 非
pending_shipping状态的订单不允许提交或更新寄入运单,返回422。 - 找不到当前客户下的
external_order_no时返回404。
8. 订单状态
常见订单状态如下,最终以接口返回的 order_status 和 display_status 为准。
| order_status | display_status | 说明 |
|---|---|---|
pending_shipping |
待寄送商品 / 已提交运单 | 订单已创建,等待物品到仓或人工确认收货 |
received |
鉴定中心已收货 | 物品已到仓 |
appraising |
物品鉴定中 | 鉴定师正在鉴定 |
generating_report |
物品鉴定完成 | 鉴定完成,报告生成中 |
report_published |
报告已发布 | 报告已发布,可查看报告摘要 |
return_shipped |
物品已寄回 | 物品已退回寄出 |
completed |
已完成 | 订单完成 |
pending_supplement |
需要补充资料 | 需要补充资料 |
9. 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 且无网络错误 |
9.1 回调报文
{
"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
}
9.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 |
需要补充资料 |
9.3 回调接收建议
第三方接收 webhook 时建议:
- 使用
event_id做事件幂等,避免重复处理。 - 收到事件后返回 HTTP 2xx。
- 如需强一致的最新状态,可以收到 webhook 后再调用订单查询接口确认。
10. 对接流程建议
- 平台分配
app_key和app_secret。 - 第三方完成签名调试。
- 第三方调用套餐获取接口,确认可用套餐和
price_package_code。 - 第三方调用创建订单接口。最小只传
external_order_no即可;如需要减少后续人工补录,建议同步传price_package_code、product_info、return_address、materials和inbound_logistics。 - 商品实际寄出后,第三方调用发货通知接口提交
express_company和tracking_no。 - 第三方可通过查询接口主动查询订单状态。
- 如启用 webhook,平台在订单状态变化时主动通知第三方。