前言
我的第一篇博客,因为在网上没有搜索到自己满意的结果,自己总结下吧
最近,需要用到快递查询功能,本以为快递100官网 http://www.kuaidi100.com/ 有这么一个查询的功能,把接口拿过来用用,但是接口中的请求参数被加密处理了,把快递单号第一次输入进去,会返回一个对应快递公司的编码,再次点击查询的时候,会用这个快递公司编码加上其他的请求参数,去调用查询快递的接口,虽说每回都会返回快递信息,但是我用代码调用那个接口的信息时,返回的数据不是真正的物流数据(因为有个参数我们不知道怎么计算的),这就导致,我们只能通过官网免费获取快递单号的信息,其实,我想也是,这玩意能给你免费使用啊,哪有这么好的事儿呢,是吧!
1.申请快递100的API
我们要想使用快递100的接口查询物流信息怎么弄呢,当然是申请快递100的API,申请地址:http://www.kuaidi100.com/openapi/api_post.shtml, 申请过程就那样吧,就不详细介绍了吧
2.申请成功后
申请成功后快递100会给我们两个参数,作为调用接口时传参以及校验用的,一个是customer编码,另一个是授权的 key 编码。
接下来我解释下请求中的参数:
expressCategory : 快递单号所对应的快递公司的编码,比如 “yuantong”
number : 要查询的快递单号
customer : 快递100分配的客户编码
key:授权的 key
sign : 签名 param + key + customer,这几个必须有
/**
* 调用快递100接口,查询物流信息
* @param number 要查询的快递单号
* @param expressCategory 快递单号所对应的快递公司的编码,比如 “yuantong”
* @return
*/
public List<Map<String,Object>> rightKuaidi100(String number, String expressCategory ){
//此处根据快递单号拿到对应的公司的编码,比如 “yuantong”,这部分代码我就不上了
//String expressCategory = kuaidi100Service.getExpressCategory(number);
String param = "{"com":"" + expressCategory + "","num":"" + number + "","from":"","to":""}";
String customer = "88C6CA**************B65AE2FO1";
String key = "rt*******66";
String sign = signMD5(param + key + customer);
HashMap params = new HashMap();
params.put("param", param);
params.put("sign", sign.toUpperCase());
//params.put("sign",sign);
params.put("customer", customer);
String responseString = HttpUtils.okHttpPostString("http://poll.kuaidi100.com/poll/query.do", params);
//格式化返回参数信息
Map<String, Object> map1 = (Map<String, Object>) JSONObject.parse(responseString);
return datas = (List<Map<String,Object>>)map1.get("data");
}
/**
* 快递100 签名
* @param s
* @return
*/
public static String signMD5(String s) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = md.digest(s.getBytes("utf-8"));
return bytesToHex(bytes);
} catch (Exception var3) {
throw new RuntimeException(var3);
}
}
public static String bytesToHex(byte[] bytes) {
char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
StringBuilder ret = new StringBuilder(bytes.length * 2);
for(int i = 0; i < bytes.length; ++i) {
ret.append(HEX_DIGITS[bytes[i] >> 4 & 15]);
ret.append(HEX_DIGITS[bytes[i] & 15]);
}
return ret.toString();
}
Http请求部分代码
/**
* okHttp3的 POST 请求 , 请求参数格式为 key-value
* @param url 请求url
* @param params 请求参数 , Map
* @return
* @author zfan
* @email zfanxyz@gmail.com
*/
public static String okHttpPostString(String url, Map<String, Object> params) {
List<NameValuePair> paramList = new ArrayList<NameValuePair>();
Collection<String> keyset = params.keySet();
List<String> keylist = new ArrayList<String>(keyset);
Collections.sort(keylist);
for (int i = 0; i < keylist.size(); i++) {
if (keylist.get(i) != null && !"".equals(params.get(keylist.get(i)))) {
paramList.add(new BasicNameValuePair(keylist.get(i), params.get(keylist.get(i)).toString()));
}
}
//请求参数
String requestString = URLEncodedUtils.format(paramList, Charset.forName("UTF-8"));
//创建一个默认的OkHttpClient实例:
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(100, TimeUnit.SECONDS) //设置读取的超时时间 s
.writeTimeout(60, TimeUnit.SECONDS) //设置写的超时时间 s
.connectTimeout(60, TimeUnit.SECONDS) //设置连接的超时时间 s
.build();
//post 的 key-value 形式的请求参数的格式
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded"); //数据类型为 key-value 格式
//创建一个实体 RequestBody
RequestBody requestBody = RequestBody.create(mediaType, requestString);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
try {
Response response = client.newCall(request).execute();
if(response.isSuccessful()){
return response.body().string();
}else {
throw new IOException("Unexpected code : " + response);
}
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
应该没啥漏掉的吧,欢迎指正
那个kuaidi100最后返回的参数,我对请求的响应参数做了处理,仅仅取出了data中的数据。
data的数据格式如下,如果想要全部的,可以打印下日志,按照格式取出想要的数据。
"data": [
{
"ftime": "2019-04-04 08:17:57",
"context": "【**市】 已签收 : 由已签收(***1号 )代签收,如有问题联系***(13333333333)",
"time": "2019-04-04 08:17:57"
},
{
"ftime": "2019-04-02 04:04:35",
"context": "【深圳市】 已到达 广东深圳公司 大包称重",
"time": "2019-04-02 04:04:35"
},
{
"ftime": "2019-04-01 22:18:27",
"context": "【深圳市】 ************包分部 已揽收",
"time": "2019-04-01 22:18:27"
}
]
好了,至此调用快递100接口的数据到此完毕了,当然要向快递100官方申请的。欢迎大家指正,后续把通过快递单号拿到对应的快递公司编码的代码补充上