├── src ├── main │ └── java │ │ └── net │ │ └── kdks │ │ ├── enums │ │ ├── package-info.java │ │ ├── ValueEnum.java │ │ ├── ExpressStateEnum.java │ │ └── ExpressCompanyCodeEnum.java │ │ ├── utils │ │ ├── package-info.java │ │ ├── Assert.java │ │ ├── DigestUtils.java │ │ ├── MapUtils.java │ │ ├── DateUtils.java │ │ ├── StringUtils.java │ │ └── Base64Utils.java │ │ ├── model │ │ ├── package-info.java │ │ ├── sf │ │ │ ├── package-info.java │ │ │ ├── RouteResps.java │ │ │ ├── WaybillNoInfo.java │ │ │ ├── MsgData.java │ │ │ ├── ApiResultData.java │ │ │ ├── ShunfengResult.java │ │ │ └── Route.java │ │ ├── htky │ │ │ ├── package-info.java │ │ │ ├── BaishiTrace.java │ │ │ ├── BaishiProblem.java │ │ │ ├── BaishiTraceLog.java │ │ │ ├── BaishiResult.java │ │ │ ├── BaishiProblemItems.java │ │ │ └── BaishiTraceItems.java │ │ ├── sto │ │ │ ├── package-info.java │ │ │ ├── price │ │ │ │ ├── ShentongPriceDataItem.java │ │ │ │ ├── ShentongPriceResult.java │ │ │ │ ├── ShentongFeeModel.java │ │ │ │ └── ShentongPriceData.java │ │ │ ├── ShentongBaseResult.java │ │ │ ├── ShentongResult.java │ │ │ └── ShentongRoute.java │ │ ├── yto │ │ │ ├── package-info.java │ │ │ ├── YuanTongErrorResult.java │ │ │ └── YuanTongResult.java │ │ ├── zto │ │ │ ├── package-info.java │ │ │ ├── ZhongtongScanSite.java │ │ │ ├── price │ │ │ │ └── ZhongtongPriceData.java │ │ │ ├── ZhongtongResult.java │ │ │ ├── ZhongtongResultV1.java │ │ │ ├── ZhongtongData.java │ │ │ ├── ZhongtongTraceV1.java │ │ │ └── ZhongtongTrace.java │ │ ├── yd │ │ │ ├── route │ │ │ │ ├── YundaRouteSubscribeResult.java │ │ │ │ ├── YundaRouteSubscribeItem.java │ │ │ │ ├── YundaRouteResult.java │ │ │ │ └── YundaRouteItem.java │ │ │ └── YundaResult.java │ │ ├── jt │ │ │ ├── JituResult.java │ │ │ ├── route │ │ │ │ ├── JituRouteResult.java │ │ │ │ └── JituRouteItem.java │ │ │ └── price │ │ │ │ └── JituPriceResult.java │ │ ├── jd │ │ │ ├── JingdongResult.java │ │ │ └── route │ │ │ │ ├── JingdongRouteResult.java │ │ │ │ └── JingdongRouteItem.java │ │ ├── OrderResult.java │ │ ├── BaseParam.java │ │ ├── ExpressPriceResult.java │ │ ├── ExpressRouteSubscribeData.java │ │ ├── ExpressBatchParam.java │ │ ├── CreateOrderParam.java │ │ ├── ExpressParam.java │ │ ├── CargoDetail.java │ │ ├── ContactInfo.java │ │ ├── ExpressData.java │ │ ├── ExpressResult.java │ │ ├── ExpressPriceParam.java │ │ └── ExpressResponse.java │ │ ├── config │ │ ├── package-info.java │ │ ├── BaishiConfig.java │ │ ├── ShentongConfig.java │ │ ├── YundaConfig.java │ │ ├── ShunfengConfig.java │ │ ├── YuantongConfig.java │ │ ├── JingdongConfig.java │ │ ├── ZhongtongConfig.java │ │ └── JituConfig.java │ │ ├── constant │ │ ├── package-info.java │ │ ├── RequestConstant.java │ │ ├── HttpStatusCode.java │ │ ├── ExpressResponseStatus.java │ │ ├── ZhongtongRouteVersion.java │ │ ├── JingdongConstant.java │ │ ├── JituMethod.java │ │ ├── CommonConstant.java │ │ ├── JingdongMethod.java │ │ ├── JituConstant.java │ │ ├── YuantongScanType.java │ │ ├── YuantongMethod.java │ │ ├── ShentongScanType.java │ │ ├── YundaMethod.java │ │ ├── ShentongMethod.java │ │ ├── JingdongScanType.java │ │ ├── JituScanType.java │ │ ├── ZhongtongScanType.java │ │ ├── ZhongtongMethod.java │ │ ├── ShunfengOpCode.java │ │ ├── BaishiScanType.java │ │ └── YundaScanType.java │ │ ├── handler │ │ ├── package-info.java │ │ ├── ExpressHandler.java │ │ ├── ExpressHandlers.java │ │ ├── ExpressJingdongHandler.java │ │ ├── ExpressBaishiHandler.java │ │ ├── ExpressYundaHandler.java │ │ ├── ExpressShentongHandler.java │ │ ├── ExpressJituHandler.java │ │ ├── ExpressYuantongHandler.java │ │ └── ExpressZhongtongHandler.java │ │ └── request │ │ ├── ShentongRequest.java │ │ ├── YundaRequest.java │ │ ├── JituRequest.java │ │ ├── YuantongRequest.java │ │ ├── JingdongRequest.java │ │ └── ZhongtongRequest.java └── test │ ├── resources │ └── config-dev.properties │ └── java │ └── net │ └── kdks │ ├── handler │ ├── ExpressInfoTest.java │ └── ExpressPriceTest.java │ └── config │ └── InitConfig.java ├── .gitignore ├── .github └── workflows │ └── release.yml ├── LICENSE ├── README.md └── pom.xml /src/main/java/net/kdks/enums/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 枚举状态. 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.enums; -------------------------------------------------------------------------------- /src/main/java/net/kdks/utils/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 自定义工具类. 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.utils; -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 实体,包含入参、结构等. 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.model; -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sf/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 顺丰轨迹查询结果 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.model.sf; -------------------------------------------------------------------------------- /src/main/java/net/kdks/config/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 各快递公司开放平台相关配置. 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.config; -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 常量、状态码、类型等. 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.constant; -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/htky/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 百世轨迹查询结果 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.model.htky; -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sto/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 申通轨迹查询结果. 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.model.sto; -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/yto/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 圆通轨迹查询结果. 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.model.yto; -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/zto/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 中通轨迹查询结果. 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.model.zto; -------------------------------------------------------------------------------- /src/main/java/net/kdks/handler/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 快递业务实现,包含轨迹查询、下单等. 3 | * 4 | * @author Ze.Wang 5 | */ 6 | 7 | package net.kdks.handler; -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/zto/ZhongtongScanSite.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.zto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 中通轨迹扫描网点. 7 | * 8 | * @author Ze.Wang 9 | * @since 1.0.0 10 | */ 11 | @Data 12 | public class ZhongtongScanSite { 13 | private String name; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/RequestConstant.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 通用状态、常量. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface RequestConstant { 10 | 11 | 12 | String JSON = "JSON"; 13 | 14 | String XML = "XML"; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sto/price/ShentongPriceDataItem.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sto.price; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 申通运费预估数据. 7 | * 8 | * @author Ze.Wang 9 | * @since 0.0.1 10 | */ 11 | @Data 12 | public class ShentongPriceDataItem { 13 | 14 | private ShentongFeeModel feeModel; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/HttpStatusCode.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * http状态码. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface HttpStatusCode { 10 | /** 11 | * 200. 12 | */ 13 | Integer SUCCESS = 200; 14 | /** 15 | * 500. 16 | */ 17 | Integer EXCEPTION = 500; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/htky/BaishiTrace.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.htky; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | 6 | /** 7 | * 流转信息. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class BaishiTrace { 14 | /** 15 | * 流转信息项. 16 | */ 17 | private List trace; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/ExpressResponseStatus.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 响应状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface ExpressResponseStatus { 10 | 11 | /** 12 | * 成功. 13 | */ 14 | Integer SUCCESS = 1; 15 | /** 16 | * 失败. 17 | */ 18 | Integer FAIL = 0; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/ZhongtongRouteVersion.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 中通路由查询类型. 5 | * 6 | * @author Ze.Wang 7 | * @since 1.0.0 8 | */ 9 | public interface ZhongtongRouteVersion { 10 | /** 11 | * v1. 12 | */ 13 | String V1 = "v1"; 14 | 15 | /** 16 | * v2,最新. 17 | */ 18 | String V2 = "v2"; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # Package Files 8 | target/ 9 | *.jar 10 | *.war 11 | *.nar 12 | *.ear 13 | *.zip 14 | *.tar.gz 15 | *.rarp 16 | 17 | 18 | # exclude idea files 19 | .idea 20 | .settings/ 21 | .project 22 | .classpath 23 | dump.rdb 24 | 25 | # private config 26 | config-prod.properties 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/JingdongConstant.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 京东常量. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.11 8 | */ 9 | public interface JingdongConstant { 10 | String URL = "https://api.jdl.com"; 11 | 12 | String URL_TEST = 13 | "https://uat-api.jdl.com"; 14 | 15 | String REQUEST_SUCCESS_CODE = "0"; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/JituMethod.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 圆通路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface JituMethod { 10 | /** 11 | * 路由查询方法名. 12 | */ 13 | String QUERY_ROUTE = "logistics/trace"; 14 | 15 | /** 16 | * 运费预估方法名. 17 | */ 18 | String QUERY_PRICE = "spmComCost/getComCost"; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sf/RouteResps.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sf; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | 6 | /** 7 | * 路由集. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class RouteResps { 14 | /** 15 | * 单号. 16 | */ 17 | private String mailNo; 18 | /** 19 | * 路由集合. 20 | */ 21 | private List routes; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/zto/price/ZhongtongPriceData.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.zto.price; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 中通运费估算数据. 7 | * 8 | * @author Ze.Wang 9 | * @since 0.0.7 10 | */ 11 | @Data 12 | public class ZhongtongPriceData { 13 | 14 | /** 15 | * 运费. 16 | */ 17 | private String price; 18 | /** 19 | * 时效. 20 | */ 21 | private String hour; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/CommonConstant.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 通用状态、常量. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface CommonConstant { 10 | /** 11 | * 是. 12 | */ 13 | Integer YES = 1; 14 | /** 15 | * 否. 16 | */ 17 | Integer NO = 0; 18 | 19 | String NO_INFO = "单号不存在"; 20 | 21 | String NO_SOPPORT = "暂不支持"; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sf/WaybillNoInfo.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sf; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 单号. 7 | * 8 | * @author Ze.Wang 9 | * @since 0.0.1 10 | */ 11 | @Data 12 | public class WaybillNoInfo { 13 | /** 14 | * 运单号类型1:母单 2 :子单 3 : 签回单. 15 | */ 16 | private Integer waybillType; 17 | 18 | /** 19 | * 运单号. 20 | */ 21 | private String waybillNo; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/JingdongMethod.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 京东路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.11 8 | */ 9 | public interface JingdongMethod { 10 | /** 11 | * 路由查询方法名. 12 | */ 13 | String QUERY_ROUTE = "/ecap/v1/orders/trace/query"; 14 | 15 | /** 16 | * 运费预估方法名. 17 | */ 18 | String QUERY_PRICE = "/ecap/v1/orders/actualfee/query"; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/JituConstant.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 极兔常量. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.8 8 | */ 9 | public interface JituConstant { 10 | String URL = "https://openapi.jtexpress.com.cn/webopenplatformapi/api/"; 11 | 12 | String URL_TEST = 13 | "https://uat-openapi.jtexpress.com.cn/webopenplatformapi/api/"; 14 | 15 | String REQUEST_SUCCESS_CODE = "1"; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/yd/route/YundaRouteSubscribeResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.yd.route; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | 6 | /** 7 | * 韵达轨迹订阅结果. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.9 11 | */ 12 | @Data 13 | public class YundaRouteSubscribeResult { 14 | /** 15 | * 路由信息. 16 | */ 17 | private List orders; 18 | 19 | private Boolean result; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/YuantongScanType.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 圆通路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface YuantongScanType { 10 | /** 11 | * 派件. 12 | */ 13 | String DELIVERING = "派件中"; 14 | /** 15 | * 收件. 16 | */ 17 | String COLLECTED = "已收件"; 18 | 19 | /** 20 | * 客户签收. 21 | */ 22 | String SIGNED = "已签收"; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/htky/BaishiProblem.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.htky; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | 6 | /** 7 | * 问题件. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class BaishiProblem { 14 | 15 | /** 16 | * 问题信息. 17 | */ 18 | private List problem; 19 | /** 20 | * 运单号. 21 | */ 22 | private String mailNo; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/jt/JituResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.jt; 2 | 3 | import lombok.Data; 4 | /** 5 | * 极兔通用请求结果. 6 | * 7 | * @author Ze.Wang 8 | * @since 0.0.8 9 | */ 10 | @Data 11 | public class JituResult { 12 | /** 13 | * code. 14 | */ 15 | private String code; 16 | /** 17 | * msg. 18 | */ 19 | private String msg; 20 | /** 21 | * data. 22 | */ 23 | private T data; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sf/MsgData.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sf; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | 6 | /** 7 | * 查询信心. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class MsgData { 14 | /** 15 | * 路由集. 16 | */ 17 | private List routeResps; 18 | 19 | /** 20 | * 单号集. 21 | */ 22 | private List waybillNoInfoList; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/jt/route/JituRouteResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.jt.route; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | 6 | /** 7 | * 极兔路由查询结果. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.8 11 | */ 12 | @Data 13 | public class JituRouteResult { 14 | /** 15 | * 快递单号. 16 | */ 17 | private String billCode; 18 | 19 | /** 20 | * 路由轨迹信息. 21 | */ 22 | private List details; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/jd/JingdongResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.jd; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 极兔通用请求结果. 7 | * 8 | * @author Ze.Wang 9 | * @since 0.0.8 10 | */ 11 | 12 | @Data 13 | public class JingdongResult { 14 | /** 15 | * code. 16 | */ 17 | private String code; 18 | /** 19 | * msg. 20 | */ 21 | private String msg; 22 | /** 23 | * data. 24 | */ 25 | private T data; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/jd/route/JingdongRouteResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.jd.route; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | 6 | /** 7 | * 极兔路由查询结果. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.8 11 | */ 12 | @Data 13 | public class JingdongRouteResult { 14 | /** 15 | * 快递单号. 16 | */ 17 | private String billCode; 18 | 19 | /** 20 | * 路由轨迹信息. 21 | */ 22 | private List traceDetails; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sto/price/ShentongPriceResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sto.price; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import net.kdks.model.sto.ShentongBaseResult; 6 | 7 | /** 8 | * 申通运费预估结果. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.7 12 | */ 13 | @Data 14 | @EqualsAndHashCode(callSuper = true) 15 | public class ShentongPriceResult extends ShentongBaseResult { 16 | 17 | private ShentongPriceData data; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/jt/price/JituPriceResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.jt.price; 2 | 3 | import java.math.BigDecimal; 4 | import lombok.Data; 5 | import net.kdks.model.ExpressPriceResult; 6 | 7 | /** 8 | * 极兔运费查询结果. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.8 12 | */ 13 | @Data 14 | public class JituPriceResult extends ExpressPriceResult { 15 | 16 | public void setTotalPrice(BigDecimal totalPrice) { 17 | super.setPrice(totalPrice.setScale(2)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sto/ShentongBaseResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 申通轨迹查询结果. 7 | * 8 | * @author Ze.Wang 9 | * @since 0.0.1 10 | */ 11 | @Data 12 | public class ShentongBaseResult { 13 | /** 14 | * 是否成功. 15 | */ 16 | private Boolean success; 17 | /** 18 | * 错误编码. 19 | */ 20 | private String errorCode; 21 | /** 22 | * 错误信息. 23 | */ 24 | private String errorMsg; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sto/price/ShentongFeeModel.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sto.price; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 申通FeeModel 7 | * date: 2021-01-13 18:17:51. 8 | * 9 | * @author Ze.Wang 10 | */ 11 | @Data 12 | public class ShentongFeeModel { 13 | private String startPrice; 14 | 15 | private String continuedHeavy; 16 | 17 | private String totalPrice; 18 | 19 | private String startWeight; 20 | 21 | private String continuedHeavyPrice; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/OrderResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 下单结果. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class OrderResult implements Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | /** 18 | * 订单号. 19 | */ 20 | private String orderId; 21 | /** 22 | * 运单号. 23 | */ 24 | private String expressNo; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/yd/YundaResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.yd; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 中通轨迹查询结果. 7 | * 8 | * @author Ze.Wang 9 | * @since 1.0.0 10 | */ 11 | @Data 12 | public class YundaResult { 13 | 14 | /** 15 | * 数据. 16 | */ 17 | private T data; 18 | 19 | /** 20 | * 是否成功. 21 | */ 22 | private Boolean result; 23 | /** 24 | * 错误信息. 25 | */ 26 | private String message; 27 | 28 | private String code; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/yto/YuanTongErrorResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.yto; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import lombok.Data; 6 | 7 | /** 8 | * 圆通轨迹查询错误信息. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.1 12 | */ 13 | @Data 14 | public class YuanTongErrorResult { 15 | 16 | private Map map; 17 | 18 | private String code; 19 | 20 | private String success; 21 | 22 | private String message; 23 | 24 | private String reason; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/zto/ZhongtongResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.zto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 中通轨迹查询结果. 7 | * 8 | * @author Ze.Wang 9 | * @since 1.0.0 10 | */ 11 | @Data 12 | public class ZhongtongResult { 13 | 14 | /** 15 | * 数据. 16 | */ 17 | private T result; 18 | 19 | /** 20 | * 是否成功. 21 | */ 22 | private Boolean status; 23 | /** 24 | * 错误信息. 25 | */ 26 | private String message; 27 | 28 | private String statusCode; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/BaseParam.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | import net.kdks.constant.RequestConstant; 6 | 7 | /** 8 | * 物流查询入参. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.1 12 | */ 13 | @Data 14 | public class BaseParam implements Serializable { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | private String format = RequestConstant.JSON; 19 | 20 | /** 21 | * 快递公司官方简称. 22 | */ 23 | private String expressCompanyNo; 24 | 25 | } -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sto/price/ShentongPriceData.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sto.price; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | import java.util.List; 5 | import lombok.Data; 6 | 7 | /** 8 | * 申通运费预估数据. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.1 12 | */ 13 | @Data 14 | public class ShentongPriceData { 15 | @JSONField(name = "Ageing") 16 | private String ageing; 17 | 18 | @JSONField(name = "AvailableServiceItemList") 19 | private List availableServiceItemList; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/ExpressPriceResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import java.math.BigDecimal; 5 | import lombok.Data; 6 | 7 | /** 8 | * 运费估算结果. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.7 12 | */ 13 | @Data 14 | public class ExpressPriceResult implements Serializable { 15 | 16 | private static final long serialVersionUID = 1L; 17 | /** 18 | * 时效. 19 | */ 20 | private BigDecimal time; 21 | /** 22 | * 邮费. 23 | */ 24 | private BigDecimal price; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/ExpressRouteSubscribeData.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | 7 | /** 8 | * 订阅结果. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.1 12 | */ 13 | @Data 14 | public class ExpressRouteSubscribeData implements Serializable { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | /** 19 | * 订阅单号. 20 | */ 21 | private String expressNo; 22 | 23 | /** 24 | * 订阅结果. 25 | */ 26 | private Boolean result; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sf/ApiResultData.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sf; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 顺丰轨迹查询结果. 7 | * 8 | * @author Ze.Wang 9 | * @since 0.0.1 10 | */ 11 | @Data 12 | public class ApiResultData { 13 | /** 14 | * 是否成功. 15 | */ 16 | private Boolean success; 17 | /** 18 | * 错误码. 19 | */ 20 | private String errorCode; 21 | /** 22 | * 错误信息. 23 | */ 24 | private String errorMsg; 25 | /** 26 | * 查询信息. 27 | */ 28 | private MsgData msgData; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/htky/BaishiTraceLog.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.htky; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 流转信息. 7 | * 8 | * @author Ze.Wang 9 | * @since 0.0.1 10 | */ 11 | @Data 12 | public class BaishiTraceLog { 13 | /** 14 | * 抽检标记. 15 | */ 16 | private Boolean check; 17 | /** 18 | * 问题件. 19 | */ 20 | private BaishiProblem problems; 21 | /** 22 | * 运单号. 23 | */ 24 | private String mailNo; 25 | /** 26 | * 流转信息. 27 | */ 28 | private BaishiTrace traces; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/yd/route/YundaRouteSubscribeItem.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.yd.route; 2 | 3 | import lombok.Data; 4 | import net.kdks.model.ExpressRouteSubscribeData; 5 | 6 | /** 7 | * 韵达路由轨迹信息. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.9 11 | */ 12 | @Data 13 | public class YundaRouteSubscribeItem extends ExpressRouteSubscribeData { 14 | @Override 15 | public void setResult(Boolean result) { 16 | super.setResult(result); 17 | } 18 | 19 | public void setOrderid(String orderid) { 20 | super.setExpressNo(orderid); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/zto/ZhongtongResultV1.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.zto; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | 6 | /** 7 | * 中通轨迹查询结果. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class ZhongtongResultV1 { 14 | 15 | /** 16 | * 数据. 17 | */ 18 | private List data; 19 | /** 20 | * 信息. 21 | */ 22 | private String msg; 23 | /** 24 | * 是否成功. 25 | */ 26 | private Boolean status; 27 | /** 28 | * 错误信息. 29 | */ 30 | private String message; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/zto/ZhongtongData.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.zto; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | 6 | /** 7 | * 中通轨迹查询数据. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class ZhongtongData { 14 | /** 15 | * 路由信息. 16 | */ 17 | private List traces; 18 | /** 19 | * 快递号. 20 | */ 21 | private String billCode; 22 | 23 | /** 24 | * 扫描类型. 25 | */ 26 | private String scanType; 27 | 28 | /** 29 | * 扫描时间(ms). 30 | */ 31 | private Long scanDate; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/ExpressBatchParam.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 物流查询入参. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class ExpressBatchParam implements Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | /** 18 | * 快递公司官方简称. 19 | */ 20 | private String expressCompanyNo; 21 | 22 | /** 23 | * 快递号. 24 | */ 25 | private String[] expressNos; 26 | 27 | /** 28 | * 手机号. 29 | */ 30 | private String mobile; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/config/BaishiConfig.java: -------------------------------------------------------------------------------- 1 | package net.kdks.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * 百世快递配置. 10 | * 11 | *

API配置,包含[partnerId,secretKey],isProduct标识测试与生成
12 | * 配置获取:百世开放平台 13 | * 14 | * @author Ze.Wang 15 | * @since 0.0.1 16 | */ 17 | @Data 18 | @Builder 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class BaishiConfig { 22 | 23 | private String partnerId; 24 | private String secretKey; 25 | private int isProduct = 1; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/config/ShentongConfig.java: -------------------------------------------------------------------------------- 1 | package net.kdks.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * 申通快递配置. 10 | * 11 | *

API配置,包含[appkey,secretKey],isProduct标识测试与生成
12 | * 配置获取:申通开放平台 13 | * 14 | * @author Ze.Wang 15 | * @since 0.0.1 16 | */ 17 | @Data 18 | @Builder 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class ShentongConfig { 22 | 23 | private String appkey; 24 | 25 | private String secretKey; 26 | 27 | private int isProduct = 1; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/config/YundaConfig.java: -------------------------------------------------------------------------------- 1 | package net.kdks.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * 韵达快递配置. 10 | * 11 | *

API配置,包含[appKey,appSecret],isProduct标识测试与生产环境
12 | * 配置获取:顺丰开放平台 13 | * 14 | * @author Ze.Wang 15 | * @since 0.0.1 16 | */ 17 | @Data 18 | @Builder 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class YundaConfig { 22 | 23 | private String appKey; 24 | private String appSecret; 25 | 26 | private int isProduct = 1; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/htky/BaishiResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.htky; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | 6 | /** 7 | * 百世轨迹查询结果. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class BaishiResult { 14 | /** 15 | * 结果描述,true成功,false失败. 16 | */ 17 | private Boolean result; 18 | /** 19 | * 备注. 20 | */ 21 | private String remark; 22 | /** 23 | * 错误码. 24 | */ 25 | private String errorCode; 26 | /** 27 | * 错误描述. 28 | */ 29 | private String errorDescription; 30 | 31 | private List traceLogs; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/config/ShunfengConfig.java: -------------------------------------------------------------------------------- 1 | package net.kdks.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * 顺丰快递配置. 10 | * 11 | *

API配置,包含[partnerId,requestId,checkWord],isProduct标识测试与生产环境
12 | * 配置获取:顺丰开放平台 13 | * 14 | * @author Ze.Wang 15 | * @since 0.0.1 16 | */ 17 | @Data 18 | @Builder 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class ShunfengConfig { 22 | 23 | private String partnerId; 24 | private String requestId; 25 | private String checkWord; 26 | 27 | private int isProduct = 1; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/config/YuantongConfig.java: -------------------------------------------------------------------------------- 1 | package net.kdks.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * 圆通快递配置. 10 | * 11 | *

API配置,包含[partnerId,secretKey,userId],isProduct标识测试与生产环境
12 | * 配置获取:圆通开放平台 13 | * 14 | * @author Ze.Wang 15 | * @since 0.0.1 16 | */ 17 | @Data 18 | @Builder 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class YuantongConfig { 22 | 23 | private String appkey; 24 | 25 | private String secretKey; 26 | 27 | private String userId; 28 | 29 | private int isProduct = 1; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/YuantongMethod.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 圆通路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface YuantongMethod { 10 | /** 11 | * 路由查询. 12 | */ 13 | String QUERY_ROUTE = "yto.Marketing.WaybillTrace"; 14 | /** 15 | * 运费预估. 16 | */ 17 | String QUERY_PRICE = "yto.Marketing.TransportPrice"; 18 | 19 | String URL_PREFIX = "http://openapi.yto.net.cn/service/"; 20 | 21 | String URL_TEST_PREFIX = "http://opentestapi.yto.net.cn/service/"; 22 | 23 | String URL_VERSION = "/v1/"; 24 | 25 | String QUERY_ROUTE_URL = "waybill_query"; 26 | 27 | String QUERY_PRICE_URL = "charge_query"; 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/CreateOrderParam.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 下单参数. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class CreateOrderParam implements Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | /** 18 | * 物品信息. 19 | */ 20 | private CargoDetail cargoDetail; 21 | 22 | /** 23 | * 发件人信息. 24 | */ 25 | private ContactInfo sendContactInfo; 26 | 27 | /** 28 | * 收件人信息. 29 | */ 30 | private ContactInfo receiptContactInfo; 31 | 32 | /** 33 | * 手机号. 34 | */ 35 | private String orderId; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sf/ShunfengResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sf; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.annotation.JSONField; 5 | import lombok.Data; 6 | 7 | /** 8 | * 顺丰轨迹查询请求结果. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.1 12 | */ 13 | @Data 14 | public class ShunfengResult { 15 | private String apiErrorMsg; 16 | 17 | @JSONField(name = "apiResponseID") 18 | private String apiResponseId; 19 | 20 | private String apiResultCode; 21 | 22 | private ApiResultData apiResultData; 23 | 24 | public void setApiResultData(String apiResultData) { 25 | 26 | this.apiResultData = JSON.parseObject(apiResultData, ApiResultData.class); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/ShentongScanType.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 申通路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface ShentongScanType { 10 | /** 11 | * 装袋. 12 | */ 13 | String TRUCK_LOADING = "装袋"; 14 | /** 15 | * 到件. 16 | */ 17 | String ARRIVED = "到件"; 18 | /** 19 | * 发件. 20 | */ 21 | String SENDING = "发件"; 22 | /** 23 | * 派件. 24 | */ 25 | String DELIVERING = "派件"; 26 | /** 27 | * 收件. 28 | */ 29 | String COLLECTED = "收件"; 30 | 31 | /** 32 | * 客户签收. 33 | */ 34 | String SIGNED = "客户签收"; 35 | 36 | /** 37 | * 驿站代收. 38 | */ 39 | String AGENT = "驿站代收"; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sto/ShentongResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sto; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | 8 | /** 9 | * 申通轨迹查询结果. 10 | * 11 | * @author Ze.Wang 12 | * @since 0.0.1 13 | */ 14 | @Data 15 | @EqualsAndHashCode(callSuper = true) 16 | public class ShentongResult extends ShentongBaseResult { 17 | /** 18 | * 是否重试. 19 | */ 20 | private Boolean needRetry; 21 | /** 22 | * 请求id. 23 | */ 24 | private String requestId; 25 | /** 26 | * 异常信息. 27 | */ 28 | private String expInfo; 29 | /** 30 | * 查询结果Map,key是查询的单号,value是对应的轨迹集合. 31 | */ 32 | private Map> data; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/YundaMethod.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 韵达接口方法. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.9 8 | */ 9 | public interface YundaMethod { 10 | /** 11 | * url前缀. 12 | */ 13 | String URL_PREFIX = "https://openapi.yundaex.com/"; 14 | /** 15 | * 测试url前缀. 16 | */ 17 | String URL_TEST_PREFIX = "https://u-openapi.yundasys.com/"; 18 | /** 19 | * 路由查询后缀. 20 | */ 21 | String QUERY_ROUTE_URL = "openapi/outer/logictis/query"; 22 | 23 | /** 24 | * 路由订阅后缀. 25 | */ 26 | String SUBSCRIBE_ROUTE_URL = "openapi/outer/logictis/subscribe"; 27 | 28 | /** 29 | * 运费查询服务名. 30 | */ 31 | String QUERY_PRICE_URL = "openapi-api/v1/order/getFreightInfo"; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/yd/route/YundaRouteResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.yd.route; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | import net.kdks.model.zto.ZhongtongTraceV1; 6 | 7 | /** 8 | * 韵达轨迹查询数据. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.9 12 | */ 13 | @Data 14 | public class YundaRouteResult { 15 | /** 16 | * 路由信息. 17 | */ 18 | private List steps; 19 | 20 | private Boolean result; 21 | /** 22 | * 快递号. 23 | */ 24 | private String mailno; 25 | 26 | /** 27 | * 扫描类型. 28 | */ 29 | private String scanType; 30 | 31 | /** 32 | * 扫描时间(ms). 33 | */ 34 | private String time; 35 | 36 | private String remark; 37 | 38 | private String status; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/config/JingdongConfig.java: -------------------------------------------------------------------------------- 1 | package net.kdks.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * 京东快递配置. 10 | * 11 | *

API配置,包含[appKey,appSecret,accessToken,customerCode],isProduct标识测试与生成
12 | * 配置获取:京东开放平台 13 | * 14 | * @author Ze.Wang 15 | * @since 0.0.11 16 | */ 17 | @Data 18 | @Builder 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class JingdongConfig { 22 | 23 | private String appKey; 24 | private String appSecret; 25 | private String accessToken; 26 | /** 27 | * 月结号. 28 | */ 29 | private String customerCode; 30 | 31 | private int isProduct = 1; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/utils/Assert.java: -------------------------------------------------------------------------------- 1 | package net.kdks.utils; 2 | 3 | /** 4 | * 断言. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.8 8 | */ 9 | public class Assert { 10 | /** 11 | * 判断是否为null. 12 | * 13 | * @param object 判断的对象 14 | * @param message 错误消息 15 | */ 16 | public static void notNull(Object object, String message) { 17 | if (object == null) { 18 | throw new IllegalArgumentException(message); 19 | } 20 | } 21 | 22 | /** 23 | * 判断字符串是否为空. 24 | * 25 | * @param str 判断的对象 26 | * @param message 错误消息 27 | */ 28 | public static void notEmpty(String str, String message) { 29 | if (StringUtils.isEmpty(str)) { 30 | throw new IllegalArgumentException(message); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/ExpressParam.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | 8 | /** 9 | * 物流查询入参. 10 | * 11 | * @author Ze.Wang 12 | * @since 0.0.1 13 | */ 14 | @Data 15 | @EqualsAndHashCode(callSuper = true) 16 | public class ExpressParam extends BaseParam implements Serializable { 17 | 18 | private static final long serialVersionUID = 1L; 19 | 20 | /** 21 | * 快递号 22 | */ 23 | private List expressNos; 24 | 25 | /** 26 | * 手机号 27 | */ 28 | private String mobile; 29 | 30 | /** 31 | * 是否展示路由 32 | */ 33 | private boolean isViewRoute = true; 34 | 35 | /** 36 | * 是否展示原生信息 37 | */ 38 | private boolean isViewOriginal = false; 39 | 40 | } -------------------------------------------------------------------------------- /src/test/resources/config-dev.properties: -------------------------------------------------------------------------------- 1 | express.sf.partnerID= 2 | express.sf.requestID= 3 | express.sf.checkWord= 4 | express.sf.isProduct=1 5 | express.sto.appkey= 6 | express.sto.secretKey= 7 | express.sto.isProduct=1 8 | express.htky.partnerID= 9 | express.htky.secretKey= 10 | express.htky.isProduct=1 11 | express.yto.appkey= 12 | express.yto.secretKey= 13 | express.yto.userId= 14 | express.yto.isProduct=1 15 | express.zto.companyId=kfpttestCode 16 | express.zto.secretKeyV1=kfpttestkey== 17 | express.zto.appKey= 18 | express.zto.secretKey= 19 | express.zto.routeVersion=v2 20 | express.zto.isProduct=0 21 | express.jt.apiAccount= 22 | express.jt.privateKey= 23 | express.jt.uuid= 24 | express.jt.customerCode= 25 | express.jt.customerPwd= 26 | express.jt.isProduct=1 27 | express.yd.appKey= 28 | express.yd.appSecret= 29 | express.yd.isProduct=1 30 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/ShentongMethod.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 圆通路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface ShentongMethod { 10 | 11 | String URL = "https://cloudinter-linkgatewayonline.sto.cn/gateway/link.do"; 12 | 13 | String URL_TEST = "http://cloudinter-linkgatewaytest.sto.cn/gateway/link.do"; 14 | 15 | /** 16 | * 路由查询. 17 | */ 18 | String QUERY_ROUTE_API_NAME = "STO_TRACE_QUERY_COMMON"; 19 | 20 | String QUERY_ROUTE_TO_APPKEY = "sto_trace_query"; 21 | 22 | String QUERY_ROUTE_TO_CODE = "sto_trace_query"; 23 | /** 24 | * 运费预估. 25 | */ 26 | String QUERY_PRICE_API_NAME = "QUERY_SEND_SERVICE_DETAIL"; 27 | 28 | String QUERY_PRICE_TO_APPKEY = "ORDERMS_API"; 29 | 30 | String QUERY_PRICE_TO_CODE = "ORDERMS_API"; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/CargoDetail.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import java.math.BigDecimal; 5 | import lombok.Data; 6 | 7 | /** 8 | * 物品信息. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.1 12 | */ 13 | @Data 14 | public class CargoDetail implements Serializable { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | /** 19 | * 数量. 20 | */ 21 | private BigDecimal count; 22 | 23 | /** 24 | * 单位. 25 | */ 26 | private String unit; 27 | 28 | /** 29 | * 重量. 30 | */ 31 | private BigDecimal weight; 32 | 33 | /** 34 | * 金额. 35 | */ 36 | private BigDecimal amount; 37 | /** 38 | * 币种. 39 | */ 40 | private String currency; 41 | 42 | /** 43 | * 名字. 44 | */ 45 | private String name; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/config/ZhongtongConfig.java: -------------------------------------------------------------------------------- 1 | package net.kdks.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * 中通快递配置. 10 | * 11 | *

API配置,包含[appKey,secretKey],isProduct标识测试与生产环境
12 | *

若需使用v1版本的路由查询,需填写companyId与secretKeyV1,并将routeVersion设置为v1

13 | * 配置获取:中通开放平台 14 | * 15 | * @author Ze.Wang 16 | * @since 0.0.1 17 | */ 18 | @Data 19 | @Builder 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | public class ZhongtongConfig { 23 | 24 | private String companyId; 25 | 26 | private String secretKeyV1; 27 | 28 | private String appKey; 29 | 30 | private String secretKey; 31 | 32 | /** 33 | * 路由查询版本(v1/v2). 34 | */ 35 | private String routeVersion; 36 | 37 | private int isProduct = 1; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/enums/ValueEnum.java: -------------------------------------------------------------------------------- 1 | package net.kdks.enums; 2 | 3 | 4 | import java.util.stream.Stream; 5 | 6 | /** 7 | * 枚举接口. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | public interface ValueEnum { 13 | 14 | /** 15 | * 枚举转换. 16 | * 17 | * @param enumType 类型 18 | * @param value 值 19 | * @param 通用值 20 | * @param 通用枚举 21 | * @return corresponding enum 22 | */ 23 | static > E valueToEnum(Class enumType, V value) { 24 | 25 | return Stream.of(enumType.getEnumConstants()) 26 | .filter(item -> item.getValue().equals(value)) 27 | .findFirst() 28 | .orElseThrow(() -> new IllegalArgumentException("unknown value: " + value)); 29 | } 30 | 31 | /** 32 | * 获取枚举值. 33 | * 34 | * @return enum value 35 | */ 36 | T getValue(); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/JingdongScanType.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 京东路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.11 8 | */ 9 | public interface JingdongScanType { 10 | 11 | /** 12 | * 下单. 13 | */ 14 | Integer ORDER = 100; 15 | 16 | /** 17 | * 快件揽收中. 18 | */ 19 | Integer COLLECTING = 390; 20 | /** 21 | * 快件已揽收. 22 | */ 23 | Integer COLLECTED = 420; 24 | 25 | /** 26 | * 运输中. 27 | */ 28 | Integer TRANSPORTING = 430; 29 | 30 | /** 31 | * 派件. 32 | */ 33 | Integer DELIVERING = 440; 34 | 35 | /** 36 | * 已签收. 37 | */ 38 | Integer SIGNED = 510; 39 | 40 | /** 41 | * 拒收. 42 | */ 43 | Integer REJECTED = 530; 44 | 45 | /** 46 | * 已取消. 47 | */ 48 | Integer CANCELLED = 690; 49 | 50 | /** 51 | * 退款. 52 | */ 53 | Integer REFUND = 700; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/config/JituConfig.java: -------------------------------------------------------------------------------- 1 | package net.kdks.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * 百世快递配置. 10 | * 11 | *

API配置,包含[partnerId,secretKey],isProduct标识测试与生成
12 | * 配置获取:百世开放平台 13 | * 14 | * @author Ze.Wang 15 | * @since 0.0.1 16 | */ 17 | @Data 18 | @Builder 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class JituConfig { 22 | 23 | private String apiAccount; 24 | private String privateKey; 25 | 26 | /** 27 | * 沙箱环境uuid. 28 | */ 29 | private String uuid; 30 | /** 31 | * 客户账号(选填),以下需要必填: 32 | * 运费查询、下单. 33 | */ 34 | private String customerCode; 35 | /** 36 | * 客户密码(选填),以下需要必填: 37 | * 运费查询、下单. 38 | */ 39 | private String customerPwd; 40 | 41 | private int isProduct = 1; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/ContactInfo.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 收寄人信息. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | @Data 13 | public class ContactInfo implements Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | /** 18 | * 公司名. 19 | */ 20 | private String company; 21 | /** 22 | * 联系人姓名. 23 | */ 24 | private String contact; 25 | 26 | /** 27 | * 邮编. 28 | */ 29 | private String postCode; 30 | 31 | /** 32 | * 省. 33 | */ 34 | private String province; 35 | /** 36 | * 市. 37 | */ 38 | private String city; 39 | 40 | /** 41 | * 区. 42 | */ 43 | private String county; 44 | /** 45 | * 详细地址. 46 | */ 47 | private String address; 48 | /** 49 | * 电话. 50 | */ 51 | private String tel; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/JituScanType.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 中通路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface JituScanType { 10 | 11 | /** 12 | * 快件揽收. 13 | */ 14 | String COLLECTED = "快件揽收"; 15 | 16 | /** 17 | * 发件. 18 | */ 19 | String SENDING = "发件扫描"; 20 | 21 | /** 22 | * 到件. 23 | */ 24 | String ARRIVED = "到件扫描"; 25 | 26 | String OUT_WAREHOUSE = "出仓扫描"; 27 | 28 | /** 29 | * 入库扫描. 30 | */ 31 | String PUT_STORAGE = "入库扫描"; 32 | 33 | /** 34 | * 代理点收入扫描. 35 | */ 36 | String AGENT = "代理点收入扫描"; 37 | 38 | /** 39 | * 快件取出扫描. 40 | */ 41 | String OUT = "快件取出扫描"; 42 | 43 | /** 44 | * 出库扫描. 45 | */ 46 | String OUT_STORAGE = "出库扫描"; 47 | 48 | /** 49 | * 客户签收. 50 | */ 51 | String SIGNED = "快件签收"; 52 | 53 | /** 54 | * 问题件. 55 | */ 56 | String PROBLEM = "问题件扫描"; 57 | 58 | } 59 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: deploy 2 | 3 | on: 4 | workflow_dispatch: 5 | release: 6 | types: [released] 7 | jobs: 8 | release: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Set up JDK 1.8 14 | uses: actions/setup-java@v1 15 | with: 16 | java-version: 1.8 17 | 18 | - name: Set up Apache Maven Central 19 | uses: actions/setup-java@v1 20 | with: 21 | java-version: 1.8 22 | server-id: sonatype_releases 23 | server-username: MAVEN_USERNAME 24 | server-password: MAVEN_CENTRAL_TOKEN 25 | gpg-passphrase: MAVEN_GPG_PASSPHRASE 26 | gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} 27 | 28 | - name: Publish to Apache Maven Central 29 | run: mvn clean deploy 30 | env: 31 | MAVEN_USERNAME: fuzui 32 | MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }} 33 | MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} 34 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/ExpressData.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | 7 | /** 8 | * 路由信息. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.1 12 | */ 13 | @Data 14 | public class ExpressData implements Serializable { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | /** 19 | * 物流轨迹节点内容. 20 | */ 21 | private String context; 22 | 23 | /** 24 | * 时间,原始格式. 25 | */ 26 | private Long time; 27 | /** 28 | * 格式化后时间. 29 | */ 30 | private String ftime; 31 | /** 32 | * 本数据元对应的签收状态。只有在开通签收状态服务(见上面"status"后的说明) 33 | * 且在接口中提交resultv2标记后才会出现. 34 | */ 35 | private Integer status; 36 | 37 | /** 38 | * 本数据元对应的行政区域的编码,只有在开通签收状态服务 39 | * (见上面"status"后的说明)且在接口中提交resultv2标记后才会出现. 40 | */ 41 | private String areaCode; 42 | 43 | /** 44 | * 本数据元对应的行政区域的名称,开通签收状态服务(见上面"status"后的说明) 45 | * 且在接口中提交resultv2标记后才会出现. 46 | */ 47 | private String areaName; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/ZhongtongScanType.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 中通路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface ZhongtongScanType { 10 | /** 11 | * 到件. 12 | */ 13 | String ARRIVED = "到件"; 14 | /** 15 | * 发件. 16 | */ 17 | String SENDING = "发件"; 18 | /** 19 | * 派件. 20 | */ 21 | String DELIVERING = "派件"; 22 | /** 23 | * 收件. 24 | */ 25 | String COLLECTED = "收件"; 26 | 27 | /** 28 | * 客户签收. 29 | */ 30 | String SIGNED = "签收"; 31 | /** 32 | * 第三方签收. 33 | */ 34 | String THIRD_PARTY_SIGNED = "第三方签收"; 35 | /** 36 | * 退件. 37 | */ 38 | String BACK = "退件"; 39 | /** 40 | * 退件签收. 41 | */ 42 | String BACK_SIGNED = "退件签收"; 43 | /** 44 | * 问题件. 45 | */ 46 | String PROBLEM = "问题件"; 47 | 48 | /** 49 | * 驿站代收. 50 | */ 51 | String AGENT = "ARRIVAL"; 52 | 53 | /** 54 | * 收件人已从第三方代理点签收. 55 | */ 56 | String CLIENT_SIGNED = "SIGNED"; 57 | 58 | } 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 扶醉 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/enums/ExpressStateEnum.java: -------------------------------------------------------------------------------- 1 | package net.kdks.enums; 2 | 3 | /** 4 | * 快递查询状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public enum ExpressStateEnum implements ValueEnum { 10 | 11 | /** 12 | * 暂无物流信息. 13 | */ 14 | NO_INFO(-1), 15 | 16 | /** 17 | * 在途. 18 | */ 19 | TRANSITING(0), 20 | /** 21 | * 揽收. 22 | */ 23 | COLLECTED(1), 24 | /** 25 | * 疑难. 26 | */ 27 | EXCEPTION(2), 28 | /** 29 | * 签收. 30 | */ 31 | SIGNED(3), 32 | /** 33 | * 退回. 34 | */ 35 | BACK(4), 36 | /** 37 | * 派件. 38 | */ 39 | DELIVERING(5), 40 | /** 41 | * 代理. 42 | */ 43 | AGENT(6), 44 | 45 | /** 46 | * 转投. 47 | */ 48 | FORWARD(7); 49 | 50 | private final Integer value; 51 | 52 | ExpressStateEnum(Integer value) { 53 | this.value = value; 54 | } 55 | 56 | /** 57 | * Get enum value. 58 | * 59 | * @return enum value 60 | */ 61 | @Override 62 | public Integer getValue() { 63 | return value; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/ZhongtongMethod.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 中通路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface ZhongtongMethod { 10 | /** 11 | * 路由查询方法名. 12 | */ 13 | @Deprecated 14 | String QUERY_ROUTE_V1 = "NEW_TRACES"; 15 | 16 | /** 17 | * 运费预估方法名. 18 | */ 19 | @Deprecated 20 | String QUERY_PRICE = "GET_HOUR_PRICE"; 21 | /** 22 | * 测试url前缀. 23 | */ 24 | @Deprecated 25 | String URL_TEST_PREFIX_V1 = "https://japi-test.zto.com/"; 26 | /** 27 | * 路由查询服务名. 28 | */ 29 | @Deprecated 30 | String QUERY_ROUTE_URL_V1 = "traceInterfaceNewTraces"; 31 | 32 | /** 33 | * url前缀. 34 | */ 35 | String URL_PREFIX = "https://japi.zto.com/"; 36 | /** 37 | * 测试url前缀. 38 | */ 39 | String URL_TEST_PREFIX = "https://japi-test.zto.com/"; 40 | /** 41 | * 路由查询服务名. 42 | */ 43 | String QUERY_ROUTE_URL = "zto.merchant.waybill.track.query"; 44 | /** 45 | * 运费查询服务名. 46 | */ 47 | String QUERY_PRICE_URL = "zto.open.obtainPicePrescription"; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/enums/ExpressCompanyCodeEnum.java: -------------------------------------------------------------------------------- 1 | package net.kdks.enums; 2 | 3 | /** 4 | * 快递公司编码. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public enum ExpressCompanyCodeEnum implements ValueEnum { 10 | 11 | /** 12 | * 顺丰. 13 | */ 14 | SF("SF"), 15 | /** 16 | * 圆通. 17 | */ 18 | YTO("YTO"), 19 | /** 20 | * 申通. 21 | */ 22 | STO("STO"), 23 | /** 24 | * 中通. 25 | */ 26 | ZTO("ZTO"), 27 | /** 28 | * 韵达. 29 | */ 30 | YD("YD"), 31 | /** 32 | * 百世. 33 | */ 34 | HTKY("HTKY"), 35 | /** 36 | * 邮政. 37 | */ 38 | YZPY("YZPY"), 39 | 40 | /** 41 | * 德邦. 42 | */ 43 | DBL("DBL"), 44 | 45 | /** 46 | * 极兔. 47 | */ 48 | JT("JT"), 49 | 50 | /** 51 | * 京东. 52 | */ 53 | JD("JD"); 54 | 55 | private final String value; 56 | 57 | ExpressCompanyCodeEnum(String value) { 58 | this.value = value; 59 | } 60 | 61 | /** 62 | * Get enum value. 63 | * 64 | * @return enum value 65 | */ 66 | @Override 67 | public String getValue() { 68 | return value; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/ExpressResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import java.io.Serializable; 5 | import java.util.List; 6 | import lombok.Data; 7 | 8 | /** 9 | * 物流查询结果. 10 | * 11 | * @author Ze.Wang 12 | * @since 0.0.1 13 | */ 14 | @Data 15 | public class ExpressResult implements Serializable { 16 | 17 | private static final long serialVersionUID = 1L; 18 | /** 19 | * -1 暂无物流信息 0在途,1揽收,2疑难,3签收,4退回,5派件,6转投,7转投. 20 | */ 21 | private Integer state; 22 | /** 23 | * 信息. 24 | */ 25 | private String msg; 26 | /** 27 | * 是否签收标记. 28 | */ 29 | private Integer ischeck; 30 | 31 | /** 32 | * 快递公司编码. 33 | */ 34 | private String com; 35 | /** 36 | * 快递单号. 37 | */ 38 | private String nu; 39 | 40 | private List data; 41 | 42 | private String originalResult; 43 | 44 | /** 45 | * 结果处理. 46 | * 47 | * @param msg 信息 48 | * @return 处理结果 49 | */ 50 | public static ExpressResult restResult(String msg) { 51 | ExpressResult apiResult = new ExpressResult(); 52 | apiResult = JSONObject.parseObject(msg, ExpressResult.class); 53 | return apiResult; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/utils/DigestUtils.java: -------------------------------------------------------------------------------- 1 | package net.kdks.utils; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | 6 | /** 7 | * 加密工具. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | public class DigestUtils { 13 | /** 14 | * MD5 加密. 15 | * 16 | * @param str 待加密字符串 17 | * @return 加密结果 18 | */ 19 | public static byte[] md5Digest(String str) { 20 | 21 | try { 22 | MessageDigest md = MessageDigest.getInstance("MD5"); 23 | md.update(str.getBytes()); 24 | return md.digest(); 25 | } catch (NoSuchAlgorithmException e) { 26 | e.printStackTrace(); 27 | return null; 28 | } 29 | } 30 | 31 | /** 32 | * MD5 加密. 33 | * 34 | * @param str 待加密字符串 35 | * @return 加密结果 36 | */ 37 | public static String md5DigestToStr(String str) { 38 | StringBuffer result = new StringBuffer(); 39 | byte[] bytes = md5Digest(str); 40 | for (byte b : bytes) { 41 | int bt = b & 0xff; 42 | if (bt < 16) { 43 | result.append(0); 44 | } 45 | result.append(Integer.toHexString(bt)); 46 | } 47 | return result.toString(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/htky/BaishiProblemItems.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.htky; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 问题件子项. 7 | * 8 | * @author Ze.Wang 9 | * @since 0.0.1 10 | */ 11 | @Data 12 | public class BaishiProblemItems { 13 | /** 14 | * 序列号. 15 | */ 16 | private Long seqNum; 17 | /** 18 | * 问题件类型,包括: 19 | * 应到未到件、非法面单、无头件、被污染件、双面单、退件、 20 | * 违规包装、其他、学校件、面单信息遗失无法正常投递、查无此人、 21 | * 超大超长超重、节假日无人收货、快件遗失、代收结算问题、面单破损、 22 | * 大笔错写、地址不详、更改派送地址、客户要求延迟派送、超区件、内部运力不足、 23 | * 联系不上收件人、分拣差错、 拒付到付款、客户拒收、快件破损、违禁品、 24 | * 未带/少带派送费、自提件、到付结算问题. 25 | */ 26 | private String problemType; 27 | /** 28 | * 登记人. 29 | */ 30 | private String registerMan; 31 | /** 32 | * 登记日期 (通过“yyyy-MM-dd HH:mm:ss”格式化). 33 | */ 34 | private String registerDate; 35 | /** 36 | * 登记站点. 37 | */ 38 | private String registerSite; 39 | /** 40 | * 问题件类型. 41 | */ 42 | private String problemCause; 43 | /** 44 | * 通知站点. 45 | */ 46 | private String noticeSite; 47 | /** 48 | * 回复人. 49 | */ 50 | private String replyMan; 51 | /** 52 | * 回复日期 (通过“yyyy-MM-dd HH:mm:ss”格式化). 53 | */ 54 | private String replyDate; 55 | /** 56 | * 回复内容. 57 | */ 58 | private String replyContent; 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/handler/ExpressHandler.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import java.util.List; 4 | import net.kdks.model.CreateOrderParam; 5 | import net.kdks.model.ExpressParam; 6 | import net.kdks.model.ExpressPriceParam; 7 | import net.kdks.model.ExpressPriceResult; 8 | import net.kdks.model.ExpressResponse; 9 | import net.kdks.model.ExpressResult; 10 | import net.kdks.model.OrderResult; 11 | 12 | /** 13 | * 业务处理接口. 14 | * 15 | * @author Ze.Wang 16 | * @since 0.0.1 17 | */ 18 | public interface ExpressHandler { 19 | 20 | /** 21 | * 查询轨迹信息. 22 | * 23 | * @param expressParam 快递号、手机、快递公司编码 24 | * @return 查询接口 25 | */ 26 | ExpressResponse> getExpressInfo(ExpressParam expressParam); 27 | 28 | /** 29 | * 运费预估. 30 | * 31 | * @param expressPriceParam 起始省份、起始城市、目的身份、目的城市、重量、长、宽、高 32 | * @return 运费 33 | */ 34 | ExpressResponse getExpressPrice(ExpressPriceParam expressPriceParam); 35 | 36 | /** 37 | * 创建订单. 38 | * 39 | * @param createOrderParam 下单参数,主要包含物品信息、收件人信息、寄件人信息等 40 | * @return 快递单号等信息 41 | */ 42 | ExpressResponse createOrder(CreateOrderParam createOrderParam); 43 | 44 | /** 45 | * 获取当前快递公司编码. 46 | * 47 | * @return 快递公司编码 48 | */ 49 | String getExpressCompanyCode(); 50 | } -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/ShunfengOpCode.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 顺丰路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface ShunfengOpCode { 10 | /** 11 | * 快件在【XXX营业点】已装车,准备发往 【XXX集散中心】. 12 | */ 13 | String TRUCK_LOADING = "30"; 14 | /** 15 | * 快件到达 【XXX集散中心】. 16 | */ 17 | String ARRIVED = "31"; 18 | /** 19 | * 派件异常原因. 20 | */ 21 | String EXCEPTION = "33"; 22 | /** 23 | * 快件在XXX ,准备送往下一站. 24 | */ 25 | String READY_NEXT = "3036"; 26 | /** 27 | * 正在派送途中,请您准备签收(派件人:XXX,电话:XXX). 28 | */ 29 | String DELIVERING = "44"; 30 | /** 31 | * 顺丰已收件. 32 | */ 33 | String COLLECTED = "50"; 34 | /** 35 | * 由于XXX原因 派件不成功. 36 | */ 37 | String FAILED = "70"; 38 | /** 39 | * 已签收,感谢使用顺丰,期待再次为您服务. 40 | */ 41 | String SIGNED = "80"; 42 | /** 43 | * 在官网"运单资料&签收图",可查看签收人信. 44 | */ 45 | String VIEW = "8000"; 46 | /** 47 | * 快件到达顺丰店/站. 48 | */ 49 | String ARRIVED_STORE = "130"; 50 | /** 51 | * 快件正送往顺丰店/站. 52 | */ 53 | String DELIVERING_STORE = "123"; 54 | /** 55 | * 代理收件. 56 | */ 57 | String AGENT = "607"; 58 | /** 59 | * 应客户要求,快件正在转寄中. 60 | */ 61 | String FORWARD = "99"; 62 | /** 63 | * 快件已退回/转寄,新单号为: XXX. 64 | */ 65 | String BACK = "648"; 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/ExpressPriceParam.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import java.io.Serializable; 4 | import java.math.BigDecimal; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | 8 | /** 9 | * 运费预估入参. 10 | * 11 | * @author Ze.Wang 12 | * @since 0.0.7 13 | */ 14 | @Data 15 | @EqualsAndHashCode(callSuper = true) 16 | public class ExpressPriceParam extends BaseParam implements Serializable { 17 | 18 | private static final long serialVersionUID = 1L; 19 | 20 | /** 21 | * 起始省份. 22 | */ 23 | private String startProvince; 24 | /** 25 | * 起始城市. 26 | */ 27 | private String startCity; 28 | /** 29 | * 起始区. 30 | */ 31 | private String startDistrict; 32 | /** 33 | * 起始详细地址. 34 | */ 35 | private String startAddress; 36 | /** 37 | * 目的省份. 38 | */ 39 | private String endProvince; 40 | /** 41 | * 目的城市. 42 | */ 43 | private String endCity; 44 | /** 45 | * 起始区. 46 | */ 47 | private String endDistrict; 48 | /** 49 | * 起始详细地址. 50 | */ 51 | private String endAddress; 52 | /** 53 | * 重量. 54 | */ 55 | private BigDecimal weight; 56 | /** 57 | * 长度. 58 | */ 59 | private BigDecimal length; 60 | /** 61 | * 宽度. 62 | */ 63 | private BigDecimal width; 64 | /** 65 | * 高度. 66 | */ 67 | private BigDecimal height; 68 | 69 | } -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/BaishiScanType.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 百世路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.1 8 | */ 9 | public interface BaishiScanType { 10 | /** 11 | * 到件. 12 | */ 13 | String ARRIVED = "到件"; 14 | /** 15 | * 发件. 16 | */ 17 | String SENDING = "发件"; 18 | /** 19 | * 派件. 20 | */ 21 | String DELIVERING = "派件"; 22 | /** 23 | * 收件. 24 | */ 25 | String COLLECTED = "收件"; 26 | 27 | /** 28 | * 客户签收. 29 | */ 30 | String SIGNED = "签收"; 31 | 32 | /** 33 | * 代理点签收. 34 | */ 35 | String AGENT = "代理点签收"; 36 | /** 37 | * 特殊签收. 38 | */ 39 | String SPECIAL_SIGNED = "特殊签收"; 40 | /** 41 | * 百世邻里. 42 | */ 43 | String BAISHILINLI = "百世邻里"; 44 | /** 45 | * 入库/入柜. 46 | */ 47 | String PUT_STORAGE = "入库/入柜"; 48 | /** 49 | * 用户提货. 50 | */ 51 | String PICK = "用户提货"; 52 | 53 | /** 54 | * 转同行. 55 | */ 56 | String FORWARD = "转同行"; 57 | /** 58 | * 快递员取出包裹. 59 | */ 60 | String COURIER_TAKE = "快递员取出包裹"; 61 | /** 62 | * 客户拒收. 63 | */ 64 | String REFUSE = "客户拒收"; 65 | /** 66 | * 二次派件. 67 | */ 68 | String SECONDARY_PACKAGE = "二次派件"; 69 | /** 70 | * 货物破损. 71 | */ 72 | String BROKEN = "货物破损"; 73 | /** 74 | * 退件. 75 | */ 76 | String BACK = "退件"; 77 | /** 78 | * 管理员取出包裹. 79 | */ 80 | String ADMIN_TAKE = "管理员取出包裹"; 81 | /** 82 | * 更改派送地址. 83 | */ 84 | String MODIFY_ADDRESS = "更改派送地址"; 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/yto/YuanTongResult.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.yto; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | import lombok.ToString; 5 | import net.kdks.constant.YuantongScanType; 6 | import net.kdks.enums.ExpressStateEnum; 7 | import net.kdks.model.ExpressData; 8 | import net.kdks.utils.DateUtils; 9 | 10 | /** 11 | * 路由信息. 12 | * 13 | * @author Ze.Wang 14 | * @since 0.0.1 15 | */ 16 | @ToString 17 | public class YuanTongResult extends ExpressData { 18 | private static final long serialVersionUID = 1L; 19 | 20 | @JSONField(name = "waybill_No") 21 | public void setWaybillNo(String waybillNo) { 22 | super.setAreaName(null); 23 | } 24 | 25 | @JSONField(name = "upload_Time") 26 | public void setUploadTime(String uploadTime) { 27 | super.setTime(DateUtils.strToTimestamp(uploadTime)); 28 | super.setFtime(uploadTime); 29 | } 30 | 31 | /** 32 | * 处理路由信息. 33 | * 34 | * @param processInfo 路由信息 35 | */ 36 | public void setProcessInfo(String processInfo) { 37 | super.setContext(processInfo); 38 | // 揽收 39 | if (processInfo.contains(YuantongScanType.COLLECTED)) { 40 | super.setStatus(ExpressStateEnum.COLLECTED.getValue()); 41 | return; 42 | } 43 | // 已签收 44 | if (processInfo.contains(YuantongScanType.SIGNED)) { 45 | super.setStatus(ExpressStateEnum.SIGNED.getValue()); 46 | return; 47 | } 48 | // 正在派送途中 49 | if (processInfo.contains(YuantongScanType.DELIVERING)) { 50 | super.setStatus(ExpressStateEnum.DELIVERING.getValue()); 51 | return; 52 | } 53 | super.setStatus(ExpressStateEnum.TRANSITING.getValue()); 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/jt/route/JituRouteItem.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.jt.route; 2 | 3 | import lombok.Data; 4 | import net.kdks.constant.JituScanType; 5 | import net.kdks.enums.ExpressStateEnum; 6 | import net.kdks.model.ExpressData; 7 | import net.kdks.utils.DateUtils; 8 | 9 | /** 10 | * 极兔路由轨迹信息. 11 | * 12 | * @author Ze.Wang 13 | * @since 0.0.8 14 | */ 15 | @Data 16 | public class JituRouteItem extends ExpressData { 17 | public void setScanNetworkCity(String scanNetworkCity) { 18 | super.setAreaName(scanNetworkCity); 19 | } 20 | 21 | public void setScanTime(String scanTime) { 22 | super.setTime(DateUtils.strToTimestamp(scanTime)); 23 | super.setFtime(scanTime); 24 | } 25 | 26 | public void setDesc(String desc) { 27 | super.setContext(desc); 28 | } 29 | 30 | /** 31 | * 处理路由状态. 32 | * 33 | * @param scanType 路由状态 34 | */ 35 | public void setScanType(String scanType) { 36 | // 收件 37 | if (scanType.equals(JituScanType.COLLECTED)) { 38 | super.setStatus(ExpressStateEnum.COLLECTED.getValue()); 39 | return; 40 | } 41 | // 已签收 42 | if (scanType.equals(JituScanType.SIGNED) 43 | || scanType.equals(JituScanType.OUT_STORAGE)) { 44 | super.setStatus(ExpressStateEnum.SIGNED.getValue()); 45 | return; 46 | } 47 | // 代理收件 48 | if (scanType.equals(JituScanType.AGENT)) { 49 | super.setStatus(ExpressStateEnum.AGENT.getValue()); 50 | return; 51 | } 52 | // 疑难 53 | if (scanType.equals(JituScanType.PROBLEM)) { 54 | super.setStatus(ExpressStateEnum.EXCEPTION.getValue()); 55 | return; 56 | } 57 | 58 | super.setStatus(ExpressStateEnum.TRANSITING.getValue()); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sto/ShentongRoute.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sto; 2 | 3 | import lombok.ToString; 4 | import net.kdks.constant.ShentongScanType; 5 | import net.kdks.enums.ExpressStateEnum; 6 | import net.kdks.model.ExpressData; 7 | import net.kdks.utils.DateUtils; 8 | 9 | /** 10 | * 路由信息. 11 | * 12 | * @author Ze.Wang 13 | * @since 0.0.1 14 | */ 15 | @ToString 16 | public class ShentongRoute extends ExpressData { 17 | private static final long serialVersionUID = 1L; 18 | 19 | public void setOpOrgCityName(String opOrgCityName) { 20 | super.setAreaName(opOrgCityName); 21 | } 22 | 23 | public void setOpTime(String opTime) { 24 | super.setTime(DateUtils.strToTimestamp(opTime)); 25 | super.setFtime(opTime); 26 | } 27 | 28 | /** 29 | * 处理轨迹信息. 30 | * 31 | * @param memo 轨迹信息 32 | */ 33 | public void setMemo(String memo) { 34 | super.setContext(memo); 35 | } 36 | 37 | /** 38 | * 处理路由状态. 39 | * 40 | * @param scanType 路由状态 41 | */ 42 | public void setScanType(String scanType) { 43 | // 收件 44 | if (scanType.equals(ShentongScanType.COLLECTED)) { 45 | super.setStatus(ExpressStateEnum.COLLECTED.getValue()); 46 | return; 47 | } 48 | // 已签收 49 | if (scanType.equals(ShentongScanType.SIGNED)) { 50 | super.setStatus(ExpressStateEnum.SIGNED.getValue()); 51 | return; 52 | } 53 | // 正在派送途中 54 | if (scanType.equals(ShentongScanType.DELIVERING)) { 55 | super.setStatus(ExpressStateEnum.DELIVERING.getValue()); 56 | return; 57 | } 58 | // 代理收件 59 | if (scanType.equals(ShentongScanType.AGENT)) { 60 | super.setStatus(ExpressStateEnum.AGENT.getValue()); 61 | return; 62 | } 63 | super.setStatus(ExpressStateEnum.TRANSITING.getValue()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/ExpressResponse.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import net.kdks.constant.ExpressResponseStatus; 7 | 8 | /** 9 | * 响应结果. 10 | * 11 | * @author Ze.Wang 12 | * @since 0.0.1 13 | */ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class ExpressResponse { 18 | 19 | /** 20 | * 授权响应状态码. 21 | */ 22 | private int code; 23 | 24 | /** 25 | * 授权响应信息. 26 | */ 27 | private String msg; 28 | 29 | /** 30 | * 授权响应数据,当且仅当 code = 2000 时返回. 31 | */ 32 | private T data; 33 | 34 | private static ExpressResponse restResult(T data, int code, String msg) { 35 | ExpressResponse apiResult = new ExpressResponse<>(); 36 | apiResult.setCode(code); 37 | apiResult.setData(data); 38 | apiResult.setMsg(msg); 39 | return apiResult; 40 | } 41 | 42 | public static ExpressResponse ok() { 43 | return restResult(null, ExpressResponseStatus.SUCCESS, null); 44 | } 45 | 46 | public static ExpressResponse ok(T data) { 47 | return restResult(data, ExpressResponseStatus.SUCCESS, null); 48 | } 49 | 50 | public static ExpressResponse ok(T data, String msg) { 51 | return restResult(data, ExpressResponseStatus.SUCCESS, msg); 52 | } 53 | 54 | public static ExpressResponse failed() { 55 | return restResult(null, ExpressResponseStatus.FAIL, null); 56 | } 57 | 58 | public static ExpressResponse failed(String msg) { 59 | return restResult(null, ExpressResponseStatus.FAIL, msg); 60 | } 61 | 62 | public static ExpressResponse failed(T data) { 63 | return restResult(data, ExpressResponseStatus.FAIL, null); 64 | } 65 | 66 | public static ExpressResponse failed(T data, String msg) { 67 | return restResult(data, ExpressResponseStatus.FAIL, msg); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/utils/MapUtils.java: -------------------------------------------------------------------------------- 1 | package net.kdks.utils; 2 | 3 | import java.util.HashMap; 4 | import java.util.LinkedHashMap; 5 | 6 | /** 7 | * Map相关工具类 8 | * 参考 hutool MapUtil. 9 | * 10 | * @author Ze.Wang 11 | * @since 0.0.1 12 | */ 13 | public class MapUtils { 14 | 15 | /** 16 | * 默认初始大小. 17 | */ 18 | public static final int DEFAULT_INITIAL_CAPACITY = 16; 19 | /** 20 | * 默认增长因子,当Map的size达到 容量*增长因子时,开始扩充Map. 21 | */ 22 | public static final float DEFAULT_LOAD_FACTOR = 0.75f; 23 | 24 | 25 | /** 26 | * 新建一个HashMap. 27 | * 28 | * @param Key类型 29 | * @param Value类型 30 | * @return HashMap对象 31 | */ 32 | public static HashMap newHashMap() { 33 | return newHashMap(DEFAULT_INITIAL_CAPACITY); 34 | } 35 | 36 | /** 37 | * 新建一个HashMap. 38 | * 39 | * @param Key类型 40 | * @param Value类型 41 | * @param size 初始大小,由于默认负载因子0.75,传入的size会实际初始大小为size / 0.75 + 1 42 | * @param isOrder Map的Key是否有序,有序返回 {@link LinkedHashMap},否则返回 {@link HashMap} 43 | * @return HashMap对象 44 | * @since 3.0.4 45 | */ 46 | public static HashMap newHashMap(int size, boolean isOrder) { 47 | int initialCapacity = (int) (size / DEFAULT_LOAD_FACTOR) + 1; 48 | return isOrder ? new LinkedHashMap<>(initialCapacity) : new HashMap<>(initialCapacity); 49 | } 50 | 51 | /** 52 | * 新建一个HashMap. 53 | * 54 | * @param Key类型 55 | * @param Value类型 56 | * @param size 初始大小,由于默认负载因子0.75,传入的size会实际初始大小为size / 0.75 + 1 57 | * @return HashMap对象 58 | */ 59 | public static HashMap newHashMap(int size) { 60 | return newHashMap(size, false); 61 | } 62 | 63 | /** 64 | * 新建一个HashMap. 65 | * 66 | * @param Key类型 67 | * @param Value类型 68 | * @param isOrder Map的Key是否有序,有序返回 {@link LinkedHashMap},否则返回 {@link HashMap} 69 | * @return HashMap对象 70 | */ 71 | public static HashMap newHashMap(boolean isOrder) { 72 | return newHashMap(DEFAULT_INITIAL_CAPACITY, isOrder); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/constant/YundaScanType.java: -------------------------------------------------------------------------------- 1 | package net.kdks.constant; 2 | 3 | /** 4 | * 韵达路由状态. 5 | * 6 | * @author Ze.Wang 7 | * @since 0.0.9 8 | */ 9 | public interface YundaScanType { 10 | 11 | /** 12 | * 收件扫描. 13 | */ 14 | String ACCEPT = "ACCEPT"; 15 | 16 | /** 17 | * 已揽件. 18 | */ 19 | String GOT = "GOT"; 20 | 21 | /** 22 | * 入中转. 23 | */ 24 | String ARRIVAL = "ARRIVAL"; 25 | 26 | /** 27 | * 出中转. 28 | */ 29 | String DEPARTURE = "DEPARTURE"; 30 | 31 | /** 32 | * 派件中. 33 | */ 34 | String SENT = "SENT"; 35 | 36 | /** 37 | * 第三方代收入库. 38 | */ 39 | String INBOUND = "INBOUND"; 40 | 41 | /** 42 | * 已签收. 43 | */ 44 | String SIGNED = "SIGNED"; 45 | 46 | /** 47 | * 第三方代收快递员取出. 48 | */ 49 | String OUTBOUND = "OUTBOUND"; 50 | 51 | /** 52 | * 签收失败. 53 | */ 54 | String SIGNFAIL = "SIGNFAIL"; 55 | 56 | /** 57 | * 退回件. 58 | */ 59 | String RETURN = "RETURN"; 60 | 61 | /** 62 | * 问题件. 63 | */ 64 | String ISSUE = "ISSUE"; 65 | 66 | /** 67 | * 拒收. 68 | */ 69 | String REJECTION = "REJECTION"; 70 | 71 | /** 72 | * 其他. 73 | */ 74 | String OTHER = "OTHER"; 75 | 76 | /** 77 | * 入库扫描. 78 | */ 79 | String OVERSEA_IN = "OVERSEA_IN"; 80 | 81 | /** 82 | * 出库扫描. 83 | */ 84 | String OVERSEA_OUT = "OVERSEA_OUT"; 85 | 86 | /** 87 | * 清关开始. 88 | */ 89 | String CLEARANCE_START = "CLEARANCE_START"; 90 | 91 | /** 92 | * 清关结束. 93 | */ 94 | String CLEARANCE_FINISH = "CLEARANCE_FINISH"; 95 | 96 | /** 97 | * 清关失败. 98 | */ 99 | String CLEARANCE_FAIL = "CLEARANCE_FAIL"; 100 | 101 | /** 102 | * 干线到达. 103 | */ 104 | String OVERSEA_ARRIVAL = "OVERSEA_ARRIVAL"; 105 | 106 | /** 107 | * 干线离开. 108 | */ 109 | String OVERSEA_DEPARTURE = "OVERSEA_DEPARTURE"; 110 | 111 | /** 112 | * 转单. 113 | */ 114 | String TRANSFER = "TRANSFER"; 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/jd/route/JingdongRouteItem.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.jd.route; 2 | 3 | import lombok.Data; 4 | import net.kdks.constant.JingdongScanType; 5 | import net.kdks.constant.JituScanType; 6 | import net.kdks.enums.ExpressStateEnum; 7 | import net.kdks.model.ExpressData; 8 | import net.kdks.utils.DateUtils; 9 | 10 | /** 11 | * 极兔路由轨迹信息. 12 | * 13 | * @author Ze.Wang 14 | * @since 0.0.8 15 | */ 16 | @Data 17 | public class JingdongRouteItem extends ExpressData { 18 | // public void setScanNetworkCity(String scanNetworkCity) { 19 | // super.setAreaName(scanNetworkCity); 20 | // } 21 | 22 | /** 23 | * 运单号. 24 | */ 25 | private String waybillCode; 26 | 27 | public void setOperationTime(String operationTime) { 28 | super.setTime(DateUtils.strToTimestamp(operationTime)); 29 | super.setFtime(operationTime); 30 | } 31 | 32 | public void setOperationRemark(String operationRemark) { 33 | super.setContext(operationRemark); 34 | } 35 | 36 | /** 37 | * 处理路由状态. 38 | * 39 | * @param category 路由状态 40 | */ 41 | public void setCategory(Integer category) { 42 | // 收件 43 | if (category.equals(JingdongScanType.COLLECTED) 44 | || category.equals(JingdongScanType.COLLECTING) 45 | || category.equals(JingdongScanType.ORDER)) { 46 | super.setStatus(ExpressStateEnum.COLLECTED.getValue()); 47 | return; 48 | } 49 | 50 | if (category.equals(JingdongScanType.REJECTED) 51 | || category.equals(JingdongScanType.REFUND)) { 52 | super.setStatus(ExpressStateEnum.BACK.getValue()); 53 | return; 54 | } 55 | 56 | if (category.equals(JingdongScanType.DELIVERING)) { 57 | super.setStatus(ExpressStateEnum.DELIVERING.getValue()); 58 | return; 59 | } 60 | // 已签收 61 | if (category.equals(JingdongScanType.SIGNED)) { 62 | super.setStatus(ExpressStateEnum.SIGNED.getValue()); 63 | return; 64 | } 65 | 66 | // 疑难 67 | if (category.equals(JingdongScanType.CANCELLED)) { 68 | super.setStatus(ExpressStateEnum.EXCEPTION.getValue()); 69 | return; 70 | } 71 | 72 | super.setStatus(ExpressStateEnum.TRANSITING.getValue()); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/zto/ZhongtongTraceV1.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.zto; 2 | 3 | import lombok.ToString; 4 | import net.kdks.constant.ZhongtongScanType; 5 | import net.kdks.enums.ExpressStateEnum; 6 | import net.kdks.model.ExpressData; 7 | import net.kdks.utils.DateUtils; 8 | 9 | /** 10 | * 路由信息. 11 | * 12 | * @author Ze.Wang 13 | * @since 0.0.1 14 | */ 15 | @ToString 16 | public class ZhongtongTraceV1 extends ExpressData { 17 | public void setScanCity(String scanCity) { 18 | super.setAreaName(scanCity); 19 | } 20 | 21 | public void setScanDate(String scanDate) { 22 | super.setTime(DateUtils.strToTimestamp(scanDate)); 23 | super.setFtime(scanDate); 24 | } 25 | 26 | public void setDesc(String desc) { 27 | super.setContext(desc); 28 | } 29 | 30 | /** 31 | * 处理路由状态. 32 | * 33 | * @param scanType 路由状态 34 | */ 35 | public void setScanType(String scanType) { 36 | // 收件 37 | if (scanType.equals(ZhongtongScanType.COLLECTED)) { 38 | super.setStatus(ExpressStateEnum.COLLECTED.getValue()); 39 | return; 40 | } 41 | // 已签收 42 | if (scanType.equals(ZhongtongScanType.SIGNED) 43 | || scanType.equals(ZhongtongScanType.THIRD_PARTY_SIGNED) 44 | || scanType.equals(ZhongtongScanType.CLIENT_SIGNED)) { 45 | super.setStatus(ExpressStateEnum.SIGNED.getValue()); 46 | return; 47 | } 48 | // 正在派送途中 49 | if (scanType.equals(ZhongtongScanType.DELIVERING)) { 50 | super.setStatus(ExpressStateEnum.DELIVERING.getValue()); 51 | return; 52 | } 53 | // 代理收件 54 | if (scanType.equals(ZhongtongScanType.AGENT)) { 55 | super.setStatus(ExpressStateEnum.AGENT.getValue()); 56 | return; 57 | } 58 | 59 | // 退回 60 | if (scanType.equals(ZhongtongScanType.BACK) 61 | || scanType.equals(ZhongtongScanType.BACK_SIGNED)) { 62 | super.setStatus(ExpressStateEnum.BACK.getValue()); 63 | return; 64 | } 65 | 66 | // 疑难 67 | if (scanType.equals(ZhongtongScanType.PROBLEM)) { 68 | super.setStatus(ExpressStateEnum.EXCEPTION.getValue()); 69 | return; 70 | } 71 | 72 | super.setStatus(ExpressStateEnum.TRANSITING.getValue()); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/zto/ZhongtongTrace.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.zto; 2 | 3 | import lombok.ToString; 4 | import net.kdks.constant.ZhongtongScanType; 5 | import net.kdks.enums.ExpressStateEnum; 6 | import net.kdks.model.ExpressData; 7 | import net.kdks.utils.DateUtils; 8 | 9 | /** 10 | * 路由信息. 11 | * 12 | * @author Ze.Wang 13 | * @since 1.0.0 14 | */ 15 | @ToString 16 | public class ZhongtongTrace extends ExpressData { 17 | private static final long serialVersionUID = 1L; 18 | 19 | public void setScanCity(ZhongtongScanSite scanSite) { 20 | super.setAreaName(scanSite.getName()); 21 | } 22 | 23 | public void setScanDate(Long scanDate) { 24 | super.setTime(DateUtils.millisToSeconds(scanDate)); 25 | super.setFtime(DateUtils.millLongToDateStr(scanDate)); 26 | } 27 | 28 | public void setDesc(String desc) { 29 | super.setContext(desc); 30 | } 31 | 32 | /** 33 | * 处理路由状态. 34 | * 35 | * @param scanType 路由状态 36 | */ 37 | public void setScanType(String scanType) { 38 | // 收件 39 | if (scanType.equals(ZhongtongScanType.COLLECTED)) { 40 | super.setStatus(ExpressStateEnum.COLLECTED.getValue()); 41 | return; 42 | } 43 | // 已签收 44 | if (scanType.equals(ZhongtongScanType.SIGNED) 45 | || scanType.equals(ZhongtongScanType.THIRD_PARTY_SIGNED) 46 | || scanType.equals(ZhongtongScanType.CLIENT_SIGNED)) { 47 | super.setStatus(ExpressStateEnum.SIGNED.getValue()); 48 | return; 49 | } 50 | // 正在派送途中 51 | if (scanType.equals(ZhongtongScanType.DELIVERING)) { 52 | super.setStatus(ExpressStateEnum.DELIVERING.getValue()); 53 | return; 54 | } 55 | // 代理收件 56 | if (scanType.equals(ZhongtongScanType.AGENT)) { 57 | super.setStatus(ExpressStateEnum.AGENT.getValue()); 58 | return; 59 | } 60 | 61 | // 退回 62 | if (scanType.equals(ZhongtongScanType.BACK) 63 | || scanType.equals(ZhongtongScanType.BACK_SIGNED)) { 64 | super.setStatus(ExpressStateEnum.BACK.getValue()); 65 | return; 66 | } 67 | 68 | // 疑难 69 | if (scanType.equals(ZhongtongScanType.PROBLEM)) { 70 | super.setStatus(ExpressStateEnum.EXCEPTION.getValue()); 71 | return; 72 | } 73 | 74 | super.setStatus(ExpressStateEnum.TRANSITING.getValue()); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/yd/route/YundaRouteItem.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.yd.route; 2 | 3 | import lombok.Data; 4 | import net.kdks.constant.JituScanType; 5 | import net.kdks.constant.YundaScanType; 6 | import net.kdks.enums.ExpressStateEnum; 7 | import net.kdks.model.ExpressData; 8 | import net.kdks.utils.DateUtils; 9 | 10 | /** 11 | * 韵达路由轨迹信息. 12 | * 13 | * @author Ze.Wang 14 | * @since 0.0.9 15 | */ 16 | @Data 17 | public class YundaRouteItem extends ExpressData { 18 | public void setCity(String city) { 19 | super.setAreaName(city); 20 | } 21 | 22 | public void setTime(String time) { 23 | super.setTime(DateUtils.strToTimestamp(time)); 24 | super.setFtime(time); 25 | } 26 | 27 | public void setDescription(String description) { 28 | super.setContext(description); 29 | } 30 | 31 | /** 32 | * 处理路由状态. 33 | * 34 | * @param action 路由状态 35 | */ 36 | public void setAction(String action) { 37 | // 收件 38 | if (action.equals(YundaScanType.GOT) || action.equals(YundaScanType.ACCEPT)) { 39 | super.setStatus(ExpressStateEnum.COLLECTED.getValue()); 40 | return; 41 | } 42 | // 已签收 43 | if (action.equals(YundaScanType.SIGNED) 44 | || action.equals(YundaScanType.OUTBOUND)) { 45 | super.setStatus(ExpressStateEnum.SIGNED.getValue()); 46 | return; 47 | } 48 | // 退货 49 | if (action.equals(YundaScanType.RETURN) || action.equals(YundaScanType.REJECTION)) { 50 | super.setStatus(ExpressStateEnum.BACK.getValue()); 51 | return; 52 | } 53 | 54 | // 问题件 55 | if (action.equals(YundaScanType.ISSUE) || action.equals(YundaScanType.SIGNFAIL)) { 56 | super.setStatus(ExpressStateEnum.EXCEPTION.getValue()); 57 | return; 58 | } 59 | 60 | // 派件 61 | if (action.equals(YundaScanType.SENT)) { 62 | super.setStatus(ExpressStateEnum.DELIVERING.getValue()); 63 | return; 64 | } 65 | 66 | // 代理 67 | if (action.equals(YundaScanType.INBOUND)) { 68 | super.setStatus(ExpressStateEnum.AGENT.getValue()); 69 | return; 70 | } 71 | 72 | // 转投 73 | if (action.equals(YundaScanType.TRANSFER)) { 74 | super.setStatus(ExpressStateEnum.FORWARD.getValue()); 75 | return; 76 | } 77 | 78 | super.setStatus(ExpressStateEnum.TRANSITING.getValue()); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/sf/Route.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.sf; 2 | 3 | import lombok.ToString; 4 | import net.kdks.constant.ShunfengOpCode; 5 | import net.kdks.enums.ExpressStateEnum; 6 | import net.kdks.model.ExpressData; 7 | import net.kdks.utils.DateUtils; 8 | 9 | /** 10 | * 路由信息. 11 | * 12 | * @author Ze.Wang 13 | * @since 0.0.1 14 | */ 15 | @ToString 16 | public class Route extends ExpressData { 17 | 18 | private static final long serialVersionUID = 1L; 19 | 20 | public void setAcceptAddress(String acceptAddress) { 21 | super.setAreaName(acceptAddress); 22 | } 23 | 24 | /** 25 | * 处理接收时间. 26 | * 27 | * @param acceptTime 接收时间 28 | */ 29 | public void setAcceptTime(String acceptTime) { 30 | super.setTime(DateUtils.strToTimestamp(acceptTime)); 31 | super.setFtime(acceptTime); 32 | } 33 | 34 | /** 35 | * 处理轨迹信息. 36 | * 37 | * @param remark 轨迹信息 38 | */ 39 | public void setRemark(String remark) { 40 | super.setContext(remark); 41 | } 42 | 43 | /** 44 | * 处理路由状态. 45 | * 46 | * @param opCode 路由状态码 47 | */ 48 | public void setOpCode(String opCode) { 49 | // 顺丰已收件 50 | if (opCode.equals(ShunfengOpCode.COLLECTED)) { 51 | super.setStatus(ExpressStateEnum.COLLECTED.getValue()); 52 | return; 53 | } 54 | // 异常 55 | if (opCode.equals(ShunfengOpCode.EXCEPTION)) { 56 | super.setStatus(ExpressStateEnum.EXCEPTION.getValue()); 57 | return; 58 | } 59 | // 已签收,感谢使用顺丰,期待再次为您服务 60 | if (opCode.equals(ShunfengOpCode.SIGNED) || opCode.equals(ShunfengOpCode.VIEW)) { 61 | super.setStatus(ExpressStateEnum.SIGNED.getValue()); 62 | return; 63 | } 64 | // 快件已退回/转寄,新单号为: XXX 65 | if (opCode.equals(ShunfengOpCode.BACK)) { 66 | super.setStatus(ExpressStateEnum.BACK.getValue()); 67 | return; 68 | } 69 | // 正在派送途中,请您准备签收(派件人:XXX,电话:XXX) 70 | if (opCode.equals(ShunfengOpCode.DELIVERING)) { 71 | super.setStatus(ExpressStateEnum.DELIVERING.getValue()); 72 | return; 73 | } 74 | // 代理收件 75 | if (opCode.equals(ShunfengOpCode.AGENT)) { 76 | super.setStatus(ExpressStateEnum.AGENT.getValue()); 77 | return; 78 | } 79 | // 应客户要求,快件正在转寄中 80 | if (opCode.equals(ShunfengOpCode.FORWARD)) { 81 | super.setStatus(ExpressStateEnum.FORWARD.getValue()); 82 | return; 83 | } 84 | super.setStatus(ExpressStateEnum.TRANSITING.getValue()); 85 | 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/request/ShentongRequest.java: -------------------------------------------------------------------------------- 1 | package net.kdks.request; 2 | 3 | import cn.hutool.http.HttpUtil; 4 | import java.util.Base64; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import net.kdks.config.ShentongConfig; 8 | import net.kdks.constant.ShentongMethod; 9 | import net.kdks.utils.DigestUtils; 10 | 11 | /** 12 | *

申通请求封装

13 | *

date: 2021-01-13 17:23:55

. 14 | * 15 | * @author Ze.Wang 16 | * @since 0.0.7 17 | */ 18 | public class ShentongRequest { 19 | 20 | private String secretKey; 21 | private String appkey; 22 | private String code; 23 | 24 | private String requestUrl; 25 | 26 | /** 27 | * Constructor. 28 | * 29 | * @param shentongConfig 申通配置 30 | */ 31 | public ShentongRequest(ShentongConfig shentongConfig) { 32 | this.secretKey = shentongConfig.getSecretKey(); 33 | this.appkey = shentongConfig.getAppkey(); 34 | this.code = shentongConfig.getAppkey(); 35 | this.requestUrl = ShentongMethod.URL; 36 | if (shentongConfig.getIsProduct() == 0) { 37 | this.requestUrl = ShentongMethod.URL_TEST; 38 | } 39 | } 40 | 41 | /** 42 | * 路由查询. 43 | * 44 | * @param param 参数 45 | * @param format 格式 46 | * @return 查询结果 47 | */ 48 | public String queryRouteRequest(String param, String format) { 49 | return request(ShentongMethod.QUERY_ROUTE_API_NAME, 50 | ShentongMethod.QUERY_ROUTE_TO_APPKEY, 51 | ShentongMethod.QUERY_ROUTE_TO_CODE, 52 | param, 53 | format); 54 | } 55 | 56 | /** 57 | * 运费预估. 58 | * 59 | * @param param 参数 60 | * @param format 格式 61 | * @return 查询结果 62 | */ 63 | public String queryPriceRequest(String param, String format) { 64 | return request(ShentongMethod.QUERY_PRICE_API_NAME, 65 | ShentongMethod.QUERY_PRICE_TO_APPKEY, 66 | ShentongMethod.QUERY_PRICE_TO_CODE, 67 | param, 68 | format); 69 | } 70 | 71 | /** 72 | * 申通通用请求. 73 | * 74 | * @param method 方法 75 | * @param param 参数 76 | * @param format 格式 77 | * @return 请求结果 78 | */ 79 | public String request(String method, String toAppkey, String toCode, String param, 80 | String format) { 81 | Map paramMap = new HashMap<>(7); 82 | paramMap.put("content", param); 83 | paramMap.put("api_name", method); 84 | paramMap.put("from_appkey", appkey); 85 | paramMap.put("from_code", code); 86 | paramMap.put("to_appkey", toAppkey); 87 | paramMap.put("to_code", toCode); 88 | String beforeDigestStr = param + secretKey; 89 | String dataDigest = 90 | Base64.getEncoder().encodeToString(DigestUtils.md5Digest(beforeDigestStr)); 91 | paramMap.put("data_digest", dataDigest); 92 | 93 | return HttpUtil.post(requestUrl, paramMap); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/model/htky/BaishiTraceItems.java: -------------------------------------------------------------------------------- 1 | package net.kdks.model.htky; 2 | 3 | import lombok.ToString; 4 | import net.kdks.constant.BaishiScanType; 5 | import net.kdks.enums.ExpressStateEnum; 6 | import net.kdks.model.ExpressData; 7 | import net.kdks.utils.DateUtils; 8 | 9 | /** 10 | * 路由信息. 11 | * 12 | * @author Ze.Wang 13 | * @since 0.0.1 14 | */ 15 | @ToString 16 | public class BaishiTraceItems extends ExpressData { 17 | 18 | private static final long serialVersionUID = 1L; 19 | 20 | public void setAcceptAddress(String acceptAddress) { 21 | super.setAreaName(acceptAddress); 22 | } 23 | 24 | /** 25 | * 到达时间设置. 26 | * 27 | * @param acceptTime 到达时间 28 | */ 29 | public void setAcceptTime(String acceptTime) { 30 | 31 | super.setTime(DateUtils.strToTimestamp(acceptTime)); 32 | super.setFtime(acceptTime); 33 | } 34 | 35 | /** 36 | * 处理备注. 37 | * 38 | * @param remark 备注 39 | */ 40 | public void setRemark(String remark) { 41 | super.setContext(remark); 42 | } 43 | 44 | /** 45 | * 处理路由状态. 46 | * 47 | * @param scanType 路由状态 48 | */ 49 | public void setScanType(String scanType) { 50 | 51 | // 已收件. 52 | if (scanType.equals(BaishiScanType.COLLECTED)) { 53 | super.setStatus(ExpressStateEnum.COLLECTED.getValue()); 54 | return; 55 | } 56 | // 异常. 57 | if (scanType.equals(BaishiScanType.COURIER_TAKE) 58 | || scanType.equals(BaishiScanType.SECONDARY_PACKAGE) 59 | || scanType.equals(BaishiScanType.BROKEN) 60 | || scanType.equals(BaishiScanType.ADMIN_TAKE) 61 | || scanType.equals(BaishiScanType.MODIFY_ADDRESS)) { 62 | super.setStatus(ExpressStateEnum.EXCEPTION.getValue()); 63 | return; 64 | } 65 | // 已签收. 66 | if (scanType.equals(BaishiScanType.SIGNED) 67 | || scanType.equals(BaishiScanType.PICK)) { 68 | super.setStatus(ExpressStateEnum.SIGNED.getValue()); 69 | return; 70 | } 71 | // 快件已退回. 72 | if (scanType.equals(BaishiScanType.BACK) || scanType.equals(BaishiScanType.REFUSE)) { 73 | super.setStatus(ExpressStateEnum.BACK.getValue()); 74 | return; 75 | } 76 | // 派送中. 77 | if (scanType.equals(BaishiScanType.DELIVERING)) { 78 | super.setStatus(ExpressStateEnum.DELIVERING.getValue()); 79 | return; 80 | } 81 | // 代理收件. 82 | if (scanType.equals(BaishiScanType.AGENT) 83 | || scanType.equals(BaishiScanType.SPECIAL_SIGNED) 84 | || scanType.equals(BaishiScanType.BAISHILINLI) 85 | || scanType.equals(BaishiScanType.PUT_STORAGE)) { 86 | super.setStatus(ExpressStateEnum.AGENT.getValue()); 87 | return; 88 | } 89 | // 应客户要求,快件正在转寄中. 90 | if (scanType.equals(BaishiScanType.FORWARD)) { 91 | super.setStatus(ExpressStateEnum.FORWARD.getValue()); 92 | return; 93 | } 94 | super.setStatus(ExpressStateEnum.TRANSITING.getValue()); 95 | 96 | } 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/request/YundaRequest.java: -------------------------------------------------------------------------------- 1 | package net.kdks.request; 2 | 3 | import cn.hutool.http.HttpRequest; 4 | import java.util.Base64; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import net.kdks.config.YundaConfig; 8 | import net.kdks.config.ZhongtongConfig; 9 | import net.kdks.constant.YundaMethod; 10 | import net.kdks.constant.ZhongtongMethod; 11 | import net.kdks.constant.ZhongtongRouteVersion; 12 | import net.kdks.utils.DateUtils; 13 | import net.kdks.utils.DigestUtils; 14 | import net.kdks.utils.StringUtils; 15 | 16 | /** 17 | *

中通请求封装

18 | *

date: 2021-01-12 13:29:57

. 19 | * 20 | * @author Ze.Wang 21 | * @since 0.0.7 22 | */ 23 | public class YundaRequest { 24 | 25 | private String appKey; 26 | 27 | private String appSecret; 28 | private String requestUrlPrefix; 29 | 30 | /** 31 | * Constructor. 32 | * 33 | * @param yundaConfig 韵达配置 34 | */ 35 | public YundaRequest(YundaConfig yundaConfig) { 36 | this.appKey = yundaConfig.getAppKey(); 37 | this.appSecret = yundaConfig.getAppSecret(); 38 | this.requestUrlPrefix = YundaMethod.URL_PREFIX; 39 | if (yundaConfig.getIsProduct() == 0) { 40 | this.requestUrlPrefix = YundaMethod.URL_TEST_PREFIX; 41 | } 42 | } 43 | 44 | /** 45 | * 路由查询. 46 | * 47 | * @param param 参数 48 | * @param format 格式 49 | * @return 查询结果 50 | */ 51 | public String queryRouteRequest(String param, String format) { 52 | String requestUrl = requestUrlPrefix + YundaMethod.QUERY_ROUTE_URL; 53 | return request(requestUrl, param, format); 54 | } 55 | 56 | /** 57 | * 路由订阅. 58 | * 59 | * @param param 参数 60 | * @param format 格式 61 | * @return 查询结果 62 | */ 63 | public String subscribeRouteRequest(String param, String format) { 64 | String requestUrl = requestUrlPrefix + YundaMethod.SUBSCRIBE_ROUTE_URL; 65 | return request(requestUrl, param, format); 66 | } 67 | 68 | /** 69 | * 运费预估. 70 | * 71 | * @param param 参数 72 | * @param format 格式 73 | * @return 请求结果 74 | */ 75 | public String queryPriceRequest(String param, String format) { 76 | String requestUrl = requestUrlPrefix + YundaMethod.QUERY_PRICE_URL; 77 | return request(requestUrl, param, format); 78 | } 79 | 80 | /** 81 | * 通用请求. 82 | * 83 | * @param param 参数 84 | * @param format 格式 85 | * @return 请求结果 86 | */ 87 | public String request(String requestUrl, String param, String format) { 88 | String beforeDigestStr = param + "_" + appSecret; 89 | String dataDigest = DigestUtils.md5DigestToStr(beforeDigestStr); 90 | Map requestHeader = new HashMap<>(3); 91 | requestHeader.put("app-key", appKey); 92 | requestHeader.put("sign", dataDigest); 93 | requestHeader.put("req-time", Long.toString(DateUtils.currentTimeMillis())); 94 | requestHeader.put("Content-Type", "application/json; charset=utf-8"); 95 | return HttpRequest.post(requestUrl) 96 | .addHeaders(requestHeader) 97 | .body(param) 98 | .execute().body(); 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/request/JituRequest.java: -------------------------------------------------------------------------------- 1 | package net.kdks.request; 2 | 3 | import cn.hutool.http.HttpRequest; 4 | import java.util.Base64; 5 | import java.util.Map; 6 | import net.kdks.config.JituConfig; 7 | import net.kdks.constant.JituConstant; 8 | import net.kdks.constant.JituMethod; 9 | import net.kdks.utils.Assert; 10 | import net.kdks.utils.DateUtils; 11 | import net.kdks.utils.DigestUtils; 12 | import net.kdks.utils.MapUtils; 13 | import net.kdks.utils.StringUtils; 14 | 15 | /** 16 | *

极兔请求封装

17 | *

date: 2021-01-13 17:23:55

. 18 | * 19 | * @author Ze.Wang 20 | * @since 0.0.8 21 | */ 22 | public class JituRequest { 23 | 24 | private String apiAccount; 25 | private String privateKey; 26 | 27 | private String uuid; 28 | 29 | private int isProduct; 30 | 31 | /** 32 | * Constructor. 33 | * 34 | * @param jituConfig 极兔配置 35 | */ 36 | public JituRequest(JituConfig jituConfig) { 37 | this.apiAccount = jituConfig.getApiAccount(); 38 | this.privateKey = jituConfig.getPrivateKey(); 39 | this.isProduct = jituConfig.getIsProduct(); 40 | this.uuid = jituConfig.getUuid(); 41 | 42 | } 43 | 44 | /** 45 | * 获取请求地址. 46 | * 47 | * @param method 方法 48 | * @return 请求地址 49 | */ 50 | public String getRequestUrl(String method) { 51 | if (isProduct == 0) { 52 | Assert.notEmpty(uuid, "请填写沙箱环境uuid!"); 53 | Map param = MapUtils.newHashMap(1); 54 | param.put("uuid", uuid); 55 | return 56 | JituConstant.URL_TEST + method + "?" + StringUtils.buildMapToStrUrl(param, "UTF-8"); 57 | } 58 | return JituConstant.URL + method; 59 | } 60 | 61 | /** 62 | * 路由查询. 63 | * 64 | * @param param 参数 65 | * @param format 格式 66 | * @return 查询结果 67 | */ 68 | public String queryRouteRequest(String param, String format) { 69 | return request(JituMethod.QUERY_ROUTE, param, format); 70 | } 71 | 72 | /** 73 | * 运费预估. 74 | * 75 | * @param param 参数 76 | * @param format 格式 77 | * @return 查询结果 78 | */ 79 | public String queryPriceRequest(String param, String format) { 80 | return request(JituMethod.QUERY_PRICE, param, format); 81 | } 82 | 83 | /** 84 | * 极兔通用请求. 85 | * 86 | * @param method 方法 87 | * @param param 参数 88 | * @param format 格式 89 | * @return 请求结果 90 | */ 91 | public String request(String method, String param, String format) { 92 | Map requestHeader = MapUtils.newHashMap(4); 93 | requestHeader.put("apiAccount", apiAccount); 94 | String timestamp = DateUtils.currentTimeStr(); 95 | requestHeader.put("timestamp", timestamp); 96 | String digest = 97 | Base64.getEncoder().encodeToString(DigestUtils.md5Digest(param + privateKey)); 98 | requestHeader.put("digest", digest); 99 | requestHeader.put("ContentType", "application/x-www-form-urlencoded; charset=utf-8"); 100 | 101 | Map paramMap = MapUtils.newHashMap(1); 102 | paramMap.put("bizContent", param); 103 | return HttpRequest.post(getRequestUrl(method)) 104 | .addHeaders(requestHeader) 105 | .body(StringUtils.buildMapToStrUrl(paramMap, "UTF-8")) 106 | .execute().body(); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Build Status 3 | Build Status 4 | Build Status 5 |

6 | 7 | 8 | # 聚合物流(aggregatelogistics) 9 | 10 | 它是一个聚合多家物流公司开放平台的**Java工具类库**,为解决公司电商项目集成物流而生。 11 | 12 | 当前已聚合顺丰、中通、申通、圆通、百世、极兔、京东。 13 | 14 | > 提示:多数快递公司都需要企业认证,即营业执照(公司或个体工商户)。所以个人用户难以配置并使用该类库。 15 | 16 | # 功能 17 | 18 | * 运单轨迹查询: 19 | 20 | 当前支持顺丰、中通、申通、圆通、百世、极兔、韵达、京东; 21 | 22 | * 运费及实效查询: 23 | 24 | 当前支持中通、申通、圆通、极兔; 25 | 26 | * 下单: 27 | 28 | 当前支持顺丰; 29 | 30 | # 使用 31 | 32 | ## 1. 引入 33 | 34 | * Maven 35 | 36 | ```xml 37 | 38 | net.kdks 39 | aggregatelogistics 40 | 0.0.13 41 | 42 | ``` 43 | 44 | * Gradle 45 | 46 | ``` 47 | compile 'net.kdks:aggregatelogistics:0.0.13' 48 | ``` 49 | 50 | ## 2. 调用 51 | 52 | ```java 53 | // 配置,每行最后一个参数0表示测试环境,1表示正式环境,不填为正式环境. 可选择性配置自己所需的快递公司 54 | // 所有配置参数需注册该快递公司开放平台,且多数需要企业认证(营业执照) 55 | ExpressConfig config=ExpressConfig.builder() 56 | // 顺丰配置 57 | .shunfengConfig("partnerId", "requestId", "checkWord", 1) 58 | // 申通配置 59 | .shentongConfig("appkey","secretKey",1) 60 | // 圆通配置 61 | .yuantongConfig("appkey", "secretKey", "userId", 1) 62 | // 中通配置 63 | .zhongtongConfig("companyId", "secretKey", "companyId", "secretKey", "routeVersioon", 1) 64 | // 极兔配置 65 | .jituConfig("apiAccount", "privateKey", "uuid", "customerCode", "customerPwd", 1) 66 | // 韵达配置 67 | .yundaConfig("appKey", "appSecret", 1) 68 | // 韵达配置 69 | .jingdongConfig("appKey", "appSecret", "accessToken", "customerCode", 1) 70 | .build(); 71 | ExpressHandlers expressHandlers=new ExpressHandlers(config); 72 | // 快递公司编号,具体查看net.kdks.enums.ExpressCompanyCodeEnum 73 | String expressCompanyNo="SF"; 74 | // 轨迹查询参数 75 | ExpressParam param=new ExpressParam(); 76 | // 单号必传 77 | List expressNo = new ArrayList<>(); 78 | expressNo.add("SF1028911111316"); 79 | param.setExpressNos(expressNo); 80 | // 手机号,顺丰必填(全11位或后4位),中通未绑定面单账号情况下必填 81 | param.setMobile("0728"); 82 | // 调用运单轨迹查询 83 | ExpressResponse expressResult=expressHandlers.getExpressInfo(param, "SF"); 84 | 85 | // 运费及实效查询参数,此处省略赋值,具体查看net.kdks.model.ExpressPriceParam 86 | ExpressPriceParam expressPriceParam = new ExpressPriceParam(); 87 | ExpressResponse result = expressHandlers.getExpressPrice(expressPriceParam, "STO"); 88 | 89 | // 下单参数,此处省略赋值,具体查看net.kdks.model.CreateOrderParam 90 | CreateOrderParam createOrderParam=new CreateOrderParam(); 91 | // 调用下单 92 | ExpressResponse orderResult=expressHandlers.createOrder(createOrderParam, "SF"); 93 | ``` 94 | 95 | 96 | 97 | ## 3. 文档 98 | 99 | > 提示:多数都需要企业认证,即营业执照(公司或个体工商户)。所以个人用户难以配置并使用该类库。 100 | 101 | * [Github wiki](https://github.com/fuzui/aggregatelogistics/wiki) 102 | 103 | * [Gitee wiki](https://gitee.com/fuzui/aggregatelogistics/wikis/Home) 104 | 105 | # 示例 106 | 107 | * [aggregatelogistics-demo-jfinal]([王泽/aggregatelogistics-demo-jfinal (gitee.com)](https://gitee.com/fuzui/aggregatelogistics-demo-jfinal)) 108 | 109 | # 反馈或建议 110 | 111 | * [Gitee issues](https://gitee.com/fuzui/aggregatelogistics/issues) 112 | 113 | * [Github issues](https://github.com/fuzui/aggregatelogistics/issues) 114 | 115 | # 致谢 116 | 117 | * [JustAuth](小而全而美的第三方登录开源组件) 参考了其部分设计结构与思想 118 | * [halo](https://github.com/halo-dev/halo) 参考了其部分设计结构与思想 119 | * [fastjson](https://github.com/alibaba/fastjson) 120 | 121 | * [hutool-http](https://gitee.com/loolly/hutool) -------------------------------------------------------------------------------- /src/main/java/net/kdks/request/YuantongRequest.java: -------------------------------------------------------------------------------- 1 | package net.kdks.request; 2 | 3 | import cn.hutool.http.Header; 4 | import cn.hutool.http.HttpRequest; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import net.kdks.config.YuantongConfig; 8 | import net.kdks.constant.YuantongMethod; 9 | import net.kdks.utils.DateUtils; 10 | import net.kdks.utils.DigestUtils; 11 | import net.kdks.utils.StringUtils; 12 | 13 | /** 14 | *

圆通请求封装

15 | *

date: 2021-01-12 13:29:57

. 16 | * 17 | * @author Ze.Wang 18 | * @since 0.0.7 19 | */ 20 | public class YuantongRequest { 21 | 22 | private String secretKey; 23 | private String appKey; 24 | private String userId; 25 | private String requestUrlPrefix; 26 | private String version = "1"; 27 | 28 | /** 29 | * Constructor. 30 | * 31 | * @param yuantongConfig 圆通配置 32 | */ 33 | public YuantongRequest(YuantongConfig yuantongConfig) { 34 | this.secretKey = yuantongConfig.getSecretKey(); 35 | this.appKey = yuantongConfig.getAppkey(); 36 | this.userId = yuantongConfig.getUserId(); 37 | this.requestUrlPrefix = YuantongMethod.URL_PREFIX; 38 | if (yuantongConfig.getIsProduct() == 0) { 39 | this.requestUrlPrefix = YuantongMethod.URL_TEST_PREFIX; 40 | } 41 | } 42 | 43 | /** 44 | * 路由查询. 45 | * 46 | * @param param 参数 47 | * @param format 格式 48 | * @return 查询结果 49 | */ 50 | public String queryRouteRequest(String param, String format) { 51 | String requestUrl = 52 | requestUrlPrefix + YuantongMethod.QUERY_ROUTE_URL + YuantongMethod.URL_VERSION + userId; 53 | return request(YuantongMethod.QUERY_ROUTE, requestUrl, param, format); 54 | } 55 | 56 | /** 57 | * 运费预估. 58 | * 59 | * @param param 参数 60 | * @param format 格式 61 | * @return 查询结果 62 | */ 63 | public String queryPriceRequest(String param, String format) { 64 | String requestUrl = 65 | requestUrlPrefix + YuantongMethod.QUERY_PRICE_URL + YuantongMethod.URL_VERSION + userId; 66 | return request(YuantongMethod.QUERY_PRICE, requestUrl, param, format); 67 | } 68 | 69 | /** 70 | * 圆通通用请求. 71 | * 72 | * @param method 方法 73 | * @param param 参数 74 | * @param format 格式 75 | * @return 请求结果 76 | */ 77 | public String request(String method, String requestUrl, String param, String format) { 78 | Map paramMap = new HashMap<>(8); 79 | String timestamp = DateUtils.currentTimeStr(); 80 | paramMap.put("app_key", appKey); 81 | paramMap.put("format", format); 82 | paramMap.put("method", method); 83 | paramMap.put("timestamp", timestamp); 84 | paramMap.put("user_id", userId); 85 | paramMap.put("v", version); 86 | paramMap.put("param", param); 87 | StringBuilder beforeDigestStr = new StringBuilder(secretKey); 88 | beforeDigestStr.append("app_key").append(appKey) 89 | .append("format").append(format) 90 | .append("method").append(method) 91 | .append("timestamp").append(timestamp) 92 | .append("user_id").append(userId) 93 | .append("v").append(version); 94 | String dataDigest = StringUtils.strTo16(DigestUtils.md5Digest(beforeDigestStr.toString())); 95 | paramMap.put("sign", dataDigest.toUpperCase()); 96 | 97 | return HttpRequest.post(requestUrl) 98 | .header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded") 99 | .body(StringUtils.buildMapToStr(paramMap, "UTF-8")) 100 | .execute().body(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/utils/DateUtils.java: -------------------------------------------------------------------------------- 1 | package net.kdks.utils; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.time.Instant; 5 | import java.time.LocalDateTime; 6 | import java.time.OffsetDateTime; 7 | import java.time.ZoneOffset; 8 | import java.time.format.DateTimeFormatter; 9 | import java.time.temporal.ChronoField; 10 | import java.util.Date; 11 | 12 | /** 13 | * 日期时间处理. 14 | * 15 | * @author Ze.Wang 16 | * @since 0.0.1 17 | */ 18 | public class DateUtils { 19 | private static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss"; 20 | 21 | /** 22 | * 获取当前日期. 23 | * 24 | * @return 当前日期 25 | */ 26 | public static String currentTimeStr() { 27 | return currentTimeStr(DEFAULT_FORMAT); 28 | } 29 | 30 | /** 31 | * 获取指定格式的日期. 32 | * 33 | * @param format 日期格式 34 | * @return 当前日期 35 | */ 36 | public static String currentTimeStr(String format) { 37 | if (format == null || "".equals(format)) { 38 | format = DEFAULT_FORMAT; 39 | } 40 | LocalDateTime dateTime = LocalDateTime.now(); 41 | return dateTime.format(DateTimeFormatter.ofPattern(format)); 42 | } 43 | 44 | /** 45 | * 获取当前时间戳(毫秒). 46 | * 47 | * @return 当前时间戳(毫秒) 48 | */ 49 | public static long currentTimeMillis() { 50 | return currentTimes().getLong(ChronoField.INSTANT_SECONDS) * 1000 51 | + currentTimes().getLong(ChronoField.MILLI_OF_SECOND); 52 | } 53 | 54 | /** 55 | * 获取当前时间戳(秒). 56 | * 57 | * @return 当前时间戳(秒) 58 | */ 59 | public static long currentTimeSeconds() { 60 | return currentTimes().getLong(ChronoField.INSTANT_SECONDS); 61 | } 62 | 63 | public static long millisToSeconds(Long millis) { 64 | return millis / 1000; 65 | } 66 | 67 | /** 68 | * 字符串时间转时间戳. 69 | * 70 | * @return 当前时间戳(秒) 71 | */ 72 | public static long strToTimestamp(String date) { 73 | DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 74 | LocalDateTime localDateTime = LocalDateTime.parse(date, dateTimeFormatter); 75 | return localDateTime.toInstant(ZoneOffset.ofHours(8)).getEpochSecond(); 76 | } 77 | 78 | /** 79 | * 毫秒转日期字符串. 80 | * 81 | * @param millSec 毫秒 82 | * @param dateFormat 格式 83 | * @return 日期字符串 84 | */ 85 | public static String millLongToDateStr(Long millSec, String dateFormat) { 86 | SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); 87 | Date date = new Date(millSec); 88 | return sdf.format(date); 89 | } 90 | 91 | /** 92 | * 毫秒转日期字符串. 93 | * 94 | * @param millSec 毫秒 95 | * @return 日期字符串 96 | */ 97 | public static String millLongToDateStr(Long millSec) { 98 | return millLongToDateStr(millSec, DEFAULT_FORMAT); 99 | } 100 | 101 | /** 102 | * 秒转日期字符串. 103 | * 104 | * @param sec 秒 105 | * @param dateFormat 格式 106 | * @return 日期字符串 107 | */ 108 | public static String secondLongToDateStr(Long sec, String dateFormat) { 109 | return millLongToDateStr(sec * 1000L, dateFormat); 110 | } 111 | 112 | /** 113 | * 秒转日期字符串. 114 | * 115 | * @param sec 秒 116 | * @return 日期字符串 117 | */ 118 | public static String secondLongToDateStr(Long sec) { 119 | return secondLongToDateStr(sec, DEFAULT_FORMAT); 120 | } 121 | 122 | /** 123 | * 获取当前日期(+8). 124 | * 125 | * @return 当前日期(+ 8) 126 | */ 127 | private static OffsetDateTime currentTimes() { 128 | Instant instant = Instant.now(); 129 | return instant.atOffset(ZoneOffset.ofHours(8)); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/request/JingdongRequest.java: -------------------------------------------------------------------------------- 1 | package net.kdks.request; 2 | 3 | import cn.hutool.http.HttpRequest; 4 | import java.time.LocalDateTime; 5 | import java.util.Base64; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import net.kdks.config.JingdongConfig; 9 | import net.kdks.config.JituConfig; 10 | import net.kdks.constant.JingdongConstant; 11 | import net.kdks.constant.JingdongMethod; 12 | import net.kdks.constant.JituConstant; 13 | import net.kdks.constant.JituMethod; 14 | import net.kdks.utils.Assert; 15 | import net.kdks.utils.DateUtils; 16 | import net.kdks.utils.DigestUtils; 17 | import net.kdks.utils.MapUtils; 18 | import net.kdks.utils.StringUtils; 19 | 20 | /** 21 | *

极兔请求封装

22 | *

date: 2021-01-13 17:23:55

. 23 | * 24 | * @author Ze.Wang 25 | * @since 0.0.8 26 | */ 27 | public class JingdongRequest { 28 | 29 | private String appKey; 30 | private String appSecret; 31 | 32 | private String accessToken; 33 | 34 | private int isProduct; 35 | 36 | /** 37 | * Constructor. 38 | * 39 | * @param jingdongConfig 京东配置 40 | */ 41 | public JingdongRequest(JingdongConfig jingdongConfig) { 42 | this.appKey = jingdongConfig.getAppKey(); 43 | this.appSecret = jingdongConfig.getAppSecret(); 44 | this.accessToken = jingdongConfig.getAccessToken(); 45 | this.isProduct = jingdongConfig.getIsProduct(); 46 | } 47 | 48 | /** 49 | * 获取请求地址. 50 | * 51 | * @return 请求地址 52 | */ 53 | public String getRequestUrl() { 54 | if (isProduct == 0) { 55 | return 56 | JingdongConstant.URL_TEST; 57 | } 58 | return JingdongConstant.URL; 59 | } 60 | 61 | /** 62 | * 路由查询. 63 | * 64 | * @param param 参数 65 | * @param format 格式 66 | * @return 查询结果 67 | */ 68 | public String queryRouteRequest(String param, String format) { 69 | return request(JingdongMethod.QUERY_ROUTE, param, format); 70 | } 71 | 72 | /** 73 | * 运费预估. 74 | * 75 | * @param param 参数 76 | * @param format 格式 77 | * @return 查询结果 78 | */ 79 | public String queryPriceRequest(String param, String format) { 80 | return request(JituMethod.QUERY_PRICE, param, format); 81 | } 82 | 83 | /** 84 | * 京东兔通用请求. 85 | * 86 | * @param method 方法 87 | * @param param 参数 88 | * @param format 格式 89 | * @return 请求结果 90 | */ 91 | @SuppressWarnings("checkstyle:LocalVariableName") 92 | public String request(String method, String param, String format) { 93 | Map query = MapUtils.newHashMap(7);; 94 | query.put("LOP-DN", "ECAP"); 95 | query.put("app_key", appKey); 96 | query.put("access_token", accessToken); 97 | String timestamp = DateUtils.currentTimeStr(); 98 | query.put("timestamp", timestamp); 99 | query.put("v", "2.0"); 100 | String content = String.join("", new String[]{ 101 | appSecret, 102 | "access_token", accessToken, 103 | "app_key", appKey, 104 | "method", method, 105 | "param_json", param, 106 | "timestamp", timestamp, 107 | "v", "2.0", 108 | appSecret}); 109 | 110 | String sign = DigestUtils.md5DigestToStr(content); 111 | query.put("sign", sign); 112 | query.put("algorithm", "md5-salt"); 113 | String url = getRequestUrl() + method + "?" 114 | + StringUtils.buildMapToStrUrl(query, "UTF-8"); 115 | Map requestHeader = MapUtils.newHashMap(1);; 116 | requestHeader.put("ContentType", "application/json; charset=utf-8"); 117 | 118 | return HttpRequest.post(url) 119 | .addHeaders(requestHeader) 120 | .body(param) 121 | .execute().body(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/request/ZhongtongRequest.java: -------------------------------------------------------------------------------- 1 | package net.kdks.request; 2 | 3 | import cn.hutool.http.HttpRequest; 4 | import java.util.Base64; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import net.kdks.config.ZhongtongConfig; 8 | import net.kdks.constant.ZhongtongMethod; 9 | import net.kdks.constant.ZhongtongRouteVersion; 10 | import net.kdks.utils.DigestUtils; 11 | import net.kdks.utils.StringUtils; 12 | 13 | /** 14 | *

中通请求封装

15 | *

date: 2021-01-12 13:29:57

. 16 | * 17 | * @author Ze.Wang 18 | * @since 0.0.7 19 | */ 20 | public class ZhongtongRequest { 21 | 22 | private String companyId; 23 | private String secretKeyV1; 24 | 25 | private String appKey; 26 | 27 | private String secretKey; 28 | private String requestUrlPrefix; 29 | 30 | /** 31 | * Constructor. 32 | * 33 | * @param zhongtongConfig 中通配置 34 | */ 35 | public ZhongtongRequest(ZhongtongConfig zhongtongConfig) { 36 | if (ZhongtongRouteVersion.V1.equals(zhongtongConfig.getRouteVersion())) { 37 | this.companyId = zhongtongConfig.getCompanyId(); 38 | this.secretKeyV1 = zhongtongConfig.getSecretKeyV1(); 39 | } else { 40 | this.appKey = zhongtongConfig.getAppKey(); 41 | this.secretKey = zhongtongConfig.getSecretKey(); 42 | } 43 | this.requestUrlPrefix = ZhongtongMethod.URL_PREFIX; 44 | if (zhongtongConfig.getIsProduct() == 0) { 45 | this.requestUrlPrefix = ZhongtongMethod.URL_TEST_PREFIX; 46 | } 47 | 48 | 49 | } 50 | 51 | /** 52 | * 路由查询. 53 | * 54 | * @param param 参数 55 | * @param format 格式 56 | * @return 查询结果 57 | */ 58 | public String queryRouteRequest(String param, String format) { 59 | String requestUrl = requestUrlPrefix + ZhongtongMethod.QUERY_ROUTE_URL; 60 | return request(requestUrl, param, format); 61 | } 62 | 63 | /** 64 | * 路由查询v1. 65 | * 66 | * @param param 参数 67 | * @param format 格式 68 | * @return 查询结果 69 | */ 70 | public String queryRouteRequestV1(String param, String format) { 71 | String requestUrl = requestUrlPrefix + ZhongtongMethod.QUERY_ROUTE_URL_V1; 72 | return requestV1(ZhongtongMethod.QUERY_ROUTE_V1, requestUrl, param, format); 73 | } 74 | 75 | /** 76 | * 运费预估. 77 | * 78 | * @param param 参数 79 | * @param format 格式 80 | * @return 请求结果 81 | */ 82 | public String queryPriceRequest(String param, String format) { 83 | String requestUrl = requestUrlPrefix + ZhongtongMethod.QUERY_PRICE_URL; 84 | return request(requestUrl, param, format); 85 | } 86 | 87 | /** 88 | * 通用请求. 89 | * 90 | * @param param 参数 91 | * @param format 格式 92 | * @return 请求结果 93 | */ 94 | public String request(String requestUrl, String param, String format) { 95 | String beforeDigestStr = param + secretKey; 96 | String dataDigest = 97 | Base64.getEncoder().encodeToString(DigestUtils.md5Digest(beforeDigestStr)); 98 | Map requestHeader = new HashMap<>(3); 99 | requestHeader.put("x-appKey", appKey); 100 | requestHeader.put("x-dataDigest", dataDigest); 101 | requestHeader.put("Content-Type", "application/json; charset=utf-8"); 102 | return HttpRequest.post(requestUrl) 103 | .addHeaders(requestHeader) 104 | .body(param) 105 | .execute().body(); 106 | } 107 | 108 | /** 109 | * 通用请求v1. 110 | * 111 | * @param method 方法 112 | * @param param 参数 113 | * @param format 格式 114 | * @return 请求结果 115 | */ 116 | public String requestV1(String method, String requestUrl, String param, String format) { 117 | HashMap paramMap = new HashMap<>(3); 118 | paramMap.put("company_id", companyId); 119 | paramMap.put("msg_type", method); 120 | paramMap.put("data", param); 121 | String beforeDigestStr = StringUtils.buildMapToStr(paramMap, "UTF-8") + secretKeyV1; 122 | String dataDigest = 123 | Base64.getEncoder().encodeToString(DigestUtils.md5Digest(beforeDigestStr)); 124 | Map requestHeader = new HashMap<>(3); 125 | requestHeader.put("x-companyid", companyId); 126 | requestHeader.put("x-datadigest", dataDigest); 127 | requestHeader.put("ContentType", "application/x-www-form-urlencoded; charset=utf-8"); 128 | return HttpRequest.post(requestUrl) 129 | .addHeaders(requestHeader) 130 | .body(StringUtils.buildMapToStrUrl(paramMap, "UTF-8")) 131 | .execute().body(); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package net.kdks.utils; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.URLEncoder; 5 | import java.nio.charset.Charset; 6 | import java.util.Map; 7 | import java.util.Map.Entry; 8 | 9 | /** 10 | * 字符串处理. 11 | * 12 | * @author Ze.Wang 13 | * @since 0.0.1 14 | */ 15 | public class StringUtils { 16 | 17 | public static boolean isEmpty(String str) { 18 | return null == str || str.isEmpty(); 19 | } 20 | 21 | public static boolean isNotEmpty(String str) { 22 | return !isEmpty(str); 23 | } 24 | 25 | /** 26 | * 如果给定字符串{@code str}中不包含{@code appendStr},则在{@code str}后追加{@code appendStr}; 27 | * 如果已包含{@code appendStr},则在{@code str}后追加{@code otherwise}. 28 | * 29 | * @param str 给定的字符串 30 | * @param appendStr 需要追加的内容 31 | * @param otherwise 当{@code appendStr}不满足时追加到{@code str}后的内容 32 | * @return 追加后的字符串 33 | */ 34 | public static String appendIfNotContain(String str, String appendStr, String otherwise) { 35 | if (isEmpty(str) || isEmpty(appendStr)) { 36 | return str; 37 | } 38 | if (str.contains(appendStr)) { 39 | return str.concat(otherwise); 40 | } 41 | return str.concat(appendStr); 42 | } 43 | 44 | /** 45 | * 编码字符串. 46 | * 47 | * @param str 字符串 48 | * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 49 | * @return 编码后的字节码 50 | */ 51 | public static byte[] bytes(CharSequence str, Charset charset) { 52 | if (str == null) { 53 | return null; 54 | } 55 | 56 | if (null == charset) { 57 | return str.toString().getBytes(); 58 | } 59 | return str.toString().getBytes(charset); 60 | } 61 | 62 | /** 63 | * 解码字节码. 64 | * 65 | * @param data 字符串 66 | * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 67 | * @return 解码后的字符串 68 | */ 69 | public static String str(byte[] data, Charset charset) { 70 | if (data == null) { 71 | return null; 72 | } 73 | 74 | if (null == charset) { 75 | return new String(data); 76 | } 77 | return new String(data, charset); 78 | } 79 | 80 | /** 81 | * map转String. 82 | * 83 | * @param params map 84 | * @param charset 字符集 85 | * @return 转换结果 86 | */ 87 | public static String buildMapToStr(Map params, String charset) { 88 | if (params == null || params.isEmpty()) { 89 | return null; 90 | } 91 | 92 | StringBuffer data = new StringBuffer(); 93 | boolean flag = false; 94 | 95 | for (Entry entry : params.entrySet()) { 96 | if (flag) { 97 | data.append("&"); 98 | } else { 99 | flag = true; 100 | } 101 | data.append(entry.getKey()).append("=") 102 | .append(entry.getValue().toString()); 103 | 104 | } 105 | return data.toString(); 106 | } 107 | 108 | /** 109 | * map转String. 110 | * 111 | * @param params map 112 | * @param charset 字符集. 113 | * @return 转换结果 114 | */ 115 | public static String buildMapToStrUrl(Map params, String charset) { 116 | 117 | if (params == null || params.isEmpty()) { 118 | return null; 119 | } 120 | 121 | StringBuffer data = new StringBuffer(); 122 | boolean flag = false; 123 | 124 | for (Entry entry : params.entrySet()) { 125 | if (flag) { 126 | data.append("&"); 127 | } else { 128 | flag = true; 129 | } 130 | try { 131 | data.append(entry.getKey()).append("=") 132 | .append(URLEncoder.encode(entry.getValue().toString(), charset)); 133 | } catch (UnsupportedEncodingException e) { 134 | e.printStackTrace(); 135 | } 136 | } 137 | return data.toString(); 138 | } 139 | 140 | /** 141 | * 字符串转换成为16进制(无需Unicode编码). 142 | * 143 | * @param bs 字符串字节数组 144 | * @return 16进制字符串 145 | */ 146 | public static String strTo16(byte[] bs) { 147 | char[] chars = "0123456789ABCDEF".toCharArray(); 148 | StringBuilder sb = new StringBuilder(); 149 | int bit; 150 | for (int i = 0; i < bs.length; i++) { 151 | bit = (bs[i] & 0x0f0) >> 4; 152 | sb.append(chars[bit]); 153 | bit = bs[i] & 0x0f; 154 | sb.append(chars[bit]); 155 | } 156 | return sb.toString().trim(); 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/test/java/net/kdks/handler/ExpressInfoTest.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import net.kdks.config.InitConfig; 7 | import net.kdks.enums.ExpressCompanyCodeEnum; 8 | import net.kdks.model.ExpressParam; 9 | import net.kdks.model.ExpressResponse; 10 | import net.kdks.model.ExpressResult; 11 | import org.junit.Test; 12 | 13 | /** 14 | * 物流轨迹测试. 15 | * 16 | * @author Ze.Wang 17 | * @since 0.0.8 18 | */ 19 | public class ExpressInfoTest { 20 | 21 | private final ExpressHandlers expressHandlers = new ExpressHandlers(InitConfig.getConfig()); 22 | 23 | /** 24 | * 中通 25 | */ 26 | @Test 27 | public void zto() { 28 | ExpressParam expressParam = new ExpressParam(); 29 | List expressNo = new ArrayList<>(); 30 | expressNo.add("73100059800035"); 31 | expressParam.setExpressNos(expressNo); 32 | ExpressResponse> result = 33 | expressHandlers.getExpressInfo(expressParam, "ZTO"); 34 | System.out.println(JSON.toJSONString(result)); 35 | } 36 | 37 | /** 38 | * 顺丰 39 | */ 40 | @Test 41 | public void sf() { 42 | ExpressParam expressParam = new ExpressParam(); 43 | List expressNo = new ArrayList<>(); 44 | expressNo.add(""); 45 | expressParam.setExpressNos(expressNo); 46 | expressParam.setMobile(""); 47 | ExpressResponse> result = 48 | expressHandlers.getExpressInfo(expressParam, ExpressCompanyCodeEnum.SF.getValue()); 49 | System.out.println(JSON.toJSONString(result)); 50 | } 51 | 52 | /** 53 | * 圆通 54 | */ 55 | @Test 56 | public void yto() { 57 | ExpressParam expressParam = new ExpressParam(); 58 | List expressNo = new ArrayList<>(); 59 | expressNo.add("YT1447279684726"); 60 | expressParam.setExpressNos(expressNo); 61 | ExpressResponse> result = 62 | expressHandlers.getExpressInfo(expressParam, ExpressCompanyCodeEnum.YTO.getValue()); 63 | System.out.println(JSON.toJSONString(result)); 64 | } 65 | 66 | /** 67 | * 申通 68 | */ 69 | @Test 70 | public void sto() { 71 | ExpressParam expressParam = new ExpressParam(); 72 | List expressNo = new ArrayList<>(); 73 | expressNo.add(""); 74 | expressParam.setExpressNos(expressNo); 75 | ExpressResponse> result = 76 | expressHandlers.getExpressInfo(expressParam, ExpressCompanyCodeEnum.STO.getValue()); 77 | System.out.println(JSON.toJSONString(result)); 78 | } 79 | 80 | /** 81 | * 百世 82 | */ 83 | @Test 84 | public void htky() { 85 | ExpressParam expressParam = new ExpressParam(); 86 | List expressNo = new ArrayList<>(); 87 | expressNo.add(""); 88 | expressParam.setExpressNos(expressNo); 89 | ExpressResponse> result = 90 | expressHandlers.getExpressInfo(expressParam, ExpressCompanyCodeEnum.HTKY.getValue()); 91 | System.out.println(JSON.toJSONString(result)); 92 | } 93 | 94 | /** 95 | * 极兔. 96 | */ 97 | @Test 98 | public void jt() { 99 | ExpressParam expressParam = new ExpressParam(); 100 | List expressNo = new ArrayList<>(); 101 | expressNo.add("UT0000352320970"); 102 | expressParam.setExpressNos(expressNo); 103 | ExpressResponse> result = 104 | expressHandlers.getExpressInfo(expressParam, ExpressCompanyCodeEnum.JT.getValue()); 105 | System.out.println(JSON.toJSONString(result)); 106 | } 107 | 108 | /** 109 | * 韵达. 110 | */ 111 | @Test 112 | public void yd() { 113 | ExpressParam expressParam = new ExpressParam(); 114 | List expressNo = new ArrayList<>(); 115 | expressNo.add(""); 116 | expressParam.setExpressNos(expressNo); 117 | ExpressResponse> result = 118 | expressHandlers.getExpressInfo(expressParam, ExpressCompanyCodeEnum.YD.getValue()); 119 | System.out.println(JSON.toJSONString(result)); 120 | } 121 | 122 | /** 123 | * 京东. 124 | */ 125 | @Test 126 | public void jd() { 127 | ExpressParam expressParam = new ExpressParam(); 128 | List expressNo = new ArrayList<>(); 129 | expressNo.add("11111111111"); 130 | expressParam.setExpressNos(expressNo); 131 | ExpressResponse> result = 132 | expressHandlers.getExpressInfo(expressParam, ExpressCompanyCodeEnum.JD.getValue()); 133 | System.out.println(JSON.toJSONString(result)); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/test/java/net/kdks/handler/ExpressPriceTest.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import java.math.BigDecimal; 5 | import net.kdks.config.InitConfig; 6 | import net.kdks.enums.ExpressCompanyCodeEnum; 7 | import net.kdks.model.ExpressPriceParam; 8 | import net.kdks.model.ExpressPriceResult; 9 | import net.kdks.model.ExpressResponse; 10 | import org.junit.Test; 11 | 12 | public class ExpressPriceTest { 13 | 14 | private final ExpressHandlers expressHandlers = new ExpressHandlers(InitConfig.getConfig()); 15 | 16 | /** 17 | * 申通. 18 | */ 19 | @Test 20 | public void sto() { 21 | ExpressPriceParam expressPriceParam = new ExpressPriceParam(); 22 | expressPriceParam.setStartProvince("北京"); 23 | expressPriceParam.setStartCity("北京市"); 24 | expressPriceParam.setStartDistrict("通州区"); 25 | expressPriceParam.setStartAddress("北京市通州区梨园中街道"); 26 | expressPriceParam.setEndProvince("山西省"); 27 | expressPriceParam.setEndCity("晋城市"); 28 | expressPriceParam.setEndDistrict("阳城县"); 29 | expressPriceParam.setEndAddress("山西省高平市阳城县"); 30 | expressPriceParam.setLength(new BigDecimal("20.00")); 31 | expressPriceParam.setWidth(new BigDecimal("5.00")); 32 | expressPriceParam.setHeight(new BigDecimal("5.00")); 33 | expressPriceParam.setWeight(null); 34 | ExpressResponse result = 35 | expressHandlers.getExpressPrice(expressPriceParam, 36 | ExpressCompanyCodeEnum.STO.getValue()); 37 | System.out.println(JSON.toJSONString(result)); 38 | } 39 | 40 | /** 41 | * 圆通. 42 | */ 43 | @Test 44 | public void yto() { 45 | ExpressPriceParam expressPriceParam = new ExpressPriceParam(); 46 | expressPriceParam.setStartProvince("北京市"); 47 | expressPriceParam.setStartCity("北京市"); 48 | // expressPriceParam.setStartDistrict("通州区"); 49 | // expressPriceParam.setStartAddress("北京市通州区梨园中街道"); 50 | expressPriceParam.setEndProvince("山西省"); 51 | expressPriceParam.setEndCity("晋城市"); 52 | // expressPriceParam.setEndDistrict("阳城县"); 53 | // expressPriceParam.setEndAddress("山西省高平市阳城县"); 54 | // expressPriceParam.setLength(new BigDecimal("20.00")); 55 | // expressPriceParam.setWidth(new BigDecimal("5.00")); 56 | // expressPriceParam.setHeight(new BigDecimal("5.00")); 57 | expressPriceParam.setWeight(new BigDecimal("1.00")); 58 | ExpressResponse result = 59 | expressHandlers.getExpressPrice(expressPriceParam, 60 | ExpressCompanyCodeEnum.YTO.getValue()); 61 | System.out.println(JSON.toJSONString(result)); 62 | } 63 | 64 | /** 65 | * 中通. 66 | */ 67 | @Test 68 | public void zto() { 69 | ExpressPriceParam expressPriceParam = new ExpressPriceParam(); 70 | expressPriceParam.setStartProvince("北京市"); 71 | expressPriceParam.setStartCity("北京市"); 72 | expressPriceParam.setStartDistrict("通州区"); 73 | // expressPriceParam.setStartAddress("北京市通州区梨园中街道"); 74 | expressPriceParam.setEndProvince("山西省"); 75 | expressPriceParam.setEndCity("晋城市"); 76 | expressPriceParam.setEndDistrict("阳城县"); 77 | // expressPriceParam.setEndAddress("山西省高平市阳城县"); 78 | // expressPriceParam.setLength(new BigDecimal("20.00")); 79 | // expressPriceParam.setWidth(new BigDecimal("5.00")); 80 | // expressPriceParam.setHeight(new BigDecimal("5.00")); 81 | expressPriceParam.setWeight(new BigDecimal("11.00")); 82 | ExpressResponse result = 83 | expressHandlers.getExpressPrice(expressPriceParam, 84 | ExpressCompanyCodeEnum.ZTO.getValue()); 85 | System.out.println(JSON.toJSONString(result)); 86 | } 87 | 88 | /** 89 | * 极兔. 90 | */ 91 | @Test 92 | public void jt() { 93 | ExpressPriceParam expressPriceParam = new ExpressPriceParam(); 94 | expressPriceParam.setStartProvince("北京"); 95 | expressPriceParam.setStartCity("北京市"); 96 | expressPriceParam.setStartDistrict("通州区"); 97 | expressPriceParam.setStartAddress("北京市通州区梨园中街道"); 98 | expressPriceParam.setEndProvince("山西省"); 99 | expressPriceParam.setEndCity("晋城市"); 100 | expressPriceParam.setEndDistrict("阳城县"); 101 | expressPriceParam.setEndAddress("山西省高平市阳城县"); 102 | expressPriceParam.setLength(new BigDecimal("20.00")); 103 | expressPriceParam.setWidth(new BigDecimal("5.00")); 104 | expressPriceParam.setHeight(new BigDecimal("5.00")); 105 | expressPriceParam.setWeight(null); 106 | ExpressResponse result = 107 | expressHandlers.getExpressPrice(expressPriceParam, 108 | ExpressCompanyCodeEnum.JT.getValue()); 109 | System.out.println(JSON.toJSONString(result)); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/test/java/net/kdks/config/InitConfig.java: -------------------------------------------------------------------------------- 1 | package net.kdks.config; 2 | 3 | import java.util.MissingResourceException; 4 | import java.util.ResourceBundle; 5 | 6 | public class InitConfig { 7 | 8 | public static ExpressConfig getConfig() { 9 | ResourceBundle bundle; 10 | try { 11 | bundle = ResourceBundle.getBundle("config-prod"); 12 | } catch (MissingResourceException e) { 13 | bundle = ResourceBundle.getBundle("config-dev"); 14 | } 15 | ExpressConfig.Builder configBuild = ExpressConfig.builder(); 16 | // 顺丰速运 17 | if (bundle.containsKey("express.sf.partnerID") && bundle.containsKey("express.sf.requestID") 18 | && bundle.containsKey("express.sf.checkWord") && 19 | bundle.containsKey("express.sf.isProduct")) { 20 | configBuild.shunfengConfig(bundle.getString("express.sf.partnerID"), 21 | bundle.getString("express.sf.requestID"), 22 | bundle.getString("express.sf.checkWord"), 23 | Integer.parseInt(bundle.getString("express.sf.isProduct"))); 24 | } 25 | // 申通 26 | if (bundle.containsKey("express.sto.appkey") && bundle.containsKey("express.sto.secretKey") 27 | && bundle.containsKey("express.sto.isProduct")) { 28 | configBuild.shentongConfig(bundle.getString("express.sto.appkey"), 29 | bundle.getString("express.sto.secretKey"), 30 | Integer.parseInt(bundle.getString("express.sto.isProduct"))); 31 | } 32 | // 百世 33 | if (bundle.containsKey("express.htky.partnerID") && 34 | bundle.containsKey("express.htky.secretKey") 35 | && bundle.containsKey("express.htky.isProduct")) { 36 | configBuild.baishiConfig(bundle.getString("express.htky.partnerID"), 37 | bundle.getString("express.htky.secretKey"), 38 | Integer.parseInt(bundle.getString("express.htky.isProduct"))); 39 | } 40 | // 圆通 41 | if (bundle.containsKey("express.yto.appkey") && bundle.containsKey("express.yto.secretKey") 42 | && bundle.containsKey("express.yto.userId") && 43 | bundle.containsKey("express.yto.isProduct")) { 44 | configBuild.yuantongConfig(bundle.getString("express.yto.appkey"), 45 | bundle.getString("express.yto.secretKey"), 46 | bundle.getString("express.yto.userId"), 47 | Integer.parseInt(bundle.getString("express.yto.isProduct"))); 48 | } 49 | // 中通 50 | if (bundle.containsKey("express.zto.companyId") && 51 | bundle.containsKey("express.zto.secretKey") 52 | && bundle.containsKey("express.zto.isProduct")) { 53 | configBuild.zhongtongConfig(bundle.getString("express.zto.companyId"), 54 | bundle.getString("express.zto.secretKeyV1"), 55 | bundle.getString("express.zto.appKey"), 56 | bundle.getString("express.zto.secretKey"), 57 | bundle.getString("express.zto.routeVersion"), 58 | Integer.parseInt(bundle.getString("express.zto.isProduct"))); 59 | } 60 | if (bundle.containsKey("express.jt.apiAccount") && 61 | bundle.containsKey("express.jt.privateKey") 62 | && bundle.containsKey("express.jt.isProduct")) { 63 | configBuild.jituConfig(bundle.getString("express.jt.apiAccount"), 64 | bundle.getString("express.jt.privateKey"), 65 | bundle.getString("express.jt.uuid"), 66 | Integer.parseInt(bundle.getString("express.jt.isProduct"))); 67 | configBuild.jituConfig(bundle.getString("express.jt.apiAccount"), 68 | bundle.getString("express.jt.privateKey"), 69 | bundle.getString("express.jt.uuid"), 70 | bundle.getString("express.jt.customerCode"), 71 | bundle.getString("express.jt.customerPwd"), 72 | Integer.parseInt(bundle.getString("express.jt.isProduct"))); 73 | } 74 | if (bundle.containsKey("express.yd.appKey") && 75 | bundle.containsKey("express.yd.appSecret") 76 | && bundle.containsKey("express.yd.isProduct")) { 77 | configBuild.yundaConfig(bundle.getString("express.yd.appKey"), 78 | bundle.getString("express.yd.appSecret"), 79 | Integer.parseInt(bundle.getString("express.yd.isProduct"))); 80 | } 81 | 82 | if (bundle.containsKey("express.jd.appKey") && 83 | bundle.containsKey("express.jd.appSecret") 84 | && bundle.containsKey("express.jd.accessToken") 85 | && bundle.containsKey("express.jd.isProduct") 86 | && bundle.containsKey("express.jd.isProduct")) { 87 | configBuild.jingdongConfig(bundle.getString("express.jd.appKey"), 88 | bundle.getString("express.jd.appSecret"), 89 | bundle.getString("express.jd.accessToken"), 90 | bundle.getString("express.jd.customerCode"), 91 | Integer.parseInt(bundle.getString("express.jd.isProduct"))); 92 | } 93 | return configBuild.build(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/handler/ExpressHandlers.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.List; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | import net.kdks.config.ExpressConfig; 8 | import net.kdks.enums.ExpressCompanyCodeEnum; 9 | import net.kdks.model.CreateOrderParam; 10 | import net.kdks.model.ExpressParam; 11 | import net.kdks.model.ExpressPriceParam; 12 | import net.kdks.model.ExpressPriceResult; 13 | import net.kdks.model.ExpressResponse; 14 | import net.kdks.model.ExpressResult; 15 | import net.kdks.model.OrderResult; 16 | import net.kdks.utils.Assert; 17 | 18 | /** 19 | * 业务处理. 20 | * 21 | * @author Ze.Wang 22 | * @since 0.0.1 23 | */ 24 | public class ExpressHandlers { 25 | 26 | /** 27 | * 快递公司实例. 28 | */ 29 | private final ConcurrentHashMap expressHandlers = 30 | new ConcurrentHashMap<>(16); 31 | 32 | /** 33 | * Add all express handler. 34 | * 35 | * @param expressConfig 快递配置 36 | */ 37 | public ExpressHandlers(ExpressConfig expressConfig) { 38 | List expressHandlerList = new ArrayList<>(); 39 | if (expressConfig.getShentongConfig() != null) { 40 | expressHandlerList.add(new ExpressShentongHandler(expressConfig.getShentongConfig())); 41 | } 42 | if (expressConfig.getYuantongConfig() != null) { 43 | expressHandlerList.add(new ExpressYuantongHandler(expressConfig.getYuantongConfig())); 44 | } 45 | if (expressConfig.getZhongtongConfig() != null) { 46 | expressHandlerList.add(new ExpressZhongtongHandler(expressConfig.getZhongtongConfig())); 47 | } 48 | if (expressConfig.getBaishiConfig() != null) { 49 | expressHandlerList.add(new ExpressBaishiHandler(expressConfig.getBaishiConfig())); 50 | } 51 | if (expressConfig.getShunfengConfig() != null) { 52 | expressHandlerList.add(new ExpressShunfengHandler(expressConfig.getShunfengConfig())); 53 | } 54 | if (expressConfig.getJituConfig() != null) { 55 | expressHandlerList.add(new ExpressJituHandler(expressConfig.getJituConfig())); 56 | } 57 | if (expressConfig.getYundaConfig() != null) { 58 | expressHandlerList.add(new ExpressYundaHandler(expressConfig.getYundaConfig())); 59 | } 60 | if (expressConfig.getJingdongConfig() != null) { 61 | expressHandlerList.add(new ExpressJingdongHandler(expressConfig.getJingdongConfig())); 62 | } 63 | addLogisticsHandlers(expressHandlerList); 64 | } 65 | 66 | /** 67 | * 查询轨迹信息. 68 | * 69 | * @param expressParam 快递号、手机、快递公司编码 70 | * @param expressCompanyCode 快递公司编码 71 | * @return 查询接口 72 | */ 73 | public ExpressResponse> getExpressInfo(ExpressParam expressParam, 74 | String expressCompanyCode) { 75 | return getSupportedCode(expressCompanyCode).getExpressInfo(expressParam); 76 | } 77 | 78 | /** 79 | * 运费预估. 80 | * 81 | * @param expressPriceParam 起始省份、起始城市、目的身份、目的城市、重量、长、宽、高 82 | * @return 运费 83 | */ 84 | public ExpressResponse getExpressPrice(ExpressPriceParam expressPriceParam, 85 | String expressCompanyCode) { 86 | return getSupportedCode(expressCompanyCode).getExpressPrice(expressPriceParam); 87 | } 88 | 89 | /** 90 | * 创建订单. 91 | * 92 | * @param createOrderParam 下单参数,主要包含物品信息、收件人信息、寄件人信息等 93 | * @param expressCompanyCode 快递公司编码 94 | * @return 快递单号等信息 95 | */ 96 | public ExpressResponse createOrder(CreateOrderParam createOrderParam, 97 | String expressCompanyCode) { 98 | return getSupportedCode(expressCompanyCode).createOrder(createOrderParam); 99 | } 100 | 101 | /** 102 | * Adds express handlers. 103 | * 104 | * @param expressHandlers express handler collection 105 | * @return current express handlers 106 | */ 107 | public ExpressHandlers addLogisticsHandlers(Collection expressHandlers) { 108 | if (expressHandlers != null && expressHandlers.size() > 0) { 109 | for (ExpressHandler handler : expressHandlers) { 110 | if (this.expressHandlers.containsKey(handler.getExpressCompanyCode())) { 111 | System.out.println("Same express company code implements must be unique"); 112 | } 113 | this.expressHandlers.put(handler.getExpressCompanyCode(), handler); 114 | } 115 | } 116 | return this; 117 | } 118 | 119 | /** 120 | * get supported code. 121 | * 122 | * @param code express company code 123 | * @return ExpressHandler 124 | */ 125 | private ExpressHandler getSupportedCode(String code) { 126 | ExpressHandler handler = expressHandlers.getOrDefault(code, 127 | expressHandlers.get(ExpressCompanyCodeEnum.STO.getValue())); 128 | Assert.notNull(handler, "不支持的快递公司!"); 129 | return handler; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/handler/ExpressJingdongHandler.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.TypeReference; 5 | import java.util.ArrayList; 6 | import java.util.Base64; 7 | import java.util.List; 8 | import java.util.Map; 9 | import net.kdks.config.JingdongConfig; 10 | import net.kdks.config.JituConfig; 11 | import net.kdks.constant.CommonConstant; 12 | import net.kdks.constant.JingdongConstant; 13 | import net.kdks.constant.JituConstant; 14 | import net.kdks.enums.ExpressCompanyCodeEnum; 15 | import net.kdks.enums.ExpressStateEnum; 16 | import net.kdks.model.CreateOrderParam; 17 | import net.kdks.model.ExpressData; 18 | import net.kdks.model.ExpressParam; 19 | import net.kdks.model.ExpressPriceParam; 20 | import net.kdks.model.ExpressPriceResult; 21 | import net.kdks.model.ExpressResponse; 22 | import net.kdks.model.ExpressResult; 23 | import net.kdks.model.OrderResult; 24 | import net.kdks.model.jd.JingdongResult; 25 | import net.kdks.model.jd.route.JingdongRouteItem; 26 | import net.kdks.model.jd.route.JingdongRouteResult; 27 | import net.kdks.model.jt.JituResult; 28 | import net.kdks.model.jt.price.JituPriceResult; 29 | import net.kdks.model.jt.route.JituRouteItem; 30 | import net.kdks.model.jt.route.JituRouteResult; 31 | import net.kdks.request.JingdongRequest; 32 | import net.kdks.request.JituRequest; 33 | import net.kdks.utils.Assert; 34 | import net.kdks.utils.DigestUtils; 35 | import net.kdks.utils.MapUtils; 36 | 37 | /** 38 | * 京东. 39 | * 40 | * @author Ze.Wang 41 | * @since 0.0.11 42 | */ 43 | public class ExpressJingdongHandler implements ExpressHandler { 44 | 45 | 46 | private JingdongRequest jingdongRequest; 47 | 48 | private JingdongConfig jingdongConfig; 49 | 50 | public ExpressJingdongHandler(JingdongConfig jingdongConfig) { 51 | this.jingdongConfig = jingdongConfig; 52 | this.jingdongRequest = new JingdongRequest(jingdongConfig); 53 | } 54 | 55 | /** 56 | * 查询轨迹信息. 57 | * 58 | * @param expressParam 快递号、手机、快递公司编码 59 | * @return 查询接口 60 | */ 61 | @Override 62 | public ExpressResponse> getExpressInfo(ExpressParam expressParam) { 63 | List expressResults = new ArrayList<>(); 64 | for (String expressNo : expressParam.getExpressNos()) { 65 | Map paramMap = MapUtils.newHashMap(3); 66 | paramMap.put("waybillCode", expressNo); 67 | paramMap.put("orderOrigin", "1"); 68 | paramMap.put("customerCode", jingdongConfig.getCustomerCode()); 69 | List> paramList = new ArrayList<>(); 70 | paramList.add(paramMap); 71 | String param = JSON.toJSONString(paramList); 72 | String responseData = jingdongRequest.queryRouteRequest(param, expressParam.getFormat()); 73 | ExpressResult expressResult = disposeResult(responseData, expressNo, expressParam); 74 | expressResults.add(expressResult); 75 | } 76 | return ExpressResponse.ok(expressResults); 77 | } 78 | 79 | /** 80 | * 结果处理. 81 | * 82 | * @param responseData 响应 83 | * @return 查询结果 84 | */ 85 | private ExpressResult disposeResult(String responseData, String expressNo, 86 | ExpressParam expressParam) { 87 | 88 | ExpressResult expressResult = new ExpressResult(); 89 | if (expressParam.isViewOriginal()) { 90 | expressResult.setOriginalResult(responseData); 91 | } 92 | expressResult.setCom(ExpressCompanyCodeEnum.JD.getValue()); 93 | expressResult.setNu(expressNo); 94 | JingdongResult result = 95 | JSON.parseObject(responseData, 96 | new TypeReference>() {}); 97 | if (!JingdongConstant.REQUEST_SUCCESS_CODE.equals(result.getCode()) 98 | || result.getData() == null) { 99 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 100 | expressResult.setMsg(result.getMsg()); 101 | return expressResult; 102 | } 103 | List routes = result.getData().getTraceDetails(); 104 | if (routes == null || routes.isEmpty()) { 105 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 106 | expressResult.setMsg(CommonConstant.NO_INFO); 107 | return expressResult; 108 | } 109 | if (expressParam.isViewRoute()) { 110 | List data = new ArrayList<>(routes.size()); 111 | data.addAll(routes); 112 | expressResult.setData(data); 113 | } 114 | expressResult.setState(routes.get(0).getStatus()); 115 | if (ExpressStateEnum.SIGNED.getValue().equals(expressResult.getState())) { 116 | expressResult.setIscheck(CommonConstant.YES); 117 | } 118 | return expressResult; 119 | 120 | 121 | } 122 | 123 | /** 124 | * 运费预估. 125 | * 126 | * @param expressPriceParam 起始省份、起始城市、目的身份、目的城市、重量、长、宽、高 127 | * @return 运费 128 | */ 129 | @Override 130 | public ExpressResponse getExpressPrice( 131 | ExpressPriceParam expressPriceParam) { 132 | return ExpressResponse.failed(CommonConstant.NO_SOPPORT); 133 | } 134 | 135 | /** 136 | * 创建订单. 137 | * 138 | * @param createOrderParam 下单参数,主要包含物品信息、收件人信息、寄件人信息等 139 | * @return 快递单号等信息 140 | */ 141 | @Override 142 | public ExpressResponse createOrder(CreateOrderParam createOrderParam) { 143 | return ExpressResponse.failed(CommonConstant.NO_SOPPORT); 144 | } 145 | 146 | /** 147 | * 获取当前快递公司编码. 148 | * 149 | * @return 快递公司编码 150 | */ 151 | @Override 152 | public String getExpressCompanyCode() { 153 | return ExpressCompanyCodeEnum.JD.getValue(); 154 | } 155 | 156 | } 157 | 158 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/utils/Base64Utils.java: -------------------------------------------------------------------------------- 1 | package net.kdks.utils; 2 | 3 | import java.nio.charset.Charset; 4 | import java.nio.charset.StandardCharsets; 5 | 6 | /** 7 | * Base64编码. 8 | * 9 | * @author Ze.Wang 10 | * @since 0.0.1 11 | */ 12 | public class Base64Utils { 13 | 14 | private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; 15 | /** 16 | * 标准编码表. 17 | */ 18 | private static final byte[] STANDARD_ENCODE_TABLE = { 19 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 20 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 21 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 22 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 23 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 24 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 25 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', 26 | '4', '5', '6', '7', '8', '9', '+', '/' 27 | }; 28 | /** 29 | * URL安全的编码表,将 + 和 / 替换为 - 和 _. 30 | */ 31 | private static final byte[] URL_SAFE_ENCODE_TABLE = { 32 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 33 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 34 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 35 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 36 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 37 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 38 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', 39 | '4', '5', '6', '7', '8', '9', '-', '_' 40 | }; 41 | 42 | /** 43 | * 编码为Base64,URL安全的. 44 | * 45 | * @param arr 被编码的数组 46 | * @param lineSep 在76个char之后是CRLF还是EOF 47 | * @return 编码后的bytes 48 | * @since 3.0.6 49 | */ 50 | public static byte[] encodeUrlSafe(byte[] arr, boolean lineSep) { 51 | return encode(arr, lineSep, true); 52 | } 53 | 54 | /** 55 | * base64编码,URL安全. 56 | * 57 | * @param source 被编码的base64字符串 58 | * @return 被加密后的字符串 59 | * @since 3.0.6 60 | */ 61 | public static String encodeUrlSafe(CharSequence source) { 62 | return encodeUrlSafe(source, DEFAULT_CHARSET); 63 | } 64 | 65 | /** 66 | * base64编码,URL安全的. 67 | * 68 | * @param source 被编码的base64字符串 69 | * @param charset 字符集 70 | * @return 被加密后的字符串 71 | * @since 3.0.6 72 | */ 73 | public static String encodeUrlSafe(CharSequence source, Charset charset) { 74 | return encodeUrlSafe(StringUtils.bytes(source, charset)); 75 | } 76 | 77 | /** 78 | * base64编码,URL安全的. 79 | * 80 | * @param source 被编码的base64字符串 81 | * @return 被加密后的字符串 82 | * @since 3.0.6 83 | */ 84 | public static String encodeUrlSafe(byte[] source) { 85 | return StringUtils.str(encodeUrlSafe(source, false), DEFAULT_CHARSET); 86 | } 87 | 88 | /** 89 | * 编码为Base64,非URL安全的. 90 | * 91 | * @param arr 被编码的数组 92 | * @param lineSep 在76个char之后是CRLF还是EOF 93 | * @return 编码后的bytes 94 | */ 95 | public static byte[] encode(byte[] arr, boolean lineSep) { 96 | return encode(arr, lineSep, false); 97 | } 98 | 99 | /** 100 | * base64编码. 101 | * 102 | * @param source 被编码的base64字符串 103 | * @return 被加密后的字符串 104 | */ 105 | public static String encode(CharSequence source) { 106 | return encode(source, DEFAULT_CHARSET); 107 | } 108 | 109 | /** 110 | * base64编码. 111 | * 112 | * @param source 被编码的base64字符串 113 | * @param charset 字符集 114 | * @return 被加密后的字符串 115 | */ 116 | public static String encode(CharSequence source, Charset charset) { 117 | return encode(StringUtils.bytes(source, charset)); 118 | } 119 | 120 | /** 121 | * base64编码. 122 | * 123 | * @param source 被编码的base64字符串 124 | * @return 被加密后的字符串 125 | */ 126 | public static String encode(byte[] source) { 127 | return StringUtils.str(encode(source, false), DEFAULT_CHARSET); 128 | } 129 | 130 | /** 131 | * 编码为Base64
132 | * 如果isMultiLine为true,则每76个字符一个换行符,否则在一行显示. 133 | * 134 | * @param arr 被编码的数组 135 | * @param isMultiLine 在76个char之后是CRLF还是EOF 136 | * @param isUrlSafe 是否使用URL安全字符,一般为false 137 | * @return 编码后的bytes 138 | */ 139 | public static byte[] encode(byte[] arr, boolean isMultiLine, boolean isUrlSafe) { 140 | if (null == arr) { 141 | return null; 142 | } 143 | 144 | int len = arr.length; 145 | if (len == 0) { 146 | return new byte[0]; 147 | } 148 | 149 | int evenlen = (len / 3) * 3; 150 | int cnt = ((len - 1) / 3 + 1) << 2; 151 | int destlen = cnt + (isMultiLine ? (cnt - 1) / 76 << 1 : 0); 152 | byte[] dest = new byte[destlen]; 153 | 154 | byte[] encodeTable = isUrlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE; 155 | 156 | for (int s = 0, d = 0, cc = 0; s < evenlen; ) { 157 | int i = (arr[s++] & 0xff) << 16 | (arr[s++] & 0xff) << 8 | (arr[s++] & 0xff); 158 | 159 | dest[d++] = encodeTable[(i >>> 18) & 0x3f]; 160 | dest[d++] = encodeTable[(i >>> 12) & 0x3f]; 161 | dest[d++] = encodeTable[(i >>> 6) & 0x3f]; 162 | dest[d++] = encodeTable[i & 0x3f]; 163 | 164 | if (isMultiLine && ++cc == 19 && d < destlen - 2) { 165 | dest[d++] = '\r'; 166 | dest[d++] = '\n'; 167 | cc = 0; 168 | } 169 | } 170 | 171 | // 剩余位数 172 | int left = len - evenlen; 173 | if (left > 0) { 174 | int i = ((arr[evenlen] & 0xff) << 10) | (left == 2 ? ((arr[len - 1] & 0xff) << 2) : 0); 175 | 176 | dest[destlen - 4] = encodeTable[i >> 12]; 177 | dest[destlen - 3] = encodeTable[(i >>> 6) & 0x3f]; 178 | 179 | if (isUrlSafe) { 180 | // 在URL Safe模式下,=为URL中的关键字符,不需要补充。空余的byte位要去掉。 181 | int urlSafeLen = destlen - 2; 182 | int leftFlag = 2; 183 | if (left == leftFlag) { 184 | dest[destlen - 2] = encodeTable[i & 0x3f]; 185 | urlSafeLen += 1; 186 | } 187 | byte[] urlSafeDest = new byte[urlSafeLen]; 188 | System.arraycopy(dest, 0, urlSafeDest, 0, urlSafeLen); 189 | return urlSafeDest; 190 | } else { 191 | dest[destlen - 2] = (left == 2) ? encodeTable[i & 0x3f] : (byte) '='; 192 | dest[destlen - 1] = '='; 193 | } 194 | } 195 | return dest; 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/handler/ExpressBaishiHandler.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import cn.hutool.http.HttpRequest; 4 | import com.alibaba.fastjson.JSON; 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import net.kdks.config.BaishiConfig; 11 | import net.kdks.constant.CommonConstant; 12 | import net.kdks.enums.ExpressCompanyCodeEnum; 13 | import net.kdks.enums.ExpressStateEnum; 14 | import net.kdks.model.CreateOrderParam; 15 | import net.kdks.model.ExpressData; 16 | import net.kdks.model.ExpressParam; 17 | import net.kdks.model.ExpressPriceParam; 18 | import net.kdks.model.ExpressPriceResult; 19 | import net.kdks.model.ExpressResponse; 20 | import net.kdks.model.ExpressResult; 21 | import net.kdks.model.OrderResult; 22 | import net.kdks.model.htky.BaishiResult; 23 | import net.kdks.model.htky.BaishiTraceItems; 24 | import net.kdks.model.htky.BaishiTraceLog; 25 | import net.kdks.utils.DigestUtils; 26 | import net.kdks.utils.MapUtils; 27 | import net.kdks.utils.StringUtils; 28 | 29 | /** 30 | * 百世. 31 | * 32 | * @author Ze.Wang 33 | * @since 0.0.1 34 | */ 35 | public class ExpressBaishiHandler implements ExpressHandler { 36 | 37 | private BaishiConfig baishiConfig; 38 | 39 | public ExpressBaishiHandler(BaishiConfig baishiConfig) { 40 | this.baishiConfig = baishiConfig; 41 | } 42 | 43 | /** 44 | * 查询轨迹信息. 45 | * 46 | * @param expressParam 快递号、手机、快递公司编码 47 | * @return 查询接口 48 | */ 49 | @Override 50 | public ExpressResponse> getExpressInfo(ExpressParam expressParam) { 51 | String requestUrl = "http://edi-q9.ns.800best.com/kd/api/process"; 52 | if (baishiConfig.getIsProduct() == 0) { 53 | requestUrl = "http://kdtest.800best.com/kd/api/process"; 54 | } 55 | 56 | HashMap paramMap = new HashMap<>(5); 57 | HashMap paramItemsMap = new HashMap<>(1); 58 | HashMap paramItems = new HashMap<>(1); 59 | List expressNos = expressParam.getExpressNos(); 60 | paramItems.put("mailNo", expressNos); 61 | paramItemsMap.put("mailNos", paramItems); 62 | String bizData = JSON.toJSONString(paramItemsMap); 63 | paramMap.put("bizData", bizData); 64 | paramMap.put("serviceType", "KD_TRACE_QUERY"); 65 | paramMap.put("partnerID", baishiConfig.getPartnerId()); 66 | paramMap.put("messageType", "JSON"); 67 | 68 | String beforeDigestStr = bizData + baishiConfig.getSecretKey(); 69 | String sign = StringUtils.strTo16(DigestUtils.md5Digest(beforeDigestStr)); 70 | paramMap.put("sign", sign.toLowerCase()); 71 | 72 | Map requestHeader = new HashMap<>(1); 73 | 74 | requestHeader.put("ContentType", "application/x-www-form-urlencoded"); 75 | String responseData = HttpRequest.post(requestUrl) 76 | .addHeaders(requestHeader) 77 | .body(StringUtils.buildMapToStrUrl(paramMap, "UTF-8")) 78 | .execute().body(); 79 | return disposeResult(responseData, expressParam); 80 | 81 | } 82 | 83 | /** 84 | * 结果处理. 85 | * 86 | * @param responseData 响应 87 | * @return 查询结果 88 | */ 89 | private ExpressResponse> disposeResult(String responseData, 90 | ExpressParam expressParam) { 91 | List expressNos = expressParam.getExpressNos(); 92 | BaishiResult result = JSON.parseObject(responseData, BaishiResult.class); 93 | List expressResults = new ArrayList<>(); 94 | if (result.getResult()) { 95 | //此结果必然存在不会出现空指针,无需判断 96 | if (result.getTraceLogs() == null || result.getTraceLogs().size() == 0) { 97 | return ExpressResponse.failed(CommonConstant.NO_INFO); 98 | } 99 | 100 | Map traceLogMap = 101 | MapUtils.newHashMap(result.getTraceLogs().size()); 102 | for (BaishiTraceLog traceLog : result.getTraceLogs()) { 103 | traceLogMap.put(traceLog.getMailNo(), traceLog); 104 | } 105 | for (String expressNo : expressNos) { 106 | ExpressResult expressResult = new ExpressResult(); 107 | if (expressParam.isViewOriginal()) { 108 | expressResult.setOriginalResult(responseData); 109 | } 110 | expressResult.setCom(ExpressCompanyCodeEnum.HTKY.getValue()); 111 | expressResult.setNu(expressNo); 112 | List routes = traceLogMap.get(expressNo).getTraces().getTrace(); 113 | if (routes == null || routes.size() == 0) { 114 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 115 | expressResult.setMsg(CommonConstant.NO_INFO); 116 | expressResults.add(expressResult); 117 | continue; 118 | } 119 | //官方默认正序,改为倒序 120 | Collections.reverse(routes); 121 | ExpressData latestData = routes.get(0); 122 | if (expressParam.isViewRoute()) { 123 | List data = new ArrayList<>(routes.size()); 124 | data.addAll(routes); 125 | expressResult.setData(data); 126 | } 127 | expressResult.setState(latestData.getStatus()); 128 | if (ExpressStateEnum.SIGNED.getValue().equals(expressResult.getState())) { 129 | expressResult.setIscheck(CommonConstant.YES); 130 | } 131 | 132 | expressResults.add(expressResult); 133 | } 134 | return ExpressResponse.ok(expressResults); 135 | } 136 | return ExpressResponse.failed(result.getErrorDescription()); 137 | 138 | } 139 | 140 | /** 141 | * 运费预估. 142 | * 143 | * @param expressPriceParam 起始省份、起始城市、目的身份、目的城市、重量、长、宽、高 144 | * @return 运费 145 | */ 146 | @Override 147 | public ExpressResponse getExpressPrice( 148 | ExpressPriceParam expressPriceParam) { 149 | return ExpressResponse.failed(CommonConstant.NO_SOPPORT); 150 | } 151 | 152 | /** 153 | * 创建订单. 154 | * 155 | * @param createOrderParam 下单参数,主要包含物品信息、收件人信息、寄件人信息等 156 | * @return 快递单号等信息 157 | */ 158 | @Override 159 | public ExpressResponse createOrder(CreateOrderParam createOrderParam) { 160 | return ExpressResponse.failed(CommonConstant.NO_SOPPORT); 161 | } 162 | 163 | /** 164 | * 获取当前快递公司编码. 165 | * 166 | * @return 快递公司编码 167 | */ 168 | @Override 169 | public String getExpressCompanyCode() { 170 | return ExpressCompanyCodeEnum.HTKY.getValue(); 171 | } 172 | 173 | } 174 | 175 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/handler/ExpressYundaHandler.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import cn.hutool.http.Header; 4 | import cn.hutool.http.HttpRequest; 5 | import com.alibaba.fastjson.JSON; 6 | import com.alibaba.fastjson.TypeReference; 7 | import java.io.UnsupportedEncodingException; 8 | import java.net.URLEncoder; 9 | import java.util.ArrayList; 10 | import java.util.Base64; 11 | import java.util.Collections; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | import net.kdks.config.ShunfengConfig; 16 | import net.kdks.config.YundaConfig; 17 | import net.kdks.constant.CommonConstant; 18 | import net.kdks.constant.ZhongtongRouteVersion; 19 | import net.kdks.enums.ExpressCompanyCodeEnum; 20 | import net.kdks.enums.ExpressStateEnum; 21 | import net.kdks.model.CreateOrderParam; 22 | import net.kdks.model.ExpressData; 23 | import net.kdks.model.ExpressParam; 24 | import net.kdks.model.ExpressPriceParam; 25 | import net.kdks.model.ExpressPriceResult; 26 | import net.kdks.model.ExpressResponse; 27 | import net.kdks.model.ExpressResult; 28 | import net.kdks.model.ExpressRouteSubscribeData; 29 | import net.kdks.model.OrderResult; 30 | import net.kdks.model.sf.Route; 31 | import net.kdks.model.sf.RouteResps; 32 | import net.kdks.model.sf.ShunfengResult; 33 | import net.kdks.model.sf.WaybillNoInfo; 34 | import net.kdks.model.yd.YundaResult; 35 | import net.kdks.model.yd.route.YundaRouteItem; 36 | import net.kdks.model.yd.route.YundaRouteResult; 37 | import net.kdks.model.yd.route.YundaRouteSubscribeItem; 38 | import net.kdks.model.yd.route.YundaRouteSubscribeResult; 39 | import net.kdks.model.zto.ZhongtongResult; 40 | import net.kdks.model.zto.ZhongtongTrace; 41 | import net.kdks.request.YundaRequest; 42 | import net.kdks.request.ZhongtongRequest; 43 | import net.kdks.utils.DateUtils; 44 | import net.kdks.utils.DigestUtils; 45 | import net.kdks.utils.MapUtils; 46 | import net.kdks.utils.StringUtils; 47 | 48 | /** 49 | * 顺丰. 50 | * 51 | * @author Ze.Wang 52 | * @since 0.0.1 53 | */ 54 | public class ExpressYundaHandler implements ExpressHandler { 55 | 56 | private YundaRequest yundaRequest; 57 | private YundaConfig yundaConfig; 58 | 59 | public ExpressYundaHandler(YundaConfig yundaConfig) { 60 | this.yundaConfig = yundaConfig; 61 | this.yundaRequest = new YundaRequest(yundaConfig); 62 | } 63 | 64 | /** 65 | * 查询轨迹信息. 66 | * 67 | * @param expressParam 快递号、手机、快递公司编码 68 | * @return 查询接口 69 | */ 70 | @Override 71 | public ExpressResponse> getExpressInfo(ExpressParam expressParam) { 72 | List expressResults = new ArrayList<>(); 73 | subscribeRoute(expressParam); 74 | for (String expressNo : expressParam.getExpressNos()) { 75 | Map param = MapUtils.newHashMap(1); 76 | param.put("mailno", expressNo); 77 | String responseData = yundaRequest.queryRouteRequest(JSON.toJSONString(param), 78 | expressParam.getFormat()); 79 | ExpressResult expressResult = disposeResult(responseData, expressNo, expressParam); 80 | expressResults.add(expressResult); 81 | } 82 | return ExpressResponse.ok(expressResults); 83 | } 84 | 85 | /** 86 | * 结果处理. 87 | * 88 | * @param responseData 响应 89 | * @return 处理结果 90 | */ 91 | private ExpressResult disposeResult(String responseData, String expressNo, 92 | ExpressParam expressParam) { 93 | ExpressResult expressResult = new ExpressResult(); 94 | if (expressParam.isViewOriginal()) { 95 | expressResult.setOriginalResult(responseData); 96 | } 97 | expressResult.setCom(ExpressCompanyCodeEnum.YD.getValue()); 98 | expressResult.setNu(expressNo); 99 | List expressNos = expressParam.getExpressNos(); 100 | YundaResult result = JSON.parseObject(responseData, 101 | new TypeReference>() { 102 | }); 103 | if (!result.getResult()) { 104 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 105 | expressResult.setMsg(result.getMessage()); 106 | return expressResult; 107 | } 108 | if (result.getData() == null || result.getData().getSteps() == null 109 | || result.getData().getSteps().size() == 0) { 110 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 111 | expressResult.setMsg(CommonConstant.NO_INFO); 112 | return expressResult; 113 | } 114 | List routes = result.getData().getSteps(); 115 | // 默认正序,改为倒序 116 | Collections.reverse(routes); 117 | ExpressData latestData = routes.get(0); 118 | if (expressParam.isViewRoute()) { 119 | List data = new ArrayList<>(routes.size()); 120 | data.addAll(routes); 121 | expressResult.setData(data); 122 | } 123 | expressResult.setState(latestData.getStatus()); 124 | if (ExpressStateEnum.SIGNED.getValue().equals(expressResult.getState())) { 125 | expressResult.setIscheck(CommonConstant.YES); 126 | } 127 | return expressResult; 128 | } 129 | 130 | /** 131 | * 订阅物流轨迹. 132 | * 133 | * @param expressParam 快递号、手机、快递公司编码 134 | * @return 查询接口 135 | */ 136 | private ExpressResponse> subscribeRoute( 137 | ExpressParam expressParam) { 138 | List expressResults = new ArrayList<>(); 139 | Map param = MapUtils.newHashMap(1); 140 | List> orders = new ArrayList<>(); 141 | for (String expressNo : expressParam.getExpressNos()) { 142 | Map order = MapUtils.newHashMap(2); 143 | order.put("orderid", expressNo); 144 | order.put("mailno", expressNo); 145 | orders.add(order); 146 | } 147 | param.put("orders", orders); 148 | String responseData = yundaRequest.subscribeRouteRequest(JSON.toJSONString(param), 149 | expressParam.getFormat()); 150 | YundaResult> result = JSON.parseObject(responseData, 151 | new TypeReference>>() { 152 | }); 153 | List yundaRouteSubscribeItems = result.getData(); 154 | List data = new ArrayList<>(); 155 | data.addAll(yundaRouteSubscribeItems); 156 | return ExpressResponse.ok(data); 157 | } 158 | 159 | /** 160 | * 运费预估. 161 | * 162 | * @param expressPriceParam 起始省份、起始城市、目的身份、目的城市、重量、长、宽、高 163 | * @return 运费 164 | */ 165 | @Override 166 | public ExpressResponse getExpressPrice( 167 | ExpressPriceParam expressPriceParam) { 168 | return ExpressResponse.failed(CommonConstant.NO_SOPPORT); 169 | } 170 | 171 | /** 172 | * 创建订单. 173 | * 174 | * @param createOrderParam 下单参数,主要包含物品信息、收件人信息、寄件人信息等 175 | * @return 快递单号等信息 176 | */ 177 | @Override 178 | public ExpressResponse createOrder(CreateOrderParam createOrderParam) { 179 | return ExpressResponse.failed(CommonConstant.NO_SOPPORT); 180 | } 181 | 182 | /** 183 | * 获取当前快递公司编码. 184 | * 185 | * @return 快递公司编码 186 | */ 187 | @Override 188 | public String getExpressCompanyCode() { 189 | return ExpressCompanyCodeEnum.YD.getValue(); 190 | } 191 | 192 | } 193 | 194 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/handler/ExpressShentongHandler.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.JSONException; 5 | import java.math.BigDecimal; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import net.kdks.config.ShentongConfig; 11 | import net.kdks.constant.CommonConstant; 12 | import net.kdks.enums.ExpressCompanyCodeEnum; 13 | import net.kdks.enums.ExpressStateEnum; 14 | import net.kdks.model.CreateOrderParam; 15 | import net.kdks.model.ExpressData; 16 | import net.kdks.model.ExpressParam; 17 | import net.kdks.model.ExpressPriceParam; 18 | import net.kdks.model.ExpressPriceResult; 19 | import net.kdks.model.ExpressResponse; 20 | import net.kdks.model.ExpressResult; 21 | import net.kdks.model.OrderResult; 22 | import net.kdks.model.sto.ShentongResult; 23 | import net.kdks.model.sto.ShentongRoute; 24 | import net.kdks.model.sto.price.ShentongPriceResult; 25 | import net.kdks.request.ShentongRequest; 26 | 27 | /** 28 | * 申通. 29 | * 30 | * @author Ze.Wang 31 | * @since 0.0.1 32 | */ 33 | public class ExpressShentongHandler implements ExpressHandler { 34 | 35 | private ShentongRequest shentongRequest; 36 | 37 | public ExpressShentongHandler(ShentongConfig shentongConfig) { 38 | this.shentongRequest = new ShentongRequest(shentongConfig); 39 | } 40 | 41 | /** 42 | * 查询轨迹信息. 43 | * 44 | * @param expressParam 快递号、手机、快递公司编码 45 | * @return 查询接口 46 | */ 47 | @Override 48 | public ExpressResponse> getExpressInfo(ExpressParam expressParam) { 49 | Map paramsItem = new HashMap<>(2); 50 | List expressNos = expressParam.getExpressNos(); 51 | paramsItem.put("order", "desc"); 52 | paramsItem.put("waybillNoList", expressNos); 53 | String param = JSON.toJSONString(paramsItem); 54 | String responseData = shentongRequest.queryRouteRequest(param, expressParam.getFormat()); 55 | return disposeResult(responseData, expressParam); 56 | 57 | } 58 | 59 | /** 60 | * 结果处理. 61 | * 62 | * @param responseData 响应 63 | * @return 处理结果 64 | */ 65 | private ExpressResponse> disposeResult(String responseData, 66 | ExpressParam expressParam) { 67 | List expressNos = expressParam.getExpressNos(); 68 | ShentongResult result; 69 | List expressResults = new ArrayList<>(); 70 | try { 71 | result = JSON.parseObject(responseData, ShentongResult.class); 72 | } catch (JSONException e) { 73 | String messageStart = ""; 74 | String messageEnd = ""; 75 | int strStartIndex = responseData.indexOf(messageStart); 76 | int strEndIndex = responseData.indexOf(messageEnd); 77 | String errorResult = 78 | responseData.substring(strStartIndex, strEndIndex).substring(messageStart.length()); 79 | return ExpressResponse.failed(errorResult); 80 | } 81 | if (result.getSuccess()) { 82 | for (String expressNo : expressNos) { 83 | ExpressResult expressResult = new ExpressResult(); 84 | if (expressParam.isViewOriginal()) { 85 | expressResult.setOriginalResult(responseData); 86 | } 87 | expressResult.setCom(ExpressCompanyCodeEnum.STO.getValue()); 88 | expressResult.setNu(expressNo); 89 | List routes = result.getData().get(expressNo); 90 | if (routes == null || routes.size() == 0) { 91 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 92 | expressResult.setMsg(CommonConstant.NO_INFO); 93 | expressResults.add(expressResult); 94 | continue; 95 | } 96 | ExpressData latestData = routes.get(0); 97 | if (expressParam.isViewRoute()) { 98 | List data = new ArrayList<>(routes.size()); 99 | data.addAll(routes); 100 | expressResult.setData(data); 101 | } 102 | expressResult.setState(latestData.getStatus()); 103 | if (ExpressStateEnum.SIGNED.getValue().equals(expressResult.getState())) { 104 | expressResult.setIscheck(CommonConstant.YES); 105 | } 106 | expressResults.add(expressResult); 107 | } 108 | return ExpressResponse.ok(expressResults); 109 | } 110 | return ExpressResponse.failed(result.getErrorMsg()); 111 | } 112 | 113 | /** 114 | * 运费预估. 115 | * 116 | * @param expressPriceParam 起始省份、起始城市、目的身份、目的城市、重量、长、宽、高 117 | * @return 运费 118 | */ 119 | @Override 120 | public ExpressResponse getExpressPrice( 121 | ExpressPriceParam expressPriceParam) { 122 | Map paramsItem = new HashMap<>(2); 123 | paramsItem.put("SendProv", expressPriceParam.getStartProvince()); 124 | paramsItem.put("SendCity", expressPriceParam.getStartCity()); 125 | paramsItem.put("SendArea", expressPriceParam.getStartDistrict()); 126 | paramsItem.put("SendAddress", expressPriceParam.getStartAddress()); 127 | 128 | paramsItem.put("RecProv", expressPriceParam.getEndProvince()); 129 | paramsItem.put("RecCity", expressPriceParam.getEndCity()); 130 | paramsItem.put("RecArea", expressPriceParam.getEndDistrict()); 131 | paramsItem.put("RecAddress", expressPriceParam.getEndAddress()); 132 | 133 | paramsItem.put("Weight", expressPriceParam.getWeight()); 134 | paramsItem.put("Length", expressPriceParam.getLength()); 135 | paramsItem.put("Width", expressPriceParam.getWidth()); 136 | paramsItem.put("Height", expressPriceParam.getHeight()); 137 | String param = JSON.toJSONString(paramsItem); 138 | String responseData = 139 | shentongRequest.queryPriceRequest(param, expressPriceParam.getFormat()); 140 | ShentongPriceResult shentongPriceResult; 141 | ExpressPriceResult result = new ExpressPriceResult(); 142 | try { 143 | shentongPriceResult = JSON.parseObject(responseData, ShentongPriceResult.class); 144 | } catch (JSONException e) { 145 | String messageStart = ""; 146 | String messageEnd = ""; 147 | int strStartIndex = responseData.indexOf(messageStart); 148 | int strEndIndex = responseData.indexOf(messageEnd); 149 | String errorResult = 150 | responseData.substring(strStartIndex, strEndIndex).substring(messageStart.length()); 151 | return ExpressResponse.failed(errorResult); 152 | } 153 | if (shentongPriceResult.getSuccess()) { 154 | BigDecimal price = new BigDecimal( 155 | shentongPriceResult.getData().getAvailableServiceItemList().get(0).getFeeModel() 156 | .getTotalPrice()).movePointLeft(2).setScale(2); 157 | BigDecimal time = new BigDecimal(shentongPriceResult.getData().getAgeing()).setScale(2); 158 | result.setPrice(price); 159 | result.setTime(time); 160 | return ExpressResponse.ok(result); 161 | } 162 | return ExpressResponse.failed(shentongPriceResult.getErrorMsg()); 163 | } 164 | 165 | /** 166 | * 创建订单. 167 | * 168 | * @param createOrderParam 下单参数,主要包含物品信息、收件人信息、寄件人信息等 169 | * @return 快递单号等信息 170 | */ 171 | @Override 172 | public ExpressResponse createOrder(CreateOrderParam createOrderParam) { 173 | return ExpressResponse.failed(CommonConstant.NO_SOPPORT); 174 | } 175 | 176 | /** 177 | * 获取当前快递公司编码. 178 | * 179 | * @return 快递公司编码 180 | */ 181 | @Override 182 | public String getExpressCompanyCode() { 183 | return ExpressCompanyCodeEnum.STO.getValue(); 184 | } 185 | 186 | } 187 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 4.0.0 7 | net.kdks 8 | aggregatelogistics 9 | 0.0.13 10 | aggregatelogistics 11 | https://github.com/fuzui/aggregatelogistics 12 | 13 | 聚合物流,支持: 14 | 中通、申通、圆通、百世、顺丰轨迹查询; 15 | 顺丰下单; 16 | 17 | 18 | 19 | 20 | MIT 21 | https://github.com/fuzui/aggregatelogistics/blob/main/LICENSE 22 | 23 | 24 | 25 | 26 | scm:git:https://github.com/fuzui/aggregatelogistics.git 27 | scm:git:https://github.com/fuzui/aggregatelogistics.git 28 | https://github.com/fuzui/aggregatelogistics 29 | 30 | 31 | 32 | 33 | Ze.Wang 34 | 73400@163.com 35 | https://www.fuzui.net 36 | +8 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | sonatype_releases 45 | fuzui 46 | 47 | https://oss.sonatype.org/service/local/staging/deploy/maven2 48 | 49 | 50 | 51 | sonatype_snapshots 52 | fuzui 53 | 54 | https://oss.sonatype.org/content/repositories/snapshots 55 | 56 | 57 | 58 | 59 | UTF-8 60 | 1.8 61 | 2.2.1 62 | 3.8.1 63 | 3.1.0 64 | 2.20 65 | 1.6 66 | 4.11 67 | 1.2.73 68 | 5.4.3 69 | 1.18.24 70 | 1.6.7 71 | 72 | 73 | 74 | junit 75 | junit 76 | ${junit.version} 77 | test 78 | 79 | 80 | com.alibaba 81 | fastjson 82 | ${fastjson.version} 83 | 84 | 85 | cn.hutool 86 | hutool-http 87 | ${hutool-http.version} 88 | 89 | 90 | 91 | org.projectlombok 92 | lombok 93 | ${lombok.version} 94 | 95 | 96 | 97 | 98 | 99 | org.sonatype.plugins 100 | nexus-staging-maven-plugin 101 | ${nexus-staging-maven-plugin.version} 102 | true 103 | 104 | 105 | sonatype_releases 106 | https://oss.sonatype.org/ 107 | 108 | true 109 | 60 110 | 111 | 112 | 113 | 114 | org.apache.maven.plugins 115 | maven-compiler-plugin 116 | ${maven-compiler.version} 117 | 118 | ${project.build.sourceEncoding} 119 | ${java.version} 120 | ${java.version} 121 | 122 | 123 | 124 | org.apache.maven.plugins 125 | maven-source-plugin 126 | ${maven-source.version} 127 | true 128 | 129 | 130 | package 131 | 132 | jar-no-fork 133 | 134 | 135 | 136 | 137 | 138 | org.apache.maven.plugins 139 | maven-javadoc-plugin 140 | ${maven-javadoc.version} 141 | 142 | 143 | package 144 | 145 | jar 146 | 147 | 148 | 149 | 150 | 151 | 152 | -Xdoclint:none 153 | 154 | 155 | 156 | 157 | org.apache.maven.plugins 158 | maven-surefire-plugin 159 | ${maven-surefire.version} 160 | 161 | true 162 | 163 | 164 | 165 | org.apache.maven.plugins 166 | maven-gpg-plugin 167 | ${maven-gpg.version} 168 | 169 | 170 | sign-artifacts 171 | verify 172 | 173 | sign 174 | 175 | 176 | 177 | 178 | --pinentry-mode 179 | loopback 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/handler/ExpressJituHandler.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.TypeReference; 5 | import java.util.ArrayList; 6 | import java.util.Base64; 7 | import java.util.List; 8 | import java.util.Map; 9 | import net.kdks.config.JituConfig; 10 | import net.kdks.constant.CommonConstant; 11 | import net.kdks.constant.JituConstant; 12 | import net.kdks.enums.ExpressCompanyCodeEnum; 13 | import net.kdks.enums.ExpressStateEnum; 14 | import net.kdks.model.CreateOrderParam; 15 | import net.kdks.model.ExpressData; 16 | import net.kdks.model.ExpressParam; 17 | import net.kdks.model.ExpressPriceParam; 18 | import net.kdks.model.ExpressPriceResult; 19 | import net.kdks.model.ExpressResponse; 20 | import net.kdks.model.ExpressResult; 21 | import net.kdks.model.OrderResult; 22 | import net.kdks.model.jt.JituResult; 23 | import net.kdks.model.jt.price.JituPriceResult; 24 | import net.kdks.model.jt.route.JituRouteItem; 25 | import net.kdks.model.jt.route.JituRouteResult; 26 | import net.kdks.request.JituRequest; 27 | import net.kdks.utils.Assert; 28 | import net.kdks.utils.DigestUtils; 29 | import net.kdks.utils.MapUtils; 30 | 31 | /** 32 | * 极兔. 33 | * 34 | * @author Ze.Wang 35 | * @since 0.0.8 36 | */ 37 | public class ExpressJituHandler implements ExpressHandler { 38 | 39 | 40 | private JituRequest jituRequest; 41 | 42 | private JituConfig jituConfig; 43 | 44 | public ExpressJituHandler(JituConfig jituConfig) { 45 | this.jituConfig = jituConfig; 46 | this.jituRequest = new JituRequest(jituConfig); 47 | } 48 | 49 | /** 50 | * 查询轨迹信息. 51 | * 52 | * @param expressParam 快递号、手机、快递公司编码 53 | * @return 查询接口 54 | */ 55 | @Override 56 | public ExpressResponse> getExpressInfo(ExpressParam expressParam) { 57 | List expressNos = expressParam.getExpressNos(); 58 | String billCodes = String.join(",", expressNos); 59 | Map paramMap = MapUtils.newHashMap(1); 60 | paramMap.put("billCodes", billCodes); 61 | String param = JSON.toJSONString(paramMap); 62 | String responseData = jituRequest.queryRouteRequest(param, expressParam.getFormat()); 63 | return disposeResult(responseData, expressParam); 64 | } 65 | 66 | /** 67 | * 结果处理. 68 | * 69 | * @param responseData 响应 70 | * @return 查询结果 71 | */ 72 | private ExpressResponse> disposeResult(String responseData, 73 | ExpressParam expressParam) { 74 | List expressNos = expressParam.getExpressNos(); 75 | JituResult> result = 76 | JSON.parseObject(responseData, new TypeReference>>() { 77 | }); 78 | List expressResults = new ArrayList<>(); 79 | if (JituConstant.REQUEST_SUCCESS_CODE.equals(result.getCode())) { 80 | //此结果必然存在不会出现空指针,无需判断 81 | if (result.getData() == null || result.getData().size() == 0) { 82 | return ExpressResponse.failed(CommonConstant.NO_INFO); 83 | } 84 | 85 | Map routeResultMap = 86 | MapUtils.newHashMap(result.getData().size()); 87 | for (JituRouteResult routeResult : result.getData()) { 88 | routeResultMap.put(routeResult.getBillCode(), routeResult); 89 | } 90 | for (String expressNo : expressNos) { 91 | ExpressResult expressResult = new ExpressResult(); 92 | if (expressParam.isViewOriginal()) { 93 | expressResult.setOriginalResult(responseData); 94 | } 95 | expressResult.setCom(ExpressCompanyCodeEnum.JT.getValue()); 96 | expressResult.setNu(expressNo); 97 | List routes = routeResultMap.get(expressNo).getDetails(); 98 | if (routes == null || routes.size() == 0) { 99 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 100 | expressResult.setMsg(CommonConstant.NO_INFO); 101 | expressResults.add(expressResult); 102 | continue; 103 | } 104 | ExpressData latestData = routes.get(0); 105 | if (expressParam.isViewRoute()) { 106 | List data = new ArrayList<>(routes.size()); 107 | data.addAll(routes); 108 | expressResult.setData(data); 109 | } 110 | expressResult.setState(latestData.getStatus()); 111 | if (ExpressStateEnum.SIGNED.getValue().equals(expressResult.getState())) { 112 | expressResult.setIscheck(CommonConstant.YES); 113 | } 114 | 115 | expressResults.add(expressResult); 116 | } 117 | return ExpressResponse.ok(expressResults); 118 | } 119 | return ExpressResponse.failed(result.getMsg()); 120 | 121 | } 122 | 123 | /** 124 | * 运费预估. 125 | * 126 | * @param expressPriceParam 起始省份、起始城市、目的身份、目的城市、重量、长、宽、高 127 | * @return 运费 128 | */ 129 | @Override 130 | public ExpressResponse getExpressPrice( 131 | ExpressPriceParam expressPriceParam) { 132 | checkCustomerCodeAndPwd(); 133 | // 寄件人 134 | Map senderMap = MapUtils.newHashMap(4); 135 | senderMap.put("prov", expressPriceParam.getStartProvince()); 136 | senderMap.put("city", expressPriceParam.getStartCity()); 137 | senderMap.put("area", expressPriceParam.getStartDistrict()); 138 | senderMap.put("address", expressPriceParam.getStartAddress()); 139 | // 收件人 140 | Map receiverMap = MapUtils.newHashMap(4); 141 | receiverMap.put("prov", expressPriceParam.getEndProvince()); 142 | receiverMap.put("city", expressPriceParam.getEndCity()); 143 | receiverMap.put("area", expressPriceParam.getEndDistrict()); 144 | receiverMap.put("address", expressPriceParam.getEndAddress()); 145 | 146 | Map param = MapUtils.newHashMap(4); 147 | param.put("customerCode", jituConfig.getCustomerCode()); 148 | 149 | String pwd = 150 | DigestUtils.md5DigestToStr(jituConfig.getCustomerPwd() + "jadada236t2").toUpperCase(); 151 | String digest = Base64.getEncoder().encodeToString( 152 | DigestUtils.md5Digest(jituConfig.getCustomerCode() + pwd + jituConfig.getPrivateKey())); 153 | param.put("digest", digest); 154 | param.put("sender", senderMap); 155 | param.put("receiver", receiverMap); 156 | param.put("length", expressPriceParam.getLength()); 157 | param.put("width", expressPriceParam.getWidth()); 158 | param.put("height", expressPriceParam.getHeight()); 159 | param.put("weight", expressPriceParam.getWeight()); 160 | String responseData = 161 | jituRequest.queryPriceRequest(JSON.toJSONString(param), 162 | expressPriceParam.getFormat()); 163 | 164 | JituResult result = 165 | JSON.parseObject(responseData, new TypeReference>() { 166 | }); 167 | if (JituConstant.REQUEST_SUCCESS_CODE.equals(result.getCode())) { 168 | return ExpressResponse.ok(result.getData()); 169 | } 170 | return ExpressResponse.failed(result.getMsg()); 171 | } 172 | 173 | /** 174 | * 检查客户编号和密码. 175 | */ 176 | private void checkCustomerCodeAndPwd() { 177 | Assert.notEmpty(jituConfig.getCustomerCode(), "请配置客户编号"); 178 | Assert.notEmpty(jituConfig.getCustomerPwd(), "请配置客户密码"); 179 | } 180 | 181 | /** 182 | * 创建订单. 183 | * 184 | * @param createOrderParam 下单参数,主要包含物品信息、收件人信息、寄件人信息等 185 | * @return 快递单号等信息 186 | */ 187 | @Override 188 | public ExpressResponse createOrder(CreateOrderParam createOrderParam) { 189 | return ExpressResponse.failed(CommonConstant.NO_SOPPORT); 190 | } 191 | 192 | /** 193 | * 获取当前快递公司编码. 194 | * 195 | * @return 快递公司编码 196 | */ 197 | @Override 198 | public String getExpressCompanyCode() { 199 | return ExpressCompanyCodeEnum.JT.getValue(); 200 | } 201 | 202 | } 203 | 204 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/handler/ExpressYuantongHandler.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.JSONException; 5 | import com.alibaba.fastjson.TypeReference; 6 | import java.io.UnsupportedEncodingException; 7 | import java.math.BigDecimal; 8 | import java.net.URLEncoder; 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | import net.kdks.config.YuantongConfig; 15 | import net.kdks.constant.CommonConstant; 16 | import net.kdks.enums.ExpressCompanyCodeEnum; 17 | import net.kdks.enums.ExpressStateEnum; 18 | import net.kdks.model.CreateOrderParam; 19 | import net.kdks.model.ExpressData; 20 | import net.kdks.model.ExpressParam; 21 | import net.kdks.model.ExpressPriceParam; 22 | import net.kdks.model.ExpressPriceResult; 23 | import net.kdks.model.ExpressResponse; 24 | import net.kdks.model.ExpressResult; 25 | import net.kdks.model.OrderResult; 26 | import net.kdks.model.yto.YuanTongErrorResult; 27 | import net.kdks.model.yto.YuanTongResult; 28 | import net.kdks.request.YuantongRequest; 29 | import net.kdks.utils.StringUtils; 30 | 31 | /** 32 | * 圆通. 33 | * 34 | * @author Ze.Wang 35 | * @since 0.0.1 36 | */ 37 | public class ExpressYuantongHandler implements ExpressHandler { 38 | 39 | private YuantongRequest yuantongRequest; 40 | 41 | public ExpressYuantongHandler(YuantongConfig yuantongConfig) { 42 | this.yuantongRequest = new YuantongRequest(yuantongConfig); 43 | } 44 | 45 | /** 46 | * 查询轨迹信息. 47 | * 48 | * @param expressParam 快递号、手机、快递公司编码 49 | * @return 查询接口 50 | */ 51 | @Override 52 | public ExpressResponse> getExpressInfo(ExpressParam expressParam) { 53 | 54 | List expressResults = new ArrayList<>(); 55 | for (String expressNo : expressParam.getExpressNos()) { 56 | Map[] paramItemsMap = new Map[1]; 57 | paramItemsMap[0] = new HashMap<>(1); 58 | paramItemsMap[0].put("Number", expressNo); 59 | String param = null; 60 | try { 61 | param = URLEncoder.encode(JSON.toJSONString(paramItemsMap), "UTF-8"); 62 | } catch (UnsupportedEncodingException e) { 63 | e.printStackTrace(); 64 | } 65 | String responseData = 66 | yuantongRequest.queryRouteRequest(param, expressParam.getFormat()); 67 | ExpressResult expressResult = disposeResult(responseData, expressNo, expressParam); 68 | expressResults.add(expressResult); 69 | } 70 | return ExpressResponse.ok(expressResults); 71 | } 72 | 73 | /** 74 | * 结果处理. 75 | * 76 | * @param responseData 响应 77 | * @return 处理结果 78 | */ 79 | private ExpressResult disposeResult(String responseData, String expressNo, 80 | ExpressParam expressParam) { 81 | 82 | ExpressResult expressResult = new ExpressResult(); 83 | if (expressParam.isViewOriginal()) { 84 | expressResult.setOriginalResult(responseData); 85 | } 86 | expressResult.setCom(ExpressCompanyCodeEnum.YTO.getValue()); 87 | expressResult.setNu(expressNo); 88 | 89 | try { 90 | List routes = 91 | JSON.parseObject(responseData, new TypeReference>() { 92 | }); 93 | if (routes == null || routes.size() == 0) { 94 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 95 | expressResult.setMsg(CommonConstant.NO_INFO); 96 | return expressResult; 97 | } 98 | //官方默认正序,改为倒序 99 | Collections.reverse(routes); 100 | ExpressData latestData = routes.get(0); 101 | if (expressParam.isViewRoute()) { 102 | List data = new ArrayList<>(routes.size()); 103 | data.addAll(routes); 104 | expressResult.setData(data); 105 | } 106 | 107 | expressResult.setState(latestData.getStatus()); 108 | if (ExpressStateEnum.SIGNED.getValue().equals(expressResult.getState())) { 109 | expressResult.setIscheck(CommonConstant.YES); 110 | } 111 | return expressResult; 112 | } catch (JSONException e) { 113 | YuanTongErrorResult errorResult = new YuanTongErrorResult(); 114 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 115 | try { 116 | errorResult = JSON.parseObject(responseData, YuanTongErrorResult.class); 117 | } catch (JSONException e2) { 118 | String messageStart = ""; 119 | String messageEnd = ""; 120 | int strStartIndex = responseData.indexOf(messageStart); 121 | int strEndIndex = responseData.indexOf(messageEnd); 122 | String result = 123 | responseData.substring(strStartIndex, strEndIndex) 124 | .substring(messageStart.length()); 125 | errorResult.setReason(result); 126 | } 127 | expressResult.setMsg( 128 | StringUtils.isNotEmpty(errorResult.getMessage()) ? errorResult.getMessage() : 129 | errorResult.getReason()); 130 | return expressResult; 131 | } 132 | } 133 | 134 | /** 135 | * 运费预估. 136 | * 137 | * @param expressPriceParam 起始省份、起始城市、目的身份、目的城市、重量、长、宽、高 138 | * @return 运费 139 | */ 140 | @Override 141 | public ExpressResponse getExpressPrice( 142 | ExpressPriceParam expressPriceParam) { 143 | Map[] paramItemsMap = new Map[1]; 144 | paramItemsMap[0] = new HashMap<>(1); 145 | paramItemsMap[0].put("StartProvince", expressPriceParam.getStartProvince()); 146 | paramItemsMap[0].put("StartCity", expressPriceParam.getStartCity()); 147 | paramItemsMap[0].put("EndProvince", expressPriceParam.getEndProvince()); 148 | paramItemsMap[0].put("EndCity", expressPriceParam.getEndCity()); 149 | paramItemsMap[0].put("GoodsWeight", expressPriceParam.getWeight()); 150 | paramItemsMap[0].put("GoodsLength", expressPriceParam.getLength()); 151 | paramItemsMap[0].put("GoodsWidth", expressPriceParam.getWidth()); 152 | paramItemsMap[0].put("GoodsHeight", expressPriceParam.getHeight()); 153 | String param = null; 154 | try { 155 | param = URLEncoder.encode(JSON.toJSONString(paramItemsMap), "UTF-8"); 156 | } catch (UnsupportedEncodingException e) { 157 | e.printStackTrace(); 158 | } 159 | String responseData = 160 | yuantongRequest.queryPriceRequest(param, expressPriceParam.getFormat()); 161 | try { 162 | BigDecimal price = new BigDecimal(responseData).setScale(2); 163 | ExpressPriceResult expressPriceResult = new ExpressPriceResult(); 164 | expressPriceResult.setPrice(price); 165 | return ExpressResponse.ok(expressPriceResult); 166 | } catch (NumberFormatException e) { 167 | try { 168 | YuanTongErrorResult errorResult = 169 | JSON.parseObject(responseData, YuanTongErrorResult.class); 170 | return ExpressResponse.failed(errorResult.getReason()); 171 | } catch (JSONException e2) { 172 | String messageStart = ""; 173 | String messageEnd = ""; 174 | int strStartIndex = responseData.indexOf(messageStart); 175 | int strEndIndex = responseData.indexOf(messageEnd); 176 | String result = 177 | responseData.substring(strStartIndex, strEndIndex) 178 | .substring(messageStart.length()); 179 | return ExpressResponse.failed(result); 180 | } 181 | } 182 | } 183 | 184 | /** 185 | * 创建订单. 186 | * 187 | * @param createOrderParam 下单参数,主要包含物品信息、收件人信息、寄件人信息等 188 | * @return 快递单号等信息 189 | */ 190 | @Override 191 | public ExpressResponse createOrder(CreateOrderParam createOrderParam) { 192 | return ExpressResponse.failed(CommonConstant.NO_SOPPORT); 193 | } 194 | 195 | /** 196 | * 获取当前快递公司编码. 197 | * 198 | * @return 快递公司编码 199 | */ 200 | @Override 201 | public String getExpressCompanyCode() { 202 | return ExpressCompanyCodeEnum.YTO.getValue(); 203 | } 204 | 205 | } 206 | 207 | -------------------------------------------------------------------------------- /src/main/java/net/kdks/handler/ExpressZhongtongHandler.java: -------------------------------------------------------------------------------- 1 | package net.kdks.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.TypeReference; 5 | import java.math.BigDecimal; 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.List; 9 | import java.util.Map; 10 | import net.kdks.config.ZhongtongConfig; 11 | import net.kdks.constant.CommonConstant; 12 | import net.kdks.constant.ZhongtongRouteVersion; 13 | import net.kdks.enums.ExpressCompanyCodeEnum; 14 | import net.kdks.enums.ExpressStateEnum; 15 | import net.kdks.model.CreateOrderParam; 16 | import net.kdks.model.ExpressData; 17 | import net.kdks.model.ExpressParam; 18 | import net.kdks.model.ExpressPriceParam; 19 | import net.kdks.model.ExpressPriceResult; 20 | import net.kdks.model.ExpressResponse; 21 | import net.kdks.model.ExpressResult; 22 | import net.kdks.model.OrderResult; 23 | import net.kdks.model.zto.ZhongtongData; 24 | import net.kdks.model.zto.ZhongtongResult; 25 | import net.kdks.model.zto.ZhongtongResultV1; 26 | import net.kdks.model.zto.ZhongtongTrace; 27 | import net.kdks.model.zto.ZhongtongTraceV1; 28 | import net.kdks.model.zto.price.ZhongtongPriceData; 29 | import net.kdks.request.ZhongtongRequest; 30 | import net.kdks.utils.Assert; 31 | import net.kdks.utils.MapUtils; 32 | 33 | /** 34 | * 中通. 35 | * 36 | * @author Ze.Wang 37 | * @since 0.0.1 38 | */ 39 | public class ExpressZhongtongHandler implements ExpressHandler { 40 | 41 | private ZhongtongRequest zhongtongRequest; 42 | 43 | private ZhongtongConfig zhongtongConfig; 44 | 45 | public ExpressZhongtongHandler(ZhongtongConfig zhongtongConfig) { 46 | this.zhongtongConfig = zhongtongConfig; 47 | this.zhongtongRequest = new ZhongtongRequest(zhongtongConfig); 48 | } 49 | 50 | /** 51 | * 查询轨迹信息. 52 | * 53 | * @param expressParam 快递号、手机、快递公司编码 54 | * @return 查询接口 55 | */ 56 | @Override 57 | public ExpressResponse> getExpressInfo(ExpressParam expressParam) { 58 | if (ZhongtongRouteVersion.V1.equals(this.zhongtongConfig.getRouteVersion())) { 59 | return getExpressInfoV1(expressParam); 60 | } 61 | List expressResults = new ArrayList<>(); 62 | for (String expressNo : expressParam.getExpressNos()) { 63 | Map param = MapUtils.newHashMap(2); 64 | param.put("billCode", expressNo); 65 | param.put("mobilePhone", expressParam.getMobile()); 66 | String responseData = zhongtongRequest.queryRouteRequest(JSON.toJSONString(param), 67 | expressParam.getFormat()); 68 | ExpressResult expressResult = disposeResult(responseData, expressNo, expressParam); 69 | expressResults.add(expressResult); 70 | } 71 | return ExpressResponse.ok(expressResults); 72 | } 73 | 74 | /** 75 | * 结果处理. 76 | * 77 | * @param responseData 响应 78 | * @return 处理结果 79 | */ 80 | private ExpressResult disposeResult(String responseData, String expressNo, 81 | ExpressParam expressParam) { 82 | ExpressResult expressResult = new ExpressResult(); 83 | if (expressParam.isViewOriginal()) { 84 | expressResult.setOriginalResult(responseData); 85 | } 86 | expressResult.setCom(ExpressCompanyCodeEnum.ZTO.getValue()); 87 | expressResult.setNu(expressNo); 88 | List expressNos = expressParam.getExpressNos(); 89 | ZhongtongResult> result = JSON.parseObject(responseData, 90 | new TypeReference>>() { 91 | }); 92 | if (!result.getStatus()) { 93 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 94 | expressResult.setMsg(result.getMessage()); 95 | return expressResult; 96 | } 97 | if (result.getResult() == null && result.getResult().size() == 0) { 98 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 99 | expressResult.setMsg(CommonConstant.NO_INFO); 100 | return expressResult; 101 | } 102 | List routes = result.getResult(); 103 | // 默认正序,改为倒序 104 | Collections.reverse(routes); 105 | ExpressData latestData = routes.get(0); 106 | if (expressParam.isViewRoute()) { 107 | List data = new ArrayList<>(routes.size()); 108 | data.addAll(routes); 109 | expressResult.setData(data); 110 | } 111 | expressResult.setState(latestData.getStatus()); 112 | if (ExpressStateEnum.SIGNED.getValue().equals(expressResult.getState())) { 113 | expressResult.setIscheck(CommonConstant.YES); 114 | } 115 | return expressResult; 116 | } 117 | 118 | /** 119 | * 查询轨迹信息v1. 120 | * 121 | * @param expressParam 快递号、手机、快递公司编码 122 | * @return 查询接口 123 | */ 124 | public ExpressResponse> getExpressInfoV1(ExpressParam expressParam) { 125 | List expressNos = expressParam.getExpressNos(); 126 | String param = JSON.toJSONString(expressNos); 127 | String responseData = zhongtongRequest.queryRouteRequestV1(param, expressParam.getFormat()); 128 | return disposeResultV1(responseData, expressParam); 129 | } 130 | 131 | /** 132 | * 结果处理. 133 | * 134 | * @param responseData 响应 135 | * @return 处理结果 136 | */ 137 | private ExpressResponse> disposeResultV1(String responseData, 138 | ExpressParam expressParam) { 139 | List expressNos = expressParam.getExpressNos(); 140 | ZhongtongResultV1 result = JSON.parseObject(responseData, ZhongtongResultV1.class); 141 | List expressResults = new ArrayList<>(); 142 | if (result.getStatus()) { 143 | List zhongtongDatas = result.getData(); 144 | if (zhongtongDatas == null || zhongtongDatas.size() == 0) { 145 | return ExpressResponse.failed(CommonConstant.NO_INFO); 146 | } 147 | Map zhongtongDataMap = 148 | MapUtils.newHashMap(zhongtongDatas.size()); 149 | for (ZhongtongData zhongtongData : zhongtongDatas) { 150 | zhongtongDataMap.put(zhongtongData.getBillCode(), zhongtongData); 151 | } 152 | for (String expressNo : expressNos) { 153 | ExpressResult expressResult = new ExpressResult(); 154 | if (expressParam.isViewOriginal()) { 155 | expressResult.setOriginalResult(responseData); 156 | } 157 | expressResult.setCom(ExpressCompanyCodeEnum.ZTO.getValue()); 158 | expressResult.setNu(expressNo); 159 | List routes = zhongtongDataMap.get(expressNo).getTraces(); 160 | if (routes == null || routes.size() == 0) { 161 | expressResult.setState(ExpressStateEnum.NO_INFO.getValue()); 162 | expressResult.setMsg(CommonConstant.NO_INFO); 163 | expressResults.add(expressResult); 164 | continue; 165 | } 166 | //官方默认正序,改为倒序 167 | Collections.reverse(routes); 168 | ExpressData latestData = routes.get(0); 169 | if (expressParam.isViewRoute()) { 170 | List data = new ArrayList<>(routes.size()); 171 | data.addAll(routes); 172 | expressResult.setData(data); 173 | } 174 | expressResult.setState(latestData.getStatus()); 175 | if (ExpressStateEnum.SIGNED.getValue().equals(expressResult.getState())) { 176 | expressResult.setIscheck(CommonConstant.YES); 177 | } 178 | expressResults.add(expressResult); 179 | } 180 | return ExpressResponse.ok(expressResults); 181 | } 182 | return ExpressResponse.failed(result.getMessage()); 183 | } 184 | 185 | /** 186 | * 运费预估. 187 | * 188 | * @param expressPriceParam 起始省份、起始城市、目的身份、目的城市、重量、长、宽、高 189 | * @return 运费 190 | */ 191 | @Override 192 | public ExpressResponse getExpressPrice( 193 | ExpressPriceParam expressPriceParam) { 194 | Map sender = MapUtils.newHashMap(4); 195 | sender.put("province", expressPriceParam.getStartProvince()); 196 | sender.put("city", expressPriceParam.getStartCity()); 197 | sender.put("district", expressPriceParam.getStartDistrict()); 198 | sender.put("address", expressPriceParam.getStartAddress()); 199 | Map addresser = MapUtils.newHashMap(4); 200 | addresser.put("province", expressPriceParam.getEndProvince()); 201 | addresser.put("city", expressPriceParam.getEndCity()); 202 | addresser.put("district", expressPriceParam.getEndDistrict()); 203 | addresser.put("address", expressPriceParam.getEndAddress()); 204 | Map param = MapUtils.newHashMap(4); 205 | param.put("transportType", 1); 206 | param.put("sender", sender); 207 | param.put("addresser", addresser); 208 | Assert.notNull(expressPriceParam.getWeight(), "请填写重量!"); 209 | param.put("weight", expressPriceParam.getWeight().setScale(2, BigDecimal.ROUND_HALF_UP)); 210 | String responseData = 211 | zhongtongRequest.queryPriceRequest(JSON.toJSONString(param), 212 | expressPriceParam.getFormat()); 213 | ZhongtongResult zhongtongResult = JSON.parseObject(responseData, 214 | new TypeReference>() { 215 | }); 216 | if (!zhongtongResult.getStatus()) { 217 | return ExpressResponse.failed(zhongtongResult.getMessage()); 218 | } 219 | ExpressPriceResult expressPriceResult = new ExpressPriceResult(); 220 | expressPriceResult.setPrice( 221 | new BigDecimal(zhongtongResult.getResult().getPrice()).setScale(2)); 222 | expressPriceResult.setTime( 223 | new BigDecimal(zhongtongResult.getResult().getHour()).setScale(2)); 224 | return ExpressResponse.ok(expressPriceResult); 225 | } 226 | 227 | /** 228 | * 创建订单. 229 | * 230 | * @param createOrderParam 下单参数,主要包含物品信息、收件人信息、寄件人信息等 231 | * @return 快递单号等信息 232 | */ 233 | @Override 234 | public ExpressResponse createOrder(CreateOrderParam createOrderParam) { 235 | return ExpressResponse.failed(CommonConstant.NO_SOPPORT); 236 | } 237 | 238 | /** 239 | * 获取当前快递公司编码. 240 | * 241 | * @return 快递公司编码 242 | */ 243 | @Override 244 | public String getExpressCompanyCode() { 245 | return ExpressCompanyCodeEnum.ZTO.getValue(); 246 | } 247 | 248 | } 249 | 250 | --------------------------------------------------------------------------------