You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chajia/deploy/第三方对接指南.md

12 KiB

卡派查价 — 第三方系统对接指南

本文档面向宿主业务系统(如美美与共)开发方,说明如何通过 HTTP API 接入实时卡派LTL询价。

接口速查见 API.md。示例 JSON 见 host-candidates-req.example.json


1. 对接前准备

说明
Base URL 由我方提供,例如 https://if.dev.51track.vip
推荐方式 方式 A:两步宿主接口,免 Token服务端同步返回报价
备用方式 方式 BToken + 三步接口 + 宿主自行轮询(后期启用鉴权时使用)
协议 HTTPS + JSONUTF-8

服务器开关(我方运维配置):

HOST_PUBLIC_API_ENABLED=true
HOST_PUBLIC_DEFAULT_CUSTOMER_ID=CUST_001

2. 方式 A两步接口推荐美美与共当前使用

2.1 流程概览

sequenceDiagram
    participant 用户
    participant 宿主前端 as 宿主前端
    participant 查价 as 查价 API

    用户->>宿主前端: 填写地址 + 货物,点「获取报价」
    宿主前端->>查价: ① POST /api/host/quote/candidates
    查价-->>宿主前端: 候选列表 + host_session_id
    宿主前端->>用户: 展示候选,选择提货/派送地址
    用户->>宿主前端: 确认候选
    宿主前端->>查价: ② POST /api/host/quote/submit
    Note over 查价: 内部提交询价 + 轮询10420 秒
    查价-->>宿主前端: status=done + quotes
    宿主前端->>用户: 展示 final_total 等
调用次序 接口 宿主做什么 查价做什么
第 1 次 POST /api/host/quote/candidates 传地址 + 货物 返回联想候选 + host_session_id
第 2 次 POST /api/host/quote/submit 传会话 ID + 用户选的候选 内部轮询,直接返回最终报价

宿主无需: Token、GET 轮询、quote_id 管理。

宿主需要: 地址候选选择 UI、报价结果 UI、第 2 步 Loading约 1030 秒,最长约 7 分钟)。

2.2 鉴权

方式 A 不需要任何 Authorization 头,只需:

Content-Type: application/json

2.3 第一步:联想地址 + 暂存货物

POST /api/host/quote/candidates
Content-Type: application/json

请求体:

{
  "pickup_address": {
    "street": "1234 Warehouse Blvd",
    "city": "Los Angeles",
    "state": "CA",
    "zip": "90001"
  },
  "delivery_address": {
    "street": "5678 Distribution Dr",
    "city": "Dallas",
    "state": "TX",
    "zip": "75201"
  },
  "cargo": {
    "weight": { "value": 500, "unit": "kg" },
    "dimensions": { "length": 120, "width": 100, "height": 150, "unit": "cm" },
    "pallet_count": 2,
    "cargo_type": "general_freight"
  }
}
字段 必填 说明
pickup_address / delivery_address 草稿地址
*.street / *.city / *.state 美国地址;state 为二字码
*.zip 美国邮编,可省略或空字符串
cargo 货物信息(第一步传入后由服务端暂存,第二步无需重复传)

成功响应示例:

{
  "code": 0,
  "message": "ok",
  "data": {
    "host_session_id": "eb75548a-2c0b-4282-becd-ca3a0f5a3c15",
    "pickup_candidates": [
      {
        "option_id": "Eisx...",
        "display_label": "1234 Warehouse Street, Los Angeles, CA, USA",
        "formatted_address": "1234 Warehouse Street, Los Angeles, CA, USA",
        "street": "1234 Warehouse Street",
        "city": "Los Angeles",
        "state": "CA",
        "zip": "90001",
        "selectable": true
      }
    ],
    "delivery_candidates": [
      {
        "option_id": "EihE...",
        "display_label": "Distribution Dr, Wilmer, Dallas, TX, USA",
        "formatted_address": "Distribution Dr, Wilmer, Dallas, TX, USA",
        "street": "5678 Distribution Dr, Wilmer",
        "city": "Dallas",
        "state": "TX",
        "zip": "75201",
        "selectable": true
      }
    ],
    "requires_selection": true
  }
}

