From 90b805d0f49f0b662de32bde1ab32371bcb4b49b Mon Sep 17 00:00:00 2001 From: tzy Date: Fri, 18 Apr 2025 14:09:04 +0800 Subject: [PATCH] =?UTF-8?q?fix(cloud):=20=E4=BC=98=E5=8C=96=E9=A2=84?= =?UTF-8?q?=E7=BA=A6=E5=8D=95=E8=BF=87=E6=9C=9F=E5=A4=84=E7=90=86=E5=92=8C?= =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E6=94=AF=E4=BB=98=E5=9B=9E=E8=B0=83=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加费标准详情字段并实现相关查询逻辑 - 优化预约单过期处理逻辑,增加缓冲期和精确的时间判断 - 完善微信支付回调处理,增加参数校验和幂等性检查 - 添加支付成功通知功能 --- .../core/entity/cloud/OrderSwapBattery.java | 4 + .../impl/OrderSwapBatteryServiceImpl.java | 17 ++++- .../cloud/service/impl/TradeServiceImpl.java | 71 +++++++++++++----- .../hd/cloud/task/OrderSwapBatteryTask.java | 73 +++++++++++++------ .../src/main/resources/application.yml | 4 +- 5 files changed, 122 insertions(+), 47 deletions(-) diff --git a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBattery.java b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBattery.java index a25bb20..e03217c 100644 --- a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBattery.java +++ b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBattery.java @@ -1,6 +1,7 @@ package com.evotech.hd.common.core.entity.cloud; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.evotech.hd.common.core.entity.BaseEntity; @@ -96,6 +97,9 @@ public class OrderSwapBattery extends BaseEntity implements Serializable { @Schema(description = "费用标准") private String feeStandardJson; + @Schema(description = "费用标准详情") + @TableField(exist = false) + private BatteryStationHdFeeStandard feeStandardDetail; @Schema(description = "上次租赁电池时车辆里程") private BigDecimal lastRentBatCarOdo; diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/OrderSwapBatteryServiceImpl.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/OrderSwapBatteryServiceImpl.java index a3390fa..bd517e3 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/OrderSwapBatteryServiceImpl.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/OrderSwapBatteryServiceImpl.java @@ -53,6 +53,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; + @Slf4j @Service public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService { @@ -87,6 +89,8 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService { private BatteryStationDao batteryStationDao; @Resource private GZHTemplateMessageService gzhTemplateMessageService; + @Resource + private BatteryStationHdFeeStandardDao batteryStationHdFeeStandardDao; @Override @@ -247,8 +251,17 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService { if (page.getRecords().isEmpty()) { return new Result>().error(CodeMsg.DATABASE_RESULT_NULL); } - return new Result>().success(page); - } + page.getRecords().forEach(osb -> { + if (StringUtils.hasText(osb.getFeeStandardJson())){ + String feeStandardJson = osb.getFeeStandardJson(); + BatteryStationHdFeeStandard bean = JSONUtil.toBean(feeStandardJson, BatteryStationHdFeeStandard.class); + osb.setFeeStandardDetail(bean); + } + + }); + + return new Result>().success(page); + } @Override public Result> listByCompany(PageListSwapOrderRequest plsor) { diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/TradeServiceImpl.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/TradeServiceImpl.java index f70a184..2497504 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/TradeServiceImpl.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/TradeServiceImpl.java @@ -86,28 +86,59 @@ public class TradeServiceImpl implements TradeService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public Result wechatPayNotifyHandle(TradeDetail tradeDetail) { - // 1. 添加交易 - boolean b = tradeDetailDao.exists(new QueryWrapper() - .eq("out_trade_no", tradeDetail.getOutTradeNo()) - .eq("transaction_id", tradeDetail.getTransactionId()) - .eq("pay_result", tradeDetail.getPayResult())); - if (b) { - log.info("\r\n===>>>已处理过此回调:" + tradeDetail); - return new Result().error("重复消息!"); + try { + // 1. 参数校验 + if (tradeDetail == null || !StringUtils.hasText(tradeDetail.getOutTradeNo())) { + log.error("微信支付回调参数异常: {}", JSONUtil.toJsonStr(tradeDetail)); + return new Result().error("参数异常"); + } + + // 2. 幂等性检查 + boolean isProcessed = tradeDetailDao.exists(new QueryWrapper() + .eq("out_trade_no", tradeDetail.getOutTradeNo()) + .eq("transaction_id", tradeDetail.getTransactionId()) + .eq("pay_result", tradeDetail.getPayResult())); + + if (isProcessed) { + log.info("重复的微信支付回调, outTradeNo: {}", tradeDetail.getOutTradeNo()); + return new Result().error("重复消息"); + } + + // 3. 记录交易 + log.info("开始处理微信支付回调, outTradeNo: {}, 交易信息: {}", + tradeDetail.getOutTradeNo(), + JSONUtil.toJsonStr(tradeDetail)); + + add(tradeDetail); + + // 4. 业务处理 + payNotifyHandleService.payNotifyBussinessHandle(tradeDetail); + + // 5. 发送支付成功通知 + if (StringUtils.hasText(tradeDetail.getOrderNo())) { + OrderSwapBattery order = orderSwapBatteryDao.selectOne( + new LambdaQueryWrapper() + .eq(OrderSwapBattery::getOrderNo, tradeDetail.getOrderNo()) + ); + + if (order != null) { + gzhTemplateMessageService.orderMessageSend2(order.getPkId(), 3); + log.info("支付成功通知已发送, orderNo: {}", tradeDetail.getOrderNo()); + } else { + log.warn("未找到对应的订单, orderNo: {}", tradeDetail.getOrderNo()); + } + } + + return new Result().success("OK"); + } catch (Exception e) { + log.error("处理微信支付回调异常, outTradeNo: {}, 异常信息: {}", + tradeDetail.getOutTradeNo(), + e.getMessage(), + e); + throw new RuntimeException("处理支付回调失败", e); } - - // 添加交易 - log.info("请求时间{} 是否存在交易{} 添加交易>>>>>{}" ,new Date() ,b, JSONUtil.toJsonStr(tradeDetail)); - add(tradeDetail); - // 2. 业务类型处理 - payNotifyHandleService.payNotifyBussinessHandle(tradeDetail); - - return new Result().success("OK"); } - - - } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/task/OrderSwapBatteryTask.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/task/OrderSwapBatteryTask.java index 450e04b..604ddf5 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/task/OrderSwapBatteryTask.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/task/OrderSwapBatteryTask.java @@ -3,6 +3,7 @@ package com.evotech.hd.cloud.task; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUnit; import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.evotech.hd.cloud.dao.OrderSwapBatteryPreDao; import com.evotech.hd.cloud.service.OrderSwapBatteryService; @@ -16,6 +17,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.Date; @@ -32,37 +34,62 @@ public class OrderSwapBatteryTask { @Resource private RedisUtil redisUtil; - @Scheduled(cron = "0 0 * * * ?") // 每小时执行一次 + // @Scheduled(cron = "0 0 * * * ?") // 每小时执行一次 + @Scheduled(cron = "0 */2 * * * ?") + @Transactional(rollbackFor = Exception.class) public void orderSwapBatteryExpired() { log.info("\r\n===>>> 开始查找预约单更新预约状态.."); - // 查询条件,排除已过期和无效状态 - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper - .ne("status", 4)//无效 - .ne("status", 3) //过期 - .ne("status", 2); //过期 - + // 查询条件,只查询未处理的预约单 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq( OrderSwapBatteryPre::getStatus,1) + .le( OrderSwapBatteryPre::getReservationTime, new Date()) + .select(OrderSwapBatteryPre::getPkId, + OrderSwapBatteryPre::getSourceId, + OrderSwapBatteryPre::getReservationTime, + OrderSwapBatteryPre::getSwapDuration, + OrderSwapBatteryPre::getStatus) + .orderByDesc(OrderSwapBatteryPre::getReservationTime) + .last("limit 1000"); List orderSwapBatteryPreList = orderSwapBatteryPreDao.selectList(queryWrapper); - - // 获取当前时间 Date currentTime = new Date(); - int expiredCount = 0; // 记录过期的预约单数量 + int expiredCount = 0; for (OrderSwapBatteryPre order : orderSwapBatteryPreList) { - // 检查预约时间是否已过期 - if (order.getReservationTime() != null && order.getReservationTime().before(currentTime)) { - // 更新状态为过期 - order.setStatus(4); // 设置为过期状态 - try { - orderSwapBatteryPreDao.updateById(order); - //发送公众号过期提醒 - //templateMessageService.orderMessageSend(order, 4); - expiredCount++; - log.info("预约单已过期,订单ID: {}", order.getSourceId()); // 记录过期的订单ID - } catch (Exception e) { - log.error("更新预约单状态失败,预约人:{},订单ID: {}, 错误信息: {}", order.getUname(), order.getPkId(), e.getMessage()); + try { + // 1. 解析预约时间段 + String[] timeRange = order.getSwapDuration().split("-"); + if (timeRange.length != 2) { + log.error("预约时间段格式错误,订单ID: {}", order.getPkId()); + continue; } + + // 2. 计算预约结束时间 + Date reservationDate = order.getReservationTime(); + String endTimeStr = timeRange[1].trim(); + Date endTime = DateUtil.parse(DateUtil.format(reservationDate, "yyyy-MM-dd") + " " + endTimeStr, + "yyyy-MM-dd HH:mm"); + + // 3. 添加30分钟缓冲期 + Date expireTime = DateUtil.offsetMinute(endTime, 30); + + // 4. 判断是否过期 + if (currentTime.after(expireTime)) { + order.setStatus(4); // 设置为过期状态 + orderSwapBatteryPreDao.updateById(order); + + // 发送公众号过期提醒 + // templateMessageService.preOrderMessageSend(order); + + expiredCount++; + log.info("预约单已过期,订单ID: {}, 预约时间: {}, 过期时间: {}", + order.getSourceId(), + DateUtil.format(order.getReservationTime(), "yyyy-MM-dd HH:mm:ss"), + DateUtil.format(expireTime, "yyyy-MM-dd HH:mm:ss")); + } + } catch (Exception e) { + log.error("处理预约单过期失败,预约人:{},订单ID: {}, 错误信息: {}", + order.getUname(), order.getPkId(), e.getMessage()); } } diff --git a/wechat-server/src/main/resources/application.yml b/wechat-server/src/main/resources/application.yml index 79d22fa..70479f7 100644 --- a/wechat-server/src/main/resources/application.yml +++ b/wechat-server/src/main/resources/application.yml @@ -123,5 +123,5 @@ hbyt: order_swap_end_template_id: wGll5W3NSHXkHjcEprjUbd1shigGOqywGX7A0BVnzUs order_to_pay_template_id: IE0_RGuN5ufU4GFrCgM9JeUfvlWfbneEuUMDsn0RBQs order_end_template_id: C5-AGh67aFXChQONqSwxaRrJgFrn_Z25VTlTk0jHSUY - wallet_recharge_template_id: 8JXsn_VkI0S0YZSbT2EKmV_zOxyudo4IsBLeU7V-SFk - \ No newline at end of file + wallet_recharge_template_id: 8JXsn_VkI0S0YZSbT2EKmV_zOxyudo4IsBLeU7V-SFk + order_to_pay_template_id2: K6cdaBOkxGJpah0vsz5rq5UBID04mk-eEWp2XM0KyA0 \ No newline at end of file