api开发实践查询物流路径

知止      2022-02-11     769

关键词:

查询物流可以使用现成的API,本文使用的快递鸟查询。

查询方法主要在两个类:errorManage、kdniaoTrackQueryAPI中

 

各种快递查询Api接口(快递鸟)

 

调用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相应,然后解析资料,显示到应用... 查看详情