前端处理:

  • display_label 展示给用户。
  • 仅允许选择 selectable: true 的项;不可选项展示 unavailable_reason
  • 保存 host_session_id30 分钟有效)和用户选中的完整候选对象

2.4 第二步:确认候选并取报价(同步)

POST /api/host/quote/submit
Content-Type: application/json

请求体:

{
  "host_session_id": "eb75548a-2c0b-4282-becd-ca3a0f5a3c15",
  "pickup_candidate": {
    "option_id": "Eisx...",
    "display_label": "1234 Warehouse Street, Los Angeles, CA, USA",
    "formatted_address": "1234 Warehouse Street, Los Angeles, CA, USA",
    "street": "1234 Warehouse Street",
    "city": "Los Angeles",
    "state": "CA",
    "zip": "90001",
    "selectable": true
  },
  "delivery_candidate": {
    "option_id": "EihE...",
    "display_label": "Distribution Dr, Wilmer, Dallas, TX, USA",
    "formatted_address": "Distribution Dr, Wilmer, Dallas, TX, USA",
    "street": "5678 Distribution Dr, Wilmer",
    "city": "Dallas",
    "state": "TX",
    "zip": "75201",
    "selectable": true
  }
}
字段 必填 说明
host_session_id 第一步返回的 UUID
pickup_candidate 第一步 pickup_candidates 中用户选中项(完整对象)
delivery_candidate 第一步 delivery_candidates 中用户选中项(完整对象)

成功响应(节选):

{
  "code": 0,
  "message": "ok",
  "data": {
    "quote_id": "QTE_20260630_0003",
    "status": "done",
    "currency": "USD",
    "valid_until": "2026-06-30T10:30:00.000Z",
    "quotes": [
      {
        "service_level": "standard",
        "rate_option": "lowest",
        "carrier": "Frontline Freight",
        "transit_days": "Est. 5 business days",
        "final_total": 337.06
      }
    ]
  }
}

展示给用户: 使用 quotes[].final_totalUSDcarriertransit_days

失败: HTTP 200 时 data.status 可能为 failed,读 error_messageHTTP 504 表示服务端轮询超时。

2.5 美美与共前端职责

模块 说明
表单 收集地址(仓库代码需先转为 street/city/state/zip和货物
地址候选 UI 第 1 步后展示 pickup_candidates / delivery_candidates 供用户选择
报价结果 UI 第 2 步后展示 quotes 列表
Loading 第 2 步显示「正在查询报价,约需 1030 秒」,禁止重复提交
不需要 Token、轮询、quote_id 管理

2.6 美美与共调用示例JavaScript

// 第 1 步:联想
async function fetchCandidates(form) {
  const res = await fetch("https://if.dev.51track.vip/api/host/quote/candidates", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      pickup_address: form.pickup,
      delivery_address: form.delivery,
      cargo: form.cargo,
    }),
  });
  const json = await res.json();
  if (json.code !== 0) throw new Error(json.message);
  return json.data; // { host_session_id, pickup_candidates, delivery_candidates }
}

// 第 2 步:确认并取报价(一次请求,无需轮询)
async function submitQuote(hostSessionId, pickupCandidate, deliveryCandidate) {
  const res = await fetch("https://if.dev.51track.vip/api/host/quote/submit", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      host_session_id: hostSessionId,
      pickup_candidate: pickupCandidate,
      delivery_candidate: deliveryCandidate,
    }),
  });
  const json = await res.json();
  if (json.code !== 0) throw new Error(json.message);
  if (json.data.status === "failed") throw new Error(json.data.error_message ?? "询价失败");
  return json.data.quotes;
}

3. 统一响应格式

{ "code": 0, "message": "ok", "data": { } }
字段 说明
code 0 成功;非 0 为错误码
message 人类可读说明
data 业务数据

4. 货物类型与限制

cargo_type 枚举:

general_freight · machinery · furniture · electronics · building_materials · auto_parts · food_nonperishable · apparel · other

