订单:

1. 增加查询物流接口
This commit is contained in:
YunaiV 2023-08-15 20:18:22 +08:00
parent 36da5d69b0
commit e4a2c738b2
22 changed files with 338 additions and 266 deletions

View File

@ -1,7 +1,6 @@
package cn.iocoder.yudao.framework.jackson.core.databind;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
@ -20,7 +19,7 @@ public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
public static final LocalDateTimeDeserializer INSTANCE = new LocalDateTimeDeserializer();
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault());
}
}

View File

@ -1,21 +0,0 @@
package cn.iocoder.yudao.framework.jackson.core.databind;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_HOUR_MINUTE_SECOND;
public class LocalTimeJson {
public static final LocalTimeSerializer SERIALIZER = new LocalTimeSerializer(DateTimeFormatter
.ofPattern(FORMAT_HOUR_MINUTE_SECOND)
.withZone(ZoneId.systemDefault()));
public static final LocalTimeDeserializer DESERIALIZABLE = new LocalTimeDeserializer(DateTimeFormatter
.ofPattern(FORMAT_HOUR_MINUTE_SECOND)
.withZone(ZoneId.systemDefault()));
}

View File

@ -35,3 +35,8 @@ tenant-id: {{appTenentId}}
GET {{appApi}}/trade/order/get-detail?id=21
Authorization: Bearer {{appToken}}
tenant-id: {{appTenentId}}
### 获得交易订单的物流轨迹
GET {{appApi}}/trade/order/get-express-track-list?id=70
Authorization: Bearer {{appToken}}
tenant-id: {{appTenentId}}

View File

