no message

This commit is contained in:
cb 2025-07-29 17:39:22 +08:00
parent d59b15c569
commit ae2f59d183
11 changed files with 809 additions and 41 deletions

View File

@ -18,6 +18,7 @@ import com.ghy.order.request.AppOrderAssignRequest;
import com.ghy.order.request.AppOrderRequest; import com.ghy.order.request.AppOrderRequest;
import com.ghy.order.request.SysOrderAssignRequest; import com.ghy.order.request.SysOrderAssignRequest;
import com.ghy.order.request.SysOrderGoodsStandards; import com.ghy.order.request.SysOrderGoodsStandards;
import com.ghy.order.request.LogisticsQueryRequest;
import com.ghy.order.service.*; import com.ghy.order.service.*;
import com.ghy.payment.domain.FinancialChangeRecord; import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.FinancialDetail; import com.ghy.payment.domain.FinancialDetail;
@ -111,6 +112,8 @@ public class OrderController extends BaseController {
@Resource @Resource
private IInsuranceManagerService insuranceManagerService; private IInsuranceManagerService insuranceManagerService;
@Resource
private LogisticsService logisticsService;
@GetMapping("/imgs") @GetMapping("/imgs")
public String orderImgs(Long orderId, ModelMap mmap) { public String orderImgs(Long orderId, ModelMap mmap) {
@ -2154,4 +2157,58 @@ public class OrderController extends BaseController {
return AjaxResult.error("生成服务订单失败: " + e.getMessage()); return AjaxResult.error("生成服务订单失败: " + e.getMessage());
} }
} }
/**
* 根据快递单号查询物流信息
*
* @param request 物流查询请求
* @return 物流信息
*/
@PostMapping("/logistics/query")
@ResponseBody
public AjaxResult queryLogistics(@RequestBody LogisticsQueryRequest request) {
try {
LogisticsInfo logisticsInfo = logisticsService.queryLogistics(request);
return AjaxResult.success("查询成功", logisticsInfo);
} catch (Exception e) {
logger.error("查询物流信息失败: {}", e.getMessage(), e);
return AjaxResult.error("查询物流信息失败: " + e.getMessage());
}
}
/**
* 根据快递单号查询物流信息简化版
*
* @param trackingNumber 快递单号
* @return 物流信息
*/
@GetMapping("/logistics/query/{trackingNumber}")
@ResponseBody
public AjaxResult queryLogisticsByNumber(@PathVariable String trackingNumber) {
try {
LogisticsInfo logisticsInfo = logisticsService.queryLogistics(trackingNumber);
return AjaxResult.success("查询成功", logisticsInfo);
} catch (Exception e) {
logger.error("查询物流信息失败: {}", e.getMessage(), e);
return AjaxResult.error("查询物流信息失败: " + e.getMessage());
}
}
/**
* 根据订单ID查询物流信息
*
* @param orderId 订单ID
* @return 物流信息
*/
@GetMapping("/logistics/query/order/{orderId}")
@ResponseBody
public AjaxResult queryLogisticsByOrderId(@PathVariable Long orderId) {
try {
LogisticsInfo logisticsInfo = logisticsService.queryLogisticsByOrderId(orderId);
return AjaxResult.success("查询成功", logisticsInfo);
} catch (Exception e) {
logger.error("查询物流信息失败: {}", e.getMessage(), e);
return AjaxResult.error("查询物流信息失败: " + e.getMessage());
}
}
} }

View File

