Commit dcb1660880064f8357955761fb03011e4a976d4c

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