Files
anxinyan/docs/api/third-party-openapi.md
2026-06-18 13:56:20 +08:00

26 KiB
Raw Permalink Blame History

第三方订单对接文档

版本v1.3 更新日期2026-06-18

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_hashsha256("")
  • 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 服务方,可选 anxinyanzhongjian;不传返回全部服务方启用套餐

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. 仓库地址列表

第三方创建订单或通知寄入物流前,可以调用本接口获取当前可寄送的安心验仓库地址列表。

GET /api/open/v1/warehouses

5.1 查询参数

字段 类型 必填 说明
service_provider string 服务方,可选 anxinyanzhongjian;不传返回全部启用仓库

5.2 cURL 示例

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 成功响应示例

{
  "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_idsservice_area_provincesservice_area_cities 为空数组时表示不限制对应条件。
  • 响应不包含后台备注、启停状态和创建更新时间等内部管理字段。

6. 创建订单

POST /api/open/v1/orders

第三方创建订单时,最小只需要传 external_order_no。平台会创建一笔待寄送商品订单;如请求中包含套餐、物品、地址、资料或寄入物流,平台会同步写入订单主表、商品资料、寄回地址、初始鉴定资料和寄入物流记录。

6.1 请求参数

字段 类型 必填 说明
external_order_no string 第三方订单号。同一对接客户下必须唯一
service_provider string 服务方,可选 anxinyanzhongjian,默认 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 单独设置寄回地址

POST /api/open/v1/orders/return-address

第三方可以在建单后单独补录或更新寄回地址。订单已生成回寄运单后,不允许再修改。

6.3 请求参数

字段 类型 必填 说明
external_order_no string 第三方订单号
return_address object 寄回地址,字段要求同创建订单接口

6.4 请求示例

{
  "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 支持两种格式:

[
  "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
  }
]

资料文件当前只支持 httphttps 图片 URL。对象格式中 file_urlurl 等价;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_companytracking_no,含义与 inbound_logistics 内字段一致。

6.6 最小请求示例

{
  "external_order_no": "THIRD202605080001"
}

6.7 带可选字段请求示例

{
  "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 示例

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 成功响应示例

{
  "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.idempotenttrue
  • 后续使用相同 external_order_no 但请求内容不一致时,返回 409
  • 如第一次只传最小字段,后续不能再用同一个 external_order_no 重推补充字段;如需补充资料,应走平台补录、入库或补料流程。

建议第三方重试创建订单时保持请求 JSON 内容一致,仅重新生成 timestampnoncesignature

7. 查询订单

支持按第三方订单号或平台订单号查询订单进度。

7.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'

7.2 通过查询参数查询

GET /api/open/v1/orders?external_order_no=THIRD202605080001
GET /api/open/v1/orders?order_no=AXY20260508120000123

7.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_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,后台待处理鉴定任务会同步移除。

POST /api/open/v1/orders/cancel

8.1 请求参数

字段 类型 必填 说明
external_order_no string 第三方订单号。只能取消当前 app_key 所属客户下的订单
cancel_reason string 取消原因,最长 255 个字符

8.2 请求示例

{
  "external_order_no": "THIRD202606160001",
  "cancel_reason": "客户取消鉴定"
}

8.3 成功响应示例

{
  "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_companytracking_no 的订单不允许取消,返回 422
  • 已到仓、鉴定中、补料中、已出报告、已完成等状态不允许取消,返回 422
  • 找不到当前客户下的 external_order_no 时返回 404
  • 重复取消已取消订单会返回成功,data.cancelledfalse,不会重复写入取消时间线。
  • 取消接口不触发 webhook 回调;调用方以接口响应或订单查询结果为准。

9. 发货通知

第三方在商品实际寄出后,可以调用本接口通知平台写入寄入物流。创建订单接口中的 inbound_logistics 仍然可用;但如果订单创建和商品寄出不是同一时点,建议创建订单时只建单,实际寄出后再调用本接口提交快递信息。

POST /api/open/v1/orders/shipping

9.1 请求参数

字段 类型 必填 说明
external_order_no string 第三方订单号。只能提交当前 app_key 所属客户下的订单
express_company string 寄入快递公司
tracking_no string 寄入运单号

9.2 请求示例

{
  "external_order_no": "THIRD202606110001",
  "express_company": "顺丰速运",
  "tracking_no": "SF1234567890"
}

9.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"
      }
    }
  }
}

9.4 重复提交规则

  • 相同 external_order_noexpress_companytracking_no 重复提交时,接口返回成功,idempotenttrue,不会重复写物流节点或订单时间线。
  • 同一订单在 pending_shipping 状态下提交不同快递公司或运单号时,会更新最新一条寄入物流,updatedtrue,并追加“已更新运单”时间线。
  • pending_shipping 状态的订单不允许提交或更新寄入运单,返回 422
  • 找不到当前客户下的 external_order_no 时返回 404

10. 订单状态

常见订单状态如下,最终以接口返回的 order_statusdisplay_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 回调报文

{
  "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_keyapp_secret
  2. 第三方完成签名调试。
  3. 第三方调用套餐获取接口,确认可用套餐和 price_package_code
  4. 第三方调用创建订单接口。最小只传 external_order_no 即可;如需要减少后续人工补录,建议同步传 price_package_codeproduct_inforeturn_addressmaterialsinbound_logistics
  5. 如订单尚未寄送且需要取消,可调用取消订单接口;已提交寄入物流后不再支持取消。
  6. 如建单时未提供寄回地址,或后续需要变更,可调用寄回地址接口补录或更新 return_address
  7. 商品实际寄出后,第三方调用发货通知接口提交 express_companytracking_no
  8. 第三方可通过查询接口主动查询订单状态,并核对 return_address、物流和报告结果。
  9. 如启用 webhook平台在订单状态变化时主动通知第三方。