mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 23:31:52 +08:00
订单:
1. 增加查询物流接口
This commit is contained in:
parent
36da5d69b0
commit
e4a2c738b2
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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()));
|
||||
|
||||
}
|
@ -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}}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 @jason:LocalDateTime
|
||||
/**
|
||||
* 发生时间
|
||||
*/
|
||||
private String time;
|
||||
// TODO @jason:其它字段可能要补充下
|
||||
private LocalDateTime time;
|
||||
|
||||
/**
|
||||
* 快递状态
|
||||
*/
|
||||
private String state;
|
||||
private String content;
|
||||
|
||||
}
|
||||
|
@ -29,20 +29,5 @@ public class Kd100ExpressQueryReqDTO {
|
||||
* 收、寄件人的电话号码
|
||||
*/
|
||||
private String phone;
|
||||
/**
|
||||
* 出发地城市
|
||||
*/
|
||||
private String from;
|
||||
/**
|
||||
* 目的地城市,到达目的地后会加大监控频率
|
||||
*/
|
||||
private String to;
|
||||
|
||||
/**
|
||||
* 返回结果排序
|
||||
*
|
||||
* desc 降序(默认), asc 升序
|
||||
*/
|
||||
private String order;
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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": "暂无轨迹信息"
|
||||
// }
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
||||
}
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
@ -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 {
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
@ -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 {
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user