一、接口概述
1.1 接口功能
item_get接口用于获取物流订单的详细信息,包括订单状态、物流轨迹、收发货人信息等。
1.2 接口特点
RESTful API设计
JSON格式数据传输
HTTPS安全传输
支持实时查询和异步回调
二、准备工作
2.1 注册开发者账号
访问锦程物流开放平台
完成企业实名认证
创建应用获取API密钥
2.2 获取接口凭证
App Key:应用唯一标识
App Secret:用于签名的密钥
Access Token:访问令牌(部分接口需要)
三、接口调用详解
3.1 接口地址
生产环境:https://api.jc56.com/v1/item/get
沙箱环境:https://sandbox-api.jc56.com/v1/item/get
3.2 请求方式
POST /v1/item/get HTTP/1.1
Content-Type: application/json
3.3 请求参数
基础参数
{
"app_key": "your_app_key",
"timestamp": "2026-02-01 10:00:00",
"sign": "生成的签名",
"sign_method": "md5",
"format": "json",
"version": "1.0"
}
业务参数
{
"order_no": "JC202602010001", // 物流订单号(必填)
"include_track": true, // 是否包含物流轨迹
"include_detail": true, // 是否包含详细信息
"language": "zh-CN" // 返回语言
}
3.4 签名生成方法
import hashlib
import time
def generate_sign(params, app_secret):
"""
生成接口签名
"""
# 1. 除sign外所有参数按key排序
sorted_params = sorted(params.items())
# 2. 拼接键值对
sign_str = ''
for key, value in sorted_params:
if key != 'sign' and value is not None:
sign_str += f"{key}{value}"
# 3. 拼接app_secret
sign_str += app_secret
# 4. 生成MD5签名(32位大写)
sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
return sign
示例
params = {
"app_key": "your_app_key",
"timestamp": "2026-02-01 10:00:00",
"order_no": "JC202602010001"
}
app_secret = "your_app_secret"
signature = generate_sign(params, app_secret)
四、代码实现示例
4.1 Python实现
import requests
import json
import hashlib
import time
class JCLogisticsAPI:
def init(self, app_key, app_secret, sandbox=False):
self.app_key = app_key
self.app_secret = app_secret
self.base_url = "https://sandbox-api.jc56.com" if sandbox else "https://api.jc56.com"
def _generate_sign(self, params):
"""生成签名"""
sorted_params = sorted(params.items())
sign_str = ''
for key, value in sorted_params:
if key != 'sign' and value is not None:
sign_str += f"{key}{value}"
sign_str += self.app_secret
return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
def item_get(self, order_no, include_track=True, include_detail=True):
"""获取订单详情"""
# 构建请求参数
params = {
"app_key": self.app_key,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"sign_method": "md5",
"format": "json",
"version": "1.0",
"order_no": order_no,
"include_track": include_track,
"include_detail": include_detail
}
# 生成签名
params["sign"] = self._generate_sign(params)
# 发送请求
url = f"{self.base_url}/v1/item/get"
headers = {
"Content-Type": "application/json",
"User-Agent": "JCLogistics-Client/1.0"
}
try:
response = requests.post(
url,
json=params,
headers=headers,
timeout=10
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
return None
使用示例
if name == "main":
# 初始化客户端
client = JCLogisticsAPI(
app_key="your_app_key",
app_secret="your_app_secret",
sandbox=True # 测试时使用沙箱环境
)
# 查询订单详情
result = client.item_get("JC202602010001")
if result and result.get("success"):
print("查询成功:")
print(json.dumps(result, ensure_ascii=False, indent=2))
else:
print(f"查询失败: {result.get('error_msg', '未知错误')}")
4.2 Java实现
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.;
public class JCLogisticsClient {
private String appKey;
private String appSecret;
private String baseUrl;
private OkHttpClient httpClient;
private ObjectMapper objectMapper;
public JCLogisticsClient(String appKey, String appSecret, boolean sandbox) {
this.appKey = appKey;
this.appSecret = appSecret;
this.baseUrl = sandbox ? "https://sandbox-api.jc56.com" : "https://api.jc56.com";
this.httpClient = new OkHttpClient();
this.objectMapper = new ObjectMapper();
}
private String generateSign(Map<String, Object> params) {
try {
// 排序参数
List<String> keys = new ArrayList<>(params.keySet());
Collections.sort(keys);
// 拼接字符串
StringBuilder signStr = new StringBuilder();
for (String key : keys) {
if (!"sign".equals(key) && params.get(key) != null) {
signStr.append(key).append(params.get(key));
}
}
signStr.append(appSecret);
// MD5加密
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(signStr.toString().getBytes("UTF-8"));
// 转换为大写十六进制
StringBuilder hexString = new StringBuilder();
for (byte b : digest) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString().toUpperCase();
} catch (Exception e) {
throw new RuntimeException("生成签名失败", e);
}
}
public Map<String, Object> itemGet(String orderNo) {
try {
// 构建请求参数
Map<String, Object> params = new HashMap<>();
params.put("app_key", appKey);
params.put("timestamp", LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
params.put("sign_method", "md5");
params.put("format", "json");
params.put("version", "1.0");
params.put("order_no", orderNo);
params.put("include_track", true);
// 生成签名
String sign = generateSign(params);
params.put("sign", sign);
// 发送请求
String jsonBody = objectMapper.writeValueAsString(params);
RequestBody body = RequestBody.create(
jsonBody,
MediaType.parse("application/json; charset=utf-8")
);
Request request = new Request.Builder()
.url(baseUrl + "/v1/item/get")
.post(body)
.addHeader("User-Agent", "JCLogistics-Client/1.0")
.build();
Response response = httpClient.newCall(request).execute();
if (response.isSuccessful()) {
String responseBody = response.body().string();
return objectMapper.readValue(responseBody, Map.class);
} else {
throw new RuntimeException("请求失败: " + response.code());
}
} catch (Exception e) {
throw new RuntimeException("调用接口失败", e);
}
}
}
4.3 PHP实现
<?php
class JCLogisticsClient {
private $appKey;
private $appSecret;
private $baseUrl;
public function __construct($appKey, $appSecret, $sandbox = false) {
$this->appKey = $appKey;
$this->appSecret = $appSecret;
$this->baseUrl = $sandbox ?
'https://sandbox-api.jc56.com' :
'https://api.jc56.com';
}
private function generateSign($params) {
// 移除sign参数并按键排序
unset($params['sign']);
ksort($params);
// 拼接字符串
$signStr = '';
foreach ($params as $key => $value) {
if ($value !== null) {
$signStr .= $key . $value;
}
}
// 添加app_secret并生成MD5
$signStr .= $this->appSecret;
return strtoupper(md5($signStr));
}
public function itemGet($orderNo, $includeTrack = true) {
// 构建请求参数
$params = [
'app_key' => $this->appKey,
'timestamp' => date('Y-m-d H:i:s'),
'sign_method' => 'md5',
'format' => 'json',
'version' => '1.0',
'order_no' => $orderNo,
'include_track' => $includeTrack
];
// 生成签名
$params['sign'] = $this->generateSign($params);
// 发送请求
$url = $this->baseUrl . '/v1/item/get';
$options = [
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\n" .
"User-Agent: JCLogistics-Client/1.0\r\n",
'content' => json_encode($params),
'timeout' => 10
]
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
return json_decode($response, true);
}
}
// 使用示例
$client = new JCLogisticsClient('your_app_key', 'your_app_secret', true);
$result = $client->itemGet('JC202602010001');
if ($result && $result['success']) {
echo "查询成功:\n";
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
} else {
echo "查询失败: " . ($result['error_msg'] ?? '未知错误');
}
?>
五、返回结果解析
5.1 成功响应示例
{
"success": true,
"code": "10000",
"message": "成功",
"data": {
"order_info": {
"order_no": "JC202602010001",
"status": "DELIVERED",
"status_desc": "已签收",
"create_time": "2026-02-01 09:00:00",
"update_time": "2026-02-01 16:30:00",
"shipper": {
"name": "张三",
"phone": "13800138000",
"address": "北京市朝阳区"
},
"consignee": {
"name": "李四",
"phone": "13900139000",
"address": "上海市浦东新区"
}
},
"track_info": {
"current_status": "DELIVERED",
"tracks": [
{
"time": "2026-02-01 09:00:00",
"desc": "订单已创建",
"location": "北京分拨中心"
},
{
"time": "2026-02-01 12:00:00",
"desc": "快件已发车",
"location": "北京"
},
{
"time": "2026-02-01 16:30:00",
"desc": "已签收,签收人:李四",
"location": "上海"
}
]
}
}
}
5.2 错误响应示例
{
"success": false,
"code": "20001",
"message": "订单不存在",
"data": null
}
5.3 状态码说明
状态码
说明
处理建议
10000
成功
-
20001
订单不存在
检查订单号是否正确
20002
参数错误
检查请求参数格式
20003
签名错误
检查签名生成算法
20004
权限不足
检查API密钥权限
20005
频率超限
降低请求频率
30001
系统错误
稍后重试或联系技术支持
六、高级功能
6.1 批量查询优化
def batch_item_get(self, order_nos, batch_size=10):
"""
批量查询订单详情
"""
results = []
for i in range(0, len(order_nos), batch_size):
batch = order_nos[i:i+batch_size]
# 使用线程池并发请求
with ThreadPoolExecutor(max_workers=5) as executor:
futures = {
executor.submit(self.item_get, order_no): order_no
for order_no in batch
}
for future in as_completed(futures):
result = future.result()
if result:
results.append(result)
time.sleep(0.1) # 避免请求过于频繁
return results
6.2 缓存策略
import redis
from functools import lru_cache
class CachedJCLogisticsAPI(JCLogisticsAPI):
def init(self, app_key, app_secret, redis_client=None, ttl=300):
super().init(app_key, app_secret)
self.redis = redis_client
self.ttl = ttl # 缓存时间(秒)
def item_get(self, order_no, force_refresh=False):
# 缓存键
cache_key = f"jc_logistics:item:{order_no}"
# 尝试从缓存获取
if not force_refresh and self.redis:
cached = self.redis.get(cache_key)
if cached:
return json.loads(cached)
# 调用API
result = super().item_get(order_no)
# 缓存结果
if self.redis and result and result.get("success"):
self.redis.setex(
cache_key,
self.ttl,
json.dumps(result)
)
return result
6.3 异步回调配置
Webhook接收示例(Flask)
from flask import Flask, request, jsonify
app = Flask(name)
@app.route('/webhook/jc-logistics', methods=['POST'])
def logistics_webhook():
"""
接收物流状态变更回调
"""
try:
data = request.json
# 验证签名
if not verify_signature(data):
return jsonify({"success": False, "message": "签名验证失败"}), 401
# 处理业务逻辑
order_no = data.get("order_no")
new_status = data.get("status")
# 更新本地订单状态
update_order_status(order_no, new_status)
# 发送通知
send_notification(order_no, new_status)
return jsonify({"success": True, "message": "接收成功"})
except Exception as e:
app.logger.error(f"Webhook处理失败: {e}")
return jsonify({"success": False, "message": "处理失败"}), 500
七、故障排查与优化
7.1 常见问题解决
Q1: 签名验证失败
可能原因:
时间戳误差过大(超过5分钟)
App Secret错误
参数顺序不正确
解决方案:
确保使用服务器时间
import datetime
import pytz
def get_server_timestamp():
tz = pytz.timezone('Asia/Shanghai')
return datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
Q2: 请求超时
解决方案:
设置合理的超时时间和重试机制
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=4, max=10)
)
def item_get_with_retry(self, order_no):
return self.item_get(order_no)
Q3: 频率限制
解决方案:
from ratelimit import limits, sleep_and_retry
@sleep_and_retry
@limits(calls=100, period=60) # 每分钟100次
def limited_item_get(self, order_no):
return self.item_get(order_no)
7.2 监控与日志
import logging
from datetime import datetime
class LoggedJCLogisticsAPI(JCLogisticsAPI):
def init(self, app_key, app_secret, logger=None):
super().init(app_key, app_secret)
self.logger = logger or logging.getLogger(name)
def item_get(self, order_no, **kwargs):
start_time = datetime.now()
try:
result = super().item_get(order_no, **kwargs)
duration = (datetime.now() - start_time).total_seconds()
self.logger.info(
f"item_get成功 - 订单号: {order_no}, "
f"耗时: {duration:.3f}s, "
f"状态码: {result.get('code')}"
)
return result
except Exception as e:
duration = (datetime.now() - start_time).total_seconds()
self.logger.error(
f"item_get失败 - 订单号: {order_no}, "
f"耗时: {duration:.3f}s, "
f"错误: {str(e)}"
)
raise
八、最佳实践
8.1 安全建议
密钥管理:使用环境变量或密钥管理服务存储API密钥
HTTPS:确保所有请求都使用HTTPS
输入验证:验证所有输入参数
错误处理:不要将详细错误信息暴露给最终用户
8.2 性能优化
连接池:复用HTTP连接
缓存策略:合理使用缓存减少API调用
批量操作:合并多个请求
异步处理:非实时需求使用异步方式
8.3 代码质量
单元测试:编写测试用例覆盖主要功能
文档注释:为关键函数添加文档字符串
代码复用:封装通用功能模块
版本管理:记录API版本变更
九、资源链接
官方文档
锦程物流开放平台
API参考文档
错误代码表
SDK下载
Python SDK: pip install jc-logistics-sdk
Java SDK: Maven Central
PHP SDK: Composer
技术支持
客服电话:400-xxx-xxxx
技术支持邮箱:api-support@jc56.com
开发者社区:https://developer.jc56.com
十、版本更新记录
版本
日期
更新内容
1.0
2026-02-01
初始版本,包含基础接口说明
1.1
2026-02-15
增加批量查询和缓存示例
1.2
2026-03-01
添加故障排查和监控部分