Преглед изворни кода

feat(charge-order): 增加充电订单补偿与修复功能

- 在AppletChargeController中新增接口查询充电订单的推送原始数据
- 在ChargeOrderInfoController添加接口支持修复未处理及指定订单号的充电订单
- ChargeOrderInfo实体新增补偿状态字段 区分正常、已补偿、异常及无需补偿状态
- ChargeOrderInfoService接口新增补偿与修复相关方法定义
- ChargeOrderInfoServiceImpl实现补偿与修复逻辑:
  - 支持通过third_party_api_log表推送数据优先修复订单
  - 备选通过third_party_charge_status表的充电数据补偿订单
  - 计算并更新平台服务费、总费用及充电时长
  - 处理账户余额扣减及订单状态更新
  - 支持定时任务对未完成订单补偿
- 增强日志记录,便于追踪补偿修复过程及结果
- 增加异常订单标记,避免重复补偿处理
wzq пре 1 недеља
родитељ
комит
7458c032ad

+ 18 - 0
src/main/java/com/zsElectric/boot/business/controller/ChargeOrderInfoController.java

@@ -93,4 +93,22 @@ public class ChargeOrderInfoController  {
         EasyExcel.write(response.getOutputStream(), ChargeOrderInfoExportDTO.class).sheet("充电订单信息")
                 .doWrite(exportList);
     }
+
+    @Operation(summary = "修复未处理的充电订单", description = "修复状态为5(未成功充电)且实际充电量>0的订单,重新计算费用并扣减余额")
+    @PostMapping("/repair-unprocessed")
+    @PreAuthorize("@ss.hasPerm('business:charge-order-info:edit')")
+    public Result<String> repairUnprocessedOrders() {
+        String result = chargeOrderInfoService.repairUnprocessedOrders();
+        return Result.success(result);
+    }
+
+    @Operation(summary = "根据订单号修复订单", description = "根据充电订单号修复订单,重新处理订单状态变更、数据修改及余额扣减")
+    @PostMapping("/repair-by-order-no/{chargeOrderNo}")
+    @PreAuthorize("@ss.hasPerm('business:charge-order-info:edit')")
+    public Result<String> repairOrderByOrderNo(
+            @Parameter(description = "充电订单号") @PathVariable String chargeOrderNo
+    ) {
+        String result = chargeOrderInfoService.repairOrderByOrderNo(chargeOrderNo);
+        return Result.success(result);
+    }
 }

+ 42 - 0
src/main/java/com/zsElectric/boot/business/controller/applet/AppletChargeController.java

@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.zsElectric.boot.business.model.entity.ChargeOrderInfo;
 import com.zsElectric.boot.business.model.entity.UserAccount;
 import com.zsElectric.boot.business.model.form.applet.AppInvokeChargeForm;
 import com.zsElectric.boot.business.model.form.applet.AppStopChargeForm;
@@ -12,6 +13,8 @@ import com.zsElectric.boot.business.model.vo.ChargeOrderInfoVO;
 import com.zsElectric.boot.business.model.vo.applet.AppChargeVO;
 import com.zsElectric.boot.business.service.ChargeOrderInfoService;
 import com.zsElectric.boot.business.service.UserAccountService;
+import com.zsElectric.boot.charging.entity.ThirdPartyApiLog;
+import com.zsElectric.boot.charging.mapper.ThirdPartyApiLogMapper;
 import com.zsElectric.boot.common.annotation.Log;
 import com.zsElectric.boot.common.enums.LogModuleEnum;
 import com.zsElectric.boot.core.exception.BusinessException;
@@ -42,6 +45,7 @@ public class AppletChargeController {
     private final ChargeOrderInfoService chargeOrderInfoService;
     private final DictItemService dictItemService;
     private final UserAccountService userAccountService;
+    private final ThirdPartyApiLogMapper thirdPartyApiLogMapper;
 
     /**
      * 充电订单记录
@@ -126,4 +130,42 @@ public class AppletChargeController {
         AppChargeVO appStopChargeVO= chargeOrderInfoService.stopCharge(formData);
         return Result.success(appStopChargeVO);
     }
+
+    /**
+     * 查询充电订单的推送数据
+     *
+     * @param chargeOrderNo 充电订单编号
+     * @return 推送数据
+     */
+    @Operation(summary = "查询充电订单推送数据", description = "通过充电订单编号查询第三方推送的原始数据")
+    @GetMapping("/queryPushData/{chargeOrderNo}")
+    public Result<String> queryPushData(@PathVariable("chargeOrderNo") String chargeOrderNo) {
+        // 1. 通过充电订单编号查询订单信息
+        ChargeOrderInfo orderInfo = chargeOrderInfoService.getOne(Wrappers.<ChargeOrderInfo>lambdaQuery()
+                .eq(ChargeOrderInfo::getChargeOrderNo, chargeOrderNo)
+                .last("LIMIT 1"));
+        
+        if (orderInfo == null) {
+            return Result.failed("订单不存在");
+        }
+        
+        if (orderInfo.getStartChargeSeq() == null) {
+            return Result.failed("订单缺少StartChargeSeq");
+        }
+        
+        // 2. 通过start_charge_seq模糊匹配third_party_api_log中的decrypted_request_data
+        ThirdPartyApiLog apiLog = thirdPartyApiLogMapper.selectOne(
+                Wrappers.<ThirdPartyApiLog>lambdaQuery()
+                        .eq(ThirdPartyApiLog::getInterfaceDescription, "推送充电订单信息")
+                        .like(ThirdPartyApiLog::getDecryptedRequestData, orderInfo.getStartChargeSeq())
+                        .orderByDesc(ThirdPartyApiLog::getCreatedTime)
+                        .last("LIMIT 1"));
+        
+        if (apiLog == null || apiLog.getDecryptedRequestData() == null) {
+            return Result.failed("未找到推送数据");
+        }
+        
+        return Result.success(apiLog.getDecryptedRequestData());
+    }
+
 }

+ 4 - 0
src/main/java/com/zsElectric/boot/business/model/entity/ChargeOrderInfo.java

@@ -182,6 +182,10 @@ public class ChargeOrderInfo extends BaseEntity {
      * 优惠卷ID
      */
     private Long couponId;
+    /**
+     * 补偿状态 0-正常 1-已补偿 2-异常无须补偿 9-异常
+     */
+    private Integer compensateStatus;
     /**
      * 备注
      */

+ 39 - 0
src/main/java/com/zsElectric/boot/business/quartz/CompensateOrderJob.java

@@ -0,0 +1,39 @@
+package com.zsElectric.boot.business.quartz;
+
+import com.zsElectric.boot.business.service.ChargeOrderInfoService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+/**
+ * 订单补偿定时任务
+ * 针对异常订单做补偿机制
+ *
+ * @author zsElectric
+ * @since 2026-01-21
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class CompensateOrderJob {
+
+    private final ChargeOrderInfoService chargeOrderInfoService;
+
+    /**
+     * 充电订单补偿定时任务 - 每10分钟执行一次
+     * 查找状态为3(已完成)或5(未成功充电)且充电数据为0的订单
+     * 优先通过third_party_api_log表获取推送数据,备选通过third_party_charge_status表查询
+     */
+    @Scheduled(cron = "0 0/10 * * * ?")
+    public void compensateChargeOrder() {
+        log.info("开始执行充电订单补偿定时任务");
+
+        try {
+            String result = chargeOrderInfoService.compensateUnprocessedOrders();
+            log.info("充电订单补偿定时任务执行完成: {}", result);
+        } catch (Exception e) {
+            log.error("执行充电订单补偿任务失败", e);
+        }
+    }
+}

+ 28 - 0
src/main/java/com/zsElectric/boot/business/service/ChargeOrderInfoService.java

@@ -87,4 +87,32 @@ public interface ChargeOrderInfoService extends IService<ChargeOrderInfo> {
      */
     List<ChargeOrderInfoExportDTO> listExportChargeOrderInfo(ChargeOrderInfoQuery queryParams);
 
+    /**
+     * 修复未处理的充电订单
+     * 查找状态为5(未成功充电)且third_party_charge_status表中total_power>0的订单
+     * 重新处理这些订单:更新状态、计算费用、扣减余额
+     *
+     * @return 修复结果描述
+     */
+    String repairUnprocessedOrders();
+
+    /**
+     * 根据充电订单号修复订单
+     * 重新处理订单状态变更、数据修改及余额扣减
+     * 优先通过third_party_api_log表获取推送数据,备选通过third_party_charge_status表查询
+     *
+     * @param chargeOrderNo 充电订单号
+     * @return 修复结果描述
+     */
+    String repairOrderByOrderNo(String chargeOrderNo);
+
+    /**
+     * 补偿未处理的充电订单(定时任务调用)
+     * 查找状态为3(已完成)或5(未成功充电)且充电数据为0的订单
+     * 优先通过third_party_api_log表获取推送数据,备选通过third_party_charge_status表查询
+     *
+     * @return 补偿结果描述
+     */
+    String compensateUnprocessedOrders();
+
 }

+ 814 - 6
src/main/java/com/zsElectric/boot/business/service/impl/ChargeOrderInfoServiceImpl.java

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.zsElectric.boot.business.converter.ChargeOrderInfoConverter;
 import com.zsElectric.boot.business.mapper.*;
+import com.zsElectric.boot.business.mapper.ThirdPartyStationInfoMapper;
 import com.zsElectric.boot.business.model.dto.ChargeOrderInfoExportDTO;
 import com.zsElectric.boot.business.model.entity.*;
 import com.zsElectric.boot.business.model.form.ChargeOrderInfoForm;
@@ -39,11 +40,27 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+import com.zsElectric.boot.charging.entity.ThirdPartyChargeStatus;
+import com.zsElectric.boot.charging.entity.ThirdPartyConnectorInfo;
+import com.zsElectric.boot.charging.entity.ThirdPartyStationInfo;
+import com.zsElectric.boot.charging.entity.ThirdPartyEquipmentPricePolicy;
+import com.zsElectric.boot.charging.entity.ThirdPartyPolicyInfo;
+import com.zsElectric.boot.charging.mapper.ThirdPartyChargeStatusMapper;
+import com.zsElectric.boot.charging.mapper.ThirdPartyConnectorInfoMapper;
+import com.zsElectric.boot.charging.mapper.ThirdPartyEquipmentPricePolicyMapper;
+import com.zsElectric.boot.charging.mapper.ThirdPartyPolicyInfoMapper;
+import com.zsElectric.boot.charging.mapper.ThirdPartyApiLogMapper;
+import com.zsElectric.boot.charging.entity.ThirdPartyApiLog;
+import com.zsElectric.boot.common.util.DateUtils;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * 充电订单信息服务实现类
@@ -74,6 +91,16 @@ public class ChargeOrderInfoServiceImpl extends ServiceImpl<ChargeOrderInfoMappe
 
     private final UserMapper userMapper;
 
+    private final ThirdPartyChargeStatusMapper chargeStatusMapper;
+    private final ThirdPartyConnectorInfoMapper connectorInfoMapper;
+    private final ThirdPartyStationInfoMapper thirdPartyStationInfoMapper;
+    private final PolicyFeeMapper policyFeeMapper;
+    private final ThirdPartyEquipmentPricePolicyMapper thirdPartyEquipmentPricePolicyMapper;
+    private final ThirdPartyPolicyInfoMapper thirdPartyPolicyInfoMapper;
+    private final DiscountsActivityMapper discountsActivityMapper;
+    private final ThirdPartyApiLogMapper thirdPartyApiLogMapper;
+    private final ObjectMapper objectMapper;
+
     //充电订单号前缀
     private final String ORDER_NO_PREFIX = "CD";
     //设备流水号前缀