@ -16,6 +16,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderService;
import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation;
@ -45,6 +46,8 @@ public class AppTradeOrderController {
@Resource
private TradeOrderService tradeOrderService;
@Resource
private TradeOrderQueryService tradeOrderQueryService;
@Resource
private DeliveryExpressService deliveryExpressService;
@Resource
@ -99,6 +102,14 @@ public class AppTradeOrderController {
propertyValueDetails, tradeOrderProperties, express));
}
@GetMapping("/get-express-track-list")
@Operation(summary = "获得交易订单的物流轨迹")
@Parameter(name = "id", description = "交易订单编号")
public CommonResult<List<?>> getOrderExpressTrackList(@RequestParam("id") Long id) {
return success(TradeOrderConvert.INSTANCE.convertList02(
tradeOrderQueryService.getExpressTrackList(id, getLoginUserId())));
}
@GetMapping("/page")
@Operation(summary = "获得交易订单分页")
public CommonResult<PageResult<AppTradeOrderPageItemRespVO>> getOrderPage(AppTradeOrderPageReqVO reqVO) {

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.trade.controller.app.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 快递查询的轨迹 Resp DTO
*
* @author jason
*/
@Schema(description = "用户 App - 快递查询的轨迹 Response VO")
@Data
public class AppOrderExpressTrackRespDTO {
@Schema(description = "发生时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime time;
@Schema(description = "快递状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "已签收")
private String content;
}

View File

@ -29,6 +29,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
@ -340,4 +341,6 @@ public interface TradeOrderConvert {
CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem,
AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);
List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list);
}

View File

@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kd100.Kd
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kdniao.KdNiaoExpressQueryReqDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kdniao.KdNiaoExpressQueryRespDTO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.List;
@ -16,9 +17,14 @@ public interface ExpressQueryConvert {
ExpressQueryConvert INSTANCE = Mappers.getMapper(ExpressQueryConvert.class);
List<ExpressTrackRespDTO> convertList(List<KdNiaoExpressQueryRespDTO.ExpressTrack> expressTrackList);
List<ExpressTrackRespDTO> convertList(List<KdNiaoExpressQueryRespDTO.ExpressTrack> list);
@Mapping(source = "acceptTime", target = "time")
@Mapping(source = "acceptStation", target = "content")
ExpressTrackRespDTO convert(KdNiaoExpressQueryRespDTO.ExpressTrack track);
List<ExpressTrackRespDTO> convertList2(List<Kd100ExpressQueryRespDTO.ExpressTrack> expressTrackList);
List<ExpressTrackRespDTO> convertList2(List<Kd100ExpressQueryRespDTO.ExpressTrack> list);
@Mapping(source = "context", target = "content")
ExpressTrackRespDTO convert(Kd100ExpressQueryRespDTO.ExpressTrack track);
KdNiaoExpressQueryReqDTO convert(ExpressTrackQueryReqDTO dto);

View File

@ -2,23 +2,24 @@ package cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 快递查询 Resp DTO
* 快递查询的轨迹 Resp DTO
*
* @author jason
*/
@Data
public class ExpressTrackRespDTO {
// TODO @jasonLocalDateTime
/**
* 发生时间
*/
private String time;
// TODO @jason其它字段可能要补充下
private LocalDateTime time;
/**
* 快递状态
*/
private String state;
private String content;
}

View File

@ -29,20 +29,5 @@ public class Kd100ExpressQueryReqDTO {
* 寄件人的电话号码
*/
private String phone;
/**
* 出发地城市
*/
private String from;
/**
* 目的地城市到达目的地后会加大监控频率
*/
private String to;
/**
* 返回结果排序
*
* desc 降序默认, asc 升序
*/
private String order;
}

View File

@ -1,12 +1,19 @@
package cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kd100;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
/**
* 快递 100 实时快递查询 Resp DTO 参见 <a href="https://api.kuaidi100.com/document/5f0ffb5ebc8da837cbd8aefc">快递 100 文档</a>
* 快递 100 实时快递查询 Resp DTO
*
* 参见 <a href="https://api.kuaidi100.com/document/5f0ffb5ebc8da837cbd8aefc">快递 100 文档</a>
*
* @author jason
*/
@ -39,21 +46,26 @@ public class Kd100ExpressQueryRespDTO {
*/
private String message;
/**
* 轨迹数组
*/
@JsonProperty("data")
private List<ExpressTrack> tracks;
@Data
public static class ExpressTrack {
/**
* 轨迹发生时间
*/
@JsonProperty("time")
private String time;
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
private LocalDateTime time;
/**
* 轨迹描述
*/
@JsonProperty("context")
private String state;
private String context;
}
}

View File

@ -1,12 +1,21 @@
package cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kdniao;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
/**
* 快递鸟快递查询 Resp DTO 参见 <a href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/wugo6k">快递鸟接口文档</a>
* 快递鸟快递查询 Resp DTO
*
* 参见 <a href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/wugo6k">快递鸟接口文档</a>
*
* @author jason
*/
@ -17,7 +26,7 @@ public class KdNiaoExpressQueryRespDTO {
* 快递公司编码
*/
@JsonProperty("ShipperCode")
private String expressCompanyCode;
private String shipperCode;
/**
* 快递单号
@ -31,10 +40,26 @@ public class KdNiaoExpressQueryRespDTO {
@JsonProperty("OrderCode")
private String orderNo;
/**
* 用户 ID
*/
@JsonProperty("EBusinessID")
private String businessId;
/**
* 普通物流状态
*
* 0 - 暂无轨迹信息
* 1 - 已揽收
* 2 - 在途中
* 3 - 签收
* 4 - 问题件
* 5 - 转寄
* 6 - 清关
*/
@JsonProperty("State")
private String state;
/**
* 成功与否
*/
@ -46,30 +71,29 @@ public class KdNiaoExpressQueryRespDTO {
@JsonProperty("Reason")
private String reason;
/**
* 轨迹数组
*/
@JsonProperty("Traces")
private List<ExpressTrack> tracks;
@Data
public static class ExpressTrack {
/**
* 轨迹发生时间
* 发生时间
*/
@JsonProperty("AcceptTime")
private String time;
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime acceptTime;
/**
* 轨迹描述
*/
@JsonProperty("AcceptStation")
private String state;
private String acceptStation;
}
// {
// "EBusinessID": "1237100",
// "Traces": [],
// "State": "0",
// "ShipperCode": "STO",
// "LogisticCode": "638650888018",
// "Success": true,
// "Reason": "暂无轨迹信息"
// }
}

View File

@ -40,18 +40,24 @@ public class Kd100ExpressClient implements ExpressClient {
private final RestTemplate restTemplate;
private final TradeExpressProperties.Kd100Config config;
/**
* 查询快递轨迹
*
* @see <a href="https://api.kuaidi100.com/debug-tool/query/">接口文档</a>
*
* @param reqDTO 查询请求参数
* @return 快递轨迹
*/
@Override
public List<ExpressTrackRespDTO> getExpressTrackList(ExpressTrackQueryReqDTO reqDTO) {
// 发起查询
Kd100ExpressQueryReqDTO kd100ReqParam = INSTANCE.convert2(reqDTO);
kd100ReqParam.setExpressCode(kd100ReqParam.getExpressCode().toLowerCase()); // 快递公司编码需要转成小写
Kd100ExpressQueryRespDTO respDTO = requestExpressQuery(REAL_TIME_QUERY_URL, kd100ReqParam,
// 发起请求
Kd100ExpressQueryReqDTO requestDTO = INSTANCE.convert2(reqDTO)
.setExpressCode(reqDTO.getExpressCode().toLowerCase());
Kd100ExpressQueryRespDTO respDTO = httpRequest(REAL_TIME_QUERY_URL, requestDTO,
Kd100ExpressQueryRespDTO.class);
log.debug("[getExpressTrackList][快递 100 接口 查询接口返回 {}]", respDTO);
// 处理结果
if (Objects.equals("false", respDTO.getResult())) {
log.error("[getExpressTrackList][快递 100 接口 返回失败 {}]", respDTO.getMessage());
throw exception(EXPRESS_API_QUERY_FAILED, respDTO.getMessage());
}
if (CollUtil.isEmpty(respDTO.getTracks())) {
@ -61,7 +67,7 @@ public class Kd100ExpressClient implements ExpressClient {
}
/**
* 发送快递 100 实时快递查询请求可以作为通用快递 100 通用请求接口 目前没有其它场景需要使用暂时放这里
* 快递 100 API 请求
*
* @param url 请求 url
* @param req 对应请求的请求参数
@ -69,24 +75,23 @@ public class Kd100ExpressClient implements ExpressClient {
* @param <Req> 每个请求的请求结构 Req DTO
* @param <Resp> 每个请求的响应结构 Resp DTO
*/
private <Req, Resp> Resp requestExpressQuery(String url, Req req, Class<Resp> respClass) {
private <Req, Resp> Resp httpRequest(String url, Req req, Class<Resp> respClass) {
// 请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
// 生成签名
String param = JsonUtils.toJsonString(req);
String sign = generateReqSign(param, config.getKey(), config.getCustomer());
// 请求体
String param = JsonUtils.toJsonString(req);
String sign = generateReqSign(param, config.getKey(), config.getCustomer()); // 签名
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("customer", config.getCustomer());
requestBody.add("sign", sign);
requestBody.add("param", param);
log.debug("[sendExpressQueryReq][快递 100 接口的请求参数: {}]", requestBody);
log.debug("[httpRequest][请求参数({})]", requestBody);
// 发送请求
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
log.debug("[sendExpressQueryReq][快递 100 接口响应结果 {}]", responseEntity);
log.debug("[httpRequest][的响应结果({})]", responseEntity);
// 处理响应
if (!responseEntity.getStatusCode().is2xxSuccessful()) {
throw exception(EXPRESS_API_QUERY_ERROR);

View File

@ -41,36 +41,40 @@ public class KdNiaoExpressClient implements ExpressClient {
* 快递鸟即时查询免费版 RequestType
*/
private static final String REAL_TIME_FREE_REQ_TYPE = "1002";
private final RestTemplate restTemplate;
private final TradeExpressProperties.KdNiaoConfig config;
/**
* 快递鸟即时查询免费版本
* 查询快递轨迹免费版
*
* 仅支持 3 申通快递圆通速递百世快递
*
* @see <a href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/wugo6k">接口文档</a>
*
* @see <a href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/wugo6k">快递鸟接口文档</a>
* @param reqDTO 查询请求参数
* @return 快递轨迹
*/
@Override
public List<ExpressTrackRespDTO> getExpressTrackList(ExpressTrackQueryReqDTO reqDTO) {
KdNiaoExpressQueryReqDTO kdNiaoReqData = INSTANCE.convert(reqDTO);
// 快递公司编码需要转成大写
kdNiaoReqData.setExpressCode(reqDTO.getExpressCode().toUpperCase());
KdNiaoExpressQueryRespDTO respDTO = requestKdNiaoApi(REAL_TIME_QUERY_URL, REAL_TIME_FREE_REQ_TYPE,
kdNiaoReqData, KdNiaoExpressQueryRespDTO.class);
log.debug("[getExpressTrackList][快递鸟即时查询接口返回 {}]", respDTO);
// 发起请求
KdNiaoExpressQueryReqDTO requestDTO = INSTANCE.convert(reqDTO)
.setExpressCode(reqDTO.getExpressCode().toUpperCase());
KdNiaoExpressQueryRespDTO respDTO = httpRequest(REAL_TIME_QUERY_URL, REAL_TIME_FREE_REQ_TYPE,
requestDTO, KdNiaoExpressQueryRespDTO.class);
// 处理结果
if (respDTO == null || !respDTO.getSuccess()) {
throw exception(EXPRESS_API_QUERY_FAILED, respDTO == null ? "" : respDTO.getReason());
}
if (CollUtil.isNotEmpty(respDTO.getTracks())) {
if (CollUtil.isEmpty(respDTO.getTracks())) {
return Collections.emptyList();
}
return INSTANCE.convertList(respDTO.getTracks());
}
/**
* 快递鸟 通用的 API 请求暂时没有其他应用场景 暂时放这里
* 快递鸟 API 请求
*
* @param url 请求 url
* @param requestType 对应的请求指令 (快递鸟的 RequestType)
@ -79,8 +83,7 @@ public class KdNiaoExpressClient implements ExpressClient {
* @param <Req> 每个请求的请求结构 Req DTO
* @param <Resp> 每个请求的响应结构 Resp DTO
*/
private <Req, Resp> Resp requestKdNiaoApi(String url, String requestType, Req req,
Class<Resp> respClass){
private <Req, Resp> Resp httpRequest(String url, String requestType, Req req, Class<Resp> respClass) {
// 请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
@ -93,11 +96,12 @@ public class KdNiaoExpressClient implements ExpressClient {
requestBody.add("EBusinessID", config.getBusinessId());
requestBody.add("DataSign", dataSign);
requestBody.add("RequestType", requestType);
log.debug("[requestKdNiaoApi][快递鸟接口 RequestType : {}, 的请求参数 {}]", requestType, requestBody);
log.debug("[httpRequest][RequestType({}) 的请求参数({})]", requestType, requestBody);
// 发送请求
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
log.debug("快递鸟接口 RequestType : {}, 的响应结果 {}", requestType, responseEntity);
log.debug("[httpRequest][RequestType({}) 的响应结果({})", requestType, responseEntity);
// 处理响应
if (!responseEntity.getStatusCode().is2xxSuccessful()) {
throw exception(EXPRESS_API_QUERY_ERROR);
@ -106,7 +110,10 @@ public class KdNiaoExpressClient implements ExpressClient {
}
/**
* 快递鸟生成请求签名 参见 <a href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/zes04h">签名说明</a>
* 快递鸟生成请求签名
*
* 参见 <a href="https://www.yuque.com/kdnjishuzhichi/dfcrg1/zes04h">签名说明</a>
*
* @param reqData 请求实体
* @param apiKey api Key
*/

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.trade.service.order;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import java.util.List;
/**
* 交易订单 Service 接口
*
* @author 芋道源码
*/
public interface TradeOrderQueryService {
/**
* 获得订单的物流轨迹
*
* @param id 订单编号
* @param userId 用户编号
* @return 物流轨迹数组
*/
List<ExpressTrackRespDTO> getExpressTrackList(Long id, Long userId);
}

View File

@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.trade.service.order;
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClientFactory;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_NOT_EXISTS;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND;
/**
* 交易订单 Service 实现类
*
* @author 芋道源码
*/
@Service
public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
@Resource
private ExpressClientFactory expressClientFactory;
@Resource
private TradeOrderMapper tradeOrderMapper;
@Resource
private DeliveryExpressService deliveryExpressService;
@Override
public List<ExpressTrackRespDTO> getExpressTrackList(Long id, Long userId) {
// 查询订单
TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId);
if (order == null) {
throw exception(ORDER_NOT_FOUND);
}
// 查询物流公司
if (order.getLogisticsId() == null) {
return Collections.emptyList();
}
DeliveryExpressDO express = deliveryExpressService.getDeliveryExpress(order.getLogisticsId());
if (express == null) {
throw exception(EXPRESS_NOT_EXISTS);
}
// 查询物流轨迹
return expressClientFactory.getDefaultExpressClient().getExpressTrackList(
new ExpressTrackQueryReqDTO().setExpressCode(express.getCode()).setLogisticsNo(order.getLogisticsNo())
.setPhone(order.getReceiverMobile()));
}
}

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kd100.Kd100ExpressClient;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* {@link Kd100ExpressClient} 的集成测试
*
* @author jason
*/
@Slf4j
public class Kd100ExpressClientIntegrationTest {
private Kd100ExpressClient client;
@BeforeEach
public void init() {
RestTemplate restTemplate = new RestTemplateBuilder().build();
TradeExpressProperties.Kd100Config config = new TradeExpressProperties.Kd100Config()
.setKey("pLXUGAwK5305")
.setCustomer("E77DF18BE109F454A5CD319E44BF5177");
client = new Kd100ExpressClient(restTemplate, config);
}
@Test
@Disabled("集成测试,暂时忽略")
public void testGetExpressTrackList() {
ExpressTrackQueryReqDTO reqDTO = new ExpressTrackQueryReqDTO();
reqDTO.setExpressCode("STO");
reqDTO.setLogisticsNo("773220402764314");
List<ExpressTrackRespDTO> tracks = client.getExpressTrackList(reqDTO);
System.out.println(JsonUtils.toJsonPrettyString(tracks));
}
}

View File

@ -1,59 +0,0 @@
package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kd100.Kd100ExpressClient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import javax.annotation.Resource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
// TODO @jason可以参考 AliyunSmsClientTest mockito无需启动 spring 容器
/**
* @author jason
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = Kd100ExpressClientTest.Application.class)
@ActiveProfiles("unit-test") // 设置使用 trade-delivery-query 配置文件
public class Kd100ExpressClientTest {
@Resource
private RestTemplateBuilder builder;
@Resource
private TradeExpressProperties expressQueryProperties;
private Kd100ExpressClient kd100ExpressClient;
@BeforeEach
public void init(){
kd100ExpressClient = new Kd100ExpressClient(builder.build(),expressQueryProperties.getKd100());
}
@Test
@Disabled("需要 授权 key. 暂时忽略")
void testRealTimeQueryExpressFailed() {
ServiceException t = assertThrows(ServiceException.class, () -> {
ExpressTrackQueryReqDTO reqDTO = new ExpressTrackQueryReqDTO();
reqDTO.setExpressCode("yto");
reqDTO.setLogisticsNo("YT9383342193097");
kd100ExpressClient.getExpressTrackList(reqDTO);
});
assertEquals(1011003005, t.getCode());
}
@Import({
RestTemplateAutoConfiguration.class
})
@EnableConfigurationProperties(TradeExpressProperties.class)
public static class Application {
}
}

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kdniao.KdNiaoExpressClient;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* {@link KdNiaoExpressClient} 的集成测试
*
* @author jason
*/
@Slf4j
public class KdNiaoExpressClientIntegrationTest {
private KdNiaoExpressClient client;
@BeforeEach
public void init() {
RestTemplate restTemplate = new RestTemplateBuilder().build();
TradeExpressProperties.KdNiaoConfig config = new TradeExpressProperties.KdNiaoConfig()
.setApiKey("cb022f1e-48f1-4c4a-a723-9001ac9676b8")
.setBusinessId("1809751");
client = new KdNiaoExpressClient(restTemplate, config);
}
@Test
@Disabled("集成测试,暂时忽略")
public void testGetExpressTrackList() {
ExpressTrackQueryReqDTO reqDTO = new ExpressTrackQueryReqDTO();
reqDTO.setExpressCode("STO");
reqDTO.setLogisticsNo("663220402764314");
List<ExpressTrackRespDTO> tracks = client.getExpressTrackList(reqDTO);
System.out.println(JsonUtils.toJsonPrettyString(tracks));
}
}

View File

@ -1,59 +0,0 @@
package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kdniao.KdNiaoExpressClient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import javax.annotation.Resource;
import static org.junit.jupiter.api.Assertions.assertThrows;
// TODO @jason可以参考 AliyunSmsClientTest mockito无需启动 spring 容器
/**
* {@link KdNiaoExpressClient} 的单元测试
*
* @author jason
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = KdNiaoExpressClientTest.Application.class)
@ActiveProfiles("unit-test")
public class KdNiaoExpressClientTest {
@Resource
private RestTemplateBuilder builder;
@Resource
private TradeExpressProperties expressQueryProperties;
private KdNiaoExpressClient kdNiaoExpressClient;
@BeforeEach
public void init(){
kdNiaoExpressClient = new KdNiaoExpressClient(builder.build(),expressQueryProperties.getKdNiao());
}
@Test
@Disabled("需要 授权 key. 暂时忽略")
void testRealTimeQueryExpressFailed() {
assertThrows(ServiceException.class,() ->{
ExpressTrackQueryReqDTO reqDTO = new ExpressTrackQueryReqDTO();
reqDTO.setExpressCode("yy");
reqDTO.setLogisticsNo("YT9383342193097");
kdNiaoExpressClient.getExpressTrackList(reqDTO);
});
}
@Import({
RestTemplateAutoConfiguration.class
})
@EnableConfigurationProperties(TradeExpressProperties.class)
public static class Application {
}
}

View File

@ -1,53 +0,0 @@
package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.module.trade.framework.delivery.config.ExpressClientConfig;
import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClient;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
// TODO @jason可以参考 AliyunSmsClientTest mockito无需启动 spring 容器
/**
* @author jason
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = NoProvideExpressClientTest.Application.class)
@ActiveProfiles("unit-test") // 设置使用 trade-delivery-query 配置文件
@Import({ExpressClientConfig.class})
public class NoProvideExpressClientTest {
@Resource
private ExpressClient expressClient;
@Test
void getExpressTrackList() {
ServiceException t = assertThrows(ServiceException.class, () -> {
expressClient.getExpressTrackList(null);
});
assertEquals(1011003006, t.getCode());
}
@Import({
RestTemplateAutoConfiguration.class,
})
@EnableConfigurationProperties(TradeExpressProperties.class)
public static class Application {
@Bean
private RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
}

View File

@ -204,6 +204,14 @@ yudao:
order:
app-id: 1 # 商户编号
expire-time: 2h # 支付的过期时间
express:
client: kd_niao
kd-niao:
api-key: cb022f1e-48f1-4c4a-a723-9001ac9676b8
business-id: 1809751
kd100:
key: pLXUGAwK5305
customer: E77DF18BE109F454A5CD319E44BF5177
debug: false