spring boot 2 : 开发快递100订阅运单数据(spring boot v2.5.4)
一,快递100开发的相关文档
1,快递公司编码的表格
登录后访问:
https://api.kuaidi100.com/manager/page/document/kdbm
2,快递公司编码的表格下载:
https://api.kuaidi100.com/manager/utils/download/kdbm.do
3,官方代码地址:
github
https://github.com/kuaidi100-api
gitee
https://gitee.com/kuaidi100-api
4,开发平台的地址:
https://api.kuaidi100.com/
说明:刘宏缔的架构森林是一个专注架构的博客,
网站:https://blog.imgtouch.com
本文: https://blog.imgtouch.com/index.php/2023/06/01/spring-boot-2-kai-fa-kuai-di-100-ding-yue-yun-dan-shu-ju/
对应的源码可以访问这里获取: https://github.com/liuhongdi/
或: https://gitee.com/liuhongdi
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,获得key和customer:
登录到后台:我的信息->企业信息
右侧有key和customer:
三,导入java库:
1,mvnrepository上的地址:
https://mvnrepository.com/artifact/com.github.kuaidi100-api/sdk
如图:
2,导入到maven:
<dependency> <groupId>com.github.kuaidi100-api</groupId> <artifactId>sdk</artifactId> <version>1.0.5</version> </dependency>
四,配置数据库:
建表:
CREATE TABLE `express` ( `expressId` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', `expressNum` varchar(100) NOT NULL DEFAULT '' COMMENT '运单编号', `companyCode` varchar(100) NOT NULL DEFAULT '' COMMENT '快递公司编码', `state` tinyint NOT NULL DEFAULT '-1' COMMENT '-1初始状态,0在途,1揽件,2疑难,3签收,4退签,5派件,6退回', `addTime` datetime NOT NULL DEFAULT '2022-01-21 00:00:00' COMMENT '添加时间', `subStatus` int NOT NULL DEFAULT '0' COMMENT '订阅状态,0,初始,200:成功', `subRequest` varchar(2000) NOT NULL DEFAULT '' COMMENT '请求参数', `subResult` varchar(2000) NOT NULL DEFAULT '' COMMENT '返回参数', PRIMARY KEY (`expressId`), UNIQUE KEY `expressNum` (`expressNum`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='运单表'
CREATE TABLE `express_data` ( `dataId` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', `expressId` bigint NOT NULL DEFAULT '0' COMMENT '运单id', `expressNum` varchar(100) NOT NULL DEFAULT '' COMMENT '运单', `dataTime` timestamp NOT NULL DEFAULT '2022-01-21 00:00:00' COMMENT '运单数据的时间', `context` varchar(500) NOT NULL DEFAULT '' COMMENT '运单说明文字', `addTime` datetime NOT NULL DEFAULT '2022-01-21 00:00:00' COMMENT '添加时间', PRIMARY KEY (`dataId`), UNIQUE KEY `expressId` (`expressId`,`dataTime`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='运单数据表’
五,配置日志:
说明:从快递100所post过来的数据,可以保存到数据库,也可以保存到日志文件,
这里我们选择保存到日志文件
log4j2.xml
<!--kuaidi100的日志记录追加器--> <RollingFile name="kd100LogRollingFile" fileName="${LOG_HOME}/kd100.log" filePattern="${LOG_HOME}/logs/$${date:yyyy-MM}/kd100-%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level %logger{35} - %msg %n"/> <Policies> <SizeBasedTriggeringPolicy size="500 MB"/> <TimeBasedTriggeringPolicy/> </Policies> </RollingFile>
六,配置文件:
kuaidi100: key: KBAABBccDD11 customer: C1FAABBccDDAABBccDD49F97B706F2E secret: 8e1AABBccDDAABBccDDAABBccDDce83 userid: 744aabbccddeeffgghhiibbdda3ba #回调地址(写上真实的回调地址) url: http://www.lhdtest.net/api/express/callback #开通行政区域解析功能以及物流轨迹增加物流状态值 resultv2: 1
七,java代码:
1,service/impl/ExpressServiceImpl.java
@Service public class ExpressServiceImpl implements ExpressService { @Resource private ConfigBeanValue configBeanValue; @Resource private ExpressMapper expressMapper; @Resource private ExpressDataMapper expressDataMapper; private Logger loggerKd100 = LogManager.getLogger("kd100LogRollingFile"); @Override public boolean subscribe(String code,String num) throws Exception { // 授权key String key = configBeanValue.kd100Key; String customer = configBeanValue.kd100Customer; // 接口回调地址 String callbackUrl = configBeanValue.kd100Url; //PropertiesReader.get("url"); // 开启行政区域解析 String resultv2 = configBeanValue.kd100Resultv2; //PropertiesReader.get("resultv2"); Express express = new Express(); SubscribeParameters subscribeParameters = new SubscribeParameters(); subscribeParameters.setCallbackurl(callbackUrl); subscribeParameters.setPhone("17725390266"); subscribeParameters.setResultv2(resultv2); SubscribeParam subscribeParam = new SubscribeParam(); subscribeParam.setParameters(subscribeParameters); subscribeParam.setCompany(code); subscribeParam.setNumber(num); subscribeParam.setKey(key); SubscribeReq subscribeReq = new SubscribeReq(); subscribeReq.setSchema(ApiInfoConstant.SUBSCRIBE_SCHEMA); subscribeReq.setParam(new Gson().toJson(subscribeParam)); IBaseClient subscribe = new Subscribe(); // 订阅推送服务 HttpResult httpResult = subscribe.execute(subscribeReq); SubscribeResp response = new Gson().fromJson(httpResult.getBody(), SubscribeResp.class); String returnCode = response.getReturnCode(); if("501".equals(returnCode)){ // 重复订阅的请求,不改变订阅成功的状态,只保存报文(以防误操作) express.setSubStatus(200); }else{ express.setSubStatus(Integer.valueOf(returnCode)); } express.setSubRequest(subscribeReq.getParam()); express.setSubResult(httpResult.getBody()); //得到express的相应字段 express.setExpressNum(num); express.setCompanyCode(code); express.setState(-1); //express.set //添加到数据库 int expressId = expressMapper.insertOneExpress(express); //返回: return true; } @Override public SubscribeResp handleCallBack(HttpServletRequest request) { // 获取参数 String param = request.getParameter("param"); String sign = request.getParameter("sign"); //写日志: //loggerKd100 loggerKd100.info("param:"); loggerKd100.info(param); loggerKd100.info("sign:"); loggerKd100.info(sign); //处理数据,add database SubscribePushParamResp backResp = new Gson().fromJson(param, SubscribePushParamResp.class); String expressNum = backResp.getLastResult().getNu(); Express express = expressMapper.selectOneExpressByExpressNum(expressNum); Long expressId = express.getExpressId(); //查询数据库, List<SubscribePushData> dataList = backResp.getLastResult().getData(); List<ExpressData> infoList = new ArrayList<>(); for (SubscribePushData data : dataList) { ExpressData info = new ExpressData(); info.setDataTime(data.getFtime()); info.setExpressId(expressId); info.setExpressNum(expressNum); info.setContext(data.getContext()); infoList.add(info); } if(infoList.size() > 0){ // 入库操作前,先删除sys_express_info表中的数据,只保留最新数据。 //expressInfoMapper.deleteSysExpressInfoByNum(expressNum); expressDataMapper.deleteExpressDataByExpressId(expressId); for (ExpressData data : infoList) { expressDataMapper.insertOneExpressData(data); } //expressInfoMapper.insertSysExpressBatch(infoList); } //更新状态 int state = Integer.parseInt(backResp.getLastResult().getState()); expressMapper.updateOneExpressState(expressId,state); //返回: SubscribeResp response = new SubscribeResp(); response.setResult(Boolean.TRUE); response.setReturnCode("200"); response.setMessage("成功"); return response; } }
2,controller/ExpressController.java
@RestController @RequestMapping("/express") public class ExpressController { @Resource private ExpressService expressService; //session详情 @GetMapping("/subscribe") @ResponseBody public Result subscribe(@NotBlank(message="快递公司编号")@RequestParam("code") String code, @NotBlank(message="运单编号")@RequestParam("num") String num) throws Exception{ Map<String, Object> data = new HashMap<String, Object>(); boolean isIns = expressService.subscribe(code, num); return Result.success(data); } /** * 快递100回调接口 * @param request */ @PostMapping("/callback") public SubscribeResp callBack(HttpServletRequest request) throws Exception { return expressService.handleCallBack(request); } }
3,ExpressMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.yj.storeback.mapper.ExpressMapper"> <insert id="insertOneExpress" parameterType="com.yj.storeback.pojo.Express" useGeneratedKeys="true" keyProperty="expressId" > insert into express(expressNum,companyCode,state,addTime,subStatus,subRequest,subResult) values( #{expressNum},#{companyCode},#{state},now(),#{subStatus},#{subRequest},#{subResult} ) </insert> <select id="selectOneExpressByExpressNum" resultType="com.yj.storeback.pojo.Express"> select * from express where expressNum=#{expressNum} </select> <update id="updateOneExpressState"> UPDATE express SET state = #{state} WHERE expressId=#{expressId} </update> </mapper>
4,ExpressDataMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.yj.storeback.mapper.ExpressDataMapper"> <insert id="insertOneExpressData" parameterType="com.yj.storeback.pojo.ExpressData" useGeneratedKeys="true" keyProperty="dataId" > insert into express_data(expressId,expressNum,dataTime,addTime,context) values( #{expressId},#{expressNum},#{dataTime},now(),#{context} ) </insert> <delete id="deleteExpressDataByExpressId" > delete from express_data where expressId = #{expressId} </delete> </mapper>
5,ExpressService.java
public interface ExpressService { public boolean subscribe(String code,String num) throws Exception; public SubscribeResp handleCallBack(HttpServletRequest request); }
6,ExpressMapper.java
@Repository @Mapper public interface ExpressMapper { int insertOneExpress(Express express); Express selectOneExpressByExpressNum(@Param("expressNum")String expressNum); int updateOneExpressState(@Param("expressId")Long expressId, @Param("state")int state); }
7,ExpressDataMapper.java
@Repository @Mapper public interface ExpressDataMapper { int insertOneExpressData(ExpressData expressData); int deleteExpressDataByExpressId(@Param("expressId")Long expressId); }
八,测试效果:
1订阅
访问:
http://www.lhdtest.net/api/express/subscribe?code=shunfeng&num=SF1322339353060
返回:
2,接收推送:
查看日志:
[lhdpc@blog logs]$ tail -100 /data/logs/nginxlogs/store.access_log
日志如下:
... 120.92.182.60 - - [29/Jan/2022:16:55:17 +0800] "POST /api/express/callback HTTP/1.1" 200 0 "-" "HttpComponents/1.1" ...
九,查看springboot的版本:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.5.4)