各类接口
快递查询API有即时查询和订阅查询两种,即时是请求即返回数据,订阅则是订阅快递单号到接口,有物流轨迹更新则全量返回数据。目前常用的有快递鸟、快递100、快递网等。
快递鸟即时API可以查询3000次,3000以上接订阅接口,统一接口模式接入,常用快递均支持查询,还有订阅API、在线下单API、电子面单API,接口均不收取费用,没有要求用户添加外链,支持418家国内外快递物流查询。
快递100每天可以免费查询2000次,超过2000次收费,每次0.06~0.1元不等,如果查询的量大的话可以降低费用,免费的接口有几家常用快递不支持接口模式,只支持htmlAPI,要求用户添加外链,支持300多家国内外快递物流查询。
快递网每天可以免费查询500次,超过500次收费,每次0.05元,只有即时查询和订阅推送接口,要求用户添加外链,支持395家国内外快递物流查询。
对接示例
以快递鸟及时查询API接入示例,不同公司的快递查询API接入类似,都需要注册,申请账号获取KEY和IDhttp://www.kdniao.com/ServiceApply.aspx,如果是订阅API需要技术联调。
根据快递单号和快递公司编码查询物流轨迹信息。接口需要指定快递单号的快递公司编码,格式不对或则编码错误都会返失败的信息。如:EMS物流单号应选择快递公司编码(EMS)查看快递公司编码返回的物流跟踪信息按照发生的时间升序排列。
接口支持的消息接收方式为HTTP POST
请求方法的编码格式(utf-8):"application/x-www-form-urlencoded;charset=utf-8"
API地址:http://api.kdniao.cc/Ebusiness/EbusinessOrderHandle.aspx
接口参数
*请求系统级参数
参数名称 | 类型 | 说明 | 必须要求 |
---|---|---|---|
RequestData | String | 请求内容需进行URL(utf-8)编码。请求内容JSON或XML格式,须和DataType一致。 | R |
EBusinessID | String | 商户ID,请在我的服务页面查看。 | R |
RequestType | String | 请求指令类型:1002 | R |
DataSign | String | 数据内容签名:把(请求内容(未编码)+AppKey)进行MD5加密,然后Base64编码,最后进行URL(utf-8)编码。详细过程请查看Demo。 | R |
DataType | String | 请求、返回数据类型:1-xml,2-json;默认为xml格式 | O |
*请求内容字段定义
参数 | 类型 | 说明 | 必须要求 |
---|---|---|---|
OrderCode | String | 订单编号 | O |
ShipperCode | String | 快递公司编码 | R |
LogisticCode | String | 物流单号 | R |
*返回参数定义
参数名称 | 类型 | 说明 | 必须要求 | |
---|---|---|---|---|
EBusinessID | String | 用户ID | R | |
OrderCode | String | 订单编号 | O | |
ShipperCode | String | 快递公司编码 | R | |
LogisticCode | String | 物流运单号 | R | |
Success | Bool | 成功与否 | R | |
Reason | String | 失败原因 | O | |
State | String | 物流状态:2-在途中,3-签收,4-问题件 | R | |
Traces | ||||
Trace | AcceptTime | String | 时间 | R |
AcceptStation | String | 描述 | R | |
Remark | String | 备注 | O |
JAVA接入示例
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 import java.io.OutputStreamWriter; 5 import java.io.UnsupportedEncodingException; 6 import java.net.HttpURLConnection; 7 import java.net.URL; 8 import java.net.URLEncoder; 9 import java.security.MessageDigest; 10 import java.util.HashMap; 11 import java.util.Map; 12 13 /** 14 * 15 * 快递鸟物流轨迹即时查询接口 16 * 17 * @技术QQ群: 456320272 18 * @see: http://www.kdniao.com/YundanChaxunAPI.aspx 19 * @copyright: 深圳市快金数据技术服务有限公司 20 * 21 * DEMO中的电商ID与私钥仅限测试使用,正式环境请单独注册账号 22 * 单日超过500单查询量,建议接入我方物流轨迹订阅推送接口 23 * 24 * ID和Key请到官网申请:http://www.kdniao.com/ServiceApply.aspx 25 */ 26 27 public class KdniaoTrackQueryAPI { 28 29 //DEMO 30 public static void main(String[] args) { 31 KdniaoTrackQueryAPI api = new KdniaoTrackQueryAPI(); 32 try { 33 String result = api.getOrderTracesByJson("ANE", "210001633605"); 34 System.out.print(result); 35 36 } catch (Exception e) { 37 e.printStackTrace(); 38 } 39 } 40 41 //电商ID 42 private String EBusinessID="请到快递鸟官网申请http://www.kdniao.com/ServiceApply.aspx"; 43 //电商加密私钥,快递鸟提供,注意保管,不要泄漏 44 private String AppKey="请到快递鸟官网申请http://www.kdniao.com/ServiceApply.aspx"; 45 //请求url 46 private String ReqURL="http://api.kdniao.cc/Ebusiness/EbusinessOrderHandle.aspx"; 47 48 /** 49 * Json方式 查询订单物流轨迹 50 * @throws Exception 51 */ 52 public String getOrderTracesByJson(String expCode, String expNo) throws Exception{ 53 String requestData= "{‘OrderCode‘:‘‘,‘ShipperCode‘:‘" + expCode + "‘,‘LogisticCode‘:‘" + expNo + "‘}"; 54 55 Map<String, String> params = new HashMap<String, String>(); 56 params.put("RequestData", urlEncoder(requestData, "UTF-8")); 57 params.put("EBusinessID", EBusinessID); 58 params.put("RequestType", "1002"); 59 String dataSign=encrypt(requestData, AppKey, "UTF-8"); 60 params.put("DataSign", urlEncoder(dataSign, "UTF-8")); 61 params.put("DataType", "2"); 62 63 String result=sendPost(ReqURL, params); 64 65 //根据公司业务处理返回的信息...... 66 67 return result; 68 } 69 70 /** 71 * XML方式 查询订单物流轨迹 72 * @throws Exception 73 */ 74 public String getOrderTracesByXml() throws Exception{ 75 String requestData= "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"+ 76 "<Content>"+ 77 "<OrderCode></OrderCode>"+ 78 "<ShipperCode>SF</ShipperCode>"+ 79 "<LogisticCode>589707398027</LogisticCode>"+ 80 "</Content>"; 81 82 Map<String, String> params = new HashMap<String, String>(); 83 params.put("RequestData", urlEncoder(requestData, "UTF-8")); 84 params.put("EBusinessID", EBusinessID); 85 params.put("RequestType", "1002"); 86 String dataSign=encrypt(requestData, AppKey, "UTF-8"); 87 params.put("DataSign", urlEncoder(dataSign, "UTF-8")); 88 params.put("DataType", "1"); 89 90 String result=sendPost(ReqURL, params); 91 92 //根据公司业务处理返回的信息...... 93 94 return result; 95 } 96 97 /** 98 * MD5加密 99 * @param str 内容 100 * @param charset 编码方式 101 * @throws Exception 102 */ 103 @SuppressWarnings("unused") 104 private String MD5(String str, String charset) throws Exception { 105 MessageDigest md = MessageDigest.getInstance("MD5"); 106 md.update(str.getBytes(charset)); 107 byte[] result = md.digest(); 108 StringBuffer sb = new StringBuffer(32); 109 for (int i = 0; i < result.length; i++) { 110 int val = result[i] & 0xff; 111 if (val <= 0xf) { 112 sb.append("0"); 113 } 114 sb.append(Integer.toHexString(val)); 115 } 116 return sb.toString().toLowerCase(); 117 } 118 119 /** 120 * base64编码 121 * @param str 内容 122 * @param charset 编码方式 123 * @throws UnsupportedEncodingException 124 */ 125 private String base64(String str, String charset) throws UnsupportedEncodingException{ 126 String encoded = base64Encode(str.getBytes(charset)); 127 return encoded; 128 } 129 130 @SuppressWarnings("unused") 131 private String urlEncoder(String str, String charset) throws UnsupportedEncodingException{ 132 String result = URLEncoder.encode(str, charset); 133 return result; 134 } 135 136 /** 137 * 电商Sign签名生成 138 * @param content 内容 139 * @param keyValue Appkey 140 * @param charset 编码方式 141 * @throws UnsupportedEncodingException ,Exception 142 * @return DataSign签名 143 */ 144 @SuppressWarnings("unused") 145 private String encrypt (String content, String keyValue, String charset) throws UnsupportedEncodingException, Exception 146 { 147 if (keyValue != null) 148 { 149 return base64(MD5(content + keyValue, charset), charset); 150 } 151 return base64(MD5(content, charset), charset); 152 } 153 154 /** 155 * 向指定 URL 发送POST方法的请求 156 * @param url 发送请求的 URL 157 * @param params 请求的参数集合 158 * @return 远程资源的响应结果 159 */ 160 @SuppressWarnings("unused") 161 private String sendPost(String url, Map<String, String> params) { 162 OutputStreamWriter out = null; 163 BufferedReader in = null; 164 StringBuilder result = new StringBuilder(); 165 try { 166 URL realUrl = new URL(url); 167 HttpURLConnection conn =(HttpURLConnection) realUrl.openConnection(); 168 // 发送POST请求必须设置如下两行 169 conn.setDoOutput(true); 170 conn.setDoInput(true); 171 // POST方法 172 conn.setRequestMethod("POST"); 173 // 设置通用的请求属性 174 conn.setRequestProperty("accept", "*/*"); 175 conn.setRequestProperty("connection", "Keep-Alive"); 176 conn.setRequestProperty("user-agent", 177 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 178 conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 179 conn.connect(); 180 // 获取URLConnection对象对应的输出流 181 out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); 182 // 发送请求参数 183 if (params != null) { 184 StringBuilder param = new StringBuilder(); 185 for (Map.Entry<String, String> entry : params.entrySet()) { 186 if(param.length()>0){ 187 param.append("&"); 188 } 189 param.append(entry.getKey()); 190 param.append("="); 191 param.append(entry.getValue()); 192 //System.out.println(entry.getKey()+":"+entry.getValue()); 193 } 194 //System.out.println("param:"+param.toString()); 195 out.write(param.toString()); 196 } 197 // flush输出流的缓冲 198 out.flush(); 199 // 定义BufferedReader输入流来读取URL的响应 200 in = new BufferedReader( 201 new InputStreamReader(conn.getInputStream(), "UTF-8")); 202 String line; 203 while ((line = in.readLine()) != null) { 204 result.append(line); 205 } 206 } catch (Exception e) { 207 e.printStackTrace(); 208 } 209 //使用finally块来关闭输出流、输入流 210 finally{ 211 try{ 212 if(out!=null){ 213 out.close(); 214 } 215 if(in!=null){ 216 in.close(); 217 } 218 } 219 catch(IOException ex){ 220 ex.printStackTrace(); 221 } 222 } 223 return result.toString(); 224 } 225 226 227 private static char[] base64EncodeChars = new char[] { 228 ‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘, ‘F‘, ‘G‘, ‘H‘, 229 ‘I‘, ‘J‘, ‘K‘, ‘L‘, ‘M‘, ‘N‘, ‘O‘, ‘P‘, 230 ‘Q‘, ‘R‘, ‘S‘, ‘T‘, ‘U‘, ‘V‘, ‘W‘, ‘X‘, 231 ‘Y‘, ‘Z‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, 232 ‘g‘, ‘h‘, ‘i‘, ‘j‘, ‘k‘, ‘l‘, ‘m‘, ‘n‘, 233 ‘o‘, ‘p‘, ‘q‘, ‘r‘, ‘s‘, ‘t‘, ‘u‘, ‘v‘, 234 ‘w‘, ‘x‘, ‘y‘, ‘z‘, ‘0‘, ‘1‘, ‘2‘, ‘3‘, 235 ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘, ‘+‘, ‘/‘ }; 236 237 public static String base64Encode(byte[] data) { 238 StringBuffer sb = new StringBuffer(); 239 int len = data.length; 240 int i = 0; 241 int b1, b2, b3; 242 while (i < len) { 243 b1 = data[i++] & 0xff; 244 if (i == len) 245 { 246 sb.append(base64EncodeChars[b1 >>> 2]); 247 sb.append(base64EncodeChars[(b1 & 0x3) << 4]); 248 sb.append("=="); 249 break; 250 } 251 b2 = data[i++] & 0xff; 252 if (i == len) 253 { 254 sb.append(base64EncodeChars[b1 >>> 2]); 255 sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); 256 sb.append(base64EncodeChars[(b2 & 0x0f) << 2]); 257 sb.append("="); 258 break; 259 } 260 b3 = data[i++] & 0xff; 261 sb.append(base64EncodeChars[b1 >>> 2]); 262 sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); 263 sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]); 264 sb.append(base64EncodeChars[b3 & 0x3f]); 265 } 266 return sb.toString(); 267 } 268 }