@ -20,6 +20,7 @@ import com.ghy.order.domain.*;
import com.ghy.order.request.OrderChangePriceReq; import com.ghy.order.request.OrderChangePriceReq;
import com.ghy.order.request.SysOrderAssignRequest; import com.ghy.order.request.SysOrderAssignRequest;
import com.ghy.order.request.SysOrderGoodsStandards; import com.ghy.order.request.SysOrderGoodsStandards;
import com.ghy.order.request.TransferOrderRequest;
import com.ghy.order.service.*; import com.ghy.order.service.*;
import com.ghy.payment.domain.FinancialChangeRecord; import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.FinancialDetail; import com.ghy.payment.domain.FinancialDetail;
@ -242,86 +243,149 @@ public class OrderMasterController extends BaseController {
/** /**
* 订单转单功能 * 订单转单功能
* *
* @param orderMaster 订单对象包含idworkerId新师傅originalWorkerId等字段 * @param request 转单请求对象
* @return 操作结果 * @return 操作结果
*/ */
@PostMapping("/transferOrder") @PostMapping("/transferOrder")
@ResponseBody @ResponseBody
@Log(title = "订单转单管理", businessType = BusinessType.UPDATE) @Log(title = "订单转单管理", businessType = BusinessType.UPDATE)
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public AjaxResult transferOrder(@RequestBody OrderMaster orderMaster) public AjaxResult transferOrder(@RequestBody TransferOrderRequest request)
{ {
try { try {
// 参数校验 // 参数校验
if (orderMaster.getId() == null) { if (request.getOrderId() == null) {
return AjaxResult.error("订单ID不能为空"); return AjaxResult.error("订单ID不能为空");
} }
if (orderMaster.getWorkerId() == null) {
return AjaxResult.error("新师傅ID不能为空");
}
// 查询原订单信息 // 查询原订单信息
OrderMaster originalOrder = orderMasterService.selectById(orderMaster.getId()); OrderMaster originalOrder = orderMasterService.selectById(request.getOrderId());
if (originalOrder == null) { if (originalOrder == null) {
return AjaxResult.error("订单不存在"); return AjaxResult.error("订单不存在");
} }
// // 检查订单状态是否允许转单 // 检查订单状态是否允许转单
// if (originalOrder.getOrderStatus() == null || originalOrder.getOrderStatus() > OrderStatus.RECEIVE.code()) { if (originalOrder.getOrderStatus() == null || originalOrder.getOrderStatus() > OrderStatus.RECEIVE.code()) {
// return AjaxResult.error("订单状态不允许转单,只有待接单、已接单、待上门、进行中状态的订单可以转单"); return AjaxResult.error("订单状态不允许转单,只有待接单、已接单、待上门、进行中状态的订单可以转单");
// }
// 检查新师傅是否存在
Worker newWorker = workerService.selectById(orderMaster.getWorkerId());
if (newWorker == null) {
return AjaxResult.error("新师傅不存在");
} }
// 如果原师傅和新师傅相同则不允许转单 // 如果指定了新师傅检查新师傅是否存在
if (originalOrder.getWorkerId() != null && originalOrder.getWorkerId().equals(orderMaster.getWorkerId())) { Worker newWorker = null;
return AjaxResult.error("新师傅不能与原师傅相同"); if (request.getNewWorkerId() != null) {
newWorker = workerService.selectById(request.getNewWorkerId());
if (newWorker == null) {
return AjaxResult.error("新师傅不存在");
}
// 如果原师傅和新师傅相同则不允许转单
if (originalOrder.getWorkerId() != null && originalOrder.getWorkerId().equals(request.getNewWorkerId())) {
return AjaxResult.error("新师傅不能与原师傅相同");
}
}
// 查询原财务主单
FinancialMaster financialMaster = financialMasterService.selectByOrderId(request.getOrderId());
if (financialMaster == null) {
return AjaxResult.error("订单财务信息不存在");
}
// 处理转单金额
if (request.getTransferAmount() != null) {
BigDecimal originalAmount = financialMaster.getServerMoney();
BigDecimal transferAmount = request.getTransferAmount();
// 验证转单金额
if (transferAmount.compareTo(BigDecimal.ZERO) <= 0) {
return AjaxResult.error("转单金额必须大于0");
}
if (transferAmount.compareTo(originalAmount) > 0) {
return AjaxResult.error("转单金额不能超过原订单金额");
}
// 计算差价
BigDecimal differenceAmount = originalAmount.subtract(transferAmount);
// 更新主单金额
financialMaster.setServerMoney(transferAmount);
financialMaster.setMoney(transferAmount);
financialMaster.setPayMoney(transferAmount);
financialMaster.setRemark("订单转单,原金额:" + originalAmount + ",新金额:" + transferAmount);
financialMasterService.updateFinancialMaster(financialMaster);
// 如果有差价创建差额子单记录
if (differenceAmount.compareTo(BigDecimal.ZERO) > 0 && originalOrder.getWorkerId() != null) {
FinancialDetail differenceDetail = new FinancialDetail();
differenceDetail.setFinancialMasterId(financialMaster.getId());
differenceDetail.setWorkerId(originalOrder.getWorkerId()); // 原师傅
differenceDetail.setMoney(differenceAmount);
differenceDetail.setFinancialDetailType(FinancialDetailType.TRANSFER_DIFFERENCE_FEE.getCode());
differenceDetail.setRemark("转单差价,原师傅获得");
financialDetailService.insertFinancialDetail(differenceDetail);
logger.info("创建转单差价记录订单ID={}, 原师傅ID={}, 差价金额={}",
request.getOrderId(), originalOrder.getWorkerId(), differenceAmount);
}
} }
// 执行转单操作 // 执行转单操作
OrderMaster updateOrder = new OrderMaster(); OrderMaster updateOrder = new OrderMaster();
updateOrder.setId(orderMaster.getId()); updateOrder.setId(request.getOrderId());
// 保存原师傅ID到originalWorkerId字段 // 保存原师傅ID到originalWorkerId字段
if (originalOrder.getWorkerId() != null) { if (originalOrder.getWorkerId() != null) {
updateOrder.setOriginalWorkerId(originalOrder.getWorkerId()); updateOrder.setOriginalWorkerId(originalOrder.getWorkerId());
} }
// 设置新师傅ID // 设置新师傅ID可以为null表示进入接单大厅
updateOrder.setWorkerId(orderMaster.getWorkerId()); updateOrder.setWorkerId(request.getNewWorkerId());
updateOrder.setUpdateBy(getLoginName()); updateOrder.setUpdateBy(getLoginName());
// 如果有转单备注添加到原有备注中 // 构建转单备注
String newRemark = originalOrder.getRemark() != null ? originalOrder.getRemark() : ""; String newRemark = originalOrder.getRemark() != null ? originalOrder.getRemark() : "";
if (StringUtils.isNotEmpty(orderMaster.getRemark())) { String transferInfo = "【转单记录:" + getLoginName() +
newRemark += "【转单记录:" + getLoginName() + "" + DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date());
"" + DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date()) +
"转单给师傅ID:" + orderMaster.getWorkerId() + if (request.getNewWorkerId() != null) {
",备注:" + orderMaster.getRemark() + ""; transferInfo += "转单给师傅ID:" + request.getNewWorkerId();
} else { } else {
newRemark += "【转单记录:" + getLoginName() + transferInfo += "转单到接单大厅";
"" + DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date()) +
"转单给师傅ID:" + orderMaster.getWorkerId() + "";
} }
updateOrder.setRemark(newRemark);
if (request.getTransferAmount() != null) {
transferInfo += ",转单金额:" + request.getTransferAmount();
}
if (StringUtils.isNotEmpty(request.getTransferReason())) {
transferInfo += ",原因:" + request.getTransferReason();
}
transferInfo += "";
updateOrder.setRemark(newRemark + transferInfo);
int result = orderMasterService.updateOrderMaster(updateOrder); int result = orderMasterService.updateOrderMaster(updateOrder);
if (result > 0) { if (result > 0) {
// 记录转单日志 // 记录转单日志
logger.info("订单转单成功订单ID={}, 原师傅ID={}, 新师傅ID={}, 操作人={}", logger.info("订单转单成功订单ID={}, 原师傅ID={}, 新师傅ID={}, 转单金额={}, 操作人={}",
orderMaster.getId(), request.getOrderId(),
originalOrder.getWorkerId(), originalOrder.getWorkerId(),
orderMaster.getWorkerId(), request.getNewWorkerId(),
request.getTransferAmount(),
getLoginName()); getLoginName());
String message = String.format("转单成功!订单已从师傅[%s]转给师傅[%s]", String message;
originalOrder.getWorkerId() != null ? originalOrder.getWorkerId() : "", if (request.getNewWorkerId() != null) {
newWorker.getName()); message = String.format("转单成功!订单已从师傅[%s]转给师傅[%s]",
originalOrder.getWorkerId() != null ? originalOrder.getWorkerId() : "",
newWorker.getName());
} else {
message = "转单成功!订单已转入接单大厅";
}
if (request.getTransferAmount() != null) {
message += ",转单金额:" + request.getTransferAmount();
}
return AjaxResult.success(message); return AjaxResult.success(message);
} else { } else {
return AjaxResult.error("转单失败,请重试"); return AjaxResult.error("转单失败,请重试");

View File

@ -145,3 +145,14 @@ aliyun:
accessSecret: EV4dzWRfKTQaPRjf3tFziMuVBCsThU accessSecret: EV4dzWRfKTQaPRjf3tFziMuVBCsThU
endpoint: dytnsapi.aliyuncs.com endpoint: dytnsapi.aliyuncs.com
authCode: od2FgE9a9g authCode: od2FgE9a9g
# 物流API配置
logistics:
kdniao:
# 快递鸟 API配置
appId: '1889454' # 快递鸟应用ID需要到快递鸟官网申请
appKey: 'b2483529-807d-49af-b0e1-1ed218baa4db' # 快递鸟API密钥需要到快递鸟官网申请
url: 'https://api.kdniao.com/api/dist' # 快递鸟即时查询接口地址
# 快递鸟支持两种接口:
# 1. 即时查询接口https://api.kdniao.com/api/dist
# 2. 物流跟踪接口https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx

View File

@ -13,7 +13,8 @@ public enum FinancialDetailType {
PLACE_FEE(3, "分销金额,可能存在多级"), PLACE_FEE(3, "分销金额,可能存在多级"),
RETURN_FEE(4, "退款金额"), RETURN_FEE(4, "退款金额"),
FINE_FEE(5, "超时罚金"), FINE_FEE(5, "超时罚金"),
COMMISSION_FEE(6,"手续费"); COMMISSION_FEE(6,"手续费"),
TRANSFER_DIFFERENCE_FEE(7, "转单差价");
private final Integer code; private final Integer code;
private final String desc; private final String desc;

View File

@ -0,0 +1,90 @@
package com.ghy.order.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 物流信息实体类
*
* @author clunt
*/
@Data
public class LogisticsInfo {
/**
* 快递单号
*/
private String trackingNumber;
/**
* 快递公司编码
*/
private String expressCode;
/**
* 快递公司名称
*/
private String expressName;
/**
* 物流状态0=在途1=揽收2=疑难3=签收4=退签5=派件6=退回
*/
private Integer status;
/**
* 物流状态描述
*/
private String statusDesc;
/**
* 物流轨迹信息
*/
private List<LogisticsTrace> traces;
/**
* 查询时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date queryTime;
/**
* 是否查询成功
*/
private Boolean success;
/**
* 错误信息
*/
private String errorMsg;
/**
* 物流轨迹详情
*/
@Data
public static class LogisticsTrace {
/**
* 时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date time;
/**
* 地点
*/
private String location;
/**
* 描述
*/
private String description;
/**
* 状态
*/
private String status;
}
}

View File

@ -0,0 +1,30 @@
package com.ghy.order.request;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 物流查询请求类
*
* @author clunt
*/
@Data
public class LogisticsQueryRequest {
/**
* 快递单号
*/
@NotBlank(message = "快递单号不能为空")
private String trackingNumber;
/**
* 快递公司编码可选如果不传会自动识别
*/
private String expressCode;
/**
* 快递公司名称可选如果不传会自动识别
*/
private String expressName;
}

View File

@ -0,0 +1,36 @@
package com.ghy.order.request;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* 转单请求类
*
* @author clunt
*/
@Data
public class TransferOrderRequest {
/**
* 订单ID
*/
@NotNull(message = "订单ID不能为空")
private Long orderId;
/**
* 新师傅ID可以为null表示进入接单大厅
*/
private Long newWorkerId;
/**
* 转单金额新师傅承担可以为null表示无转单金额
*/
private BigDecimal transferAmount;
/**
* 转单原因
*/
private String transferReason;
}

View File

@ -0,0 +1,45 @@
package com.ghy.order.service;
import com.ghy.order.domain.LogisticsInfo;
import com.ghy.order.request.LogisticsQueryRequest;
/**
* 物流服务接口
*
* @author clunt
*/
public interface LogisticsService {
/**
* 根据快递单号查询物流信息
*
* @param request 物流查询请求
* @return 物流信息
*/
LogisticsInfo queryLogistics(LogisticsQueryRequest request);
/**
* 根据快递单号查询物流信息
*
* @param trackingNumber 快递单号
* @return 物流信息
*/
LogisticsInfo queryLogistics(String trackingNumber);
/**
* 根据快递单号和快递公司编码查询物流信息
*
* @param trackingNumber 快递单号
* @param expressCode 快递公司编码
* @return 物流信息
*/
LogisticsInfo queryLogistics(String trackingNumber, String expressCode);
/**
* 根据订单ID查询物流信息
*
* @param orderId 订单ID
* @return 物流信息
*/
LogisticsInfo queryLogisticsByOrderId(Long orderId);
}

View File

@ -0,0 +1,246 @@
package com.ghy.order.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ghy.order.domain.LogisticsInfo;
import com.ghy.order.domain.OrderMaster;
import com.ghy.order.request.LogisticsQueryRequest;
import com.ghy.order.service.LogisticsService;
import com.ghy.order.service.OrderMasterService;
import com.ghy.order.utils.LogisticsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
/**
* 物流服务实现类
*
* @author clunt
*/
@Slf4j
@Service
public class LogisticsServiceImpl implements LogisticsService {
@Autowired
private OrderMasterService orderMasterService;
/**
* 快递鸟 API配置
*/
@Value("${logistics.kdniao.appId:}")
private String appId;
@Value("${logistics.kdniao.appKey:}")
private String appKey;
@Value("${logistics.kdniao.url:https://api.kdniao.com/api/dist}")
private String apiUrl;
@Override
public LogisticsInfo queryLogistics(LogisticsQueryRequest request) {
return queryLogistics(request.getTrackingNumber(), request.getExpressCode());
}
@Override
public LogisticsInfo queryLogistics(String trackingNumber) {
return queryLogistics(trackingNumber, null);
}
@Override
public LogisticsInfo queryLogistics(String trackingNumber, String expressCode) {
LogisticsInfo logisticsInfo = new LogisticsInfo();
logisticsInfo.setTrackingNumber(trackingNumber);
logisticsInfo.setQueryTime(new Date());
try {
// 验证快递单号格式
if (!LogisticsUtils.isValidTrackingNumber(trackingNumber)) {
logisticsInfo.setSuccess(false);
logisticsInfo.setErrorMsg("快递单号格式不正确");
return logisticsInfo;
}
// 如果没有指定快递公司先识别快递公司
if (StrUtil.isBlank(expressCode)) {
expressCode = LogisticsUtils.identifyExpressCompany(trackingNumber);
}
// 调用快递鸟 API查询物流信息
JSONObject result = callKdniaoAPI(trackingNumber, expressCode);
if (result.getBool("Success", false)) {
// 查询成功
logisticsInfo.setSuccess(true);
logisticsInfo.setExpressCode(expressCode);
logisticsInfo.setExpressName(result.getStr("ShipperName"));
logisticsInfo.setStatus(getKdniaoStatus(result.getStr("State")));
logisticsInfo.setStatusDesc(result.getStr("State"));
// 解析物流轨迹
List<LogisticsInfo.LogisticsTrace> traces = new ArrayList<>();
JSONArray tracesArray = result.getJSONArray("Traces");
if (tracesArray != null) {
for (int i = 0; i < tracesArray.size(); i++) {
JSONObject trace = tracesArray.getJSONObject(i);
LogisticsInfo.LogisticsTrace logisticsTrace = new LogisticsInfo.LogisticsTrace();
logisticsTrace.setTime(trace.getDate("AcceptTime"));
logisticsTrace.setLocation(trace.getStr("AcceptStation"));
logisticsTrace.setDescription(trace.getStr("AcceptStation"));
logisticsTrace.setStatus(trace.getStr("Remark"));
traces.add(logisticsTrace);
}
}
logisticsInfo.setTraces(traces);
} else {
// 查询失败
logisticsInfo.setSuccess(false);
logisticsInfo.setErrorMsg(result.getStr("Reason", "查询失败"));
}
} catch (Exception e) {
log.error("查询物流信息失败,快递单号:{},错误:{}", trackingNumber, e.getMessage(), e);
logisticsInfo.setSuccess(false);
logisticsInfo.setErrorMsg("查询物流信息失败:" + e.getMessage());
}
return logisticsInfo;
}
@Override
public LogisticsInfo queryLogisticsByOrderId(Long orderId) {
OrderMaster orderMaster = orderMasterService.selectById(orderId);
if (orderMaster == null || StrUtil.isBlank(orderMaster.getTrackingNumber())) {
LogisticsInfo logisticsInfo = new LogisticsInfo();
logisticsInfo.setSuccess(false);
logisticsInfo.setErrorMsg("订单不存在或没有快递单号");
return logisticsInfo;
}
return queryLogistics(orderMaster.getTrackingNumber());
}
/**
* 调用快递鸟 API
*
* @param trackingNumber 快递单号
* @param expressCode 快递公司编码
* @return API返回结果
*/
private JSONObject callKdniaoAPI(String trackingNumber, String expressCode) {
try {
// 构建请求数据
JSONObject requestData = new JSONObject();
requestData.set("ShipperCode", expressCode);
requestData.set("LogisticCode", trackingNumber);
String requestDataStr = requestData.toString();
// 计算数据签名 - 按照快递鸟官方文档
// S1: RequestData(未编码) + ApiKey
String s1 = requestDataStr + appKey;
log.info("S1: {}", s1);
// S2: MD5加密32位小写
String s2 = cn.hutool.crypto.digest.DigestUtil.md5Hex(s1);
log.info("S2: {}", s2);
// S3: Base64编码
String s3 = java.util.Base64.getEncoder().encodeToString(s2.getBytes("UTF-8"));
log.info("S3: {}", s3);
// S4: URL编码仅请求接口需要
String s4 = java.net.URLEncoder.encode(s3, "UTF-8");
log.info("S4: {}", s4);
// 构建请求参数 - 即时查询接口使用GET请求
Map<String, Object> requestParam = new HashMap<>();
requestParam.put("RequestData", requestDataStr);
requestParam.put("EBusinessID", appId);
requestParam.put("RequestType", "8002"); // 即时查询接口
requestParam.put("DataSign", s4); // 使用URL编码后的签名
requestParam.put("DataType", "2"); // JSON格式
log.info("快递鸟API请求参数: {}", requestParam.toString());
// 使用GET请求调用即时查询接口
String result = HttpUtil.get(apiUrl, requestParam);
log.info("快递鸟API响应结果: {}", result);
return JSONUtil.parseObj(result);
} catch (Exception e) {
log.error("调用快递鸟API失败: {}", e.getMessage(), e);
JSONObject errorResult = new JSONObject();
errorResult.set("Success", false);
errorResult.set("Reason", "API调用失败: " + e.getMessage());
return errorResult;
}
}
/**
* 将快递鸟状态转换为系统状态码
*
* @param kdniaoStatus 快递鸟状态
* @return 系统状态码
*/
private Integer getKdniaoStatus(String kdniaoStatus) {
if (StrUtil.isBlank(kdniaoStatus)) {
return 0;
}
switch (kdniaoStatus) {
case "在途":
return 0;
case "揽收":
return 1;
case "疑难":
return 2;
case "签收":
return 3;
case "退签":
return 4;
case "派件":
return 5;
case "退回":
return 6;
default:
return 0;
}
}
/**
* 获取状态描述
*
* @param status 状态码
* @return 状态描述
*/
private String getStatusDesc(Integer status) {
switch (status) {
case 0:
return "在途";
case 1:
return "揽收";
case 2:
return "疑难";
case 3:
return "签收";
case 4:
return "退签";
case 5:
return "派件";
case 6:
return "退回";
default:
return "未知";
}
}
}

View File

@ -0,0 +1,188 @@
package com.ghy.order.utils;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
/**
* 物流查询工具类
*
* @author clunt
*/
public class LogisticsUtils {
/**
* 快递公司编码映射快递鸟格式
*/
private static final Map<String, String> EXPRESS_COMPANY_MAP = new HashMap<>();
static {
// 顺丰速运
EXPRESS_COMPANY_MAP.put("SF", "SF");
EXPRESS_COMPANY_MAP.put("顺丰", "SF");
EXPRESS_COMPANY_MAP.put("顺丰速运", "SF");
// 圆通速递
EXPRESS_COMPANY_MAP.put("YTO", "YTO");
EXPRESS_COMPANY_MAP.put("圆通", "YTO");
EXPRESS_COMPANY_MAP.put("圆通速递", "YTO");
// 中通快递
EXPRESS_COMPANY_MAP.put("ZTO", "ZTO");
EXPRESS_COMPANY_MAP.put("中通", "ZTO");
EXPRESS_COMPANY_MAP.put("中通快递", "ZTO");
// 申通快递
EXPRESS_COMPANY_MAP.put("STO", "STO");
EXPRESS_COMPANY_MAP.put("申通", "STO");
EXPRESS_COMPANY_MAP.put("申通快递", "STO");
// 韵达速递
EXPRESS_COMPANY_MAP.put("YD", "YD");
EXPRESS_COMPANY_MAP.put("韵达", "YD");
EXPRESS_COMPANY_MAP.put("韵达速递", "YD");
// 百世快递
EXPRESS_COMPANY_MAP.put("HTKY", "HTKY");
EXPRESS_COMPANY_MAP.put("百世", "HTKY");
EXPRESS_COMPANY_MAP.put("百世快递", "HTKY");
// 德邦快递
EXPRESS_COMPANY_MAP.put("DBL", "DBL");
EXPRESS_COMPANY_MAP.put("德邦", "DBL");
EXPRESS_COMPANY_MAP.put("德邦快递", "DBL");
// 京东物流
EXPRESS_COMPANY_MAP.put("JD", "JD");
EXPRESS_COMPANY_MAP.put("京东", "JD");
EXPRESS_COMPANY_MAP.put("京东物流", "JD");
// EMS
EXPRESS_COMPANY_MAP.put("EMS", "EMS");
EXPRESS_COMPANY_MAP.put("中国邮政", "EMS");
EXPRESS_COMPANY_MAP.put("邮政", "EMS");
// 天天快递
EXPRESS_COMPANY_MAP.put("TTKDEX", "TTKDEX");
EXPRESS_COMPANY_MAP.put("天天", "TTKDEX");
EXPRESS_COMPANY_MAP.put("天天快递", "TTKDEX");
// 优速快递
EXPRESS_COMPANY_MAP.put("UC", "UC");
EXPRESS_COMPANY_MAP.put("优速", "UC");
EXPRESS_COMPANY_MAP.put("优速快递", "UC");
// 全峰快递
EXPRESS_COMPANY_MAP.put("QFKD", "QFKD");
EXPRESS_COMPANY_MAP.put("全峰", "QFKD");
EXPRESS_COMPANY_MAP.put("全峰快递", "QFKD");
}
/**
* 根据快递单号识别快递公司快递鸟格式
*
* @param trackingNumber 快递单号
* @return 快递公司编码
*/
public static String identifyExpressCompany(String trackingNumber) {
if (trackingNumber == null || trackingNumber.trim().isEmpty()) {
return null;
}
String number = trackingNumber.trim().toUpperCase();
// 顺丰速运以SF开头13位数字
if (Pattern.matches("^SF\\d{13}$", number)) {
return "SF";
}
// 圆通速递以YT开头10位数字
if (Pattern.matches("^YT\\d{10}$", number)) {
return "YTO";
}
// 中通快递以ZTO开头10位数字
if (Pattern.matches("^ZTO\\d{10}$", number)) {
return "ZTO";
}
// 申通快递以STO开头10位数字
if (Pattern.matches("^STO\\d{10}$", number)) {
return "STO";
}
// 韵达速递以YD开头10位数字
if (Pattern.matches("^YD\\d{10}$", number)) {
return "YD";
}
// 百世快递以HTKY开头10位数字
if (Pattern.matches("^HTKY\\d{10}$", number)) {
return "HTKY";
}
// 德邦快递以DBL开头10位数字
if (Pattern.matches("^DBL\\d{10}$", number)) {
return "DBL";
}
// 京东物流以JD开头10位数字
if (Pattern.matches("^JD\\d{13}$", number)) {
return "JD";
}
// EMS以EMS开头13位数字
if (Pattern.matches("^EMS\\d{13}$", number)) {
return "EMS";
}
// 天天快递以TT开头10位数字
if (Pattern.matches("^TT\\d{10}$", number)) {
return "TTKDEX";
}
// 优速快递以UC开头10位数字
if (Pattern.matches("^UC\\d{10}$", number)) {
return "UC";
}
// 纯数字单号可能是其他快递公司
if (Pattern.matches("^\\d{10,15}$", number)) {
// 这里可以根据数字规则进一步识别暂时返回null让API自动识别
return null;
}
return null;
}
/**
* 根据快递公司名称获取编码快递鸟格式
*
* @param companyName 快递公司名称
* @return 快递公司编码
*/
public static String getExpressCode(String companyName) {
if (companyName == null || companyName.trim().isEmpty()) {
return null;
}
return EXPRESS_COMPANY_MAP.get(companyName.trim());
}
/**
* 验证快递单号格式
*
* @param trackingNumber 快递单号
* @return 是否有效
*/
public static boolean isValidTrackingNumber(String trackingNumber) {
if (trackingNumber == null || trackingNumber.trim().isEmpty()) {
return false;
}
String number = trackingNumber.trim();
// 基本格式验证长度在10-20位之间包含字母和数字
return Pattern.matches("^[A-Za-z0-9]{10,20}$", number);
}
}

View File

@ -1460,7 +1460,7 @@ public class OrderServiceImpl implements OrderService {
} }
// 检查是否到达目标时间 // 检查是否到达目标时间
if (now.after(targetTime)) { if (now.after(targetTime)&&orderMaster.getPayStatus()==1) {
log.info("订单[{}]确认截止时间已到,开始转为确认中状态", orderDetail.getCode()); log.info("订单[{}]确认截止时间已到,开始转为确认中状态", orderDetail.getCode());
orderDetail.setWorkFinishTime(new Date()); orderDetail.setWorkFinishTime(new Date());
orderDetailService.updateOrderDetail(orderDetail); orderDetailService.updateOrderDetail(orderDetail);