From 976ff3fe092ee2f9515013dbfab77d25b2944b75 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期三, 14 十月 2026 11:18:29 +0800
Subject: [PATCH] 修改bug
---
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java | 179 +++++++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 137 insertions(+), 42 deletions(-)
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
index eaeb5b5..80c4878 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -1936,13 +1936,7 @@
chargingOrder.setPayTime(callbackPayTime);
//添加安全检测数据到缓存中,每步安全检测完成后需要更新缓存数据
- PreChargeCheck preChargeCheck = new PreChargeCheck();
- preChargeCheck.setElectronicLockLock(false);
- preChargeCheck.setInsulationTesting(false);
- preChargeCheck.setSecureConnectionDetection(false);
- preChargeCheck.setStartupSuccess(1);
- preChargeCheck.setStartCommandSent(false);
- preChargeCheck.setAddTime(chargingOrder.getReservationTime() != null ? chargingOrder.getReservationTime() : LocalDateTime.now());
+ PreChargeCheck preChargeCheck = newPreChargeCheck(chargingOrder);
String key = "AQJC_" + chargingOrder.getChargingGunId();
redisService.setCacheObject(key, preChargeCheck, 24L, TimeUnit.HOURS);
@@ -2082,6 +2076,33 @@
&& Boolean.TRUE.equals(check.getSecureConnectionDetection());
}
+ /**
+ * 查询充电枪进行中的待启动订单(支付完成、启动中)
+ */
+ private TChargingOrder getPendingStartOrder(Integer chargingGunId) {
+ return this.getOne(new LambdaQueryWrapper<TChargingOrder>()
+ .eq(TChargingOrder::getChargingGunId, chargingGunId)
+ .eq(TChargingOrder::getRechargePaymentStatus, 2)
+ .eq(TChargingOrder::getStatus, 2)
+ .eq(TChargingOrder::getDelFlag, 0)
+ .orderByDesc(TChargingOrder::getCreateTime)
+ .last("limit 1"));
+ }
+
+ /**
+ * 初始化安全检测等待对象(与建单/支付完成时的初始状态保持一致)
+ */
+ private PreChargeCheck newPreChargeCheck(TChargingOrder chargingOrder) {
+ PreChargeCheck preChargeCheck = new PreChargeCheck();
+ preChargeCheck.setElectronicLockLock(false);
+ preChargeCheck.setInsulationTesting(false);
+ preChargeCheck.setSecureConnectionDetection(false);
+ preChargeCheck.setStartupSuccess(1);
+ preChargeCheck.setStartCommandSent(false);
+ preChargeCheck.setAddTime(chargingOrder.getReservationTime() != null ? chargingOrder.getReservationTime() : LocalDateTime.now());
+ return preChargeCheck;
+ }
+
private String normalizeVin(String vin) {
return StringUtils.hasLength(vin) ? vin.replaceAll("\\s+", "").toUpperCase(Locale.ROOT) : null;
}
@@ -2119,6 +2140,44 @@
}
}
+ /**
+ * 启动超时兜底:订单支付完成后长时间未真正开始充电(等待安全检测无进展、启动指令未生效),
+ * 自动取消订单并释放锁定额度,避免订单永久停留在「启动中」导致该枪无法再次启动。
+ */
+ @Scheduled(fixedDelay = 30000L)
+ public void cancelStartupTimeoutOrders() {
+ LocalDateTime deadline = LocalDateTime.now().minusMinutes(3);
+ List<TChargingOrder> timeoutOrders = this.list(new LambdaQueryWrapper<TChargingOrder>()
+ .eq(TChargingOrder::getRechargePaymentStatus, 2)
+ .eq(TChargingOrder::getStatus, 2)
+ .eq(TChargingOrder::getDelFlag, 0)
+ .isNull(TChargingOrder::getStartTime)
+ .isNull(TChargingOrder::getReservationTime)
+ .lt(TChargingOrder::getPayTime, deadline)
+ .last("limit 100"));
+ for (TChargingOrder order : timeoutOrders) {
+ try {
+ PreChargeCheck check = redisService.getCacheObject("AQJC_" + order.getChargingGunId());
+ if (null != check && Boolean.TRUE.equals(check.getStartCommandSent())) {
+ // 已下发启动指令,交给既有启动结果检测(timingDetection)处理,避免误取消
+ continue;
+ }
+ log.warn("订单编号={}:等待安全检测超时,自动取消订单并释放额度,充电枪id={}", order.getCode(), order.getChargingGunId());
+ refund(order.getCode());
+ TChargingOrder finish = new TChargingOrder();
+ finish.setId(order.getId());
+ finish.setAppUserId(order.getAppUserId());
+ finish.setStatus(5);
+ finish.setEndMode(0);
+ finish.setEndTime(LocalDateTime.now());
+ this.updateById(finish);
+ redisService.deleteObject("AQJC_" + order.getChargingGunId());
+ } catch (Exception e) {
+ log.error("启动超时订单自动取消失败,orderCode={}", order.getCode(), e);
+ }
+ }
+ }
+
private void startChargingAfterSafety(TChargingOrder chargingOrder, PreChargeCheck check) {
RLock lock = redissonClient.getLock("START_AFTER_SAFETY:" + chargingOrder.getId());
try {
@@ -2152,12 +2211,18 @@
command.setCharging_gun_code(gun.getCode());
command.setCard_number(latest.getId().toString());
command.setAccount_balance(latest.getChargeAmount());
- check.setStartCommandSent(true);
latest.setActualVin(actualVin);
this.updateById(latest);
- redisService.setCacheObject("AQJC_" + latest.getChargingGunId(), check, 24L, TimeUnit.HOURS);
log.info(latest.getCode() + ":安全检测及VIN校验通过,下发启动充电命令:" + command);
- sendMessageClient.platformStartCharging(command);
+ try {
+ sendMessageClient.platformStartCharging(command);
+ } catch (Exception e) {
+ // 下发失败不置 startCommandSent:保留后续安全检测上报重试机会,超时订单由兜底任务取消
+ log.error(latest.getCode() + ":启动充电命令下发失败,等待下次安全检测上报重试", e);
+ return;
+ }
+ check.setStartCommandSent(true);
+ redisService.setCacheObject("AQJC_" + latest.getChargingGunId(), check, 24L, TimeUnit.HOURS);
ScheduledExecutorService resultScheduler = Executors.newScheduledThreadPool(1);
resultScheduler.scheduleAtFixedRate(() -> {
if (timingDetection(latest.getId())) {
@@ -2196,8 +2261,13 @@
Integer failure_cause = platformStartChargingReply.getFailure_cause();
Integer counter = counter_map.get(code);
PreChargeCheck preChargeCheck1 = redisService.getCacheObject(key);
- //15分钟内还未插枪则取消充电,退回金额。
- if (failure_cause == 5 && (null == counter || counter < 60 * 15)) {
+ if (null == preChargeCheck1) {
+ // 缓存缺失时用临时对象推进,避免启动结果补偿因空缓存中断
+ preChargeCheck1 = new PreChargeCheck();
+ preChargeCheck1.setStartupSuccess(1);
+ }
+ //15分钟内还未插枪则取消充电,退回金额。按10秒探测一次,90次约15分钟
+ if (failure_cause == 5 && (null == counter || counter < 90)) {
counter = (null == counter ? 0 : counter) + 1;
counter_map.put(code, counter);
//启动失败
@@ -2248,6 +2318,11 @@
return true;
} else {
PreChargeCheck preChargeCheck1 = redisService.getCacheObject(key);
+ if (null == preChargeCheck1) {
+ // 缓存缺失时用临时对象推进,避免启动结果补偿因空缓存中断
+ preChargeCheck1 = new PreChargeCheck();
+ preChargeCheck1.setStartupSuccess(1);
+ }
UploadRealTimeMonitoringData uploadRealTimeMonitoringData = uploadRealTimeMonitoringDataService.getDataByOrderCode(code, "desc");
if (null != uploadRealTimeMonitoringData) {
//启动成功
@@ -2279,8 +2354,8 @@
} else {
Integer counter = boot_failed_map.get(code);
log.info(code + ":-------------------未上传开启充电结果-------------------" + counter);
- //15分钟内未启动成功,退回金额。
- if (null == counter || counter < 60 * 15) {
+ //15分钟内未启动成功,退回金额。按10秒探测一次,90次约15分钟
+ if (null == counter || counter < 90) {
counter = (null == counter ? 0 : counter) + 1;
boot_failed_map.put(code, counter);
//启动失败
@@ -2332,25 +2407,43 @@
GetChargingGunByCode code = new GetChargingGunByCode();
code.setCharging_pile_code(securityDetection.getCharging_pile_code());
code.setCharging_gun_code(securityDetection.getCharging_gun_code());
- TChargingGun chargingGun = chargingGunClient.getChargingGunByCode(code).getData();
- PreChargeCheck preChargeCheck1 = redisService.getCacheObject("AQJC_" + chargingGun.getId());
- if (null != preChargeCheck1) {
- preChargeCheck1.setElectronicLockLock(Integer.valueOf(1).equals(securityDetection.getElectronic_lock_lock()));
- preChargeCheck1.setInsulationTesting(Integer.valueOf(0).equals(securityDetection.getNsulation_detection()));
- preChargeCheck1.setSecureConnectionDetection(Integer.valueOf(1).equals(securityDetection.getSecure_connection()));
- preChargeCheck1.setActualVin(normalizeVin(securityDetection.getVin()));
- redisService.setCacheObject("AQJC_" + chargingGun.getId(), preChargeCheck1, 24L, TimeUnit.HOURS);
- if (isSafetyCheckPassed(preChargeCheck1)) {
- TChargingOrder pendingOrder = this.getOne(new LambdaQueryWrapper<TChargingOrder>()
- .eq(TChargingOrder::getChargingGunId, chargingGun.getId())
- .eq(TChargingOrder::getRechargePaymentStatus, 2)
- .eq(TChargingOrder::getStatus, 2)
- .eq(TChargingOrder::getDelFlag, 0)
- .orderByDesc(TChargingOrder::getCreateTime)
- .last("limit 1"));
- if (pendingOrder != null) {
- startChargingAfterSafety(pendingOrder, preChargeCheck1);
- }
+ TChargingGun chargingGun = null;
+ try {
+ chargingGun = chargingGunClient.getChargingGunByCode(code).getData();
+ } catch (Exception e) {
+ log.error("安全检测上报-查询充电枪异常,charging_pile_code={},charging_gun_code={}",
+ securityDetection.getCharging_pile_code(), securityDetection.getCharging_gun_code(), e);
+ }
+ if (null == chargingGun) {
+ log.warn("安全检测上报-未匹配到充电枪,忽略,charging_pile_code={},charging_gun_code={}",
+ securityDetection.getCharging_pile_code(), securityDetection.getCharging_gun_code());
+ return;
+ }
+ String key = "AQJC_" + chargingGun.getId();
+ PreChargeCheck preChargeCheck1 = redisService.getCacheObject(key);
+ if (null == preChargeCheck1) {
+ // 缓存缺失(等待窗口内未收到上报、缓存被清理)时按该枪进行中的待启动订单重建,
+ // 保证设备后续安全检测上报仍能推进启动,避免订单永久卡在启动中
+ TChargingOrder pendingOrder = getPendingStartOrder(chargingGun.getId());
+ if (null == pendingOrder) {
+ log.info("安全检测上报-无待启动订单,忽略,充电枪id={},charging_pile_code={},charging_gun_code={}",
+ chargingGun.getId(), securityDetection.getCharging_pile_code(), securityDetection.getCharging_gun_code());
+ return;
+ }
+ preChargeCheck1 = newPreChargeCheck(pendingOrder);
+ log.warn("安全检测上报-AQJC缓存缺失,已按待启动订单重建,订单编号={},充电枪id={}", pendingOrder.getCode(), chargingGun.getId());
+ }
+ preChargeCheck1.setElectronicLockLock(Integer.valueOf(1).equals(securityDetection.getElectronic_lock_lock()));
+ preChargeCheck1.setInsulationTesting(Integer.valueOf(0).equals(securityDetection.getNsulation_detection()));
+ preChargeCheck1.setSecureConnectionDetection(Integer.valueOf(1).equals(securityDetection.getSecure_connection()));
+ preChargeCheck1.setActualVin(normalizeVin(securityDetection.getVin()));
+ // 刷新等待基准时间,避免前端等待窗口/超时判断误伤正在推进的安全检测
+ preChargeCheck1.setAddTime(LocalDateTime.now());
+ redisService.setCacheObject(key, preChargeCheck1, 24L, TimeUnit.HOURS);
+ if (isSafetyCheckPassed(preChargeCheck1)) {
+ TChargingOrder pendingOrder = getPendingStartOrder(chargingGun.getId());
+ if (pendingOrder != null) {
+ startChargingAfterSafety(pendingOrder, preChargeCheck1);
}
}
}
@@ -2375,6 +2468,11 @@
preChargeCheck1.setElectronicLockLock(true);
preChargeCheck1.setInsulationTesting(true);
preChargeCheck1.setStartupSuccess(1);
+ } else {
+ // 缓存缺失时用临时对象推进订单状态,避免设备已启动成功而订单因缓存为空无法流转
+ preChargeCheck1 = new PreChargeCheck();
+ preChargeCheck1.setElectronicLockLock(true);
+ preChargeCheck1.setInsulationTesting(true);
}
if (0 == startup_result) {
//启动失败
@@ -2769,19 +2867,22 @@
@Override
public ChargingDetails getChargingDetails(Integer id) {
Long userId = tokenService.getLoginUserApplet().getUserId();
+ // 状态包含已结束(5):订单结束后小程序需继续拿到该笔订单,用于关闭「请勿拔枪,正在结束充电」
+ // 并展示「充电完成,可拔枪」;仅取最近一笔,避免历史完成订单长期滞留结束态
TChargingOrder one = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getAppUserId, userId).eq(TChargingOrder::getChargingGunId, id)
.eq(TChargingOrder::getRechargePaymentStatus, 2)
- .in(TChargingOrder::getStatus, Arrays.asList(2, 3, 4))
+ .in(TChargingOrder::getStatus, Arrays.asList(2, 3, 4, 5))
.eq(TChargingOrder::getDelFlag, 0)
.orderByDesc(TChargingOrder::getCreateTime)
.last(" limit 0, 1"));
if (null == one || !one.getAppUserId().equals(userId)) {
// VIN 码充电订单兜底:VD 订单存于 t_vin_charging_order,且后付模式无支付动作,
// 不按 rechargePaymentStatus 过滤;TVinChargingOrder 继承 TChargingOrder,后续组装原样复用
+ // 状态同样包含已结束(5),保证 VIN 订单结束后前端仍能拿到完成态
TVinChargingOrder vinOrder = vinChargingOrderMapper.selectOne(new LambdaQueryWrapper<TVinChargingOrder>()
.eq(TVinChargingOrder::getAppUserId, userId)
.eq(TVinChargingOrder::getChargingGunId, id)
- .in(TVinChargingOrder::getStatus, Arrays.asList(2, 3, 4))
+ .in(TVinChargingOrder::getStatus, Arrays.asList(2, 3, 4, 5))
.eq(TVinChargingOrder::getDelFlag, 0)
.orderByDesc(TVinChargingOrder::getCreateTime)
.last(" limit 0, 1"));
@@ -8240,13 +8341,7 @@
//添加安全检测数据到缓存中,每步安全检测完成后需要更新缓存数据
- PreChargeCheck preChargeCheck = new PreChargeCheck();
- preChargeCheck.setElectronicLockLock(false);
- preChargeCheck.setInsulationTesting(false);
- preChargeCheck.setSecureConnectionDetection(false);
- preChargeCheck.setStartupSuccess(1);
- preChargeCheck.setStartCommandSent(false);
- preChargeCheck.setAddTime(chargingOrder.getReservationTime() != null ? chargingOrder.getReservationTime() : LocalDateTime.now());
+ PreChargeCheck preChargeCheck = newPreChargeCheck(chargingOrder);
String key = "AQJC_" + chargingOrder.getChargingGunId();
redisService.setCacheObject(key, preChargeCheck, 24L, TimeUnit.HOURS);
--
Gitblit v1.7.1