@@ -169,6 +196,7 @@ public class ChargeOrderInfoServiceImpl extends ServiceImpl<ChargeOrderInfoMappe
             //渠道方启动充电
             if (Objects.equals(formData.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_CHANNEL)) {
 
+                log.info("渠道方启动充电开始,用户ID:{},设备认证流水号:{},充电桩编号:{}", SecurityUtils.getUserId(), formData.getEquipAuthSeq(), formData.getEquipmentId());
                 String orderNo = channelInvokeCharge(formData);
                 appInvokeChargeVO.setChargeOrderNo(orderNo);
                 return appInvokeChargeVO;
@@ -336,8 +364,6 @@ public class ChargeOrderInfoServiceImpl extends ServiceImpl<ChargeOrderInfoMappe
                 throw new BusinessException("停止充电失败,请稍后再重试!");
             }
 
-            // 更新订单状态为停止中(状态3)
-            chargeOrderInfo.setStatus(SystemConstants.STATUS_THREE);
             chargeOrderInfo.setStopType(1); // 1-主动停止
             this.updateById(chargeOrderInfo);
 
@@ -411,4 +437,786 @@ public class ChargeOrderInfoServiceImpl extends ServiceImpl<ChargeOrderInfoMappe
         return head + sdf.format(date) + uid + (int) ((Math.random() * 9 + 1) * 1000);
     }
 
+    /**
+     * 修复未处理的充电订单
+     * 优先通过third_party_api_log表获取推送充电订单信息,
+     * 若没有则通过third_party_charge_status表查询total_power>0的数据
+     * 重新处理这些订单:更新状态、计算费用、扣减余额
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String repairUnprocessedOrders() {
+        log.info("开始修复未处理的充电订单...");
+        
+        // 1. 查询状态为5(未成功充电)的订单
+        List<ChargeOrderInfo> unprocessedOrders = this.list(Wrappers.<ChargeOrderInfo>lambdaQuery()
+                .eq(ChargeOrderInfo::getStatus, 5)
+                .isNotNull(ChargeOrderInfo::getStartChargeSeq));
+        
+        if (unprocessedOrders.isEmpty()) {
+            log.info("没有找到需要修复的订单");
+            return "没有找到需要修复的订单";
+        }
+        
+        int totalCount = 0;
+        int successCount = 0;
+        int skipCount = 0;
+        int apiLogCount = 0;
+        int chargeStatusCount = 0;
+        List<String> failedOrders = new ArrayList<>();
+        
+        for (ChargeOrderInfo order : unprocessedOrders) {
+            totalCount++;
+            try {
+                // 2. 优先从third_party_api_log表查询推送充电订单信息
+                ThirdPartyApiLog apiLog = thirdPartyApiLogMapper.selectOne(
+                        Wrappers.<ThirdPartyApiLog>lambdaQuery()
+                                .eq(ThirdPartyApiLog::getInterfaceDescription, "推送充电订单信息")
+                                .like(ThirdPartyApiLog::getDecryptedRequestData, order.getStartChargeSeq())
+                                .orderByDesc(ThirdPartyApiLog::getCreatedTime)
+                                .last("LIMIT 1"));
+                
+                if (apiLog != null && apiLog.getDecryptedRequestData() != null) {
+                    // 使用API日志中的推送数据处理订单
+                    boolean success = processOrderFromApiLog(order, apiLog);
+                    if (success) {
+                        // 设置补偿状态为已补偿
+                        order.setCompensateStatus(1);
+                        this.updateById(order);
+                        successCount++;
+                        apiLogCount++;
+                        log.info("订单{}通过API日志修复成功", order.getChargeOrderNo());
+                        continue;
+                    }
+                }
+                
+                // 3. 备选方案:从third_party_charge_status表查询
+                ThirdPartyChargeStatus chargeStatus = chargeStatusMapper.selectOne(
+                        Wrappers.<ThirdPartyChargeStatus>lambdaQuery()
+                                .eq(ThirdPartyChargeStatus::getStartChargeSeq, order.getStartChargeSeq()));
+                
+                if (chargeStatus == null || chargeStatus.getTotalPower() == null 
+                        || chargeStatus.getTotalPower().compareTo(BigDecimal.ZERO) <= 0) {
+                    log.info("订单{}无有效充电数据,设置为异常无须补偿", order.getChargeOrderNo());
+                    // 设置补偿状态为异常无须补偿
+                    order.setCompensateStatus(2);
+                    this.updateById(order);
+                    skipCount++;
+                    continue;
+                }
+                
+                log.info("开始通过充电状态表修复订单: {}, 充电量: {}", order.getChargeOrderNo(), chargeStatus.getTotalPower());
+                
+                // 4. 获取站点信息
+                ThirdPartyConnectorInfo connectorInfo = connectorInfoMapper.selectOne(
+                        Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
+                                .eq(ThirdPartyConnectorInfo::getConnectorId, order.getConnectorId())
+                                .last("LIMIT 1"));
+                if (connectorInfo == null) {
+                    log.warn("订单{}找不到充电接口信息", order.getChargeOrderNo());
+                    failedOrders.add(order.getChargeOrderNo());
+                    continue;
+                }
+                
+                ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectOne(
+                        Wrappers.<ThirdPartyStationInfo>lambdaQuery()
+                                .eq(ThirdPartyStationInfo::getStationId, connectorInfo.getStationId())
+                                .last("LIMIT 1"));
+                if (stationInfo == null) {
+                    log.warn("订单{}找不到站点信息", order.getChargeOrderNo());
+                    failedOrders.add(order.getChargeOrderNo());
+                    continue;
+                }
+                
+                // 5. 设置第三方费用信息
+                order.setTotalCharge(chargeStatus.getTotalPower());
+                order.setThirdPartyTotalCost(chargeStatus.getTotalMoney() != null ? chargeStatus.getTotalMoney() : BigDecimal.ZERO);
+                order.setThirdPartyServerfee(chargeStatus.getServiceMoney() != null ? chargeStatus.getServiceMoney() : BigDecimal.ZERO);
+                order.setThirdPartyElecfee(chargeStatus.getElecMoney() != null ? chargeStatus.getElecMoney() : BigDecimal.ZERO);
+                
+                // 6. 计算平台服务费
+                BigDecimal serviceFee = calculateServiceFee(order, chargeStatus, stationInfo);
+                
+                // 7. 更新订单信息
+                order.setRealServiceCost(serviceFee.setScale(2, RoundingMode.HALF_UP));
+                order.setRealCost(serviceFee.add(order.getThirdPartyTotalCost()));
+                order.setStatus(SystemConstants.STATUS_THREE); // 已完成
+                
+                // 设置充电时间
+                if (chargeStatus.getStartTime() != null && chargeStatus.getEndTime() != null) {
+                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                    order.setStartTime(chargeStatus.getStartTime().format(formatter));
+                    order.setEndTime(chargeStatus.getEndTime().format(formatter));
+                    order.setChargeTime(DateUtils.getDuration(order.getStartTime(), order.getEndTime()));
+                }
+                
+                // 设置修复备注
+                order.setRemark("通过补偿修复处理");
+                // 设置补偿状态为已补偿
+                order.setCompensateStatus(1);
+                
+                this.updateById(order);
+                
+                // 8. 执行账户余额扣减(仅平台订单和企业订单)
+                if (Objects.equals(order.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_PLATFORM)
+                        || Objects.equals(order.getOrderType(), SystemConstants.STATUS_ONE)) {
+                    orderSettlement(order.getId());
+                    log.info("订单{}余额扣减完成", order.getChargeOrderNo());
+                }
+                
+                successCount++;
+                chargeStatusCount++;
+                log.info("订单{}通过充电状态表修复成功,实际费用: {}", order.getChargeOrderNo(), order.getRealCost());
+                
+            } catch (Exception e) {
+                log.error("修复订单{}失败: {}", order.getChargeOrderNo(), e.getMessage(), e);
+                failedOrders.add(order.getChargeOrderNo());
+            }
+        }
+        
+        String result = String.format("修复完成!总计: %d, 成功: %d (API日志: %d, 充电状态: %d), 跳过: %d, 失败: %d", 
+                totalCount, successCount, apiLogCount, chargeStatusCount, skipCount, failedOrders.size());
+        if (!failedOrders.isEmpty()) {
+            result += ", 失败订单: " + String.join(",", failedOrders);
+        }
+        log.info(result);
+        return result;
+    }
+    
+    /**
+     * 通过API日志中的推送数据处理订单
+     * @param order 订单信息
+     * @param apiLog API日志
+     * @return 是否处理成功
+     */
+    private boolean processOrderFromApiLog(ChargeOrderInfo order, ThirdPartyApiLog apiLog) {
+        try {
+            JsonNode jsonNode = objectMapper.readTree(apiLog.getDecryptedRequestData());
+            
+            // 解析推送数据
+            String startChargeSeq = getJsonTextValue(jsonNode, "StartChargeSeq");
+            if (startChargeSeq == null || !startChargeSeq.equals(order.getStartChargeSeq())) {
+                log.warn("订单{}的StartChargeSeq不匹配,跳过API日志处理", order.getChargeOrderNo());
+                return false;
+            }
+            
+            String totalPowerStr = getJsonTextValue(jsonNode, "TotalPower");
+            if (totalPowerStr == null || new BigDecimal(totalPowerStr).compareTo(BigDecimal.ZERO) <= 0) {
+                log.info("订单{}的API日志充电量为0,跳过处理", order.getChargeOrderNo());
+                return false;
+            }
+            
+            log.info("开始通过API日志修复订单: {}, 充电量: {}", order.getChargeOrderNo(), totalPowerStr);
+            
+            // 设置充电信息
+            order.setTotalCharge(new BigDecimal(totalPowerStr));
+            order.setStopReason(getJsonTextValue(jsonNode, "StopReason"));
+            order.setStartTime(getJsonTextValue(jsonNode, "StartTime"));
+            order.setEndTime(getJsonTextValue(jsonNode, "EndTime"));
+            order.setChargeDetails(jsonNode.toString());
+            
+            // 第三方费用
+            String totalMoney = getJsonTextValue(jsonNode, "TotalMoney");
+            String totalSeviceMoney = getJsonTextValue(jsonNode, "TotalSeviceMoney");
+            String totalElecMoney = getJsonTextValue(jsonNode, "TotalElecMoney");
+            order.setThirdPartyTotalCost(totalMoney != null ? new BigDecimal(totalMoney) : BigDecimal.ZERO);
+            order.setThirdPartyServerfee(totalSeviceMoney != null ? new BigDecimal(totalSeviceMoney) : BigDecimal.ZERO);
+            order.setThirdPartyElecfee(totalElecMoney != null ? new BigDecimal(totalElecMoney) : BigDecimal.ZERO);
+            
+            // 获取连接器和站点信息
+            String connectorId = getJsonTextValue(jsonNode, "ConnectorID");
+            if (connectorId == null) {
+                connectorId = order.getConnectorId();
+            }
+            
+            ThirdPartyConnectorInfo connectorInfo = connectorInfoMapper.selectOne(
+                    Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
+                            .eq(ThirdPartyConnectorInfo::getConnectorId, connectorId)
+                            .last("LIMIT 1"));
+            if (connectorInfo == null) {
+                log.warn("订单{}找不到充电接口信息", order.getChargeOrderNo());
+                return false;
+            }
+            
+            ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectOne(
+                    Wrappers.<ThirdPartyStationInfo>lambdaQuery()
+                            .eq(ThirdPartyStationInfo::getStationId, connectorInfo.getStationId())
+                            .last("LIMIT 1"));
+            if (stationInfo == null) {
+                log.warn("订单{}找不到站点信息", order.getChargeOrderNo());
+                return false;
+            }
+            
+            // 计算平台服务费(从ChargeDetails中解析)
+            BigDecimal serviceFee = calculateServiceFeeFromChargeDetails(order, jsonNode, stationInfo);
+            
+            // 更新订单信息
+            order.setRealServiceCost(serviceFee.setScale(2, RoundingMode.HALF_UP));
+            order.setRealCost(serviceFee.add(order.getThirdPartyTotalCost()));
+            order.setStatus(SystemConstants.STATUS_THREE); // 已完成
+            
+            // 计算充电时间
+            if (order.getStartTime() != null && order.getEndTime() != null) {
+                order.setChargeTime(DateUtils.getDuration(order.getStartTime(), order.getEndTime()));
+            }
+            
+            // 设置修复备注
+            order.setRemark("通过补偿修复处理");
+            
+            this.updateById(order);
+            
+            // 执行账户余额扣减(仅平台订单和企业订单)
+            if (Objects.equals(order.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_PLATFORM)
+                    || Objects.equals(order.getOrderType(), SystemConstants.STATUS_ONE)) {
+                orderSettlement(order.getId());
+                log.info("订单{}余额扣减完成", order.getChargeOrderNo());
+            }
+            
+            log.info("订单{}通过API日志处理成功,实际费用: {}", order.getChargeOrderNo(), order.getRealCost());
+            return true;
+            
+        } catch (Exception e) {
+            log.error("通过API日志处理订单{}失败: {}", order.getChargeOrderNo(), e.getMessage(), e);
+            return false;
+        }
+    }
+    
+    /**
+     * 从ChargeDetails计算平台服务费
+     */
+    private BigDecimal calculateServiceFeeFromChargeDetails(ChargeOrderInfo order, JsonNode jsonNode, 
+                                                            ThirdPartyStationInfo stationInfo) {
+        BigDecimal serviceFee = BigDecimal.ZERO;
+        
+        JsonNode chargeDetails = jsonNode.get("ChargeDetails");
+        if (chargeDetails != null && chargeDetails.isArray()) {
+            for (JsonNode node : chargeDetails) {
+                String itemFlag = getJsonTextValue(node, "ItemFlag");
+                String detailPowerStr = getJsonTextValue(node, "DetailPower");
+                
+                if (itemFlag != null && detailPowerStr != null) {
+                    BigDecimal detailPower = new BigDecimal(detailPowerStr);
+                    PolicyFee policyFee = policyFeeMapper.selectOne(Wrappers.<PolicyFee>lambdaQuery()
+                            .eq(PolicyFee::getStationInfoId, stationInfo.getId())
+                            .eq(PolicyFee::getPeriodFlag, Integer.parseInt(itemFlag))
+                            .last("LIMIT 1"));
+                    if (policyFee != null && policyFee.getOpFee() != null) {
+                        serviceFee = serviceFee.add(policyFee.getOpFee().multiply(detailPower));
+                    }
+                }
+            }
+        } else {
+            // 无明细时,使用最高费用时段计算
+            log.info("订单{}无充电明细,使用简化计算", order.getChargeOrderNo());
+            ThirdPartyEquipmentPricePolicy pricePolicy = thirdPartyEquipmentPricePolicyMapper.selectOne(
+                    Wrappers.<ThirdPartyEquipmentPricePolicy>lambdaQuery()
+                            .eq(ThirdPartyEquipmentPricePolicy::getConnectorId, order.getConnectorId())
+                            .last("LIMIT 1"));
+            if (pricePolicy != null) {
+                List<ThirdPartyPolicyInfo> policyInfos = thirdPartyPolicyInfoMapper.selectList(
+                        Wrappers.<ThirdPartyPolicyInfo>lambdaQuery()
+                                .eq(ThirdPartyPolicyInfo::getPricePolicyId, pricePolicy.getId()));
+                PolicyFee maxPolicyFee = null;
+                for (ThirdPartyPolicyInfo policyInfo : policyInfos) {
+                    PolicyFee policyFee = policyFeeMapper.selectOne(Wrappers.<PolicyFee>lambdaQuery()
+                            .eq(PolicyFee::getStationInfoId, stationInfo.getId())
+                            .eq(PolicyFee::getPeriodFlag, policyInfo.getPeriodFlag())
+                            .last("LIMIT 1"));
+                    if (policyFee != null && policyFee.getOpFee() != null) {
+                        if (maxPolicyFee == null || policyFee.getOpFee().compareTo(maxPolicyFee.getOpFee()) > 0) {
+                            maxPolicyFee = policyFee;
+                        }
+                    }
+                }
+                if (maxPolicyFee != null) {
+                    serviceFee = maxPolicyFee.getOpFee().multiply(order.getTotalCharge());
+                }
+            }
+        }
+        
+        return serviceFee;
+    }
+    
+    /**
+     * 安全获取JSON节点的文本值
+     */
+    private String getJsonTextValue(JsonNode node, String fieldName) {
+        if (node == null || !node.has(fieldName) || node.get(fieldName).isNull()) {
+            return null;
+        }
+        return node.get(fieldName).asText();
+    }
+    
+    /**
+     * 计算平台服务费
+     */
+    private BigDecimal calculateServiceFee(ChargeOrderInfo order, ThirdPartyChargeStatus chargeStatus, 
+                                           ThirdPartyStationInfo stationInfo) {
+        BigDecimal serviceFee = BigDecimal.ZERO;
+        
+        // 查询价格策略
+        ThirdPartyEquipmentPricePolicy pricePolicy = thirdPartyEquipmentPricePolicyMapper.selectOne(
+                Wrappers.<ThirdPartyEquipmentPricePolicy>lambdaQuery()
+                        .eq(ThirdPartyEquipmentPricePolicy::getConnectorId, chargeStatus.getConnectorId())
+                        .last("LIMIT 1"));
+        
+        if (pricePolicy == null) {
+            log.warn("订单{}找不到价格策略", order.getChargeOrderNo());
+            return serviceFee;
+        }
+        
+        // 查询时段信息
+        List<ThirdPartyPolicyInfo> allPolicyInfos = thirdPartyPolicyInfoMapper.selectList(
+                Wrappers.<ThirdPartyPolicyInfo>lambdaQuery()
+                        .eq(ThirdPartyPolicyInfo::getPricePolicyId, pricePolicy.getId())
+                        .orderByAsc(ThirdPartyPolicyInfo::getStartTime));
+        
+        if (allPolicyInfos.isEmpty()) {
+            log.warn("订单{}找不到时段信息", order.getChargeOrderNo());
+            return serviceFee;
+        }
+        
+        // 根据充电时间段匹配费用
+        if (chargeStatus.getStartTime() != null && chargeStatus.getEndTime() != null) {
+            String chargeStartTimeStr = chargeStatus.getStartTime().format(DateTimeFormatter.ofPattern("HHmmss"));
+            String chargeEndTimeStr = chargeStatus.getEndTime().format(DateTimeFormatter.ofPattern("HHmmss"));
+            
+            // 找到充电时间跨越的所有时段,使用最高费用时段计算
+            PolicyFee maxPolicyFee = null;
+            for (ThirdPartyPolicyInfo policyInfo : allPolicyInfos) {
+                if (chargeStartTimeStr.compareTo(policyInfo.getStartTime()) >= 0 
+                        || chargeEndTimeStr.compareTo(policyInfo.getStartTime()) >= 0) {
+                    PolicyFee policyFee = policyFeeMapper.selectOne(
+                            Wrappers.<PolicyFee>lambdaQuery()
+                                    .eq(PolicyFee::getStationInfoId, stationInfo.getId())
+                                    .eq(PolicyFee::getPeriodFlag, policyInfo.getPeriodFlag())
+                                    .last("LIMIT 1"));
+                    if (policyFee != null && policyFee.getOpFee() != null) {
+                        if (maxPolicyFee == null || policyFee.getOpFee().compareTo(maxPolicyFee.getOpFee()) > 0) {
+                            maxPolicyFee = policyFee;
+                        }
+                    }
+                }
+            }
+            
+            if (maxPolicyFee != null) {
+                serviceFee = maxPolicyFee.getOpFee().multiply(order.getTotalCharge());
+            }
+        }
+        
+        return serviceFee;
+    }
+
+    /**
+     * 根据充电订单号修复已完成订单
+     * 修复状态为3(已完成)的订单,重新处理订单状态变更、数据修改及余额扣减
+     * 优先通过third_party_api_log表获取推送数据,备选通过third_party_charge_status表查询
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String repairOrderByOrderNo(String chargeOrderNo) {
+        log.info("开始根据订单号修复订单: {}", chargeOrderNo);
+        
+        // 1. 查询订单
+        ChargeOrderInfo order = this.getOne(Wrappers.<ChargeOrderInfo>lambdaQuery()
+                .eq(ChargeOrderInfo::getChargeOrderNo, chargeOrderNo)
+                .last("LIMIT 1"));
+        
+        if (order == null) {
+            return "订单不存在: " + chargeOrderNo;
+        }
+        
+        log.info("开始修复订单: {}, 当前状态: {}", chargeOrderNo, order.getStatus());
+        
+        // 2. 检查订单是否需要修复(只有充电度数、平台费用、三方费用同时为0扏null的订单才处理)
+        boolean needRepair = isZeroOrNull(order.getTotalCharge()) 
+                && isZeroOrNull(order.getRealCost()) 
+                && isZeroOrNull(order.getRealServiceCost()) 
+                && isZeroOrNull(order.getThirdPartyTotalCost()) 
+                && isZeroOrNull(order.getThirdPartyServerfee());
+        
+        if (!needRepair) {
+            return "订单" + chargeOrderNo + "已有充电数据,无需修复。充电度数:" + order.getTotalCharge() 
+                    + ", 平台收取金额:" + order.getRealCost() 
+                    + ", 平台服务费:" + order.getRealServiceCost()
+                    + ", 三方消费总额:" + order.getThirdPartyTotalCost()
+                    + ", 三方服务费:" + order.getThirdPartyServerfee();
+        }
+        
+        if (order.getStartChargeSeq() == null) {
+            return "订单缺少StartChargeSeq,无法修复";
+        }
+        
+        try {
+            // 3. 优先从third_party_api_log表查询推送充电订单信息
+            ThirdPartyApiLog apiLog = thirdPartyApiLogMapper.selectOne(
+                    Wrappers.<ThirdPartyApiLog>lambdaQuery()
+                            .eq(ThirdPartyApiLog::getInterfaceDescription, "推送充电订单信息")
+                            .like(ThirdPartyApiLog::getDecryptedRequestData, order.getStartChargeSeq())
+                            .orderByDesc(ThirdPartyApiLog::getCreatedTime)
+                            .last("LIMIT 1"));
+            
+            if (apiLog != null && apiLog.getDecryptedRequestData() != null) {
+                // 使用API日志中的推送数据处理订单
+                boolean success = repairOrderFromApiLogByOrderNo(order, apiLog);
+                if (success) {
+                    // 设置补偿状态为已补偿
+                    order.setCompensateStatus(1);
+                    this.updateById(order);
+                    log.info("订单{}通过API日志修复成功", chargeOrderNo);
+                    return "订单" + chargeOrderNo + "通过API日志修复成功,实际费用: " + order.getRealCost();
+                }
+            }
+            
+            // 4. 备选方案:从third_party_charge_status表查询
+            ThirdPartyChargeStatus chargeStatus = chargeStatusMapper.selectOne(
+                    Wrappers.<ThirdPartyChargeStatus>lambdaQuery()
+                            .eq(ThirdPartyChargeStatus::getStartChargeSeq, order.getStartChargeSeq()));
+            
+            if (chargeStatus == null || chargeStatus.getTotalPower() == null 
+                    || chargeStatus.getTotalPower().compareTo(BigDecimal.ZERO) <= 0) {
+                // 设置补偿状态为异常无须补偿
+                order.setCompensateStatus(2);
+                this.updateById(order);
+                return "订单" + chargeOrderNo + "无有效充电数据,设置为异常无须补偿";
+            }
+            
+            log.info("开始通过充电状态表修复订单: {}, 充电量: {}", chargeOrderNo, chargeStatus.getTotalPower());
+            
+            // 5. 获取站点信息
+            ThirdPartyConnectorInfo connectorInfo = connectorInfoMapper.selectOne(
+                    Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
+                            .eq(ThirdPartyConnectorInfo::getConnectorId, order.getConnectorId())
+                            .last("LIMIT 1"));
+            if (connectorInfo == null) {
+                return "订单" + chargeOrderNo + "找不到充电接口信息";
+            }
+            
+            ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectOne(
+                    Wrappers.<ThirdPartyStationInfo>lambdaQuery()
+                            .eq(ThirdPartyStationInfo::getStationId, connectorInfo.getStationId())
+                            .last("LIMIT 1"));
+            if (stationInfo == null) {
+                return "订单" + chargeOrderNo + "找不到站点信息";
+            }
+            
+            // 6. 设置第三方费用信息
+            order.setTotalCharge(chargeStatus.getTotalPower());
+            order.setThirdPartyTotalCost(chargeStatus.getTotalMoney() != null ? chargeStatus.getTotalMoney() : BigDecimal.ZERO);
+            order.setThirdPartyServerfee(chargeStatus.getServiceMoney() != null ? chargeStatus.getServiceMoney() : BigDecimal.ZERO);
+            order.setThirdPartyElecfee(chargeStatus.getElecMoney() != null ? chargeStatus.getElecMoney() : BigDecimal.ZERO);
+            
+            // 7. 计算平台服务费
+            BigDecimal serviceFee = calculateServiceFee(order, chargeStatus, stationInfo);
+            
+            // 8. 更新订单信息
+            order.setRealServiceCost(serviceFee.setScale(2, RoundingMode.HALF_UP));
+            order.setRealCost(serviceFee.add(order.getThirdPartyTotalCost()));
+            
+            // 设置充电时间
+            if (chargeStatus.getStartTime() != null && chargeStatus.getEndTime() != null) {
+                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                order.setStartTime(chargeStatus.getStartTime().format(formatter));
+                order.setEndTime(chargeStatus.getEndTime().format(formatter));
+                order.setChargeTime(DateUtils.getDuration(order.getStartTime(), order.getEndTime()));
+            }
+            
+            // 设置修复备注
+            order.setRemark("通过补偿修复处理");
+            // 设置补偿状态为已补偿
+            order.setCompensateStatus(1);
+            
+            this.updateById(order);
+            
+            // 9. 执行账户余额扣减(仅平台订单和企业订单)
+            if (Objects.equals(order.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_PLATFORM)
+                    || Objects.equals(order.getOrderType(), SystemConstants.STATUS_ONE)) {
+                orderSettlement(order.getId());
+                log.info("订单{}余额扣减完成", chargeOrderNo);
+            }
+            
+            log.info("订单{}通过充电状态表修复成功,实际费用: {}", chargeOrderNo, order.getRealCost());
+            return "订单" + chargeOrderNo + "通过充电状态表修复成功,实际费用: " + order.getRealCost();
+            
+        } catch (Exception e) {
+            log.error("修复订单{}失败: {}", chargeOrderNo, e.getMessage(), e);
+            throw new BusinessException("修复订单失败: " + e.getMessage());
+        }
+    }
+    
+    /**
+     * 通过API日志修复单个订单(根据订单号)
+     * @param order 订单信息
+     * @param apiLog API日志
+     * @return 是否处理成功
+     */
+    private boolean repairOrderFromApiLogByOrderNo(ChargeOrderInfo order, ThirdPartyApiLog apiLog) {
+        try {
+            JsonNode jsonNode = objectMapper.readTree(apiLog.getDecryptedRequestData());
+            
+            // 解析推送数据
+            String startChargeSeq = getJsonTextValue(jsonNode, "StartChargeSeq");
+            if (startChargeSeq == null || !startChargeSeq.equals(order.getStartChargeSeq())) {
+                log.warn("订单{}的StartChargeSeq不匹配,跳过API日志处理", order.getChargeOrderNo());
+                return false;
+            }
+            
+            String totalPowerStr = getJsonTextValue(jsonNode, "TotalPower");
+            if (totalPowerStr == null || new BigDecimal(totalPowerStr).compareTo(BigDecimal.ZERO) <= 0) {
+                log.info("订单{}的API日志充电量为0,跳过处理", order.getChargeOrderNo());
+                return false;
+            }
+            
+            log.info("开始通过API日志修复订单: {}, 充电量: {}", order.getChargeOrderNo(), totalPowerStr);
+            
+            // 设置充电信息
+            order.setTotalCharge(new BigDecimal(totalPowerStr));
+            order.setStopReason(getJsonTextValue(jsonNode, "StopReason"));
+            order.setStartTime(getJsonTextValue(jsonNode, "StartTime"));
+            order.setEndTime(getJsonTextValue(jsonNode, "EndTime"));
+            order.setChargeDetails(jsonNode.toString());
+            
+            // 第三方费用
+            String totalMoney = getJsonTextValue(jsonNode, "TotalMoney");
+            String totalSeviceMoney = getJsonTextValue(jsonNode, "TotalSeviceMoney");
+            String totalElecMoney = getJsonTextValue(jsonNode, "TotalElecMoney");
+            order.setThirdPartyTotalCost(totalMoney != null ? new BigDecimal(totalMoney) : BigDecimal.ZERO);
+            order.setThirdPartyServerfee(totalSeviceMoney != null ? new BigDecimal(totalSeviceMoney) : BigDecimal.ZERO);
+            order.setThirdPartyElecfee(totalElecMoney != null ? new BigDecimal(totalElecMoney) : BigDecimal.ZERO);
+            
+            // 获取连接器和站点信息
+            String connectorId = getJsonTextValue(jsonNode, "ConnectorID");
+            if (connectorId == null) {
+                connectorId = order.getConnectorId();
+            }
+            
+            ThirdPartyConnectorInfo connectorInfo = connectorInfoMapper.selectOne(
+                    Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
+                            .eq(ThirdPartyConnectorInfo::getConnectorId, connectorId)
+                            .last("LIMIT 1"));
+            if (connectorInfo == null) {
+                log.warn("订单{}找不到充电接口信息", order.getChargeOrderNo());
+                return false;
+            }
+            
+            ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectOne(
+                    Wrappers.<ThirdPartyStationInfo>lambdaQuery()
+                            .eq(ThirdPartyStationInfo::getStationId, connectorInfo.getStationId())
+                            .last("LIMIT 1"));
+            if (stationInfo == null) {
+                log.warn("订单{}找不到站点信息", order.getChargeOrderNo());
+                return false;
+            }
+            
+            // 计算平台服务费(从ChargeDetails中解析)
+            BigDecimal serviceFee = calculateServiceFeeFromChargeDetails(order, jsonNode, stationInfo);
+            
+            // 更新订单信息
+            order.setRealServiceCost(serviceFee.setScale(2, RoundingMode.HALF_UP));
+            order.setRealCost(serviceFee.add(order.getThirdPartyTotalCost()));
+            
+            // 计算充电时间
+            if (order.getStartTime() != null && order.getEndTime() != null) {
+                order.setChargeTime(DateUtils.getDuration(order.getStartTime(), order.getEndTime()));
+            }
+            
+            // 设置修复备注
+            order.setRemark("通过补偿修复处理");
+            
+            this.updateById(order);
+            
+            // 执行账户余额扣减(仅平台订单和企业订单)
+            if (Objects.equals(order.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_PLATFORM)
+                    || Objects.equals(order.getOrderType(), SystemConstants.STATUS_ONE)) {
+                orderSettlement(order.getId());
+                log.info("订单{}余额扣减完成", order.getChargeOrderNo());
+            }
+            
+            log.info("订单{}通过API日志处理成功,实际费用: {}", order.getChargeOrderNo(), order.getRealCost());
+            return true;
+            
+        } catch (Exception e) {
+            log.error("通过API日志处理订单{}失败: {}", order.getChargeOrderNo(), e.getMessage(), e);
+            return false;
+        }
+    }
+    
+    /**
+     * 判断BigDecimal是否为null或0
+     * @param value 要判断的值
+     * @return 如果为null或0返回true,否则返回false
+     */
+    private boolean isZeroOrNull(BigDecimal value) {
+        return value == null || value.compareTo(BigDecimal.ZERO) == 0;
+    }
+
+    /**
+     * 补偿未处理的充电订单(定时任务调用)
+     * 查找状态为3(已完成)或5(未成功充电)且充电数据为0的订单
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String compensateUnprocessedOrders() {
+        log.info("开始执行充电订单补偿定时任务...");
+        
+        // 1. 查询状态为3(已完成)或5(未成功充电)且充电数据为0的订单
+        List<ChargeOrderInfo> unprocessedOrders = this.list(Wrappers.<ChargeOrderInfo>lambdaQuery()
+                .in(ChargeOrderInfo::getStatus, 3, 5)
+                .isNotNull(ChargeOrderInfo::getStartChargeSeq)
+                // 充电度数为0或null
+                .and(wrapper -> wrapper
+                        .isNull(ChargeOrderInfo::getTotalCharge)
+                        .or()
+                        .eq(ChargeOrderInfo::getTotalCharge, BigDecimal.ZERO))
+                // 平台实际收取金额为0或null
+                .and(wrapper -> wrapper
+                        .isNull(ChargeOrderInfo::getRealCost)
+                        .or()
+                        .eq(ChargeOrderInfo::getRealCost, BigDecimal.ZERO))
+                // 平台总服务费为0或null
+                .and(wrapper -> wrapper
+                        .isNull(ChargeOrderInfo::getRealServiceCost)
+                        .or()
+                        .eq(ChargeOrderInfo::getRealServiceCost, BigDecimal.ZERO))
+                // 三方充电消费总额为0或null
+                .and(wrapper -> wrapper
+                        .isNull(ChargeOrderInfo::getThirdPartyTotalCost)
+                        .or()
+                        .eq(ChargeOrderInfo::getThirdPartyTotalCost, BigDecimal.ZERO))
+                // 三方充电服务费为0或null
+                .and(wrapper -> wrapper
+                        .isNull(ChargeOrderInfo::getThirdPartyServerfee)
+                        .or()
+                        .eq(ChargeOrderInfo::getThirdPartyServerfee, BigDecimal.ZERO)));
+        
+        if (unprocessedOrders.isEmpty()) {
+            log.info("充电订单补偿定时任务: 没有找到需要补偿的订单");
+            return "没有找到需要补偿的订单";
+        }
+        
+        log.info("充电订单补偿定时任务: 找到{}个需要补偿的订单", unprocessedOrders.size());
+        
+        int totalCount = 0;
+        int successCount = 0;
+        int skipCount = 0;
+        int apiLogCount = 0;
+        int chargeStatusCount = 0;
+        List<String> failedOrders = new ArrayList<>();
+        
+        for (ChargeOrderInfo order : unprocessedOrders) {
+            totalCount++;
+            try {
+                // 2. 优先从third_party_api_log表查询推送充电订单信息
+                ThirdPartyApiLog apiLog = thirdPartyApiLogMapper.selectOne(
+                        Wrappers.<ThirdPartyApiLog>lambdaQuery()
+                                .eq(ThirdPartyApiLog::getInterfaceDescription, "推送充电订单信息")
+                                .like(ThirdPartyApiLog::getDecryptedRequestData, order.getStartChargeSeq())
+                                .orderByDesc(ThirdPartyApiLog::getCreatedTime)
+                                .last("LIMIT 1"));
+                
+                if (apiLog != null && apiLog.getDecryptedRequestData() != null) {
+                    // 使用API日志中的推送数据处理订单
+                    boolean success = processOrderFromApiLog(order, apiLog);
+                    if (success) {
+                        // 设置补偿状态为已补偿
+                        order.setCompensateStatus(1);
+                        this.updateById(order);
+                        successCount++;
+                        apiLogCount++;
+                        log.info("补偿任务: 订单{}通过API日志补偿成功", order.getChargeOrderNo());
+                        continue;
+                    }
+                }
+                
+                // 3. 备选方案:从third_party_charge_status表查询
+                ThirdPartyChargeStatus chargeStatus = chargeStatusMapper.selectOne(
+                        Wrappers.<ThirdPartyChargeStatus>lambdaQuery()
+                                .eq(ThirdPartyChargeStatus::getStartChargeSeq, order.getStartChargeSeq()));
+                
+                if (chargeStatus == null || chargeStatus.getTotalPower() == null 
+                        || chargeStatus.getTotalPower().compareTo(BigDecimal.ZERO) <= 0) {
+                    log.info("补偿任务: 订单{}无有效充电数据,设置为异常无须补偿", order.getChargeOrderNo());
+                    // 设置补偿状态为异常无须补偿
+                    order.setCompensateStatus(2);
+                    this.updateById(order);
+                    skipCount++;
+                    continue;
+                }
+                
+                log.info("补偿任务: 开始通过充电状态表补偿订单: {}, 充电量: {}", order.getChargeOrderNo(), chargeStatus.getTotalPower());
+                
+                // 4. 获取站点信息
+                ThirdPartyConnectorInfo connectorInfo = connectorInfoMapper.selectOne(
+                        Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
+                                .eq(ThirdPartyConnectorInfo::getConnectorId, order.getConnectorId())
+                                .last("LIMIT 1"));
+                if (connectorInfo == null) {
+                    log.warn("补偿任务: 订单{}找不到充电接口信息", order.getChargeOrderNo());
+                    failedOrders.add(order.getChargeOrderNo());
+                    continue;
+                }
+                
+                ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectOne(
+                        Wrappers.<ThirdPartyStationInfo>lambdaQuery()
+                                .eq(ThirdPartyStationInfo::getStationId, connectorInfo.getStationId())
+                                .last("LIMIT 1"));
+                if (stationInfo == null) {
+                    log.warn("补偿任务: 订单{}找不到站点信息", order.getChargeOrderNo());
+                    failedOrders.add(order.getChargeOrderNo());
+                    continue;
+                }
+                
+                // 5. 设置第三方费用信息
+                order.setTotalCharge(chargeStatus.getTotalPower());
+                order.setThirdPartyTotalCost(chargeStatus.getTotalMoney() != null ? chargeStatus.getTotalMoney() : BigDecimal.ZERO);
+                order.setThirdPartyServerfee(chargeStatus.getServiceMoney() != null ? chargeStatus.getServiceMoney() : BigDecimal.ZERO);
+                order.setThirdPartyElecfee(chargeStatus.getElecMoney() != null ? chargeStatus.getElecMoney() : BigDecimal.ZERO);
+                
+                // 6. 计算平台服务费
+                BigDecimal serviceFee = calculateServiceFee(order, chargeStatus, stationInfo);
+                
+                // 7. 更新订单信息
+                order.setRealServiceCost(serviceFee.setScale(2, RoundingMode.HALF_UP));
+                order.setRealCost(serviceFee.add(order.getThirdPartyTotalCost()));
+                order.setStatus(SystemConstants.STATUS_THREE); // 已完成
+                
+                // 设置充电时间
+                if (chargeStatus.getStartTime() != null && chargeStatus.getEndTime() != null) {
+                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                    order.setStartTime(chargeStatus.getStartTime().format(formatter));
+                    order.setEndTime(chargeStatus.getEndTime().format(formatter));
+                    order.setChargeTime(DateUtils.getDuration(order.getStartTime(), order.getEndTime()));
+                }
+                
+                // 设置修复备注
+                order.setRemark("通过补偿修复处理");
+                
+                this.updateById(order);
+                
+                // 8. 执行账户余额扣减(仅平台订单和企业订单)
+                if (Objects.equals(order.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_PLATFORM)
+                        || Objects.equals(order.getOrderType(), SystemConstants.STATUS_ONE)) {
+                    orderSettlement(order.getId());
+                    log.info("补偿任务: 订单{}余额扣减完成", order.getChargeOrderNo());
+                }
+                
+                successCount++;
+                chargeStatusCount++;
+                log.info("补偿任务: 订单{}通过充电状态表补偿成功,实际费用: {}", order.getChargeOrderNo(), order.getRealCost());
+                
+            } catch (Exception e) {
+                log.error("补偿任务: 补偿订单{}失败: {}", order.getChargeOrderNo(), e.getMessage(), e);
+                failedOrders.add(order.getChargeOrderNo());
+            }
+        }
+        
+        String result = String.format("充电订单补偿完成!总计: %d, 成功: %d (API日志: %d, 充电状态: %d), 跳过: %d, 失败: %d", 
+                totalCount, successCount, apiLogCount, chargeStatusCount, skipCount, failedOrders.size());
+        if (!failedOrders.isEmpty()) {
+            result += ", 失败订单: " + String.join(",", failedOrders);
+        }
+        log.info(result);
+        return result;
+    }
+
 }

+ 2 - 2
src/main/java/com/zsElectric/boot/charging/quartz/ChargingJob.java

@@ -45,7 +45,7 @@ public class ChargingJob {
      * 同步充电站信息
      * 每5分钟执行一次,从第三方接口获取充电站信息并存储到数据库
      */
-    @Scheduled(cron = "0 0/15 * * * ?")
+//    @Scheduled(cron = "0 0/15 * * * ?")
     public void syncStationsInfo() {
         log.info("开始执行充电站信息同步定时任务");
 
@@ -82,7 +82,7 @@ public class ChargingJob {
      * 每10分钟执行一次,查询所有充电桩的价格策略并存储到数据库
      * cron表达式: 0 10 * * * ? 表示每10分钟执行
      */
-    @Scheduled(cron = "0 */10 * * * ?")
+//    @Scheduled(cron = "0 */10 * * * ?")
     public void syncEquipmentPricePolicy() {
         // 检查任务是否正在执行,防止并发
         if (isPricePolicySyncRunning) {

+ 261 - 243
src/main/java/com/zsElectric/boot/charging/service/impl/ChargingReceptionServiceImpl.java

@@ -91,7 +91,7 @@ public class ChargingReceptionServiceImpl implements ChargingReceptionService {
     /**
      * 锁等待时间(秒)
      */
-    private static final long LOCK_WAIT_TIME = 3;
+    private static final long LOCK_WAIT_TIME = 5;
     /**
      * 锁持有时间(秒)
      */
@@ -162,253 +162,265 @@ public class ChargingReceptionServiceImpl implements ChargingReceptionService {
             final String finalStartChargeSeq = startChargeSeq;
             
             try {
-                if (lock.tryLock(LOCK_WAIT_TIME, LOCK_LEASE_TIME, java.util.concurrent.TimeUnit.SECONDS)) {
-                    try {
-                        // 加锁后重新查询订单状态,确保状态最新
-                        ChargeOrderInfo chargeOrderInfo = chargeOrderInfoService.getOne(new LambdaQueryWrapper<ChargeOrderInfo>()
-                                .eq(ChargeOrderInfo::getStartChargeSeq, finalStartChargeSeq).last("LIMIT 1"));
-
-                        if (ObjectUtil.isNotEmpty(chargeOrderInfo)) {
-                            // 检查订单状态,如果已经是已完成状态,则跳过处理
-                            if (Objects.equals(chargeOrderInfo.getStatus(), SystemConstants.STATUS_THREE)) {
-                                log.info("订单已完成,跳过处理 - startChargeSeq: {}", finalStartChargeSeq);
-                                businessHandler.accept(jsonNode);
-                                return buildChargeResponse(finalStartChargeSeq);
-                            }
+                // 阻塞等待获取锁,确保订单处理不会被跳过
+                lock.lock(LOCK_LEASE_TIME, java.util.concurrent.TimeUnit.SECONDS);
+                try {
+                    log.info("成功获取订单锁 - StartChargeSeq: {}", finalStartChargeSeq);
+                    // 加锁后重新查询订单状态,确保状态最新
+                    ChargeOrderInfo chargeOrderInfo = chargeOrderInfoService.getOne(new LambdaQueryWrapper<ChargeOrderInfo>()
+                            .eq(ChargeOrderInfo::getStartChargeSeq, finalStartChargeSeq).last("LIMIT 1"));
+
+                    if (ObjectUtil.isNotEmpty(chargeOrderInfo)) {
+                        // 检查订单状态,如果已经是已完成状态,则跳过处理
+                        if (Objects.equals(chargeOrderInfo.getStatus(), SystemConstants.STATUS_THREE)) {
+                            log.info("订单已完成,跳过处理 - startChargeSeq: {}", finalStartChargeSeq);
+                            businessHandler.accept(jsonNode);
+                            return buildChargeResponse(finalStartChargeSeq);
+                        }
                             
-                            if (Objects.equals(chargeOrderInfo.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_CHANNEL)) {
-                                //订单信息渠道方推送
-                                Map<String, Object> map = objectMapper.convertValue(jsonNode, Map.class);
-                                map.put("chargeOrderNo", chargeOrderInfo.getChargeOrderNo());
-                                FirmInfo firmInfo = firmInfoMapper.selectById(chargeOrderInfo.getFirmId());
-                                if (ObjectUtil.isNotNull(firmInfo)) {
-                                    okHttpUtil.doPostForm(firmInfo.getChannelUrl() + "/notification_charge_order_info", map, null);
+                        if (Objects.equals(chargeOrderInfo.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_CHANNEL)) {
+                            //订单信息渠道方推送
+                            Map<String, Object> map = objectMapper.convertValue(jsonNode, Map.class);
+                            map.put("chargeOrderNo", chargeOrderInfo.getChargeOrderNo());
+                            FirmInfo firmInfo = firmInfoMapper.selectById(chargeOrderInfo.getFirmId());
+                            if (ObjectUtil.isNotNull(firmInfo)) {
+                                try {
+                                    JsonNode response = okHttpUtil.doPostForm(firmInfo.getChannelUrl() + "/notification_charge_order_info", map, null);
+                                    log.info("渠道方推送充电订单信息成功 - chargeOrderNo: {}, firmId: {}, response: {}", 
+                                            chargeOrderInfo.getChargeOrderNo(), chargeOrderInfo.getFirmId(), response);
+                                } catch (Exception e) {
+                                    log.error("渠道方推送充电订单信息失败 - chargeOrderNo: {}, firmId: {}, channelUrl: {}, 错误信息: {}", 
+                                            chargeOrderInfo.getChargeOrderNo(), chargeOrderInfo.getFirmId(), 
+                                            firmInfo.getChannelUrl() + "/notification_charge_order_info", e.getMessage(), e);
                                 }
+                            } else {
+                                log.warn("渠道方推送充电订单信息失败 - firmInfo为空, chargeOrderNo: {}, firmId: {}", 
+                                        chargeOrderInfo.getChargeOrderNo(), chargeOrderInfo.getFirmId());
                             }
-                            //推送订单明细
-                            chargeOrderInfo.setChargeDetails(jsonNode.toString());
-
-                            //优惠单价
-                            BigDecimal discountPrice = BigDecimal.ZERO;
-
-                            if (Objects.equals(chargeOrderInfo.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_PLATFORM)) {
-                                //判断当前订单是否为首单
-                                Long userId = chargeOrderInfo.getUserId();
-                                List<ChargeOrderInfo> list = chargeOrderInfoService.list(Wrappers.<ChargeOrderInfo>lambdaQuery().eq(ChargeOrderInfo::getUserId, userId).eq(ChargeOrderInfo::getStatus,
-                                        SystemConstants.STATUS_THREE));
-                                if (ObjectUtil.isEmpty(list)) {
-                                    DiscountsActivity discountsActivity = discountsActivityMapper.selectOne(Wrappers.<DiscountsActivity>lambdaQuery()
-                                            .eq(DiscountsActivity::getType, SystemConstants.STATUS_ONE)
-                                            .eq(DiscountsActivity::getStatus, SystemConstants.STATUS_ONE)
-                                            .last("LIMIT 1"));
-                                    if (ObjectUtil.isNotEmpty(discountsActivity)) {
-                                        chargeOrderInfo.setDiscountInfoId(discountsActivity.getId());
-                                        chargeOrderInfo.setDiscountDesc(discountsActivity.getActivityDesc());
-                                        discountPrice = discountsActivity.getDiscount();
-                                    }
+                        }
+                        //推送订单明细
+                        chargeOrderInfo.setChargeDetails(jsonNode.toString());
+
+                        //优惠单价
+                        BigDecimal discountPrice = BigDecimal.ZERO;
+
+                        if (Objects.equals(chargeOrderInfo.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_PLATFORM)) {
+                            //判断当前订单是否为首单
+                            Long userId = chargeOrderInfo.getUserId();
+                            List<ChargeOrderInfo> list = chargeOrderInfoService.list(Wrappers.<ChargeOrderInfo>lambdaQuery().eq(ChargeOrderInfo::getUserId, userId).eq(ChargeOrderInfo::getStatus,
+                                    SystemConstants.STATUS_THREE));
+                            if (ObjectUtil.isEmpty(list)) {
+                                DiscountsActivity discountsActivity = discountsActivityMapper.selectOne(Wrappers.<DiscountsActivity>lambdaQuery()
+                                        .eq(DiscountsActivity::getType, SystemConstants.STATUS_ONE)
+                                        .eq(DiscountsActivity::getStatus, SystemConstants.STATUS_ONE)
+                                        .last("LIMIT 1"));
+                                if (ObjectUtil.isNotEmpty(discountsActivity)) {
+                                    chargeOrderInfo.setDiscountInfoId(discountsActivity.getId());
+                                    chargeOrderInfo.setDiscountDesc(discountsActivity.getActivityDesc());
+                                    discountPrice = discountsActivity.getDiscount();
                                 }
                             }
+                        }
 
-                            chargeOrderInfo.setStopReason(stopReason);
-                            chargeOrderInfo.setStartTime(startTime);
-                            chargeOrderInfo.setEndTime(endTime);
-                            chargeOrderInfo.setTotalCharge(new BigDecimal(totalPower));
-
-                            chargeOrderInfo.setThirdPartyTotalCost(new BigDecimal(totalMoney));
-                            chargeOrderInfo.setThirdPartyServerfee(new BigDecimal(totalSeviceMoney));
-                            chargeOrderInfo.setThirdPartyElecfee(new BigDecimal(totalElecMoney));
-
-                            ThirdPartyConnectorInfo thirdPartyConnectorInfo = connectorInfoMapper.selectOne(Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
-                                    .eq(ThirdPartyConnectorInfo::getConnectorId, connectorID).last("LIMIT 1"));
-                            String stationId = thirdPartyConnectorInfo.getStationId();
-                            ThirdPartyStationInfo thirdPartyStationInfo = thirdPartyStationInfoMapper.selectOne(Wrappers.<ThirdPartyStationInfo>lambdaQuery()
-                                    .eq(ThirdPartyStationInfo::getStationId, stationId).last("LIMIT 1"));
-                            if (ObjectUtil.isEmpty(thirdPartyConnectorInfo)) {
-                                log.error("thirdPartyConnectorInfo" + "为空===============================================");
-                            }
+                        chargeOrderInfo.setStopReason(stopReason);
+                        chargeOrderInfo.setStartTime(startTime);
+                        chargeOrderInfo.setEndTime(endTime);
+                        chargeOrderInfo.setTotalCharge(new BigDecimal(totalPower));
+
+                        chargeOrderInfo.setThirdPartyTotalCost(new BigDecimal(totalMoney));
+                        chargeOrderInfo.setThirdPartyServerfee(new BigDecimal(totalSeviceMoney));
+                        chargeOrderInfo.setThirdPartyElecfee(new BigDecimal(totalElecMoney));
+
+                        ThirdPartyConnectorInfo thirdPartyConnectorInfo = connectorInfoMapper.selectOne(Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
+                                .eq(ThirdPartyConnectorInfo::getConnectorId, connectorID).last("LIMIT 1"));
+                        String stationId = thirdPartyConnectorInfo.getStationId();
+                        ThirdPartyStationInfo thirdPartyStationInfo = thirdPartyStationInfoMapper.selectOne(Wrappers.<ThirdPartyStationInfo>lambdaQuery()
+                                .eq(ThirdPartyStationInfo::getStationId, stationId).last("LIMIT 1"));
+                        if (ObjectUtil.isEmpty(thirdPartyConnectorInfo)) {
+                            log.error("thirdPartyConnectorInfo" + "为空===============================================");
+                        }
 
-                            //平台服务费
-                            BigDecimal serviceFee = BigDecimal.ZERO;
-                            //优惠金额
-                            BigDecimal discountFee = BigDecimal.ZERO;
-                            JsonNode chargeDetails = jsonNode.get("ChargeDetails");
-                            if (ObjectUtil.isNotEmpty(chargeDetails)) {
-                                for (JsonNode node : chargeDetails) {
-                                    //提取字段值
-                                    String itemFlag = node.get("ItemFlag").asText();
-                                    node.get("DetailPower").asText();
-                                    BigDecimal detailPower = new BigDecimal(node.get("DetailPower").asText());
-                                    PolicyFee policyFee = policyFeeMapper.selectOne(Wrappers.<PolicyFee>lambdaQuery()
-                                            .eq(PolicyFee::getStationInfoId, thirdPartyStationInfo.getId())
-                                            .eq(PolicyFee::getPeriodFlag, Integer.parseInt(itemFlag))
-                                            .last("LIMIT 1"));
-                                    if (ObjectUtil.isNotEmpty(policyFee)) {
-                                        BigDecimal opFee = policyFee.getOpFee();
-                                        if (ObjectUtil.isNotEmpty(chargeOrderInfo.getDiscountInfoId())) {
-                                            opFee = opFee.subtract(discountPrice);
-                                        }
-                                        log.info("策略费用:{}", opFee);
-                                        serviceFee = serviceFee.add(opFee.multiply(detailPower));
-                                        discountFee = discountFee.add(discountPrice.multiply(detailPower));
+                        //平台服务费
+                        BigDecimal serviceFee = BigDecimal.ZERO;
+                        //优惠金额
+                        BigDecimal discountFee = BigDecimal.ZERO;
+                        JsonNode chargeDetails = jsonNode.get("ChargeDetails");
+                        if (ObjectUtil.isNotEmpty(chargeDetails)) {
+                            for (JsonNode node : chargeDetails) {
+                                //提取字段值
+                                String itemFlag = node.get("ItemFlag").asText();
+                                node.get("DetailPower").asText();
+                                BigDecimal detailPower = new BigDecimal(node.get("DetailPower").asText());
+                                PolicyFee policyFee = policyFeeMapper.selectOne(Wrappers.<PolicyFee>lambdaQuery()
+                                        .eq(PolicyFee::getStationInfoId, thirdPartyStationInfo.getId())
+                                        .eq(PolicyFee::getPeriodFlag, Integer.parseInt(itemFlag))
+                                        .last("LIMIT 1"));
+                                if (ObjectUtil.isNotEmpty(policyFee)) {
+                                    BigDecimal opFee = policyFee.getOpFee();
+                                    if (ObjectUtil.isNotEmpty(chargeOrderInfo.getDiscountInfoId())) {
+                                        opFee = opFee.subtract(discountPrice);
                                     }
+                                    log.info("策略费用:{}", opFee);
+                                    serviceFee = serviceFee.add(opFee.multiply(detailPower));
+                                    discountFee = discountFee.add(discountPrice.multiply(detailPower));
                                 }
-                            } else {
-                                log.error("充电订单明细为空===============================================");
-                                if (chargeOrderInfo.getThirdPartyTotalCost().compareTo(BigDecimal.ZERO) > 0 && chargeOrderInfo.getTotalCharge().compareTo(BigDecimal.ZERO) > 0) {
-                                    //判断当前订单创建时间在哪个时段
-                                    ThirdPartyChargeStatus thirdPartyChargeStatus = chargeStatusMapper.selectOne(Wrappers.<ThirdPartyChargeStatus>lambdaQuery()
-                                            .eq(ThirdPartyChargeStatus::getStartChargeSeq, chargeOrderInfo.getStartChargeSeq()));
-
-                                    ThirdPartyEquipmentPricePolicy thirdPartyEquipmentPricePolicy = thirdPartyEquipmentPricePolicyMapper.selectOne(Wrappers.<ThirdPartyEquipmentPricePolicy>lambdaQuery()
-                                            .eq(ThirdPartyEquipmentPricePolicy::getConnectorId, thirdPartyChargeStatus.getConnectorId())
-                                            .last("LIMIT 1"));
-                                    
-                                    // 查询该价格策略下的所有时段信息,按startTime升序排列
-                                    List<ThirdPartyPolicyInfo> allPolicyInfos = thirdPartyPolicyInfoMapper.selectList(Wrappers.<ThirdPartyPolicyInfo>lambdaQuery()
-                                            .eq(ThirdPartyPolicyInfo::getPricePolicyId, thirdPartyEquipmentPricePolicy.getId())
-                                            .orderByAsc(ThirdPartyPolicyInfo::getStartTime));
-                                    
-                                    // 将充电开始时间和结束时间转换为HHmmss格式字符串进行匹配
-                                    LocalDateTime chargeStartTime = thirdPartyChargeStatus.getStartTime();
-                                    LocalDateTime chargeEndTime = thirdPartyChargeStatus.getEndTime();
-                                    String chargeStartTimeStr = chargeStartTime.format(DateTimeFormatter.ofPattern("HHmmss"));
-                                    String chargeEndTimeStr = chargeEndTime.format(DateTimeFormatter.ofPattern("HHmmss"));
-                                    
-                                    // 找到充电开始时间所在的时段索引
-                                    int startIndex = -1;
-                                    for (int i = allPolicyInfos.size() - 1; i >= 0; i--) {
-                                        if (chargeStartTimeStr.compareTo(allPolicyInfos.get(i).getStartTime()) >= 0) {
-                                            startIndex = i;
-                                            break;
-                                        }
+                            }
+                        } else {
+                            log.error("充电订单明细为空===============================================");
+                            if (chargeOrderInfo.getThirdPartyTotalCost().compareTo(BigDecimal.ZERO) > 0 && chargeOrderInfo.getTotalCharge().compareTo(BigDecimal.ZERO) > 0) {
+                                //判断当前订单创建时间在哪个时段
+                                ThirdPartyChargeStatus thirdPartyChargeStatus = chargeStatusMapper.selectOne(Wrappers.<ThirdPartyChargeStatus>lambdaQuery()
+                                        .eq(ThirdPartyChargeStatus::getStartChargeSeq, chargeOrderInfo.getStartChargeSeq()));
+
+                                ThirdPartyEquipmentPricePolicy thirdPartyEquipmentPricePolicy = thirdPartyEquipmentPricePolicyMapper.selectOne(Wrappers.<ThirdPartyEquipmentPricePolicy>lambdaQuery()
+                                        .eq(ThirdPartyEquipmentPricePolicy::getConnectorId, thirdPartyChargeStatus.getConnectorId())
+                                        .last("LIMIT 1"));
+                                
+                                // 查询该价格策略下的所有时段信息,按startTime升序排列
+                                List<ThirdPartyPolicyInfo> allPolicyInfos = thirdPartyPolicyInfoMapper.selectList(Wrappers.<ThirdPartyPolicyInfo>lambdaQuery()
+                                        .eq(ThirdPartyPolicyInfo::getPricePolicyId, thirdPartyEquipmentPricePolicy.getId())
+                                        .orderByAsc(ThirdPartyPolicyInfo::getStartTime));
+                                
+                                // 将充电开始时间和结束时间转换为HHmmss格式字符串进行匹配
+                                LocalDateTime chargeStartTime = thirdPartyChargeStatus.getStartTime();
+                                LocalDateTime chargeEndTime = thirdPartyChargeStatus.getEndTime();
+                                String chargeStartTimeStr = chargeStartTime.format(DateTimeFormatter.ofPattern("HHmmss"));
+                                String chargeEndTimeStr = chargeEndTime.format(DateTimeFormatter.ofPattern("HHmmss"));
+                                
+                                // 找到充电开始时间所在的时段索引
+                                int startIndex = -1;
+                                for (int i = allPolicyInfos.size() - 1; i >= 0; i--) {
+                                    if (chargeStartTimeStr.compareTo(allPolicyInfos.get(i).getStartTime()) >= 0) {
+                                        startIndex = i;
+                                        break;
                                     }
-                                    if (startIndex == -1 && !allPolicyInfos.isEmpty()) {
-                                        startIndex = allPolicyInfos.size() - 1;
+                                }
+                                if (startIndex == -1 && !allPolicyInfos.isEmpty()) {
+                                    startIndex = allPolicyInfos.size() - 1;
+                                }
+                                
+                                // 找到充电结束时间所在的时段索引
+                                int endIndex = -1;
+                                for (int i = allPolicyInfos.size() - 1; i >= 0; i--) {
+                                    if (chargeEndTimeStr.compareTo(allPolicyInfos.get(i).getStartTime()) >= 0) {
+                                        endIndex = i;
+                                        break;
                                     }
-                                    
-                                    // 找到充电结束时间所在的时段索引
-                                    int endIndex = -1;
-                                    for (int i = allPolicyInfos.size() - 1; i >= 0; i--) {
-                                        if (chargeEndTimeStr.compareTo(allPolicyInfos.get(i).getStartTime()) >= 0) {
-                                            endIndex = i;
-                                            break;
+                                }
+                                if (endIndex == -1 && !allPolicyInfos.isEmpty()) {
+                                    endIndex = allPolicyInfos.size() - 1;
+                                }
+                                
+                                // 获取充电时间跨越的所有时段集合
+                                List<ThirdPartyPolicyInfo> matchedPolicyInfos = new ArrayList<>();
+                                if (startIndex != -1 && endIndex != -1) {
+                                    if (startIndex <= endIndex) {
+                                        // 同一天内:从开始时段到结束时段
+                                        for (int i = startIndex; i <= endIndex; i++) {
+                                            matchedPolicyInfos.add(allPolicyInfos.get(i));
                                         }
-                                    }
-                                    if (endIndex == -1 && !allPolicyInfos.isEmpty()) {
-                                        endIndex = allPolicyInfos.size() - 1;
-                                    }
-                                    
-                                    // 获取充电时间跨越的所有时段集合
-                                    List<ThirdPartyPolicyInfo> matchedPolicyInfos = new ArrayList<>();
-                                    if (startIndex != -1 && endIndex != -1) {
-                                        if (startIndex <= endIndex) {
-                                            // 同一天内:从开始时段到结束时段
-                                            for (int i = startIndex; i <= endIndex; i++) {
-                                                matchedPolicyInfos.add(allPolicyInfos.get(i));
-                                            }
-                                        } else {
-                                            // 跨天情况:从开始时段到最后 + 从第一个到结束时段
-                                            for (int i = startIndex; i < allPolicyInfos.size(); i++) {
-                                                matchedPolicyInfos.add(allPolicyInfos.get(i));
-                                            }
-                                            for (int i = 0; i <= endIndex; i++) {
-                                                matchedPolicyInfos.add(allPolicyInfos.get(i));
-                                            }
+                                    } else {
+                                        // 跨天情况:从开始时段到最后 + 从第一个到结束时段
+                                        for (int i = startIndex; i < allPolicyInfos.size(); i++) {
+                                            matchedPolicyInfos.add(allPolicyInfos.get(i));
+                                        }
+                                        for (int i = 0; i <= endIndex; i++) {
+                                            matchedPolicyInfos.add(allPolicyInfos.get(i));
                                         }
                                     }
-                                    
-                                    log.info("充电时间段:{} - {},匹配到{}个时段", chargeStartTimeStr, chargeEndTimeStr, matchedPolicyInfos.size());
-                                    
-                                    // 遍历所有匹配的时段,找到费用最高的时段计算服务费
-                                    if (!matchedPolicyInfos.isEmpty()) {
-                                        PolicyFee maxPolicyFee = null;
-                                        ThirdPartyPolicyInfo maxPolicyInfo = null;
-                                        for (ThirdPartyPolicyInfo policyInfo : matchedPolicyInfos) {
-                                            PolicyFee policyFee = policyFeeMapper.selectOne(Wrappers.<PolicyFee>lambdaQuery()
-                                                    .eq(PolicyFee::getStationInfoId, thirdPartyStationInfo.getId())
-                                                    .eq(PolicyFee::getPeriodFlag, policyInfo.getPeriodFlag())
-                                                    .last("LIMIT 1"));
-                                            if (ObjectUtil.isNotEmpty(policyFee)) {
-                                                if (maxPolicyFee == null || policyFee.getOpFee().compareTo(maxPolicyFee.getOpFee()) > 0) {
-                                                    maxPolicyFee = policyFee;
-                                                    maxPolicyInfo = policyInfo;
-                                                }
+                                }
+                                
+                                log.info("充电时间段:{} - {},匹配到{}个时段", chargeStartTimeStr, chargeEndTimeStr, matchedPolicyInfos.size());
+                                
+                                // 遍历所有匹配的时段,找到费用最高的时段计算服务费
+                                if (!matchedPolicyInfos.isEmpty()) {
+                                    PolicyFee maxPolicyFee = null;
+                                    ThirdPartyPolicyInfo maxPolicyInfo = null;
+                                    for (ThirdPartyPolicyInfo policyInfo : matchedPolicyInfos) {
+                                        PolicyFee policyFee = policyFeeMapper.selectOne(Wrappers.<PolicyFee>lambdaQuery()
+                                                .eq(PolicyFee::getStationInfoId, thirdPartyStationInfo.getId())
+                                                .eq(PolicyFee::getPeriodFlag, policyInfo.getPeriodFlag())
+                                                .last("LIMIT 1"));
+                                        if (ObjectUtil.isNotEmpty(policyFee)) {
+                                            if (maxPolicyFee == null || policyFee.getOpFee().compareTo(maxPolicyFee.getOpFee()) > 0) {
+                                                maxPolicyFee = policyFee;
+                                                maxPolicyInfo = policyInfo;
                                             }
                                         }
-                                        if (maxPolicyFee != null) {
-                                            log.info("使用最高费用时段:startTime={}, periodFlag={}, opFee={}", 
-                                                    maxPolicyInfo.getStartTime(), maxPolicyInfo.getPeriodFlag(), maxPolicyFee.getOpFee());
-                                            serviceFee = serviceFee.add(maxPolicyFee.getOpFee().multiply(chargeOrderInfo.getTotalCharge()));
-                                        }
+                                    }
+                                    if (maxPolicyFee != null) {
+                                        log.info("使用最高费用时段:startTime={}, periodFlag={}, opFee={}", 
+                                                maxPolicyInfo.getStartTime(), maxPolicyInfo.getPeriodFlag(), maxPolicyFee.getOpFee());
+                                        serviceFee = serviceFee.add(maxPolicyFee.getOpFee().multiply(chargeOrderInfo.getTotalCharge()));
                                     }
                                 }
                             }
+                        }
 
-                            log.info("计算后的平台服务费:{}", serviceFee);
-                            if (chargeOrderInfo.getOrderType().equals(SystemConstants.CHARGE_ORDER_TYPE_PLATFORM)) {
-                                chargeOrderInfo.setDiscountMoney(discountFee);
-                                chargeOrderInfo.setRealServiceCost(serviceFee.setScale(2, RoundingMode.HALF_UP));
-                                //订单结算:平台实际收取金额 = 互联互通金额 + 中数电动金额(平台总服务费)
-                                chargeOrderInfo.setRealCost(chargeOrderInfo.getRealServiceCost().add(chargeOrderInfo.getThirdPartyTotalCost()));
-
-                                //订单状态->已完成
-                                chargeOrderInfo.setStatus(SystemConstants.STATUS_THREE);
+                        log.info("计算后的平台服务费:{}", serviceFee);
+                        if (chargeOrderInfo.getOrderType().equals(SystemConstants.CHARGE_ORDER_TYPE_PLATFORM)) {
+                            chargeOrderInfo.setDiscountMoney(discountFee);
+                            chargeOrderInfo.setRealServiceCost(serviceFee.setScale(2, RoundingMode.HALF_UP));
+                            //订单结算:平台实际收取金额 = 互联互通金额 + 中数电动金额(平台总服务费)
+                            chargeOrderInfo.setRealCost(chargeOrderInfo.getRealServiceCost().add(chargeOrderInfo.getThirdPartyTotalCost()));
 
-                                //计算充电时间
-                                chargeOrderInfo.setChargeTime(DateUtils.getDuration(chargeOrderInfo.getStartTime(), chargeOrderInfo.getEndTime()));
+                            //订单状态->已完成
+                            chargeOrderInfo.setStatus(SystemConstants.STATUS_THREE);
 
-                                //修改订单
-                                chargeOrderInfoService.updateById(chargeOrderInfo);
+                            //计算充电时间
+                            chargeOrderInfo.setChargeTime(DateUtils.getDuration(chargeOrderInfo.getStartTime(), chargeOrderInfo.getEndTime()));
 
-                                //账户余额扣减(积分增加)
-                                log.info("执行账户余额扣减(积分增加)");
-                                chargeOrderInfoService.orderSettlement(chargeOrderInfo.getId());
-                            }
-                            if (chargeOrderInfo.getOrderType().equals(SystemConstants.CHARGE_ORDER_TYPE_CHANNEL)) {
-                                chargeOrderInfo.setRealServiceCost(BigDecimal.ZERO);
-                                //订单结算:平台实际收取金额 = 互联互通金额 + 中数电动金额(平台总服务费)
-                                chargeOrderInfo.setRealCost(chargeOrderInfo.getRealServiceCost().add(chargeOrderInfo.getThirdPartyTotalCost()));
-                                //订单状态->已完成
-                                chargeOrderInfo.setStatus(SystemConstants.STATUS_THREE);
-                                //计算充电时间
-                                chargeOrderInfo.setChargeTime(DateUtils.getDuration(chargeOrderInfo.getStartTime(), chargeOrderInfo.getEndTime()));
-                                //修改订单
-                                chargeOrderInfoService.updateById(chargeOrderInfo);
-                                //渠道方账户余额扣减
-                                BigDecimal cost = chargeOrderInfo.getRealCost();
-                                FirmInfo firmInfo = firmInfoMapper.selectById(chargeOrderInfo.getFirmId());
-                                FirmAccountLog accountLog = new FirmAccountLog();
-                                accountLog.setFirmId(firmInfo.getId());
-                                accountLog.setFirmType(firmInfo.getFirmType());
-                                accountLog.setEventDesc("渠道方充电订单下账");
-                                accountLog.setSerialNo(chargeOrderInfo.getChargeOrderNo());
-                                accountLog.setIncomeType(2);
-                                accountLog.setBeforeChange(firmInfo.getBalance());
-                                accountLog.setAfterChange(firmInfo.getBalance().subtract(cost));
-                                accountLog.setMoneyChange(cost);
-                                firmAccountLogMapper.insert(accountLog);
-
-                                // 渠道方账户余额修改
-                                firmInfo.setBalance(firmInfo.getBalance().subtract(cost));
-                                firmInfoMapper.updateById(firmInfo);
-                            }
+                            //修改订单
+                            chargeOrderInfoService.updateById(chargeOrderInfo);
 
-                            // 执行业务处理
-                            businessHandler.accept(jsonNode);
+                            //账户余额扣减(积分增加)
+                            log.info("执行账户余额扣减(积分增加)");
+                            chargeOrderInfoService.orderSettlement(chargeOrderInfo.getId());
                         }
-                    } finally {
+                        if (chargeOrderInfo.getOrderType().equals(SystemConstants.CHARGE_ORDER_TYPE_CHANNEL)) {
+                            chargeOrderInfo.setRealServiceCost(BigDecimal.ZERO);
+                            //订单结算:平台实际收取金额 = 互联互通金额 + 中数电动金额(平台总服务费)
+                            chargeOrderInfo.setRealCost(chargeOrderInfo.getRealServiceCost().add(chargeOrderInfo.getThirdPartyTotalCost()));
+                            //订单状态->已完成
+                            chargeOrderInfo.setStatus(SystemConstants.STATUS_THREE);
+                            //计算充电时间
+                            chargeOrderInfo.setChargeTime(DateUtils.getDuration(chargeOrderInfo.getStartTime(), chargeOrderInfo.getEndTime()));
+                            //修改订单
+                            chargeOrderInfoService.updateById(chargeOrderInfo);
+                            //渠道方账户余额扣减
+                            BigDecimal cost = chargeOrderInfo.getRealCost();
+                            FirmInfo firmInfo = firmInfoMapper.selectById(chargeOrderInfo.getFirmId());
+                            FirmAccountLog accountLog = new FirmAccountLog();
+                            accountLog.setFirmId(firmInfo.getId());
+                            accountLog.setFirmType(firmInfo.getFirmType());
+                            accountLog.setEventDesc("渠道方充电订单下账");
+                            accountLog.setSerialNo(chargeOrderInfo.getChargeOrderNo());
+                            accountLog.setIncomeType(2);
+                            accountLog.setBeforeChange(firmInfo.getBalance());
+                            accountLog.setAfterChange(firmInfo.getBalance().subtract(cost));
+                            accountLog.setMoneyChange(cost);
+                            firmAccountLogMapper.insert(accountLog);
+
+                            // 渠道方账户余额修改
+                            firmInfo.setBalance(firmInfo.getBalance().subtract(cost));
+                            firmInfoMapper.updateById(firmInfo);
+                        }
+
+                        // 执行业务处理
+                        businessHandler.accept(jsonNode);
+                    }
+                } finally {
+                    if (lock.isHeldByCurrentThread()) {
                         lock.unlock();
+                        log.info("释放订单锁 - StartChargeSeq: {}", finalStartChargeSeq);
                     }
-                } else {
-                    log.warn("获取订单锁失败 - StartChargeSeq: {}", finalStartChargeSeq);
                 }
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-                log.error("获取订单锁被中断 - StartChargeSeq: {}", finalStartChargeSeq);
+                // 构建响应
+                return buildChargeResponse(startChargeSeq);
+            } catch (Exception e) {
+                log.error("处理订单异常 - StartChargeSeq: {}, 错误: {}", finalStartChargeSeq, e.getMessage());
+                throw new BusinessException("处理订单失败:" + e.getMessage(), e);
             }
-
-            // 构建响应
-            return buildChargeResponse(startChargeSeq);
         } catch (BusinessException e) {
             throw e;
         } catch (Exception e) {
@@ -435,6 +447,7 @@ public class ChargingReceptionServiceImpl implements ChargingReceptionService {
 
             // 推送渠道方启动充电结果
             if(chargeOrderInfo != null && chargeOrderInfo.getFirmId() != null){
+                log.info("推送渠道方启动充电结果 - StartChargeSeq: {}", startChargeSeq);
                 FirmInfo firmInfo = firmInfoMapper.selectById(chargeOrderInfo.getFirmId());
                 if (ObjectUtil.isNotNull(firmInfo)) {
                     HashMap<String, Object> map = new HashMap<>();
@@ -506,22 +519,26 @@ public class ChargingReceptionServiceImpl implements ChargingReceptionService {
                 String lockKey = CHARGE_ORDER_LOCK_KEY + startChargeSeq;
                 RLock lock = redissonClient.getLock(lockKey);
                 try {
-                    if (lock.tryLock(LOCK_WAIT_TIME, LOCK_LEASE_TIME, java.util.concurrent.TimeUnit.SECONDS)) {
-                        try {
-                            // 加锁后重新查询订单状态,确保状态最新
-                            ChargeOrderInfo chargeOrderInfo = chargeOrderInfoService.getOne(new LambdaQueryWrapper<ChargeOrderInfo>()
-                                    .eq(ChargeOrderInfo::getStartChargeSeq, startChargeSeq).last("LIMIT 1"));
-                            
-                            if (ObjectUtil.isNotEmpty(chargeOrderInfo)) {
-                                log.info("已结束 - StartChargeSeq: {}, 当前订单状态: {}", startChargeSeq, chargeOrderInfo.getStatus());
-                                // 仅当状态为0(待充电)或1(充电中)时才更新为结算中,已完成(3)的订单不再处理
-                                if (Objects.equals(chargeOrderInfo.getStatus(), 0) ||
-                                    Objects.equals(chargeOrderInfo.getStatus(), 1)) {
-                                    chargeOrderInfo.setStatus(SystemConstants.STATUS_TWO);
-                                    chargeOrderInfoService.updateById(chargeOrderInfo);
-                                    log.info("更新订单状态为结算中 - orderId: {}", chargeOrderInfo.getId());
-
-                                    // 推送停止充电订单结果
+                    // 阻塞等待获取锁,确保订单处理不会被跳过
+                    lock.lock(LOCK_LEASE_TIME, java.util.concurrent.TimeUnit.SECONDS);
+                    try {
+                        log.info("成功获取订单锁 - StartChargeSeq: {}", startChargeSeq);
+                        // 加锁后重新查询订单状态,确保状态最新
+                        ChargeOrderInfo chargeOrderInfo = chargeOrderInfoService.getOne(new LambdaQueryWrapper<ChargeOrderInfo>()
+                                .eq(ChargeOrderInfo::getStartChargeSeq, startChargeSeq).last("LIMIT 1"));
+                        
+                        if (ObjectUtil.isNotEmpty(chargeOrderInfo)) {
+                            log.info("已结束 - StartChargeSeq: {}, 当前订单状态: {}", startChargeSeq, chargeOrderInfo.getStatus());
+                            // 仅当状态为0(待充电)或1(充电中)时才更新为结算中,已完成(3)的订单不再处理
+                            if (Objects.equals(chargeOrderInfo.getStatus(), 0) ||
+                                Objects.equals(chargeOrderInfo.getStatus(), 1)) {
+                                chargeOrderInfo.setStatus(SystemConstants.STATUS_TWO);
+                                chargeOrderInfoService.updateById(chargeOrderInfo);
+                                log.info("更新订单状态为结算中 - orderId: {}", chargeOrderInfo.getId());
+
+                                // 推送停止充电订单结果
+                                if (Objects.equals(chargeOrderInfo.getOrderType(), SystemConstants.CHARGE_ORDER_TYPE_CHANNEL)) {
+                                    log.info("推送渠道方停止充电结果 - StartChargeSeq: {}", startChargeSeq);
                                     FirmInfo firmInfo = firmInfoMapper.selectById(chargeOrderInfo.getFirmId());
                                     if (ObjectUtil.isNotNull(firmInfo)) {
                                         HashMap<String, Object> map = new HashMap<>();
@@ -529,19 +546,20 @@ public class ChargingReceptionServiceImpl implements ChargingReceptionService {
                                         map.put("status", SystemConstants.STATUS_TWO);
                                         okHttpUtil.doPostForm(firmInfo.getChannelUrl() + "/notification_stop_charge_result", map, null);
                                     }
-                                } else {
-                                    log.info("订单状态已更新,跳过处理 - orderId: {}, status: {}", chargeOrderInfo.getId(), chargeOrderInfo.getStatus());
                                 }
+                            } else {
+                                log.info("订单状态已更新,跳过处理 - orderId: {}, status: {}", chargeOrderInfo.getId(), chargeOrderInfo.getStatus());
                             }
-                        } finally {
+                        }
+                    } finally {
+                        if (lock.isHeldByCurrentThread()) {
                             lock.unlock();
+                            log.info("释放订单锁 - StartChargeSeq: {}", startChargeSeq);
                         }
-                    } else {
-                        log.warn("获取订单锁失败 - StartChargeSeq: {}", startChargeSeq);
                     }
-                } catch (InterruptedException e) {
-                    Thread.currentThread().interrupt();
-                    log.error("获取订单锁被中断 - StartChargeSeq: {}", startChargeSeq);
+                } catch (Exception e) {
+                    log.error("获取订单锁异常 - StartChargeSeq: {}, 错误: {}", startChargeSeq, e.getMessage());
+                    throw new BusinessException("系统繁忙,请稍后重试");
                 }
             } else if (startChargeSeqStat != null) {
                 switch (startChargeSeqStat) {

+ 11 - 11
src/main/java/com/zsElectric/boot/common/util/electric/queryToken/JwtTokenUtil.java

@@ -2,6 +2,7 @@ package com.zsElectric.boot.common.util.electric.queryToken;
 
 import io.jsonwebtoken.Claims;
 import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.JwtParser;
 import io.jsonwebtoken.Jwts;
 import io.jsonwebtoken.MalformedJwtException;
 import io.jsonwebtoken.SignatureAlgorithm;
@@ -31,6 +32,7 @@ public class JwtTokenUtil {
     private final SecretKey secretKey;
     private final Long expireSeconds;
     private final RedisTemplate<String, Object> redisTemplate;
+    private final JwtParser jwtParser; // 缓存JwtParser实例,避免每次重新构建
     
     // Redis key前缀
     private static final String REDIS_TOKEN_PREFIX = "third_party:token:";
@@ -43,6 +45,10 @@ public class JwtTokenUtil {
         this.secretKey = Keys.hmacShaKeyFor(secret.getBytes());
         this.expireSeconds = expireSeconds;
         this.redisTemplate = redisTemplate;
+        // 初始化时构建JwtParser,避免每次验证重新构建导致的ServiceLoader问题
+        this.jwtParser = Jwts.parserBuilder()
+                .setSigningKey(secretKey)
+                .build();
     }
 
     /**
@@ -80,11 +86,8 @@ public class JwtTokenUtil {
                 return false;
             }
             log.info("Token在Redis中存在,继续验证JWT签名");
-            // 验证JWT签名和过期时间
-            Jwts.parserBuilder()
-                .setSigningKey(secretKey)
-                .build()
-                .parseClaimsJws(token);
+            // 验证JWT签名和过期时间(使用缓存的jwtParser)
+            jwtParser.parseClaimsJws(token);
             log.info("Token验证通过");
             return true;
         } catch (ExpiredJwtException e) {
@@ -106,14 +109,11 @@ public class JwtTokenUtil {
      */
     public String getOperatorIdFromToken(String token) {
         try {
-            Claims claims = Jwts.parserBuilder()
-                    .setSigningKey(secretKey)
-                    .build()
-                    .parseClaimsJws(token)
-                    .getBody();
+            // 使用缓存的jwtParser
+            Claims claims = jwtParser.parseClaimsJws(token).getBody();
             return claims.getSubject();
         } catch (Exception e) {
-            System.out.println("从Token提取OperatorID失败: " + e.getMessage());
+            log.warn("从Token提取OperatorID失败: {}", e.getMessage());
             return null;
         }
     }