限制
托盘数 1 25
单托重量 0.01 9,999 lb
单托尺寸(换算英寸后) 长 ≤ 999宽 ≤ 99高 ≤ 99

5. 自测方法

5.1 第一步联想PowerShell

注意: Windows PowerShell 下 curl.exe -d '{...}' 容易因引号转义导致 JSON 无效,返回 请求体格式无效请用 JSON 文件或 Invoke-RestMethod。

推荐JSON 文件

curl.exe -s -X POST "https://if.dev.51track.vip/api/host/quote/candidates" `
  -H "Content-Type: application/json" `
  --data-binary "@deploy/host-candidates-req.example.json"

推荐Invoke-RestMethod

$body = Get-Content "deploy/host-candidates-req.example.json" -Raw
Invoke-RestMethod -Uri "https://if.dev.51track.vip/api/host/quote/candidates" `
  -Method POST -ContentType "application/json" -Body $body

成功标志:code: 0,且 data.host_session_id 存在。

5.2 第二步:取报价

从第一步响应中各取一条 selectable: true 的候选,构造 body 调用:

# 将 host_session_id、pickup_candidate、delivery_candidate 填入 body 后:
Invoke-RestMethod -Uri "https://if.dev.51track.vip/api/host/quote/submit" `
  -Method POST -ContentType "application/json" -Body $submitJson

成功标志:data.status === "done"data.quotesfinal_total

5.3 Linux / macOS

curl -s -X POST "https://if.dev.51track.vip/api/host/quote/candidates" \
  -H "Content-Type: application/json" \
  --data-binary "@deploy/host-candidates-req.example.json"

6. 方式 BToken 三步接口

后期启用鉴权时,将 HOST_PUBLIC_API_ENABLED=false,改用以下流程。宿主须自行轮询。

6.1 鉴权

Authorization: Bearer <Service Token>
X-Customer-Id: <Customer ID>
Content-Type: application/json

6.2 流程

步骤 接口 说明
1 POST /api/addresses/mothership-candidates 仅地址,返回候选
2 POST /api/quotes 确认地址 + 货物,返回 quote_id + processing
3 GET /api/quotes/{quote_id} 每 2 秒轮询,直到 done / failed

第二步 body 须含 customer_idrequest_idUUID v4、经 MotherShip 确认的地址字段(mothership_option_idselected_from_mothership: true 等)及货物信息。

Token 由我方在 HOST_SERVICE_TOKENS 中配置后发放。


7. 错误码

方式 A 常见错误

code HTTP 说明 处理
VALIDATION_FAILED 400 参数无效 检查字段message 为「请求体格式无效」时检查 JSON 格式
FORBIDDEN 403 公开接口未启用 确认 HOST_PUBLIC_API_ENABLED=true
SESSION_EXPIRED 404 会话过期 重新调用第一步
ADDRESS_SESSION_MISMATCH 400 候选与第一步不匹配 使用第一步返回的候选对象
ADDRESS_NOT_SELECTABLE 400 选了不可用地址 selectable: true 的候选
QUOTE_TIMEOUT 504 询价超时 稍后重试
RATE_LIMITED 429 限流 降低频率

通用错误

code HTTP 说明
UNAUTHORIZED 401 Token 无效(方式 B
INTERNAL_ERROR 5xx 服务异常

询价业务失败时 HTTP 可能仍为 200data.status === "failed",见 error_message


8. 安全与运维

  1. 方式 A 当前免 Token仅建议在可信内网或已控域名下使用;上线前改方式 B。
  2. 方式 B 的 Token 仅放宿主服务端,禁止写进浏览器或公开仓库。
  3. 服务未开放 CORS;浏览器页请勿直接 fetch 查价域名,应通过宿主后端或同域代理。
  4. 第二步网关/Nginx 须设 proxy_read_timeout 420s;
  5. 报价有效期见 valid_until,过期需重新询价。

9. 联系与支持

事项 说明
开通 / 环境确认 联系查价系统管理员
接口故障 提供 host_session_idquote_id、发生时间
文档版本 2026-06-30