快递查询api
一、目的
做这个项目的初衷是因为我去年在微信卖老家水果,好多朋友下单后都问我快递单号,每天发货后我都要挨个甄别这个人是哪个快递信息,很麻烦一部小心就搞错了。基于这件小事我有了自助快递查询的这个想法。将发货的快递信息导入到我的系统里,用户访问我的系统,通过输入手机号就可以查看自己的快递物流信息。 项目是去年8月写的,一直搁浅在哪,最近无意间翻看我发的那篇文章自助快递单号查询阅读量竟然都1.8w了,有图有真相。
这着实让我很震惊,看来自助快递查询这块确实是个热点。今天我就讲一下我手撸的快递查询系统。
二、开发
项目地址:github.com/hellowHuaai… 有兴趣的可以直接下载源码,觉得项目不错的伙伴记得点个star,谢谢啦!
2.1技术栈
项目涉及到的技术栈有:
SpringBoot: 一款 Java 微服务框架。Spring boot 是 Spring 家族中的一个新框架,它用来简化 Spring 应用程序的创建和开发。
Mybitas: 一款ORM框架,即对象关系映射。ORM框架的作用是把持久化对象的保存、修改、删除等操作,转换成对数据库的操作。
Jquery:一个轻量级的写的少,做的多的 JavaScript 函数库。
Bootstrap:Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的。
2.2后端开发
创建entity 创建快递单实体类,属性包括id,用户名(userName),电话(phone),快递单号(kuaidiNo),快递公司(company),数据创建时间(createTime)。代码如下:
@Data @Builder public class KuaiDi { private Integer id; /* 收件人姓名 */ private String userName; /**收件人电话*/ private String phone; /* 快递单号*/ private String kuaidiNo; /*快递公司名称(拼音)*/ private String company; /*订单创建时间*/ private Date createTime; public KuaiDi(Integer id, String userName, String phone, String kuaidiNo, String company, Date createTime) { this.id = id; this.userName = userName; this.phone = phone; this.kuaidiNo = kuaidiNo; this.company = company; this.createTime = createTime; } public KuaiDi(Integer id, String userName, String phone, String kuaidiNo, String company) { this.id = id; this.userName = userName; this.phone = phone; this.kuaidiNo = kuaidiNo; this.company = company; } }
service,mapper是常规的增删查改操作,就是保存快递的基本信息在数据库中,并可以对数据进行简单的维护功能。详细可参考项目源码。接下来看核心代码。
查询快递信息 快递的基本信息存入数据库,然后就是通过这些信息查询快递的详细物流信息。这里我做过很多尝试,想直接调用一些快递公司的快递信息查询接口,但是都发现接口都有session,当session失效后就无法查询到数据或者就查询到的数据不正确。最终在网上找到一种付费的方案,使用快递100接口。www.kuaidi100.com/ 查询快递的demo代码如下:
public class SynQueryDemo { /** * 实时查询请求地址 */ private static final String SYNQUERY_URL = "http://poll.kuaidi100.com/poll/query.do"; private String key; //授权key private String customer; //实时查询公司编号 public SynQueryDemo(String key, String customer) { this.key = key; this.customer = customer; } /** * 实时查询快递单号 * @param com 快递公司编码 * @param num 快递单号 * @param phone 手机号 * @param from 出发地城市 * @param to 目的地城市 * @param resultv2 开通区域解析功能:0-关闭;1-开通 * @return */ public String synQueryData(String com, String num, String phone, String from, String to, int resultv2) { StringBuilder param = new StringBuilder("{"); param.append("\"com\":\"").append(com).append("\""); param.append(",\"num\":\"").append(num).append("\""); param.append(",\"phone\":\"").append(phone).append("\""); param.append(",\"from\":\"").append(from).append("\""); param.append(",\"to\":\"").append(to).append("\""); if(1 == resultv2) { param.append(",\"resultv2\":1"); } else { param.append(",\"resultv2\":0"); } param.append("}"); Map<String, String> params = new HashMap<String, String>(); params.put("customer", this.customer); String sign = MD5Utils.encode(param this.key this.customer); params.put("sign", sign); params.put("param", param.toString()); return this.post(params); } /** * 发送post请求 */ public String post(Map<String, String> params) { StringBuffer response = new StringBuffer(""); Bufferedreader reader = null; try { StringBuilder builder = new StringBuilder(); for (Map.Entry<String, String> param : params.entrySet()) { if (builder.length() > 0) { builder.append('&'); } builder.append(URLEncoder.encode(param.getKey(), "UTF-8")); builder.append('='); builder.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8")); } byte[] bytes = builder.toString().getBytes("UTF-8"); URL url = new URL(SYNQUERY_URL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(3000); conn.setReadTimeout(3000); conn.setRequestMethod("POST"); conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Content-Length", String.valueOf(bytes.length)); conn.setDoOutput(true); conn.getOutputStream().write(bytes); reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); String line = ""; while ((line = reader.readLine()) != null) { response.append(line); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != reader) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } } return response.toString(); } }
上面的代码就是通过java代码调用kuaidi100的查询接口,这个查询接口会通过快递单号自动识别快递是属于哪个快递公司,然后调用对应快递公司接口获取响应数据。付费购买接口使用权其实就是生成一个授权key和实时查询公司编号customer,在线调用会做身份认证。这样就可以获取快递信息的json数据了。我已经购买了100块大洋的接口使用权,大家可直接调用快递查询接口。
controller代码 快递信息增删查改的controller就不在列了,这里主要看下我对查询快递的接口进行了一次包装处理。代码如下: