API开发实践(三) 查询物流路径
查询物流可以使用现成的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 }