最近在做物流这块的功能相关设计,比对国内好几家第三方物流api,最终还是选择了快递100
前期准备工作:注册快递100后台,得到对应的配置信息。key、customer、secret等配置信息
快递100计费方式采用按次收费,需要购买,如果次数不足的话,接口会提交失败。
api文档地址:快递地图轨迹查询服务-快递100API开放平台
快递100地图轨迹订阅接口地址:http://poll.kuaidi100.com/pollmap
参数封装:
//调用快递100推送信息服务接口
String post;
try {
post = HttpRequestUtil.post(paramMap, properties.getSendUrl(), "application/x-www-form-urlencoded");
log.info("快递100信息返回:{}", post);
} catch (Exception e) {
log.info("快递100信息返回异常:{}", e);
throw new BizException(e.getMessage());
}
private Map<String, Object> getKuaiParamMap(String expressOrderNo, String expressCode, String from, String to) {
Map<String, Object> map = new HashMap<>();
SendCoreReq sendCoreReq = new SendCoreReq();
SendAuxiliaryReq req = new SendAuxiliaryReq();
req.setCallbackurl(properties.getCallBackUrl());
req.setResultv2("5");
sendCoreReq.setParameters(req);
sendCoreReq.setKey(properties.getKey());
sendCoreReq.setNumber(expressOrderNo);
sendCoreReq.setCompany(expressCode);
sendCoreReq.setFrom(from);
sendCoreReq.setTo(to);
String gson = new Gson().toJson(sendCoreReq);
map.put("param", gson);
return map;
}
接口成功后,代表物流订阅成功。
配置的回调地址,快递100在查询到地图物流数据之后会推送到你发送的回调url
推送接收demo: 记得验签,下面示意中我是删除了验签代码
/**
* 快递100回调
*
*/
@PostMapping("/v1/callBack/result")
public KuaiDi100Resp callBackResult(QueryBaseData param) {
try {
return express100Service.callBackResult(param);
} catch (Exception e) {
log.info("回调异常:{}",e);
KuaiDi100Resp rsp=new KuaiDi100Resp();
rsp.setResult(Boolean.FALSE);
rsp.setMessage(e.getMessage());
rsp.setReturnCode(Result.fail().getCode());
return rsp;
}
}
@Data
public class QueryBaseData {
/**签名验证**/
private String sign;
/**请求参数**/
private String param;
}
service解析param
public KuaiDi100Resp callBackResult(QueryBaseData param) {
log.info("快递100回调接口入参:{}", JSONUtil.toJsonStr(param));
KuaiDi100Resp rsp=new KuaiDi100Resp();
QueryTrackResult queryTrackResult = JSONUtil.toBean(param.getParam(), QueryTrackResult.class);
QueryTrackResp lastResult = queryTrackResult.getLastResult();
String expressOrderNo = lastResult.getNu();
int state = Integer.parseInt(lastResult.getState());
//do业务处理,更新派件、签收状态时间等业务处理
rsp.setResult(Boolean.TRUE);
//code码是200
rsp.setReturnCode(ResultConstant.OK.getCode());
rsp.setMessage("成功");
return rsp;
}
对象类:
@Data
public class QueryTrackResult {
/**监控状态**/
private String status;
/**监控状态相关消息,如:3天查询无记录,60天无变化**/
private String message;
/**快递公司编码是否出错,0为本推送信息对应的是贵司提交的原始快递公司编码,
* 1为本推送信息对应的是我方纠正后的新的快递公司编码。
* 一个单如果我们连续3天都查不到结果,我方会(1)判断一次贵司提交的快递公司编码是否正确,
* 如果正确,给贵司的回调接口(callbackurl)推送带有如下字段的信息:autoCheck=0、comOld与comNew都为空;
* (2)如果贵司提交的快递公司编码出错,我们会帮忙用正确的快递公司编码+原来的运单号重新提交订阅并开启监控
* (后续如果监控到单号有更新就给贵司的回调接口(callbackurl)推送带有如下字段的信息:autoCheck=1、comOld=原来的公司编码、comNew=新的公司编码);
* 并且给贵方的回调接口(callbackurl)推送一条含有如下字段的信息:status=abort、autoCheck=0、comOld为空、comNew=纠正后的快递公司编码。**/
private String autoCheck;
/**贵司提交的原始的快递公司编码。详细见autoCheck后说明。若开启了国际版(即在订阅请求中增加字段interCom=1),
* 则回调请求中暂无此字段
**/
private String comOld;
/**我司纠正后的新的快递公司编码。详细见autoCheck后说明。若开启了国际版(即在订阅请求中增加字段interCom=1)
* ,则回调请求中暂无此字段**/
private String comNew;
/**具体信息**/
private QueryTrackResp lastResult;
}
@Data
public class QueryTrackResp {
/**
* 消息体,请忽略
*/
private String message;
/**
* 快递单号
*/
private String nu;
/**
* 是否签收标记
*/
private String ischeck;
/**
* 快递公司编码,一律用小写字母
*/
private String com;
/**
* 通讯状态
*/
private String status;
/**
* 轨迹详情数组
*/
private List<QueryTrackData> data;
/**
* 快递单当前状态,包括0在途,1揽收,2疑难,3签收,4退签,5派件,6退回,7转投,10待清关,11清关中,12已清关,13清关异常,14拒签 等13个状态
*/
private String state;
/**
* 快递单明细状态标记
*/
private String condition;
private QueryTrackRouteInfo routeInfo;
/**
* 是否存在环路
*/
private Boolean isLoop;
/**
* 轨迹地图链接
*/
private String trailUrl;
/**
* 预计到达时间
*/
private String arrivalTime;
/**
* 平均耗时
*/
private String totalTime;
/**
* 到达还需多少时间
*/
private String remainTime;
}
@Data
public class QueryTrackData {
/**
* 时间,原始格式
*/
private String time;
/**
* 物流轨迹节点内容
*/
private String context;
/**
* 格式化后时间
*/
private String ftime;
/**
* 行政区域的编码
*/
private String areaCode;
/**
* 行政区域的名称
*/
private String areaName;
/**
* 签收状态 (0在途,1揽收,2疑难,3签收,4退签,5派件,6退回,7转投)
*/
private String status;
/**
* 本数据元对应的行政区域经纬度,resultv2=4或6标记后才会出现
*/
private String areaCenter;
/**
* 本数据元对应的行政区域拼音,resultv2=4或6标记后才会出现
*/
private String areaPinYin;
/**
* 状态值
*/
private String statusCode;
}
@Data
public class QueryTrackRouteInfo {
/**
* 出发位置
*/
private QueryTrackPosition from;
/**
* 当前位置
*/
private QueryTrackPosition cur;
/**
* 收货地
*/
private QueryTrackPosition to;
}
@Data
public class QueryTrackPosition {
/**
* 地址编码
*/
private String number;
/**
* 地址名称
*/
private String name;
}
业务逻辑处理完之后以快递100的接口返回要求返回,要不在控制台会看到推送失败的错误