关键词:
查询物流可以使用现成的API,本文使用的快递鸟查询。
查询方法主要在两个类:errorManage、kdniaoTrackQueryAPI中
调用API一定要仔细阅读文档,了解编码格式、请求方式、参数设置等信息。
上代码之前先说一下数据结构:
我们想要的物流路径可由一系列地址组成,但在实际操作中还存在查询失败及没有物流信息的情况,所以还要返回一个查询状态信息。
所以选择一个能储存所需信息的最简单结构,用List结构传递即可。
规定List第一位存储Int型转状态信息,用不同数字返回不同信息。后面的位置一次存储String型地址信息。(具体在处理错误的eM方法。)
eM返回List后,在Return方法中根据第一位的状态信息编辑返回内容,同样适用List结构。
顺便一提:
快递鸟返回的数据格式是JSON格式,还需要调用org.json.*包,自己下载就行。
代码:kdniaoTrackQueryAPI类
1 package util; 2 import java.io.BufferedReader; 3 import java.io.IOException; 4 import java.io.InputStreamReader; 5 import java.io.OutputStreamWriter; 6 import java.io.UnsupportedEncodingException; 7 import java.net.HttpURLConnection; 8 import java.net.URL; 9 import java.net.URLEncoder; 10 import java.security.MessageDigest; 11 import java.util.ArrayList; 12 import java.util.HashMap; 13 import java.util.List; 14 import java.util.Map; 15 import org.json.*; 16 import java.util.regex.Matcher; 17 import java.util.regex.Pattern; 18 19 public class kdniaoTrackQueryAPI { 20 //电商ID 21 private String EBusinessID="1287464"; 22 //电商加密私钥,快递鸟提供,注意保管,不要泄漏 23 private String AppKey="4e92ddaa-b1b8-49d1-9261-1f5ff114b57f"; 24 //请求url 25 private String ReqURL="http://112.74.108.55/Ebusiness/EbusinessOrderHandle.aspx"; 26 27 //实例化 28 public kdniaoTrackQueryAPI(){} 29 30 public List<String> Return(String ShipperCode,String LogisticCode) { //公司编号和物流运单号 31 // TODO Auto-generated method stub 32 List<String> addresses=new ArrayList<String>(); 33 kdniaoTrackQueryAPI api = new kdniaoTrackQueryAPI(); 34 try { 35 String result = api.getOrderTracesByJson(ShipperCode,LogisticCode); 36 errorManage em = eM(result); 37 if(em.getSuccess()){ 38 addresses.add("1"); 39 JSONObject json = new JSONObject(result); 40 JSONArray jsa = json.getJSONArray("Traces"); 41 for(int i = 0;i < jsa.length();i++){ 42 int j = 1; 43 JSONObject jst = jsa.getJSONObject(i); 44 Pattern p=Pattern.compile("(?<=【)(.*?)(?=】)"); 45 Matcher m=p.matcher(jst.get("AcceptStation").toString()); 46 while(m.find()&j ==1 ){ 47 System.out.println(m.group()); 48 String s = m.group(1); 49 addresses.add(s); 50 j++; 51 } 52 } 53 }else{ 54 addresses.add(0,"0"); 55 addresses.add(1, em.getReason()); 56 } 57 } catch (Exception e) { 58 e.printStackTrace(); 59 } 60 return addresses; 61 } 62 63 /** 64 * 处理没有物流信息的错误 65 */ 66 public static errorManage eM(String result){ 67 errorManage em = new errorManage(); 68 JSONObject json = new JSONObject(result); 69 System.out.println(json); 70 String logcode = json.getString("LogisticCode"); 71 String shipcode = json.getString("ShipperCode"); 72 JSONArray jsa = json.getJSONArray("Traces"); 73 boolean a = json.getBoolean("Success"); 74 boolean b = !jsa.isNull(0);//如果Traces是空的,则b为false;如果Traces不空,则b为true 75 if(a){ 76 if(json.has("State")){ 77 int i = json.getInt("State"); 78 if(b){ 79 em.setSuccess(true); 80 em.setReason(""); 81 }else{ 82 if(i == 0){ 83 em.setSuccess(false); 84 em.setReason("没有物流信息!您的包裹未发送或已到达目的城市!"); 85 }else if(i == 4){ 86 em.setSuccess(false); 87 em.setReason("问题件!"); 88 }else if(i ==3){ 89 em.setSuccess(false); 90 em.setReason("已签收"); 91 }else{ 92 em.setSuccess(false); 93 em.setReason("此单无物流信息!"); 94 } 95 } 96 }else if(!json.has("State")&b){ 97 em.setSuccess(false); 98 em.setReason("已签收!"); 99 }else{ 100 em.setSuccess(false); 101 em.setReason("没有订单信息,请检查您是否输入正确!"); 102 } 103 } 104 105 return em; 106 } 107 /** 108 * Json方式 查询订单物流轨迹 109 * @throws Exception 110 */ 111 public String getOrderTracesByJson(String expCode, String expNo) throws Exception{ 112 String requestData= "{‘OrderCode‘:‘‘,‘ShipperCode‘:‘" + expCode + "‘,‘LogisticCode‘:‘" + expNo + "‘}"; 113 114 Map<String, String> params = new HashMap<String, String>(); 115 params.put("RequestData", urlEncoder(requestData, "UTF-8")); 116 params.put("EBusinessID", EBusinessID); 117 params.put("RequestType", "1002"); 118 String dataSign=encrypt(requestData, AppKey, "UTF-8"); 119 params.put("DataSign", urlEncoder(dataSign, "UTF-8")); 120 params.put("DataType", "2"); 121 122 String result=sendPost(ReqURL, params); 123 124 //根据公司业务处理返回的信息...... 125 126 return result; 127 } 128 129 /** 130 * XML方式 查询订单物流轨迹 131 * @throws Exception 132 */ 133 public String getOrderTracesByXml() throws Exception{ 134 String requestData= "<?xml version="1.0" encoding="utf-8" ?>"+ 135 "<Content>"+ 136 "<OrderCode></OrderCode>"+ 137 "<ShipperCode>SF</ShipperCode>"+ 138 "<LogisticCode>589707398027</LogisticCode>"+ 139 "</Content>"; 140 141 Map<String, String> params = new HashMap<String, String>(); 142 params.put("RequestData", urlEncoder(requestData, "UTF-8")); 143 params.put("EBusinessID", EBusinessID); 144 params.put("RequestType", "1002"); 145 String dataSign=encrypt(requestData, AppKey, "UTF-8"); 146 params.put("DataSign", urlEncoder(dataSign, "UTF-8")); 147 params.put("DataType", "1"); 148 149 String result=sendPost(ReqURL, params); 150 151 //根据公司业务处理返回的信息...... 152 153 return result; 154 } 155 156 /** 157 * MD5加密 158 * @param str 内容 159 * @param charset 编码方式 160 * @throws Exception 161 */ 162 private String MD5(String str, String charset) throws Exception { 163 MessageDigest md = MessageDigest.getInstance("MD5"); 164 md.update(str.getBytes(charset)); 165 byte[] result = md.digest(); 166 StringBuffer sb = new StringBuffer(32); 167 for (int i = 0; i < result.length; i++) { 168 int val = result[i] & 0xff; 169 if (val <= 0xf) { 170 sb.append("0"); 171 } 172 sb.append(Integer.toHexString(val)); 173 } 174 return sb.toString().toLowerCase(); 175 } 176 177 /** 178 * base64编码 179 * @param str 内容 180 * @param charset 编码方式 181 * @throws UnsupportedEncodingException 182 */ 183 private String base64(String str, String charset) throws UnsupportedEncodingException{ 184 String encoded = base64Encode(str.getBytes(charset)); 185 return encoded; 186 } 187 188 private String urlEncoder(String str, String charset) throws UnsupportedEncodingException{ 189 String result = URLEncoder.encode(str, charset); 190 return result; 191 } 192 193 /** 194 * 电商Sign签名生成 195 * @param content 内容 196 * @param keyValue Appkey 197 * @param charset 编码方式 198 * @throws UnsupportedEncodingException ,Exception 199 * @return DataSign签名 200 */ 201 private String encrypt (String content, String keyValue, String charset) throws UnsupportedEncodingException, Exception 202 { 203 if (keyValue != null) 204 { 205 return base64(MD5(content + keyValue, charset), charset); 206 } 207 return base64(MD5(content, charset), charset); 208 } 209 210 /** 211 * 向指定 URL 发送POST方法的请求 212 * @param url 发送请求的 URL 213 * @param params 请求的参数集合 214 * @return 远程资源的响应结果 215 */ 216 private String sendPost(String url, Map<String, String> params) { 217 OutputStreamWriter out = null; 218 BufferedReader in = null; 219 StringBuilder result = new StringBuilder(); 220 try { 221 URL realUrl = new URL(url); 222 HttpURLConnection conn =(HttpURLConnection) realUrl.openConnection(); 223 // 发送POST请求必须设置如下两行 224 conn.setDoOutput(true); 225 conn.setDoInput(true); 226 // POST方法 227 conn.setRequestMethod("POST"); 228 // 设置通用的请求属性 229 conn.setRequestProperty("accept", "*/*"); 230 conn.setRequestProperty("connection", "Keep-Alive"); 231 conn.setRequestProperty("user-agent", 232 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 233 conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 234 conn.setRequestProperty("kdniao-nocache", "true"); 235 conn.connect(); 236 // 获取URLConnection对象对应的输出流 237 out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); 238 // 发送请求参数 239 if (params != null) { 240 StringBuilder param = new StringBuilder(); 241 for (Map.Entry<String, String> entry : params.entrySet()) { 242 if(param.length()>0){ 243 param.append("&"); 244 } 245 param.append(entry.getKey()); 246 param.append("="); 247 param.append(entry.getValue()); 248 //System.out.println(entry.getKey()+":"+entry.getValue()); 249 } 250 //System.out.println("param:"+param.toString()); 251 out.write(param.toString()); 252 } 253 // flush输出流的缓冲 254 out.flush(); 255 // 定义BufferedReader输入流来读取URL的响应 256 in = new BufferedReader( 257 new InputStreamReader(conn.getInputStream(), "UTF-8")); 258 String line; 259 while ((line = in.readLine()) != null) { 260 result.append(line); 261 } 262 } catch (Exception e) { 263 e.printStackTrace(); 264 } 265 //使用finally块来关闭输出流、输入流 266 finally{ 267 try{ 268 if(out!=null){ 269 out.close(); 270 } 271 if(in!=null){ 272 in.close(); 273 } 274 } 275 catch(IOException ex){ 276 ex.printStackTrace(); 277 } 278 } 279 return result.toString(); 280 } 281 282 283 private static char[] base64EncodeChars = new char[] { 284 ‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘, ‘F‘, ‘G‘, ‘H‘, 285 ‘I‘, ‘J‘, ‘K‘, ‘L‘, ‘M‘, ‘N‘, ‘O‘, ‘P‘, 286 ‘Q‘, ‘R‘, ‘S‘, ‘T‘, ‘U‘, ‘V‘, ‘W‘, ‘X‘, 287 ‘Y‘, ‘Z‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, 288 ‘g‘, ‘h‘, ‘i‘, ‘j‘, ‘k‘, ‘l‘, ‘m‘, ‘n‘, 289 ‘o‘, ‘p‘, ‘q‘, ‘r‘, ‘s‘, ‘t‘, ‘u‘, ‘v‘, 290 ‘w‘, ‘x‘, ‘y‘, ‘z‘, ‘0‘, ‘1‘, ‘2‘, ‘3‘, 291 ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘, ‘+‘, ‘/‘ }; 292 293 public static String base64Encode(byte[] data) { 294 StringBuffer sb = new StringBuffer(); 295 int len = data.length; 296 int i = 0; 297 int b1, b2, b3; 298 while (i < len) { 299 b1 = data[i++] & 0xff; 300 if (i == len) 301 { 302 sb.append(base64EncodeChars[b1 >>> 2]); 303 sb.append(base64EncodeChars[(b1 & 0x3) << 4]); 304 sb.append("=="); 305 break; 306 } 307 b2 = data[i++] & 0xff; 308 if (i == len) 309 { 310 sb.append(base64EncodeChars[b1 >>> 2]); 311 sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); 312 sb.append(base64EncodeChars[(b2 & 0x0f) << 2]); 313 sb.append("="); 314 break; 315 } 316 b3 = data[i++] & 0xff; 317 sb.append(base64EncodeChars[b1 >>> 2]); 318 sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); 319 sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]); 320 sb.append(base64EncodeChars[b3 & 0x3f]); 321 } 322 return sb.toString(); 323 } 324 }
代码:errorManage类
1 package util; 2 3 public class errorManage { 4 private boolean success; 5 private String reason; 6 errorManage(){ 7 this.success = true; 8 this.reason = ""; 9 } 10 errorManage(boolean s,String r){ 11 this.success = s; 12 this.reason = r; 13 } 14 public void setSuccess(boolean s){ 15 this.success = s; 16 } 17 public void setReason(String r){ 18 this.reason = r; 19 } 20 public boolean getSuccess(){ 21 return this.success; 22 } 23 public String getReason(){ 24 return this.reason; 25 } 26 }
从申请到调用:全国快递物流查询api使用教程(代码片段)
...言面对越来越多的快递需求和快递公司的日益增多,手动查询快递状态的工作变得愈发繁琐。此时,一个全国快递物流查询API的出现能够极大地提高查询的效率和准确性,解决人工查询的问题,为用户提供更加便捷的服务体验。... 查看详情
客快物流大数据项目(一百零七):物流信息查询服务接口开发解决方案
文章目录物流信息查询服务接口开发解决方案一、业务需求二、系统架构演变1、集中式架构2、垂直拆分3、分布式服务4、面向服务架构(SOA)5、微服务架构... 查看详情
java查询快递物流信息api接口写法免费
效果图: 快递查询API接口是使用的物流单号即可实现实时查询物流信息。主要应用在电商商城、ERP系统商、WMS系统商、快递柜、银行等企业。多家快递物流公司接口统一接入,建议对接接口提供商,一次性可以接入多家... 查看详情
快递鸟即时查询api接口和物流跟踪接口有啥区别?
参考技术A(1)接入方式不一样:即时查询接口,根据快递单号和快递公司编码实时查询物流轨迹信息。物流跟踪接口,用户订阅快递号,快递鸟系统会定时推送新的物流信息。(2)实现的功能不一样:即时查询接口,单次请求... 查看详情
api开发实践返回html
分为两个部分:生成HTML和返回HTML生成HTML:最终想要的时显示地图,不可避免的使用高德地图的API。【地图API】地址录入时如何获得准确的经纬度?淘宝收货地址详解改变几个参数即可达到目的,很简单不讲了。 重点说说如... 查看详情
客快物流大数据项目(一百零七):物流信息查询服务接口开发解决方案
文章目录物流信息查询服务接口开发解决方案一、业务需求二、系统架构演变1、集中式架构2、垂直拆分3、分布式服务4、面向服务架构(SOA)5、微服务架构... 查看详情
撸个查询物流的小程序,欢迎体验
...口用的快递100的api,不过有次数限制。小程序用wepy框架开发的,方便快捷,写法类似vue,支持es6相关操作,已可以引入npm包,不过在微信开发者工具有以下注意事项。es6:对应关闭ES6转ES5选项,关闭。postcss:对应关闭上传代码时... 查看详情
查快递,对接哪个接口比较好?
快递查询接口可以直接找物流公司对接,也可以找第三方接口服务商一次性对接所有快递公司的查询接口,做的比较好的就是菜鸟、快递鸟,目前淘宝和天猫等阿里的都用菜鸟,其他的大部分电商平台比如美团、云集、凯叔讲故... 查看详情
求快递查询api,想接入一个到自己网站上?
我们公司网站刚对接了快递鸟的物流查询接口,综合对比多家选择了快递鸟。在快递查询接口领域比较知名的了,有在途监控、在途监控地图版、快递查询、在途监控国际版等接口,支持1600+国内外主流物流快递公司,一次性对... 查看详情
热门的免费api合辑整理
快递物流查询全国快递物流查询:目前已支持600+快递公司的快递信息查询。跨境国际快递物流查询:支持900+物流商,提供实时查询和单号订阅API接口。物流时效性查询:预估从下单开始直到收到货物的时间,计算物流的时效性... 查看详情
shopex快递物流单号查询插件
...物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递、顺丰快递、圆通快递、EMS快递、汇通快递、宅急送快递、德邦物流、百世快递、汇通快递、中通快递、天天快递等知名快递订单查询服务,另有全球... 查看详情
快递物流信息推送功能接口分析
...:快递物流信息的跟踪接口分为两种方式:一种是实时的查询跟踪(主动);一种是订阅推送跟踪(被动)。实时查询(主动)是指主动发出查询请求,返回实时的物流信息数据;订阅推送(被动)是指把需要跟踪的快递物流单... 查看详情
在 Pymongo 查询路径中使用日期时间的最佳实践?
】在Pymongo查询路径中使用日期时间的最佳实践?【英文标题】:BestpracticeforusingdatetimeinPymongoquerypath?【发布时间】:2017-09-1019:52:56【问题描述】:如果我需要一些复杂的路径,如何使用datetime对象?例如我想增加位于jumps/datetime.d... 查看详情
dockerphp入门实践(三)
...kPHP框架完成一个天气查询的应用。使用天气查询-API文档-开发指南-Web服务API|高德地图API的接口来实现我们的功能。把查询数据缓存到MySql中,这样就不用每次频繁的请求第三方的接口了(有请求次数限制)选择高德开放平台-天... 查看详情
物流即时查询功能-申通快递
...接口获得的申通物流轨迹信息,显示的界面效果需要自己开发: 现在我们来聊一聊具体实现!首先我们准备好需要用到的资源,测试商户ID:test1617571 测试APIkey:554343b2-7252-439b-b4eb-1af42c8f2175(此Key仅限测试环境使用)&nb... 查看详情
使用免费快递接口查询物流信息
电商,ERP厂商可能需要物流信息接口,对运单号的物流轨迹进行跟踪,通常有些免费的不好用,及时性要求达不到,收费的也太贵了。最近发现一个免费的API接口,及时性非常高,基本上就是实时返回。需要可以联系QQ群 4791... 查看详情
物流包裹一站式查询(trackingmore)
快递查询接口目前提供快递查询的接口平台有:Trackingmore快递100快递网不同接口的区别:(1)Trackingmore支持380家快递公司,其中有55家为国内的快递,其余325家为国际快递。具体的价格为0.6分钱/单号左右,新注册用户可以免费... 查看详情
android应用开发快递单号查询介面使用啥api
参考技术Aandroid应用开发快递单号查询介面使用什么api快递查询和其他的网路资料查询(比如天气)一样,没有特殊的api。实现思路是:使用client访问资料提供方释出的网址。得到json或者 xml相应,然后解析资料,显示到应用... 查看详情