快递100官网地址:https://api.kuaidi100.com/document/5f0ffb5ebc8da837cbd8aefc
第一步:申请企业版的key(https://api.kuaidi100.com/register/enterprise/)
第二步:把得到的key相关数据放至application.yml文件中
第三步:首先先发起订阅请求,看需求是什么样的。可以在填快递单号时发送请求,也可以定时批量发送请求。
@Value("${kuaidi100.key}")
private String key;//第一步所申请的key
@Value("${kuaidi100.callbackurl}")
private String callbackurl; //回调地址 ,配置在yml文件里,需要是外网地址,本地测的时候需要发布一个测试服务,可以现在postman上面调通。callbackurl就是第4步要介绍的回调接口。
private Stringfrom =""; //出发地城市
private Stringto =""; //目的地城市
private Stringsalt =""; //加密串
private int resultv2 =1; //行政区域解析
private int autoCom =0; //单号智能识别
private int interCom =0; //开启国际版
private StringdepartureCountry =""; //出发国
private StringdepartureCom =""; //出发国快递公司编码
private StringdestinationCountry =""; //目的国
private StringdestinationCom =""; //目的国快递公司编码
private Stringphone =""; //手机号
//订阅该订单,放在某一个方法里
//传快递公司编号(必填),订单号(必填),出发地城市,目的地城市,回调地址,请求快递100订阅请求接口(具体参数可参照快递100订阅请求接口的请求参数)
逻辑层:
SubscriptionRequest subscriptionRequest =new SubscriptionRequest(key);
String result = subscriptionRequest.subscribeData(address.getExpressNo(), address.getExpressNum(), from, to, callbackurl, salt, resultv2, autoCom, interCom, departureCountry, departureCom, destinationCountry, destinationCom, phone);
JSONObject jsonObject =JSONObject.parseObject(result);
Integer returnCode = jsonObject.getInteger("returnCode");//当returnCode 为200时表示订阅成功,在15到4个小时会回调接口,改状态
if(returnCode!=200){
logger.info("订阅失败",result);
}
//上面一个方法要调用的
/**
* 订阅请求方法
* @param company 快递公司编码
* @param number 快递单号
* @param from 出发地城市
* @param to 目的地城市
* @param callbackurl 回调地址URL
* @param salt 加密签名字符串
* @param resultv2 行政区域解析
* @param autoCom 智能判断单号归属快递公司
* @param interCom 开启国际版
* @param departureCountry 出发国编码
* @param departureCom 出发国快递公司编码
* @param destinationCountry 目的国编码
* @param destinationCom 目的国快递公司编码
* @param phone 手机号
* @return
*/
public StringsubscribeData(String company, String number, String from, String to, String callbackurl, String salt, int resultv2, int autoCom,
int interCom, String departureCountry, String departureCom, String destinationCountry, String destinationCom, String phone) {
StringBuilder param =new StringBuilder("{");
param.append("\"company\":\"").append(company).append("\"");
param.append(",\"number\":\"").append(number).append("\"");
param.append(",\"from\":\"").append(from).append("\"");
param.append(",\"to\":\"").append(to).append("\"");
param.append(",\"key\":\"").append(this.key).append("\"");
param.append(",\"parameters\":{");
param.append("\"callbackurl\":\"").append(callbackurl).append("\"");
param.append(",\"salt\":\"").append(salt).append("\"");
if(1 == resultv2) {
param.append(",\"resultv2\":1");
}else {
param.append(",\"resultv2\":0");
}
if(1 == autoCom) {
param.append(",\"autoCom\":1");
}else {
param.append(",\"autoCom\":0");
}
if(1 == interCom) {
param.append(",\"interCom\":1");
}else {
param.append(",\"interCom\":0");
}
param.append(",\"departureCountry\":\"").append(departureCountry).append("\"");
param.append(",\"departureCom\":\"").append(departureCom).append("\"");
param.append(",\"destinationCountry\":\"").append(destinationCountry).append("\"");
param.append(",\"destinationCom\":\"").append(destinationCom).append("\"");
param.append(",\"phone\":\"").append(phone).append("\"");
param.append("}");
param.append("}");
Map params =new HashMap();
params.put("schema", "json");
params.put("param", param.toString());
System.out.println(params);
return PostRequest.post(SUBSCRIBE_URL,params);
}
//上面一个方法要调用的
/**
* 发送post请求
*/
public static Stringpost(String path, Map params) {
StringBuffer response =new StringBuffer("");
BufferedReader reader =null;
try {
StringBuilder builder =new StringBuilder();
for (Map.Entry 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(path);
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();
}
第四步:回调接口
controller层
@ApiOperation("快递100订阅事件回调")
@PostMapping("/callback")
@AnonymousAccess
public CallbackResponsecallback(HttpServletRequest request) {//
String param = request.getParameter("param");
Gson gson =new Gson();
CallbackResponse response;
try {
CallbackRequest callbackRequest = gson.fromJson(param, CallbackRequest.class);
response =ordersService.expressCallback(callbackRequest);
}catch (Exception ex) {
System.out.println("快递100回调错误---------------\n请求参数:\n"+param+ ex);
response =new CallbackResponse();
response.setResult(false);
response.setMessage(ex.getMessage());
response.setReturnCode("500");
}
return response;
}
service层:
/**
* 快递100回调接口
*
* @param request 回调内容
* @return 回单返回内容
*/
CallbackResponseexpressCallback(CallbackRequest request);
serviceImpl层:
@Override
@Transactional
public CallbackResponseexpressCallback(CallbackRequest request) {
CallbackResponse response =new CallbackResponse();
//最新查询结果,若在订阅报文中通过interCom字段开通了国际版,则此lastResult表示出发国的查询结果,全量,倒序(即时间最新的在最前)
CallbackRequest.LastResult lastResult = request.getLastResult();
if (lastResult !=null) {
//快递单当前签收状态,包括0在途,1揽收,2疑难,3签收,4退签,5派件,6退回,7转投,10待清关,11清关中,12已清关,13清关异常,14拒签
String state = lastResult.getState();
//快递单号
String expressNo = lastResult.getNu();
Orders order =addressRepository.findByExpressNo(expressNo);//查询订单号
//如果订单存在
if (order!=null) {
//更改运单的状态
order.setStatus(state); //快递单当前状态,包括0在途,1揽收,2疑难,3签收,4退签,5派件,6退回,7转投,10待清关,11清关中,12已清关,13清关异常,14拒签
addressRepository.save(order);
}
}
return response;
}
第五步:回调接口可以现在postman里调通
Headers设置:
Body参数设置:
param参数要严格按照快递100回调地址上的参数文档来:
{
"status": "polling",
"billstatus": "got",
"message": "",
"autoCheck": "1",
"comOld": "yuantong",
"comNew": "ems",
"lastResult": {
"message": "ok",
"state": "0",
"status": "200",
"condition": "F00",
"ischeck": "0",
"com": "yuantong",
"nu": "SF1803778191716",
"data": [
{
"context": "上海分拨中心/装件入车扫描 ",
"time": "2012-08-28 16:33:19",
"ftime": "2012-08-28 16:33:19",
"status": "在途",
"areaCode": "310000000000",
"areaName": "上海市"
},
{
"context": "上海分拨中心/下车扫描 ",
"time": "2012-08-27 23:22:42",
"ftime": "2012-08-27 23:22:42",
"status": "在途",
"areaCode": "310000000000",
"areaName": "上海市"
}
]
},
"destResult": {
"message": "ok",
"state": "0",
"status": "200",
"condition": "F00",
"ischeck": "0" ,
"com": "speedpost",
"nu": "EX015142583SG",
"data": [
{
"context": "[01000]Final delivery Delivered to: SLOVESNOV",
"time": "2016-05-24 14:00:00",
"ftime": "2016-05-24 14:00:00",
"status": "签收",
"areaCode": null,
"areaName": null
}
]
}
}
第6步:回调地址会根据不同的时间来处理订单物流状态。