Commit dcb1660880064f8357955761fb03011e4a976d4c
1 parent
e1a8e45a
mall + trade:code review 快递计算逻辑
Showing
17 changed files
with
110 additions
and
50 deletions
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
| ... | ... | @@ -110,19 +110,19 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { |
| 110 | 110 | return createFilterBean(new DemoFilter(), WebFilterOrderEnum.DEMO_FILTER); |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | + public static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) { | |
| 114 | + FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter); | |
| 115 | + bean.setOrder(order); | |
| 116 | + return bean; | |
| 117 | + } | |
| 118 | + | |
| 113 | 119 | /** |
| 114 | 120 | * 创建 RestTemplate 实例 |
| 121 | + * | |
| 115 | 122 | * @param restTemplateBuilder {@link RestTemplateAutoConfiguration#restTemplateBuilder} |
| 116 | 123 | */ |
| 117 | 124 | @Bean |
| 118 | - public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){ | |
| 125 | + public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) { | |
| 119 | 126 | return restTemplateBuilder.build(); |
| 120 | 127 | } |
| 121 | - | |
| 122 | - public static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) { | |
| 123 | - FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter); | |
| 124 | - bean.setOrder(order); | |
| 125 | - return bean; | |
| 126 | - } | |
| 127 | - | |
| 128 | 128 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/config/TradeExpressQueryProperties.java
| ... | ... | @@ -9,6 +9,8 @@ import org.springframework.validation.annotation.Validated; |
| 9 | 9 | import javax.validation.Valid; |
| 10 | 10 | import javax.validation.constraints.NotEmpty; |
| 11 | 11 | |
| 12 | +// TODO @jason:TradeExpressProperties;更通用哈 | |
| 13 | +// TODO @芋艿:未来要不要放数据库中?考虑 saas 多租户时,不同租户使用不同的配置? | |
| 12 | 14 | /** |
| 13 | 15 | * 交易快递查询的配置项 |
| 14 | 16 | * |
| ... | ... | @@ -21,9 +23,13 @@ import javax.validation.constraints.NotEmpty; |
| 21 | 23 | public class TradeExpressQueryProperties { |
| 22 | 24 | |
| 23 | 25 | /** |
| 24 | - * 快递查询服务商, 如果未配置,默认使用快递鸟 | |
| 26 | + * 快递查询服务商 | |
| 27 | + * | |
| 28 | + * 如果未配置,默认使用快递鸟 | |
| 25 | 29 | */ |
| 26 | - private ExpressQueryProviderEnum expressQueryProvider; | |
| 30 | + // TODO @jason:可以把 expressQueryProvider 改成 client 变量,更简洁一点; | |
| 31 | + private ExpressQueryProviderEnum expressQueryProvider; // TODO @jaosn:默认值可以通过属性直接赋值哈; | |
| 32 | + // TODO @jason:需要考虑下,用户只配置了其中一个; | |
| 27 | 33 | /** |
| 28 | 34 | * 快递鸟配置 |
| 29 | 35 | */ |
| ... | ... | @@ -46,12 +52,12 @@ public class TradeExpressQueryProperties { |
| 46 | 52 | */ |
| 47 | 53 | @NotEmpty(message = "快递鸟用户 ID 配置项不能为空") |
| 48 | 54 | private String businessId; |
| 49 | - | |
| 50 | 55 | /** |
| 51 | 56 | * 快递鸟 API Key |
| 52 | 57 | */ |
| 53 | 58 | @NotEmpty(message = "快递鸟 Api Key 配置项不能为空") |
| 54 | 59 | private String apiKey; |
| 60 | + | |
| 55 | 61 | } |
| 56 | 62 | |
| 57 | 63 | /** |
| ... | ... | @@ -59,6 +65,7 @@ public class TradeExpressQueryProperties { |
| 59 | 65 | */ |
| 60 | 66 | @Data |
| 61 | 67 | public static class Kd100Config { |
| 68 | + | |
| 62 | 69 | /** |
| 63 | 70 | * 快递 100 授权码 |
| 64 | 71 | */ |
| ... | ... | @@ -69,7 +76,7 @@ public class TradeExpressQueryProperties { |
| 69 | 76 | */ |
| 70 | 77 | @NotEmpty(message = "快递 100 授权 Key 配置项不能为空") |
| 71 | 78 | private String key; |
| 72 | - } | |
| 73 | 79 | |
| 80 | + } | |
| 74 | 81 | |
| 75 | 82 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/ExpressQueryClient.java
| ... | ... | @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryRes |
| 5 | 5 | |
| 6 | 6 | import java.util.List; |
| 7 | 7 | |
| 8 | +// TODO @jason:可以改成 ExpressClient,未来可能还对接别的接口噢 | |
| 8 | 9 | /** |
| 9 | 10 | * 快递查询客户端 |
| 10 | 11 | * |
| ... | ... | @@ -17,5 +18,7 @@ public interface ExpressQueryClient { |
| 17 | 18 | * |
| 18 | 19 | * @param reqDTO 查询请求参数 |
| 19 | 20 | */ |
| 21 | + // TODO @jason:可以改成 getExpressTrackList。返回字段可以参考 https://doc.youzanyun.com/detail/API/0/5 响应的 data | |
| 20 | 22 | List<ExpressQueryRespDTO> realTimeQuery(ExpressQueryReqDTO reqDTO); |
| 23 | + | |
| 21 | 24 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/ExpressQueryProvider.java
| ... | ... | @@ -11,10 +11,12 @@ import java.util.List; |
| 11 | 11 | * @author jason |
| 12 | 12 | */ |
| 13 | 13 | public interface ExpressQueryProvider { |
| 14 | + | |
| 14 | 15 | /** |
| 15 | 16 | * 快递实时查询 |
| 16 | 17 | * |
| 17 | 18 | * @param reqDTO 查询请求参数 |
| 18 | 19 | */ |
| 19 | 20 | List<ExpressQueryRespDTO> realTimeQueryExpress(ExpressQueryReqDTO reqDTO); |
| 21 | + | |
| 20 | 22 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/ExpressQueryProviderEnum.java
| ... | ... | @@ -8,9 +8,12 @@ import lombok.Getter; |
| 8 | 8 | * @author jason |
| 9 | 9 | */ |
| 10 | 10 | @Getter |
| 11 | + | |
| 11 | 12 | public enum ExpressQueryProviderEnum { |
| 13 | + | |
| 12 | 14 | KD_NIAO("kd-niao", "快递鸟"), |
| 13 | 15 | KD_100("kd-100", "快递100"); |
| 16 | + | |
| 14 | 17 | /** |
| 15 | 18 | * 快递服务商唯一编码 |
| 16 | 19 | */ |
| ... | ... | @@ -21,8 +24,10 @@ public enum ExpressQueryProviderEnum { |
| 21 | 24 | */ |
| 22 | 25 | private final String name; |
| 23 | 26 | |
| 27 | + // TODO @jaosn:@AllArgsConstructor 可以替代哈 | |
| 24 | 28 | ExpressQueryProviderEnum(String code, String name) { |
| 25 | 29 | this.code = code; |
| 26 | 30 | this.name = name; |
| 27 | 31 | } |
| 32 | + | |
| 28 | 33 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/ExpressQueryProviderFactory.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.framework.delivery.core; |
| 2 | 2 | |
| 3 | 3 | /** |
| 4 | - * 快递服务商工厂, 用于创建和缓存快递服务商服务 | |
| 4 | + * 快递服务商工厂,用于创建和缓存快递服务商服务 | |
| 5 | + * | |
| 5 | 6 | * @author jason |
| 6 | 7 | */ |
| 7 | 8 | public interface ExpressQueryProviderFactory { |
| 8 | 9 | |
| 9 | 10 | /** |
| 10 | - * 通过枚举获取快递查询服务商, 如果不存在。就创建一个对应的快递查询服务商 | |
| 11 | + * 通过枚举获取快递查询服务商 | |
| 12 | + * | |
| 13 | + * 如果不存在,就创建一个对应的快递查询服务商 | |
| 14 | + * | |
| 11 | 15 | * @param queryProviderEnum 快递服务商枚举 |
| 12 | 16 | */ |
| 13 | 17 | ExpressQueryProvider getOrCreateExpressQueryProvider(ExpressQueryProviderEnum queryProviderEnum); |
| 18 | + | |
| 14 | 19 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/convert/ExpressQueryConvert.java
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/ExpressQueryReqDTO.java
| ... | ... | @@ -14,8 +14,9 @@ public class ExpressQueryReqDTO { |
| 14 | 14 | /** |
| 15 | 15 | * 快递公司编码 |
| 16 | 16 | * |
| 17 | - * 对应 {@link DeliveryExpressDO#getCode()} } | |
| 17 | + * 对应 {@link DeliveryExpressDO#getCode()} | |
| 18 | 18 | */ |
| 19 | + // TODO @jaosn:要不改成 expressCode;项目里使用这个哈 | |
| 19 | 20 | private String expressCompanyCode; |
| 20 | 21 | |
| 21 | 22 | /** |
| ... | ... | @@ -27,4 +28,5 @@ public class ExpressQueryReqDTO { |
| 27 | 28 | * 收、寄件人的电话号码 |
| 28 | 29 | */ |
| 29 | 30 | private String phone; |
| 31 | + | |
| 30 | 32 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/ExpressQueryRespDTO.java
| ... | ... | @@ -10,13 +10,15 @@ import lombok.Data; |
| 10 | 10 | @Data |
| 11 | 11 | public class ExpressQueryRespDTO { |
| 12 | 12 | |
| 13 | + // TODO @jason:LocalDateTime | |
| 13 | 14 | /** |
| 14 | 15 | * 发生时间 |
| 15 | 16 | */ |
| 16 | 17 | private String time; |
| 17 | - | |
| 18 | + // TODO @jason:其它字段可能要补充下 | |
| 18 | 19 | /** |
| 19 | 20 | * 快递状态 |
| 20 | 21 | */ |
| 21 | 22 | private String state; |
| 23 | + | |
| 22 | 24 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/provider/kd100/Kd100ExpressQueryReqDTO.java
| ... | ... | @@ -13,6 +13,7 @@ import lombok.Data; |
| 13 | 13 | @JsonInclude(JsonInclude.Include.NON_NULL) |
| 14 | 14 | public class Kd100ExpressQueryReqDTO { |
| 15 | 15 | |
| 16 | + // TODO @jaosn:要不改成 expressCode;项目里使用这个哈 | |
| 16 | 17 | /** |
| 17 | 18 | * 快递公司编码 |
| 18 | 19 | */ |
| ... | ... | @@ -29,19 +30,20 @@ public class Kd100ExpressQueryReqDTO { |
| 29 | 30 | * 收、寄件人的电话号码 |
| 30 | 31 | */ |
| 31 | 32 | private String phone; |
| 32 | - | |
| 33 | 33 | /** |
| 34 | 34 | * 出发地城市 |
| 35 | 35 | */ |
| 36 | 36 | private String from; |
| 37 | - | |
| 38 | 37 | /** |
| 39 | 38 | * 目的地城市,到达目的地后会加大监控频率 |
| 40 | 39 | */ |
| 41 | 40 | private String to; |
| 42 | 41 | |
| 43 | 42 | /** |
| 44 | - * 返回结果排序:desc降序(默认),asc 升序 | |
| 43 | + * 返回结果排序 | |
| 44 | + * | |
| 45 | + * desc 降序(默认), asc 升序 | |
| 45 | 46 | */ |
| 46 | 47 | private String order; |
| 48 | + | |
| 47 | 49 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/provider/kd100/Kd100ExpressQueryRespDTO.java
| ... | ... | @@ -18,23 +18,22 @@ public class Kd100ExpressQueryRespDTO { |
| 18 | 18 | */ |
| 19 | 19 | @JsonProperty("com") |
| 20 | 20 | private String expressCompanyCode; |
| 21 | - | |
| 22 | 21 | /** |
| 23 | 22 | * 快递单号 |
| 24 | 23 | */ |
| 25 | 24 | @JsonProperty("nu") |
| 26 | 25 | private String logisticsNo; |
| 27 | - | |
| 28 | 26 | /** |
| 29 | 27 | * 快递单当前状态 |
| 30 | 28 | */ |
| 31 | 29 | private String state; |
| 32 | 30 | |
| 33 | 31 | /** |
| 34 | - * 查询结果, 失败返回 "false" | |
| 32 | + * 查询结果 | |
| 33 | + * | |
| 34 | + * 失败返回 "false" | |
| 35 | 35 | */ |
| 36 | 36 | private String result; |
| 37 | - | |
| 38 | 37 | /** |
| 39 | 38 | * 查询结果失败时的错误信息 |
| 40 | 39 | */ |
| ... | ... | @@ -56,4 +55,5 @@ public class Kd100ExpressQueryRespDTO { |
| 56 | 55 | @JsonProperty("context") |
| 57 | 56 | private String state; |
| 58 | 57 | } |
| 58 | + | |
| 59 | 59 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/provider/kdniao/KdNiaoExpressQueryReqDTO.java
| ... | ... | @@ -12,21 +12,22 @@ import lombok.Data; |
| 12 | 12 | @Data |
| 13 | 13 | @JsonInclude(JsonInclude.Include.NON_NULL) |
| 14 | 14 | public class KdNiaoExpressQueryReqDTO { |
| 15 | + | |
| 16 | + // TODO @jaosn:要不改成 expressCode;项目里使用这个哈 | |
| 15 | 17 | /** |
| 16 | 18 | * 快递公司编码 |
| 17 | 19 | */ |
| 18 | 20 | @JsonProperty("ShipperCode") |
| 19 | 21 | private String expressCompanyCode; |
| 20 | - | |
| 21 | 22 | /** |
| 22 | 23 | * 快递单号 |
| 23 | 24 | */ |
| 24 | 25 | @JsonProperty("LogisticCode") |
| 25 | 26 | private String logisticsNo; |
| 26 | - | |
| 27 | 27 | /** |
| 28 | 28 | * 订单编号 |
| 29 | 29 | */ |
| 30 | 30 | @JsonProperty("OrderCode") |
| 31 | 31 | private String orderNo; |
| 32 | + | |
| 32 | 33 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/ExpressQueryClientImpl.java
| ... | ... | @@ -17,6 +17,15 @@ import java.util.List; |
| 17 | 17 | |
| 18 | 18 | import static cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProviderEnum.KD_NIAO; |
| 19 | 19 | |
| 20 | +// TODO @jason:可以把整体包结构调整下;参考 sms client 的方式; | |
| 21 | +// + config | |
| 22 | +// + core | |
| 23 | +// client | |
| 24 | +// + dto | |
| 25 | +// + impl:里面可以放 kdniaoclient、kd100client | |
| 26 | +// ExpressClient | |
| 27 | +// ExpressClientFactory: 通过它直接获取默认和创建默认的 Client | |
| 28 | +// enums | |
| 20 | 29 | /** |
| 21 | 30 | * 快递查询客户端实现 |
| 22 | 31 | * |
| ... | ... | @@ -24,30 +33,33 @@ import static cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQuery |
| 24 | 33 | */ |
| 25 | 34 | @Component |
| 26 | 35 | @Slf4j |
| 27 | -public class ExpressQueryClientImpl implements ExpressQueryClient { | |
| 36 | +public class ExpressQueryClientImpl implements ExpressQueryClient { | |
| 37 | + | |
| 28 | 38 | @Resource |
| 29 | 39 | private ExpressQueryProviderFactory expressQueryProviderFactory; |
| 30 | 40 | @Resource |
| 31 | 41 | private TradeExpressQueryProperties tradeExpressQueryProperties; |
| 32 | 42 | |
| 33 | 43 | private ExpressQueryProvider expressQueryProvider; |
| 44 | + | |
| 34 | 45 | @PostConstruct |
| 35 | - private void init(){ | |
| 46 | + private void init() { | |
| 47 | + // 如果未设置,默认使用快递鸟 | |
| 36 | 48 | ExpressQueryProviderEnum queryProvider = tradeExpressQueryProperties.getExpressQueryProvider(); |
| 37 | 49 | if (queryProvider == null) { |
| 38 | - // 如果未设置,默认使用快递鸟 | |
| 39 | 50 | queryProvider = KD_NIAO; |
| 40 | 51 | } |
| 52 | + // 创建客户端 | |
| 41 | 53 | expressQueryProvider = expressQueryProviderFactory.getOrCreateExpressQueryProvider(queryProvider); |
| 42 | 54 | if (expressQueryProvider == null) { |
| 43 | - // 记录错误日志 | |
| 44 | 55 | log.error("获取创建快递查询服务商{}失败,请检查相关配置", queryProvider); |
| 45 | 56 | } |
| 46 | 57 | Assert.notNull(expressQueryProvider, "快递查询服务商不能为空"); |
| 47 | - | |
| 48 | 58 | } |
| 59 | + | |
| 49 | 60 | @Override |
| 50 | 61 | public List<ExpressQueryRespDTO> realTimeQuery(ExpressQueryReqDTO reqDTO) { |
| 51 | 62 | return expressQueryProvider.realTimeQueryExpress(reqDTO); |
| 52 | 63 | } |
| 64 | + | |
| 53 | 65 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/ExpressQueryProviderFactoryImpl.java
| ... | ... | @@ -12,12 +12,14 @@ import java.util.Map; |
| 12 | 12 | import java.util.concurrent.ConcurrentHashMap; |
| 13 | 13 | |
| 14 | 14 | /** |
| 15 | + * // TODO @jason:注释不全 | |
| 15 | 16 | * @author jason |
| 16 | 17 | */ |
| 17 | 18 | @Component |
| 18 | 19 | public class ExpressQueryProviderFactoryImpl implements ExpressQueryProviderFactory { |
| 19 | 20 | |
| 20 | 21 | private final Map<ExpressQueryProviderEnum, ExpressQueryProvider> providerMap = new ConcurrentHashMap<>(8); |
| 22 | + | |
| 21 | 23 | @Resource |
| 22 | 24 | private TradeExpressQueryProperties tradeExpressQueryProperties; |
| 23 | 25 | @Resource |
| ... | ... | @@ -31,6 +33,7 @@ public class ExpressQueryProviderFactoryImpl implements ExpressQueryProviderFact |
| 31 | 33 | |
| 32 | 34 | private ExpressQueryProvider createExpressQueryProvider(ExpressQueryProviderEnum queryProviderEnum, |
| 33 | 35 | TradeExpressQueryProperties tradeExpressQueryProperties) { |
| 36 | + // TODO @jason:是不是直接 return 就好啦,更简洁一点 | |
| 34 | 37 | ExpressQueryProvider result = null; |
| 35 | 38 | switch (queryProviderEnum) { |
| 36 | 39 | case KD_NIAO: | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/Kd100ExpressQueryProvider.java
| ... | ... | @@ -21,10 +21,11 @@ import java.util.List; |
| 21 | 21 | import java.util.Objects; |
| 22 | 22 | |
| 23 | 23 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 24 | -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_FAILED; | |
| 25 | 24 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_ERROR; |
| 25 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_FAILED; | |
| 26 | 26 | import static cn.iocoder.yudao.module.trade.framework.delivery.core.convert.ExpressQueryConvert.INSTANCE; |
| 27 | 27 | |
| 28 | +// TODO @jason:可以参考 KdNiaoExpressQueryProvider 建议改改哈 | |
| 28 | 29 | /** |
| 29 | 30 | * 快递 100 服务商 |
| 30 | 31 | * |
| ... | ... | @@ -34,8 +35,8 @@ import static cn.iocoder.yudao.module.trade.framework.delivery.core.convert.Expr |
| 34 | 35 | public class Kd100ExpressQueryProvider implements ExpressQueryProvider { |
| 35 | 36 | |
| 36 | 37 | private static final String REAL_TIME_QUERY_URL = "https://poll.kuaidi100.com/poll/query.do"; |
| 37 | - private final RestTemplate restTemplate; | |
| 38 | 38 | |
| 39 | + private final RestTemplate restTemplate; | |
| 39 | 40 | private final TradeExpressQueryProperties.Kd100Config config; |
| 40 | 41 | |
| 41 | 42 | public Kd100ExpressQueryProvider(RestTemplate restTemplate, TradeExpressQueryProperties.Kd100Config config) { |
| ... | ... | @@ -45,16 +46,19 @@ public class Kd100ExpressQueryProvider implements ExpressQueryProvider { |
| 45 | 46 | |
| 46 | 47 | @Override |
| 47 | 48 | public List<ExpressQueryRespDTO> realTimeQueryExpress(ExpressQueryReqDTO reqDTO) { |
| 49 | + // 发起查询 | |
| 48 | 50 | Kd100ExpressQueryReqDTO kd100ReqParam = INSTANCE.convert2(reqDTO); |
| 49 | - // 快递公司编码需要转成小写 | |
| 50 | - kd100ReqParam.setExpressCompanyCode(kd100ReqParam.getExpressCompanyCode().toLowerCase()); | |
| 51 | + kd100ReqParam.setExpressCompanyCode(kd100ReqParam.getExpressCompanyCode().toLowerCase()); // 快递公司编码需要转成小写 | |
| 51 | 52 | Kd100ExpressQueryRespDTO respDTO = sendExpressQueryReq(REAL_TIME_QUERY_URL, kd100ReqParam, |
| 52 | 53 | Kd100ExpressQueryRespDTO.class); |
| 53 | - log.debug("快递 100 接口 查询接口返回 {}", respDTO); | |
| 54 | + log.debug("[realTimeQueryExpress][快递 100 接口 查询接口返回 {}]", respDTO); | |
| 55 | + // 处理结果 | |
| 54 | 56 | if (Objects.equals("false", respDTO.getResult())) { |
| 55 | - log.error("快递 100 接口 返回失败 {} ", respDTO.getMessage()); | |
| 57 | + log.error("[realTimeQueryExpress][快递 100 接口 返回失败 {}]", respDTO.getMessage()); | |
| 56 | 58 | throw exception(EXPRESS_API_QUERY_FAILED, respDTO.getMessage()); |
| 59 | + // TODO @json:else 可以不用写哈; | |
| 57 | 60 | } else { |
| 61 | + // TODO @jason:convertList2 如果空,应该返回 list 了; | |
| 58 | 62 | if (CollUtil.isNotEmpty(respDTO.getTracks())) { |
| 59 | 63 | return INSTANCE.convertList2(respDTO.getTracks()); |
| 60 | 64 | } else { |
| ... | ... | @@ -65,12 +69,14 @@ public class Kd100ExpressQueryProvider implements ExpressQueryProvider { |
| 65 | 69 | |
| 66 | 70 | /** |
| 67 | 71 | * 发送快递 100 实时快递查询请求,可以作为通用快递 100 通用请求接口。 目前没有其它场景需要使用。暂时放这里 |
| 72 | + * | |
| 68 | 73 | * @param url 请求 url |
| 69 | 74 | * @param req 对应请求的请求参数 |
| 70 | 75 | * @param respClass 对应请求的响应 class |
| 71 | 76 | * @param <Req> 每个请求的请求结构 Req DTO |
| 72 | 77 | * @param <Resp> 每个请求的响应结构 Resp DTO |
| 73 | 78 | */ |
| 79 | + // TODO @jason:可以改成 request,发起请求哈; | |
| 74 | 80 | private <Req, Resp> Resp sendExpressQueryReq(String url, Req req, Class<Resp> respClass) { |
| 75 | 81 | // 请求头 |
| 76 | 82 | HttpHeaders headers = new HttpHeaders(); |
| ... | ... | @@ -78,19 +84,20 @@ public class Kd100ExpressQueryProvider implements ExpressQueryProvider { |
| 78 | 84 | // 生成签名 |
| 79 | 85 | String param = JsonUtils.toJsonString(req); |
| 80 | 86 | String sign = generateReqSign(param, config.getKey(), config.getCustomer()); |
| 81 | - log.debug("快递 100 快递 接口生成签名的: {}", sign); | |
| 82 | 87 | // 请求体 |
| 83 | 88 | MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>(); |
| 84 | 89 | requestBody.add("customer", config.getCustomer()); |
| 85 | 90 | requestBody.add("sign", sign); |
| 86 | 91 | requestBody.add("param", param); |
| 87 | - log.debug("快递 100 接口的请求参数: {}", requestBody); | |
| 88 | - | |
| 89 | - HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers); | |
| 92 | + log.debug("[sendExpressQueryReq][快递 100 接口的请求参数: {}]", requestBody); | |
| 90 | 93 | // 发送请求 |
| 94 | + HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers); | |
| 95 | + // TODO @jason:可以使用 restTemplate 的 post 方法哇? | |
| 91 | 96 | ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); |
| 92 | - log.debug("快递 100 接口响应结果 {}", responseEntity); | |
| 97 | + log.debug("[sendExpressQueryReq][快递 100 接口响应结果 {}]", responseEntity); | |
| 98 | + | |
| 93 | 99 | // 处理响应 |
| 100 | + // TODO @jason:if return 原则;if (!responseEntity.getStatusCode().is2xxSuccessful()) 抛出异常;接着处理成功的 | |
| 94 | 101 | if (responseEntity.getStatusCode().is2xxSuccessful()) { |
| 95 | 102 | String response = responseEntity.getBody(); |
| 96 | 103 | return JsonUtils.parseObject(response, respClass); |
| ... | ... | @@ -101,7 +108,8 @@ public class Kd100ExpressQueryProvider implements ExpressQueryProvider { |
| 101 | 108 | |
| 102 | 109 | private String generateReqSign(String param, String key, String customer) { |
| 103 | 110 | String plainText = String.format("%s%s%s", param, key, customer); |
| 104 | - log.debug("快递 100 接口待签名的数据 {}", plainText); | |
| 111 | + // TODO @jason:DigestUtil.md5Hex(plainText); | |
| 105 | 112 | return HexUtil.encodeHexStr(DigestUtil.md5(plainText), false); |
| 106 | 113 | } |
| 114 | + | |
| 107 | 115 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/KdNiaoExpressQueryProvider.java
| ... | ... | @@ -32,21 +32,27 @@ import static cn.iocoder.yudao.module.trade.framework.delivery.core.convert.Expr |
| 32 | 32 | */ |
| 33 | 33 | @Slf4j |
| 34 | 34 | public class KdNiaoExpressQueryProvider implements ExpressQueryProvider { |
| 35 | + | |
| 35 | 36 | private static final String REAL_TIME_QUERY_URL = "https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx"; |
| 37 | + | |
| 36 | 38 | /** |
| 37 | 39 | * 快递鸟即时查询免费版 RequestType |
| 38 | 40 | */ |
| 39 | 41 | private static final String REAL_TIME_FREE_REQ_TYPE = "1002"; |
| 42 | + | |
| 40 | 43 | private final RestTemplate restTemplate; |
| 41 | 44 | private final TradeExpressQueryProperties.KdNiaoConfig config; |
| 42 | 45 | |
| 46 | + // TODO @jason:可以改成 lombok 哈 | |
| 43 | 47 | public KdNiaoExpressQueryProvider(RestTemplate restTemplate, TradeExpressQueryProperties.KdNiaoConfig config) { |
| 44 | 48 | this.restTemplate = restTemplate; |
| 45 | 49 | this.config = config; |
| 46 | 50 | } |
| 47 | 51 | |
| 48 | 52 | /** |
| 49 | - * 快递鸟即时查询免费版本 参见 <a href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/wugo6k">快递鸟接口文档</a> | |
| 53 | + * 快递鸟即时查询免费版本 | |
| 54 | + * | |
| 55 | + * @see <a href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/wugo6k">快递鸟接口文档</a> | |
| 50 | 56 | * @param reqDTO 查询请求参数 |
| 51 | 57 | */ |
| 52 | 58 | @Override |
| ... | ... | @@ -56,7 +62,7 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider { |
| 56 | 62 | kdNiaoReqData.setExpressCompanyCode(reqDTO.getExpressCompanyCode().toUpperCase()); |
| 57 | 63 | KdNiaoExpressQueryRespDTO respDTO = sendKdNiaoApiRequest(REAL_TIME_QUERY_URL, REAL_TIME_FREE_REQ_TYPE, |
| 58 | 64 | kdNiaoReqData, KdNiaoExpressQueryRespDTO.class); |
| 59 | - log.debug("快递鸟即时查询接口返回 {}", respDTO); | |
| 65 | + log.debug("[realTimeQueryExpress][快递鸟即时查询接口返回 {}]", respDTO); | |
| 60 | 66 | if(!respDTO.getSuccess()){ |
| 61 | 67 | throw exception(EXPRESS_API_QUERY_FAILED, respDTO.getReason()); |
| 62 | 68 | }else{ |
| ... | ... | @@ -85,16 +91,16 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider { |
| 85 | 91 | // 请求体 |
| 86 | 92 | String reqData = JsonUtils.toJsonString(req); |
| 87 | 93 | String dataSign = generateDataSign(reqData, config.getApiKey()); |
| 88 | - log.trace("得到快递鸟接口 RequestType : {} 的 签名: {}", requestType, dataSign); | |
| 89 | 94 | MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>(); |
| 90 | 95 | requestBody.add("RequestData", reqData); |
| 91 | 96 | requestBody.add("DataType", "2"); |
| 92 | 97 | requestBody.add("EBusinessID", config.getBusinessId()); |
| 93 | 98 | requestBody.add("DataSign", dataSign); |
| 94 | 99 | requestBody.add("RequestType", requestType); |
| 95 | - log.debug("快递鸟接口 RequestType : {}, 的请求参数 {}", requestType, requestBody); | |
| 96 | - HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers); | |
| 100 | + log.debug("[sendKdNiaoApiRequest][快递鸟接口 RequestType : {}, 的请求参数 {}]", requestType, requestBody); | |
| 101 | + | |
| 97 | 102 | // 发送请求 |
| 103 | + HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers); | |
| 98 | 104 | ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); |
| 99 | 105 | log.debug("快递鸟接口 RequestType : {}, 的响应结果 {}", requestType, responseEntity); |
| 100 | 106 | // 处理响应 |
| ... | ... | @@ -113,7 +119,7 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider { |
| 113 | 119 | */ |
| 114 | 120 | private String generateDataSign(String reqData, String apiKey) { |
| 115 | 121 | String plainText = String.format("%s%s", reqData, apiKey); |
| 116 | - log.trace("签名前的数据 {}", plainText); | |
| 117 | 122 | return URLEncodeUtil.encode(Base64.encode(DigestUtil.md5Hex(plainText))); |
| 118 | 123 | } |
| 124 | + | |
| 119 | 125 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/KdNiaoExpressQueryProviderTest.java
| ... | ... | @@ -17,11 +17,12 @@ import javax.annotation.Resource; |
| 17 | 17 | |
| 18 | 18 | import static org.junit.jupiter.api.Assertions.assertThrows; |
| 19 | 19 | |
| 20 | +// TODO @芋艿:单测最后 review | |
| 20 | 21 | /** |
| 21 | 22 | * @author jason |
| 22 | 23 | */ |
| 23 | 24 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = KdNiaoExpressQueryProviderTest.Application.class) |
| 24 | -@ActiveProfiles("trade-delivery-query") // 设置使用 trade-delivery-query 配置文件 | |
| 25 | +@ActiveProfiles("trade-delivery-query") // 设置使用 trade-delivery-query 配置文件 TODO @jason:可以直接写到 application-unit-test.yaml 配置文件里 | |
| 25 | 26 | public class KdNiaoExpressQueryProviderTest { |
| 26 | 27 | @Resource |
| 27 | 28 | private RestTemplateBuilder builder; |
| ... | ... | @@ -51,4 +52,4 @@ public class KdNiaoExpressQueryProviderTest { |
| 51 | 52 | @EnableConfigurationProperties(TradeExpressQueryProperties.class) |
| 52 | 53 | public static class Application { |
| 53 | 54 | } |
| 54 | -} | |
| 55 | 55 | \ No newline at end of file |
| 56 | +} | ... | ... |