**
springboot集成快递100实现查询快递,面单打印;面单取消
对最近工作上面一个总结,最近公司使用了自己的系统对接京东物流,所以采用了集成快递100的方案;
这里讲一下为啥不直接他们的那个jar包,其实很简单,没啥用,浪费资源,好了,接下来开始上手操作;
基础环境就不配置了,相信大伙这个最基本的那个springboot环境会配置,不然真的拿你没办法;
1配置一下那个kuaidi100.properties里面所需参数;
kuaidi100.key=************
kuaidi100.customer=***********************
kuaidi100.userid=*************************
kuaidi100.secret=***********************
kuaidi100.siid=***************************
首先讲下那个查询快递物流信息的吧!
配置类:
```java
package com.lihua.config;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* @author 一只会飞的田园犬
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
@Component
@PropertySource("classpath:/config/kuaidi100.properties")
@ConfigurationProperties(prefix = "kuaidi100")
public class Kuaidi100Config {
private String key;
private String customer;
private String userid;
/**
* 私钥
*/
private String secret;
/**
* 快递打印机设备码
*/
private String siid;
}
@Autowired
private DtsOrderService dtsOrderService;
@Autowired
private Kuaidi100Config kuaidi100Config;
@GetMapping("queryMap")
public ResponseResult queryMap(String orderSn) {
if (StringUtils.isEmpty(orderSn)) {
return ResponseResult.setResult(ResponseEnum.PARAMETER_ISEMPTY);
} else {
DtsOrderEntity order = this.dtsOrderService.getOne(new QueryWrapper<DtsOrderEntity>().eq("order_sn", orderSn));
if (ObjectUtils.isEmpty(order)) {
return ResponseResult.setResult(ResponseEnum.ORDER_SN_IS_NOT_IN_SYSTEM);
} else {
if (StringUtils.isEmpty(order.getShipChannel())) {
return ResponseResult.setResult(ResponseEnum.EXPRESS_NOT_MESSAGE);
} else if (order.getShipChannel().equals("zt")) {
return ResponseResult.setResult(ResponseEnum.NOT_USE_EXPRESS);
} else if (StringUtils.isEmpty(order.getShipSn())) {
return ResponseResult.setResult(ResponseEnum.EXPRESS_CODE_ISNOEMPTY);
} else {
Map<String, String> paramMap = new HashMap<>(12);
paramMap.put("com", {快递公司});
paramMap.put("num",{运单号});
paramMap.put("from", {发货地址});
paramMap.put("to", {收货地址});
paramMap.put("resultv2", "0");
paramMap.put("show", "0");
paramMap.put("order", "desc");
Gson gson = new Gson();
String param = gson.toJson(paramMap);
String sign = genDigest(param, kuaidi100Config.getKey(), kuaidi100Config.getCustomer);
String data = HttpRequest.post("https://poll.kuaidi100.com/poll/query.do?" + "customer" + "=" + customer + "&" + "sign" + "=" + sign + "&" + "param" + "=" + param)
.header("Content-Type", "tapplication/x-www-form-urlencoded")
.execute().body();
DtsExpressDTO dtsExpressDto = JSONObject.parseObject(data, DtsExpressDTO.class);
Map map = JSONObject.parseObject(data, Map.class);
String message = (String) map.get("message");
String returnCode = (String) map.get("returnCode");
if (ApiCodeConstant.EXPRESS_MESSAGE.equals(message)) {
return ResponseResult.setResult(ResponseEnum.THE_EXPRESS_COMPANY_IS_NOT_SUPPORTED);
} else if (message.equals(ApiCodeConstant.KUAIDI_MESSAGE)) {
return ResponseResult.setResult(ResponseEnum.EXPRESS_NOT_MESSAGE);
} else {
List<ExpressDTO> parseObject = JSONObject.parseArray(dtsExpressDto.getData(), ExpressDTO.class);
return ResponseResult.ok().data("list", parseObject) .data("url", trailUrl);
}
}
}
}
}
加密算法
``/**
* @param param 核心数据
* @param key key
* @param customer 私钥
* 注意加密顺序: param +t+key+ secret
* @return 验证签名结果
*/
private String genDigest(String param, String key, String customer) {
return DigestUtil.md5Hex(param + key + customer).toUpperCase();
}
```/**
* @author 一只会飞的田园犬
* 快递返回数据映射实体类;
*/
@Data
public class DtsExpressDTO {
/**
* 消息
*/
private String message;
/**
* 运单编号
*/
private String nu;
/**
* 运输公司
*/
private String com;
/**
* 状态码
*/
private String status;
/**
* 快递状态码
*/
private String state;
/**
*
*/
private String data;
private Boolean result;
private String returnCode;
private Date addTime;
private Date updateTime;
private String orderSn;
}
package com.lihua.config;
/**
* @author 一只会飞的田园犬
*/
public class ApiCodeConstant {
public static final int WX_REFUND_CODE = 200;
public static final int WX_REFUND_STATUS = 204;
public static final Integer REFUND_STATUS = 5;
public static final Integer REFUND_CODE = 3;
public static final Integer ORDER_STATUS = 3;
public static final String KUAIDI_MESSAGE = "查询无结果,请隔段时间再查";
public static final String MIANDAN_EXIT_MESSAGE_OK = "取消成功";
public static final String USER_CODE = "user_id";
public static final String ADDRESS_CODE = "address";
public static final String ORDER_CODE = "order_sn";
public static final String RESPONSE_CODE = "result";
public static final String PAY_RESULT = "SUCCESS";
public static final String MSG = "成功";
public static final String TRANSPORTATION_WAY="zt";
/**
* 退款状态
*/
public static final String REFUND_MESSAGE = "SUCCESS";
public static final String RETRUN_MSG = "message";
public static final String WX_MCH_ID = "mchid";
public static final String REQUEST_CODE_NAME = "Accept";
public static final String REQUEST_CODE_VALUE = "application/json";
public static final String ORDER_ID = "out_trade_no";
public static final String NUMBER_CODE = "amount";
public static final String ADD_TIME = "add_time";
public static final String CODING = "UTF-8";
public static final String RETURN_QUESTION_TOTAL = "total";
public static final String RETURN_QUESTION_ROWS = "rows";
public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Content-Disposition";
public static final String OBJECT_DATA = "entity";
public static final String EXIT_RETRUN_CODE = "200";
public static final String COINS_TYPE = " JF";
public static final String REFUSER_MESSAGE = "抱歉,你的订单无法取消,请联系系统管理员稍后重试";
public static final String EXPRESS_MESSAGE = "不支持此快递公司";
public static final Integer FOUR = 4;
public static final Integer THREE = 3;
public static final Integer TWO = 2;
public static final Integer ONE = 1;
public static final Integer FIVE = 5;
public static final Integer ZERO = 0;
/**
* 加密方式
*/
public static final String ENCRYFPTION_MD5 = "md5-salt";
public static final String ENCRYFPTION_HMACMD5 = "HMacMD5";
public static final String ENCRYFPTION_HMACSHA1 = "HMacSHA1";
public static final String ENCRYFPTION_HMACSHA256 = "HMacSHA256";
public static final String ENCRYFPTION_HMACSHA512 = "HMacSHA512";
private ApiCodeConstant() {
}
}
import lombok.Data;
import java.util.Date;
/**
* @author 一只会飞的田园犬
* 该实体类就对应那个快递信息
*
*/
@Data
public class ExpressDTO {
/**
* 快递更新事件
*/
private Date time;
/**
* 快递更新事件
*/
private String context;
}
接下来给你们看下那个快递查询数据:
{
"code": 20000,
"message": "成功",
"data": {
"list": [
{
"time": "2022-10-25 17:49:14",
"context": "[佛山乐安营业部]京东快递 已收取快件"
},
{
"time": "2022-10-25 17:49:14",
"context": "[佛山乐安营业部]您的快件已由【佛山乐安营业部】揽收完成"
},
{
"time": "2022-10-25 17:30:32",
"context": "[佛山乐安营业部]揽收任务已分配给朱广委。给您服务的快递员已完成新冠疫苗接种,祝您身体健康。"
}
]
}
}
接下来教你查地图跟那个物流信息;
这个很简单就不粘贴代码了,把下面这个代码
String data = HttpRequest.post("https://poll.kuaidi100.com/poll/query.do?" + "customer" + "=" + customer + "&" + "sign" + "=" + sign + "&" + "param" + "=" + param)
.header("Content-Type", "tapplication/x-www-form-urlencoded")
.execute().body();
中那个url地址换成https://poll.kuaidi100.com/poll/maptrack.do
就行了,很简单就不描述了,一般情况下使用最多的是这个接口来查询物流信息,因为功能吊打上面那个,一个地图跟物流跟踪信息都有,是我就都要!!!
最后来弄弄那个快递面单打印,相信大部分开发者在这里很痛苦,我也是,🤭;
这里我就不详细写了,因为跟上面是一个套路;
相信一部分人看到上面参数很熟悉不错就是那个param;以及所需参数;
param数据结构:
method = order
key = ** ** *
sign = ** ** *
t = 1470304729724
param = {
"partnerId": "123456",
"partnerKey": "",
"code": "",
"kuaidicom": "zhaijisong",
"recMan": {
"name": "张三",
"mobile": "13888888888",
"printAddr": "广东深圳市南山区金蝶软件园",
"company": ""
},
"sendMan": {
"name": "李四",
"mobile": "13888888888",
"printAddr": "广东深圳市南山区金蝶软件园",
"company": ""
},
"cargo": "test",
"tempId": "60f6c17c7c223700131d8bc3",
"childTempId": "61bff9efc66fb00013a1b168",
"backTempId": "61bffa26c66fb00013a1b16c",
"payType": "SHIPPER",
"expType": "标准快递",
"remark": "测试下单,请勿发货",
"collection": "0",
"needChild": "0",
"needBack": "0",
"count": 1,
"printType": "CLOUD",
"siid": "KX100*******",
"needDesensitization": true,
"needLogo": true,
"needOcr": false
}
看到这个数据结构不要想,首先就是一个HashMap结构然后转为json(注意里面还有几个Map结构数据,所以做好泛型是<String,Object>);
1,这里稍微注意一个细节printAddr这个不要打错了,这个可能有些人会打成那个address是不是很熟悉?
2,还有就是一个地方值得注意,可能有些人会想为啥我不能直接打印?还要使用哪个插件打印,不能在前端点击按钮直接打印?原因很简单你那个printType这个设置不是CLOUD,这个是个重点,各位看官看到这里记得做好笔记,下次可能你会犯这个错;
3还有一个地方也要注意cargo这个最好不要写其他的,写物品或者你们公司产品,如果写上测试...等不合法字样,快递小哥会不揽收的,发不出的...
还有一个注意点,哪个子单怎么设置相信不少看官老爷们肯定掉过坑里面,导致第一天不少看官第一天发货就被骂,这个一个是看那个count值,这个很重要,但是还有一个值也要注意,哪个needChild要设置为1,这个时候就会产生子单了;
最后讲讲这个面单取消
注意这里有个小细节,哪个加密算法有些地方是参数三个,有些是四个,特别注意,别加错密了!!!
看到上面这个字段,我们只要两个就好了,快递公司编码,注意他那个有字典的,可以去看看,别搞错了,数据结构依然是HashMap转json传参;
这里用到了多种json转换工具,看你们习惯;
如果有什么疑问可以来撩我🤭!