package com.jsowell.pile.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.jsowell.adapay.dto.QueryConfirmReverseDTO;
import com.jsowell.adapay.dto.QueryPaymentConfirmDTO;
import com.jsowell.adapay.operation.PaymentReverseOperation;
import com.jsowell.adapay.response.*;
import com.jsowell.adapay.service.AdapayService;
import com.jsowell.adapay.vo.OrderSettleResult;
import com.jsowell.adapay.vo.PaymentInfo;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.domain.vo.AuthorizedDeptVO;
import com.jsowell.common.core.domain.ykc.RealTimeMonitorData;
import com.jsowell.common.core.domain.ykc.TransactionRecordsData;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.enums.AcquirerEnum;
import com.jsowell.common.enums.DelFlagEnum;
import com.jsowell.common.enums.MemberWalletEnum;
import com.jsowell.common.enums.adapay.AdapayPayChannelEnum;
import com.jsowell.common.enums.adapay.AdapayStatusEnum;
import com.jsowell.common.enums.adapay.MerchantDelayModeEnum;
import com.jsowell.common.enums.thirdparty.ThirdPartyOperatorIdEnum;
import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum;
import com.jsowell.common.enums.ykc.*;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.PageUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.common.util.bean.BeanUtils;
import com.jsowell.common.util.id.IdUtils;
import com.jsowell.common.util.id.SnowflakeIdWorker;
import com.jsowell.pile.domain.*;
import com.jsowell.pile.dto.*;
import com.jsowell.pile.dto.nanrui.NRQueryOrderDTO;
import com.jsowell.pile.dto.ningxiajiaotou.NXJTQueryOrdersInfoDTO;
import com.jsowell.pile.mapper.OrderBasicInfoMapper;
import com.jsowell.pile.service.*;
import com.jsowell.pile.service.programlogic.AbstractProgramLogic;
import com.jsowell.pile.service.programlogic.DelayMerchantProgramLogic;
import com.jsowell.pile.service.programlogic.ProgramLogicFactory;
import com.jsowell.pile.transaction.dto.ClearingBillTransactionDTO;
import com.jsowell.pile.transaction.dto.OrderTransactionDTO;
import com.jsowell.pile.transaction.service.TransactionService;
import com.jsowell.pile.util.UserUtils;
import com.jsowell.pile.vo.SupStationStatsVO;
import com.jsowell.pile.vo.base.PileInfoVO;
import com.jsowell.pile.vo.base.*;
import com.jsowell.pile.vo.lianlian.AccumulativeInfoVO;
import com.jsowell.pile.vo.nanrui.JiangSuOrderInfoVO;
import com.jsowell.pile.vo.uniapp.customer.*;
import com.jsowell.pile.vo.web.*;
import com.jsowell.wxpay.common.WeChatPayParameter;
import com.jsowell.wxpay.dto.WechatSendMsgDTO;
import com.jsowell.wxpay.response.WechatPayRefundRequest;
import com.jsowell.wxpay.response.WechatPayRefundResponse;
import com.jsowell.wxpay.service.WxAppletRemoteService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 *
 * @author jsowell
 * @date 2022-09-30
 */
@Service
public class OrderBasicInfoServiceImpl implements OrderBasicInfoService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private OrderBasicInfoMapper orderBasicInfoMapper;

    @Resource
    private MemberWalletLogService memberWalletLogService;

    @Autowired
    private TransactionService transactionService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private WxAppletRemoteService wxAppletRemoteService;

    @Autowired
    private OrderPayRecordService orderPayRecordService;

    @Autowired
    private MemberBasicInfoService memberBasicInfoService;

    @Autowired
    private WxpayCallbackRecordService wxpayCallbackRecordService;

    @Autowired
    private AdapayCallbackRecordService adapayCallbackRecordService;

    @Autowired
    private WechatPayService wechatPayService;

    @Autowired
    private OrderAbnormalRecordService orderAbnormalRecordService;

    @Autowired
    private TransactionService pileTransactionService;

    @Autowired
    private PileBasicInfoService pileBasicInfoService;

    @Autowired
    private PileConnectorInfoService pileConnectorInfoService;

    @Autowired
    private WxpayRefundCallbackService wxpayRefundCallbackService;

    @Autowired
    private PileBillingTemplateService pileBillingTemplateService;

    @Autowired
    private PileAuthCardService pileAuthCardService;

    @Autowired
    private OrderMonitorDataService orderMonitorDataService;

    @Autowired
    private PileStationInfoService pileStationInfoService;

    @Autowired
    private PileMerchantInfoService pileMerchantInfoService;

    @Autowired
    private MemberPlateNumberRelationService memberPlateNumberRelationService;

    @Autowired
    private MemberTransactionRecordService memberTransactionRecordService;

    @Autowired
    private SettleOrderReportService settleOrderReportService;

    @Autowired
    private AdapayMemberAccountService adapayMemberAccountService;

    @Autowired
    private PileRemoteService pileRemoteService;

    @Autowired
    private PileStationWhitelistService pileStationWhitelistService;

    @Autowired
    private AdapayService adapayService;

    @Autowired
    private MemberAdapayRecordService memberAdapayRecordService;

    @Autowired
    private ClearingBillInfoService clearingBillInfoService;

    @Autowired
    private PileMsgRecordService pileMsgRecordService;

    @Autowired
    private ClearingBillDetailService clearingBillDetailService;

    @Autowired
    private ThirdPartyStationRelationService thirdPartyStationRelationService;

    @Autowired
    private IThirdpartySnRelationService snRelationService;

    @Override
    public int deleteByPrimaryKey(Integer id) {
        return orderBasicInfoMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(OrderBasicInfo record) {
        return orderBasicInfoMapper.insert(record);
    }

    @Override
    public int insertOrUpdate(OrderBasicInfo record) {
        return orderBasicInfoMapper.insertOrUpdate(record);
    }

    @Override
    public int insertOrUpdateSelective(OrderBasicInfo record) {
        return orderBasicInfoMapper.insertOrUpdateSelective(record);
    }

    @Override
    public int insertSelective(OrderBasicInfo record) {
        return orderBasicInfoMapper.insertSelective(record);
    }

    @Override
    public OrderBasicInfo selectByPrimaryKey(Integer id) {
        return orderBasicInfoMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(OrderBasicInfo record) {
        return orderBasicInfoMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(OrderBasicInfo record) {
        return orderBasicInfoMapper.updateByPrimaryKey(record);
    }

    @Override
    public int updateBatch(List<OrderBasicInfo> list) {
        return orderBasicInfoMapper.updateBatch(list);
    }

    @Override
    public int updateBatchSelective(List<OrderBasicInfo> list) {
        return orderBasicInfoMapper.updateBatchSelective(list);
    }

    @Override
    public int batchInsert(List<OrderBasicInfo> list) {
        return orderBasicInfoMapper.batchInsert(list);
    }

    /**
     * 条件查询订单基本信息
     *
     * @param info
     * @return
     */
    @Override
    public OrderBasicInfo getOrderBasicInfo(OrderBasicInfo info) {
        return orderBasicInfoMapper.getOrderBasicInfo(info);
    }

    /**
     * 查询订单列表
     * 带权限过滤
     *
     * @param dto 订单
     * @return 订单
     */
    @Override
    public List<OrderListVO> selectOrderBasicInfoListWithAuth(QueryOrderDTO dto) {
        // 权限过滤
        AuthorizedDeptVO authorizedMap = UserUtils.getAuthorizedMap();
        if (authorizedMap == null) {
            // 为空表示没有权限，返回空数组
            return Lists.newArrayList();
        }
        dto.setStationDeptIds(authorizedMap.getStationDeptIds());
        dto.setMerchantDeptIds(authorizedMap.getMerchantDeptIds());
        return selectOrderBasicInfoList(dto);
    }

    /**
     * 查询订单列表
     * 无权限过滤
     *
     * @param dto 订单
     * @return 订单
     */
    @Override
    public List<OrderListVO> selectOrderBasicInfoList(QueryOrderDTO dto) {
        List<OrderListVO> orderListVOS = orderBasicInfoMapper.selectOrderBasicInfoList(dto);
        if (CollectionUtils.isEmpty(orderListVOS)) {
            return orderListVOS;
        }

        for (OrderListVO orderListVO : orderListVOS) {
            orderListVO.setPileConnectorCode(orderListVO.getPileSn() + orderListVO.getConnectorCode());
            orderListVO.setOrderStatusDescribe(transformOrderStatusDescribe(orderListVO.getOrderStatus(), orderListVO.getPayStatus()));

            // 获取实时消费金额
            List<RealTimeMonitorData> chargingRealTimeData = getChargingRealTimeData(orderListVO.getTransactionCode());
            if (CollectionUtils.isNotEmpty(chargingRealTimeData)) {
                RealTimeMonitorData realTimeMonitorData = chargingRealTimeData.get(0);
                orderListVO.setRealTimeAmount(new BigDecimal(realTimeMonitorData.getChargingAmount()));
                orderListVO.setRealTimeChargingDegree(realTimeMonitorData.getChargingDegree());
            }

            // 计算充电时长
            String chargeStartTime = orderListVO.getChargeStartTime();
            String chargeEndTime = orderListVO.getChargeEndTime();
            if (StringUtils.isNotBlank(chargeStartTime) && StringUtils.isNotBlank(chargeEndTime)) {
                orderListVO.setChargingTime(DateUtils.getDatePoor(DateUtils.parseDate(chargeEndTime), DateUtils.parseDate(chargeStartTime)));
            }
            String thirdPartyType = orderListVO.getThirdPartyType();
            if(StringUtils.isNotBlank(thirdPartyType)) {
                String label = ThirdPlatformTypeEnum.getTypeLabelByTypeCode(thirdPartyType);
                orderListVO.setThirdPartyType(label + "启动");
            }
        }

        batchQueryFeeAmt(orderListVOS);
        return orderListVOS;
    }

    private void batchQueryFeeAmt(List<OrderListVO> orderListVOS) {
        // 批量查手续费
        List<String> orderCodeList = orderListVOS.stream().map(OrderListVO::getOrderCode).collect(Collectors.toList());
        Map<String, ClearingBillDetail> billDetailMap = clearingBillDetailService.selectByOrderCodeList(orderCodeList);

        for (OrderListVO orderListVO : orderListVOS) {
            // 交易手续费
            ClearingBillDetail clearingBillDetail = billDetailMap.get(orderListVO.getOrderCode());
            if (Objects.nonNull(clearingBillDetail)) {
                orderListVO.setFeeAmount(clearingBillDetail.getFeeAmt() + "");
            }
        }

    }

    /**
     * 通过订单状态和支付状态 转换订单状态描述
     *
     * @param orderStatus
     * @param payStatus
     * @return
     */
    @Override
    public String transformOrderStatusDescribe(String orderStatus, String payStatus) {
        // 订单状态描述
        // String orderStatus = orderListVO.getOrderStatus(); // 订单状态
        // String payStatus = orderListVO.getPayStatus(); // 支付状态
        String orderStatusDescribe;
        if (StringUtils.equals(orderStatus, OrderStatusEnum.NOT_START.getValue())) {
            // 未启动还有两种情况 待支付 / 支付成功
            if (StringUtils.equals(payStatus, OrderPayStatusEnum.paid.getValue())) {
                // 支付成功，未启动
                orderStatusDescribe = OrderPayStatusEnum.paid.getLabel() + ", " + OrderStatusEnum.getOrderStatus(orderStatus);
            } else {
                // 待支付
                orderStatusDescribe = OrderPayStatusEnum.unpaid.getLabel();
            }
        } else {
            orderStatusDescribe = OrderStatusEnum.getOrderStatus(orderStatus);
        }
        return orderStatusDescribe;
    }

    /**
     * 查询时间段内订单总金额和总用电量
     *
     * @param dto
     * @return
     */
    // @DataScope(deptAlias = "t3")
    public OrderTotalDataVO getOrderTotalDataOld(QueryOrderDTO dto) {
        OrderTotalDataVO vo = new OrderTotalDataVO();
        // 只计算订单完成状态的
        dto.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
        // 查询出所有符合条件的订单
        OrderTotalDataVO resultVO = orderBasicInfoMapper.getOrderTotalData(dto);
        List<OrderListVO> list = selectOrderBasicInfoList(dto);
        BigDecimal sumOrderAmount = BigDecimal.ZERO;
        BigDecimal sumUsedElectricity = BigDecimal.ZERO;
        BigDecimal sumSettleAmount = BigDecimal.ZERO;
        vo.setDateDescription("创建时间 " + dto.getStartTime() + " - " + dto.getEndTime());
        // 计算金额
        if (CollectionUtils.isNotEmpty(list)) {
            for (OrderListVO orderListVO : list) {
                BigDecimal orderAmount = StringUtils.isBlank(orderListVO.getOrderAmount())
                        ? BigDecimal.ZERO
                        : new BigDecimal(orderListVO.getOrderAmount());
                sumOrderAmount = sumOrderAmount.add(orderAmount);

                BigDecimal chargingDegree = StringUtils.isBlank(orderListVO.getChargingDegree())
                        ? BigDecimal.ZERO
                        : new BigDecimal(orderListVO.getChargingDegree());
                sumUsedElectricity = sumUsedElectricity.add(chargingDegree);

                BigDecimal settleAmount = StringUtils.isBlank(orderListVO.getSettleAmount())
                        ? BigDecimal.ZERO
                        : new BigDecimal(orderListVO.getSettleAmount());
                sumSettleAmount = sumSettleAmount.add(settleAmount);
            }
        }
        vo.setSumOrderAmount(sumOrderAmount);
        vo.setSumUsedElectricity(sumUsedElectricity);
        vo.setSumSettleAmount(sumSettleAmount);
        return vo;
    }

    @Override
    public OrderTotalDataVO getOrderTotalData(QueryOrderDTO dto) {
        // 只计算订单完成状态的
        dto.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
        OrderTotalDataVO resultVO = orderBasicInfoMapper.getOrderTotalData(dto);
        if (StringUtils.isNotBlank(dto.getStartTime()) && StringUtils.isNotBlank(dto.getEndTime())) {
            resultVO.setDateDescription("创建时间 " + dto.getStartTime() + " - " + dto.getEndTime());
        }
        if (StringUtils.isNotBlank(dto.getStartSettleTime()) && StringUtils.isNotBlank(dto.getEndSettleTime())) {
            resultVO.setDateDescription("结算时间 " + dto.getStartSettleTime() + " - " + dto.getEndSettleTime());
        }
        return resultVO;
    }

    /**
     * 查询时间段内订单总金额和总用电量V2
     *
     * @param dto
     * @return
     */
    @Override
    public List<OrderTotalDataVO> getOrderTotalDataV2(QueryOrderDTO dto) {
        List<OrderTotalDataVO> resultList = Lists.newArrayList();
        // 只计算订单完成状态的
        dto.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
        String startTime = dto.getStartTime();
        String endTime = dto.getEndTime();
        String startSettleTime = dto.getStartSettleTime();
        String endSettleTime = dto.getEndSettleTime();
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
            dto.setStartTime(startTime);
            dto.setEndTime(endTime);
            dto.setStartSettleTime(null);
            dto.setEndSettleTime(null);
            OrderTotalDataVO resultVO = orderBasicInfoMapper.getOrderTotalData(dto);
            resultVO.setDateDescription("创建时间 " + startTime + " - " + endTime);
            resultList.add(resultVO);
        }
        if (StringUtils.isNotBlank(startSettleTime) && StringUtils.isNotBlank(endSettleTime)) {
            dto.setStartTime(null);
            dto.setEndTime(null);
            dto.setStartSettleTime(startSettleTime);
            dto.setEndSettleTime(endSettleTime);
            OrderTotalDataVO resultVO = orderBasicInfoMapper.getOrderTotalData(dto);
            resultVO.setDateDescription("结算时间 " + startSettleTime + " - " + endSettleTime);
            resultList.add(resultVO);
        }
        return resultList;
    }

    /**
     * 通过订单号查询订单信息（小程序发送消息用）
     *
     * @param orderCode
     * @return
     */
    @Override
    public SendMessageVO selectOrderInfoByOrderCode(String orderCode) {
        return orderBasicInfoMapper.selectOrderInfoByOrderCode(orderCode);
    }

    /**
     * 充电桩启动失败
     *
     * @param transactionCode 交易流水号
     * @param failedReasonMsg 失败原因
     */
    @Override
    public void chargingPileFailedToStart(String transactionCode, String failedReasonMsg) {
        logger.info("启动失败退款 transactionCode:{}, 失败原因:{}", transactionCode, failedReasonMsg);
        // OrderBasicInfo orderInfo = getOrderInfoByOrderCode(orderCode);
        OrderBasicInfo orderInfo = getOrderInfoByTransactionCode(transactionCode);
        if (orderInfo == null) {
            return;
        }
        // 启动失败原因
        orderInfo.setReason(failedReasonMsg);
        // 订单退款(结算订单)
        TransactionRecordsData data = TransactionRecordsData.builder()
                .transactionCode(orderInfo.getTransactionCode())
                .consumptionAmount(String.valueOf(orderInfo.getOrderAmount()))
                .stopReasonMsg(failedReasonMsg)
                .totalElectricity(Constants.ZERO)
                .sharpUsedElectricity(Constants.ZERO)
                .peakUsedElectricity(Constants.ZERO)
                .flatUsedElectricity(Constants.ZERO)
                .valleyUsedElectricity(Constants.ZERO)
                .build();

        // 新逻辑
        try {
            String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderInfo.getMerchantId());
            AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode);
            orderLogic.settleOrder(data, orderInfo);
        } catch (Exception e) {
            logger.error("启动失败退款, orderCode:{}, 执行订单结算逻辑发生异常", orderInfo.getOrderCode(), e);
        }
    }

    /**
     * 充电桩启动成功
     *
     * @param transactionCode
     */
    @Override
    public void chargingPileStartedSuccessfully(String transactionCode) {
        // OrderBasicInfo orderInfo = getOrderInfoByOrderCode(orderCode);
        OrderBasicInfo orderInfo = getOrderInfoByTransactionCode(transactionCode);
        if (orderInfo == null) {
            return;
        }
        // 启动成功，订单状态改为充电中
        orderInfo.setOrderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue());
        if (orderInfo.getChargeStartTime() == null) {
            orderInfo.setChargeStartTime(new Date());
        }
        updateOrderBasicInfo(orderInfo);
    }

    /**
     * 关闭启动失败订单
     *
     * @param startTime
     * @param endTime
     */
    @Override
    public void closeStartFailedOrder(String startTime, String endTime) {
        List<OrderBasicInfo> orderList = orderBasicInfoMapper.selectOrderListByTimeRangeAndStatus(startTime, endTime, OrderStatusEnum.NOT_START.getValue(), OrderPayStatusEnum.paid.getValue());
        List<String> orderCodeList = orderList.stream().map(OrderBasicInfo::getOrderCode).collect(Collectors.toList());
        logger.info("{}-{}期间，共{}条，支付成功未启动订单，订单号:{}", startTime, endTime, orderList.size(), orderCodeList);
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }
        long currentTimeMillis = System.currentTimeMillis();
        // 判断支付成功时间距当前时间是否大于15分钟
        for (OrderBasicInfo orderBasicInfo : orderList) {
            // 立即启动的订单使用支付时间判断，预约充电的订单使用预约时间判断
            long time;
            String startType = orderBasicInfo.getStartType();
            if (StringUtils.equals(StartTypeEnum.NOW.getValue(), startType)) {
                Date payTime = orderBasicInfo.getPayTime();
                time = payTime == null ? 0L : payTime.getTime();
            } else {
                Date reservedStartTime = orderBasicInfo.getReservedStartTime();
                time = reservedStartTime == null ? 0L : reservedStartTime.getTime();
            }

            if (currentTimeMillis - time < 1000 * 60 * 15) {
                continue;
            }
            // 已经支付超过15分钟 判断充电桩的状态
            String pileConnectorCode = orderBasicInfo.getPileSn() + orderBasicInfo.getConnectorCode();
            PileConnectorInfoVO connector = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(pileConnectorCode);
            // 充电桩不在线，则不做处理。请联系管理员操作
            if (PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue().equals(String.valueOf(connector.getStatus()))) {
                logger.info("订单号:{}已经支付超过15分钟，充电桩:{}未启动，但是该桩为离线状态，请联系管理员处理", orderBasicInfo.getOrderCode(), pileConnectorCode);
                continue;
            }
            // 获取订单的实时检测数据，有实时数据说明充电了，没有实时数据说明桩确实没有充电
            List<RealTimeMonitorData> chargingRealTimeData = getChargingRealTimeData(orderBasicInfo.getTransactionCode());
            if (CollectionUtils.isEmpty(chargingRealTimeData)) {
                // 充电桩在线，并且没有0x13实时数据，则执行结算退款操作
                chargingPileFailedToStart(orderBasicInfo.getTransactionCode(), "充电桩启动失败，执行退款处理");
            }
        }
    }

    /**
     * 查询充电中的订单，没有数据权限校验，后管不要用
     *
     * @param pileSn
     * @return
     */
    @Override
    public List<OrderListVO> selectChargingOrder(String pileSn) {
        QueryOrderDTO dto = QueryOrderDTO.builder()
                .pileSn(pileSn)
                .orderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue())
                .build();
        return orderBasicInfoMapper.selectOrderBasicInfoList(dto);
    }

    /**
     * 修改订单
     *
     * @param orderBasicInfo 订单
     * @return 结果
     */
    @Override
    public int updateOrderBasicInfo(OrderBasicInfo orderBasicInfo) {
        // 清缓存
        this.cleanCacheByOrderCode(orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode());
        int i = orderBasicInfoMapper.updateOrderBasicInfo(orderBasicInfo);
        CompletableFuture.runAsync(() -> this.cleanCacheByOrderCode(orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode()));
        logger.info("修改订单updateOrderBasicInfo:{}", JSON.toJSONString(orderBasicInfo));
        return i;
    }

    /**
     * 修改订单详情
     *
     * @param orderDetail
     * @return
     */
    @Override
    public int updateOrderDetail(OrderDetail orderDetail) {
        return orderBasicInfoMapper.updateOrderDetail(orderDetail);
    }

    /**
     * 清除订单缓存 订单编号或交易流水号 任意传一个
     *
     * @param orderCode       订单编号
     * @param transactionCode 交易流水号
     */
    @Override
    public void cleanCacheByOrderCode(String orderCode, String transactionCode) {
        logger.debug("清除订单缓存 orderCode:{}, transactionCode:{}", orderCode, transactionCode);
        List<String> keys = Lists.newArrayList();
        if (StringUtils.isNotBlank(orderCode)) {
            keys.add(CacheConstants.GET_ORDER_INFO_BY_ORDER_CODE + orderCode);
        }
        if (StringUtils.isNotBlank(transactionCode)) {
            keys.add(CacheConstants.GET_ORDER_INFO_BY_TRANSACTION_CODE + transactionCode);
        }
        if (CollectionUtils.isNotEmpty(keys)) {
            redisCache.deleteObject(keys);
        }
    }

    /**
     * 批量删除订单
     *
     * @param ids 需要删除的订单主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteOrderBasicInfoByIds(Long[] ids) {
        orderBasicInfoMapper.deleteOrderDetailByOrderCodes(ids);
        return orderBasicInfoMapper.deleteOrderBasicInfoByIds(ids);
    }

    /**
     * 通过订单号查询订单信息
     *
     * @param orderCode 订单号
     * @return 订单信息
     */
    @Override
    public OrderBasicInfo getOrderInfoByOrderCode(String orderCode) {
        // 如果orderCode是00000000000000000000000000000000，直接返回null
        if (StringUtils.equals(Constants.ILLEGAL_TRANSACTION_CODE, orderCode)) {
            return null;
        }
        String redisKey = CacheConstants.GET_ORDER_INFO_BY_ORDER_CODE + orderCode;
        OrderBasicInfo orderBasicInfo = redisCache.getCacheObject(redisKey);
        if (orderBasicInfo == null) {
            // 查数据库
            orderBasicInfo = orderBasicInfoMapper.getOrderInfoByOrderCode(orderCode);
            // 放缓存
            if (orderBasicInfo != null) {
                redisCache.setCacheObject(redisKey, orderBasicInfo, 5, TimeUnit.MINUTES);
            }
        }
        // logger.info("通过订单号:{}, 查询订单信息:{}", orderCode, JSON.toJSONString(orderBasicInfo));
        return orderBasicInfo;
    }

    /**
     * 通过交易流水号查询订单信息
     *
     * @param transactionCode 交易流水号
     * @return 订单信息
     */
    @Override
    public OrderBasicInfo getOrderInfoByTransactionCode(String transactionCode) {
        if (StringUtils.equals(Constants.ILLEGAL_TRANSACTION_CODE, transactionCode)) {
            return null;
        }
        String redisKey = CacheConstants.GET_ORDER_INFO_BY_TRANSACTION_CODE + transactionCode;
        OrderBasicInfo orderBasicInfo = redisCache.getCacheObject(redisKey);
        if (orderBasicInfo == null) {
            // 查数据库
            orderBasicInfo = orderBasicInfoMapper.getOrderInfoByTransactionCode(transactionCode);
            // 放缓存
            if (orderBasicInfo != null) {
                redisCache.setCacheObject(redisKey, orderBasicInfo, 5, TimeUnit.MINUTES);
            }
        }
        // logger.info("通过交易流水号:{}, 查询订单信息:{}", transactionCode, JSON.toJSONString(orderBasicInfo));
        return orderBasicInfo;
    }

    /**
     * 根据充电桩编号和枪口号查询正在充电中的订单
     *
     * @param pileSn        桩编号
     * @param connectorCode 枪口号
     * @return
     */
    @Override
    public OrderBasicInfo queryChargingByPileSnAndConnectorCode(String pileSn, String connectorCode) {
        if (StringUtils.isBlank(pileSn) || StringUtils.isBlank(connectorCode)) {
            return null;
        }
        return orderBasicInfoMapper.queryOrderBasicInfo(pileSn, connectorCode, OrderStatusEnum.IN_THE_CHARGING.getValue());
    }

    /**
     * 根据枪口编号查询正在充电中的订单
     *
     * @param pileConnectorCode 枪口编号
     * @return 订单信息
     */
    @Override
    public OrderBasicInfo queryChargingByPileConnectorCode(String pileConnectorCode) {
        if (StringUtils.isBlank(pileConnectorCode)) {
            return null;
        }
        String pileSn = pileConnectorCode.substring(0, pileConnectorCode.length() - 2);
        String connectorCode = pileConnectorCode.substring(pileConnectorCode.length() - 2);
        return queryChargingByPileSnAndConnectorCode(pileSn, connectorCode);
    }

    /**
     * 订单分账逻辑
     * 订单结算完成，就执行清分and退款
     */
    @Override
    public OrderSettleResult orderPaymentSettlementAndRefund(OrderBasicInfo orderBasicInfo) {
        String merchantId = orderBasicInfo.getMerchantId();
        String orderCode = orderBasicInfo.getOrderCode();
        // 获取一级运营商信息
        PileMerchantInfo merchantInfo = pileMerchantInfoService.getFirstLevelMerchantByMerchantId(merchantId);
        if (merchantInfo == null) {
            logger.info("订单分账逻辑-订单:{}, 查不到一级运营商信息", orderCode);
            return null;
        }

        // 获取结算账户信息
        // AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(merchantId);
        AdapayMemberAccount adapayMemberAccount = null;
        // if (adapayMemberAccount == null) {
        //     logger.info("订单分账逻辑-订单:{}, 运营商id:{}, 没有配置结算账户信息", orderCode, merchantId);
        //     return null;
        // }

        // 获取一级运营商的 延时分账设置
        String delayMode = merchantInfo.getDelayMode();
        if (StringUtils.equals(delayMode, Constants.ONE)) {
            /*
             delay商户, 如果存在退款金额, 支付的钱部分解冻(也就是只解冻需要退款的部分), 剩下的钱继续冻结等待第二天凌晨分账
             */
            // 执行退款逻辑
            delayMerchantOrderRefundLogic(orderBasicInfo, adapayMemberAccount, merchantInfo.getAppId());
        } else {
            /*
             非delay商户, 支付的钱全部解冻后, 更新消费金额和退款金额(只有在线支付才退款, 余额支付退到余额)
             */
            notDelayMerchantOrderRefundLogic(orderBasicInfo, adapayMemberAccount, merchantInfo.getAppId());
        }
        return null;
    }


    private AdapayCallbackRecord selectAdapayCallbackRecord(String orderCode) {
        AdapayCallbackRecord adapayCallbackRecord = adapayCallbackRecordService.selectByOrderCode(orderCode);
        if (adapayCallbackRecord == null) {
            logger.error("根据订单号:{}, 未查询到汇付支付回调信息", orderCode);
            throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CALLBACK_IS_NULL_ERROR);
        }
        return adapayCallbackRecord;
    }

    private AdapayCallbackRecord selectAdapayCallbackRecordByPaymentId(String paymentId) {
        AdapayCallbackRecord adapayCallbackRecord = adapayCallbackRecordService.selectByPaymentId(paymentId);
        if (adapayCallbackRecord == null) {
            logger.error("根据支付id:{}, 未查询到汇付支付回调信息", paymentId);
            throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CALLBACK_IS_NULL_ERROR);
        }
        return adapayCallbackRecord;
    }

    /**
     * 延迟商家订单退款处理逻辑
     * 例如：举视以及下面的二级运营商
     * 因为在结算时还没有到分账的时间，先解冻需要退款的金额，并退款
     *
     * @param orderBasicInfo      订单信息
     * @param adapayMemberAccount 汇付用户信息
     * @param wechatAppId         小程序appId
     */
    private void delayMerchantOrderRefundLogic(OrderBasicInfo orderBasicInfo, AdapayMemberAccount adapayMemberAccount, String wechatAppId) {
        try {
            String payMode = orderBasicInfo.getPayMode();
            if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) {
                // 余额支付
                balancePaymentOrderRefundV2(orderBasicInfo);
            } else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) {
                // 微信支付
                onlinePaymentOrderRefund(orderBasicInfo);
            } else {
                // 白名单支付
                logger.info("订单:{}使用白名单支付，不进行退款处理", orderBasicInfo.getOrderCode());
            }
        } catch (Exception e) {
            logger.error("订单退款逻辑异常orderCode:{}", orderBasicInfo.getOrderCode(), e);
        }
    }

    /**
     * 不延迟商家订单退款处理逻辑
     * 例如：希晓
     * 相当于已经分账完成了，只需要退款
     *
     * @param orderBasicInfo      订单信息
     * @param adapayMemberAccount 汇付用户信息
     * @param wechatAppId         小程序appId
     * @return
     */
    private OrderSettleResult notDelayMerchantOrderRefundLogic(OrderBasicInfo orderBasicInfo, AdapayMemberAccount adapayMemberAccount, String wechatAppId) {
        try {
            String payMode = orderBasicInfo.getPayMode();
            if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) {
                // 余额支付
                balancePaymentOrderRefundV2(orderBasicInfo);
            } else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) {
                // 微信支付
                onlinePaymentOrderRefund(orderBasicInfo);
            } else {
                // 白名单支付
                logger.info("订单:{}使用白名单支付，不进行退款处理", orderBasicInfo.getOrderCode());
            }
        } catch (Exception e) {
            logger.error("订单退款逻辑异常orderCode:{}", orderBasicInfo.getOrderCode(), e);
        }
        return null;
    }

    /**
     * 返回更新后的OrderBasicInfo对象
     * 专用方法，其他地方如果要用请仔细检查
     */
    public void returnUpdateOrderBasicInfo(OrderBasicInfo orderBasicInfo, TransactionRecordsData data) {
        // 订单编号
        String orderCode = orderBasicInfo.getOrderCode();
        // 消费金额就是订单总金额/交易记录传过来的消费金额
        BigDecimal orderAmount = new BigDecimal(data.getConsumptionAmount());
        // 付款金额 - 实际消费金额，如果有剩余，需要走退款操作 当使用余额支付时payAmount = principalPay + giftPay
        BigDecimal payAmount = orderBasicInfo.getPayAmount();

        // 有时候充电桩到达金额停止充电会多出一点金额，比如实际需要充50元的电，充电桩传来的消费金额为50.01元，在后台记录的时候需要舍去
        if (orderAmount.compareTo(payAmount) > 0) {
            logger.info("结算订单:【{}】充电桩传来的消费金额:【{}】大于付款金额:【{}】, 消费金额设置为付款金额相等数据", orderCode, orderAmount, payAmount);
            orderAmount = payAmount;
        }
        orderBasicInfo.setOrderAmount(orderAmount); // 订单总金额

        // 虚拟金额 指订单消费中不参与结算的部分
        BigDecimal virtualAmount = BigDecimal.ZERO;
        if (OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue().equals(orderBasicInfo.getPayMode())) {
            // 白名单支付所消费的金额，都属于虚拟金额，不参与结算对账
            virtualAmount = new BigDecimal(orderAmount.toString());
        }

        // 剩余需要退回的金额 residue
        BigDecimal residue = payAmount.subtract(orderAmount);

        // 把交易记录中的用电量，金额等信息 更新到orderBasicInfo和orderDetail
        orderBasicInfo.setVirtualAmount(virtualAmount); // 虚拟金额
        orderBasicInfo.setSettleAmount(orderAmount.subtract(virtualAmount)); // 结算金额
        orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
        orderBasicInfo.setReason(data.getStopReasonMsg()); // 充电停止原因
        orderBasicInfo.setSettlementTime(DateUtils.getNowDate()); // 结算时间
        orderBasicInfo.setRefundAmount(residue); // 结算退款金额
    }

    /**
     * 获取更新数据后的orderDetail对象
     * 专用方法，其他地方如果要用请仔细检查
     *
     * @return 查询并更新过数据的orderDetail
     */
    public OrderDetail returnUpdateOrderDetail(OrderBasicInfo orderBasicInfo, TransactionRecordsData data) {
        String orderCode = orderBasicInfo.getOrderCode();
        BigDecimal orderAmount = orderBasicInfo.getOrderAmount();
        // 更新订单详情 查询订单详情 修改订单数据
        OrderDetail orderDetail = getOrderDetailByOrderCode(orderCode);
        try {
            // 总电费金额
            BigDecimal totalElectricityAmount = BigDecimal.ZERO;

            // 尖时段用电量
            String sharpUsedElectricity = data.getSharpUsedElectricity();
            if (sharpUsedElectricity != null) {
                orderDetail.setSharpUsedElectricity(new BigDecimal(sharpUsedElectricity));
                if (data.getSharpPrice() != null) {
                    orderDetail.setSharpPrice(new BigDecimal(data.getSharpPrice()));
                }
                if (data.getSharpAmount() != null) {
                    orderDetail.setSharpAmount(new BigDecimal(data.getSharpAmount()));
                }
                // 计算该时段电费
                BigDecimal multiply = orderDetail.getSharpElectricityPrice()
                        .multiply(new BigDecimal(sharpUsedElectricity))
                        .setScale(2, RoundingMode.DOWN);
                totalElectricityAmount = totalElectricityAmount.add(multiply);
            }

            // 峰时段用电量
            String peakUsedElectricity = data.getPeakUsedElectricity();
            if (peakUsedElectricity != null) {
                orderDetail.setPeakUsedElectricity(new BigDecimal(peakUsedElectricity));
                if (data.getPeakPrice() != null) {
                    orderDetail.setPeakPrice(new BigDecimal(data.getPeakPrice()));
                }
                if (data.getPeakAmount() != null) {
                    orderDetail.setPeakAmount(new BigDecimal(data.getPeakAmount()));
                }
                // 计算该时段电费
                BigDecimal multiply = orderDetail.getPeakElectricityPrice()
                        .multiply(new BigDecimal(peakUsedElectricity))
                        .setScale(2, RoundingMode.DOWN);
                totalElectricityAmount = totalElectricityAmount.add(multiply);
            }

            // 平时段用电量
            String flatUsedElectricity = data.getFlatUsedElectricity();
            if (flatUsedElectricity != null) {
                orderDetail.setFlatUsedElectricity(new BigDecimal(flatUsedElectricity));
                if (data.getFlatPrice() != null) {
                    orderDetail.setFlatPrice(new BigDecimal(data.getFlatPrice()));
                }
                if (data.getFlatAmount() != null) {
                    orderDetail.setFlatAmount(new BigDecimal(data.getFlatAmount()));
                }
                // 计算该时段电费
                BigDecimal multiply = orderDetail.getFlatElectricityPrice()
                        .multiply(new BigDecimal(flatUsedElectricity))
                        .setScale(2, RoundingMode.DOWN);
                totalElectricityAmount = totalElectricityAmount.add(multiply);
            }

            // 谷时段用电量
            String valleyUsedElectricity = data.getValleyUsedElectricity();
            if (valleyUsedElectricity != null) {
                orderDetail.setValleyUsedElectricity(new BigDecimal(valleyUsedElectricity));
                if (data.getValleyPrice() != null) {
                    orderDetail.setValleyPrice(new BigDecimal(data.getValleyPrice()));
                }
                if (data.getValleyAmount() != null) {
                    orderDetail.setValleyAmount(new BigDecimal(data.getValleyAmount()));
                }
                // 计算该时段电费
                BigDecimal multiply = orderDetail.getValleyElectricityPrice()
                        .multiply(new BigDecimal(valleyUsedElectricity))
                        .setScale(2, RoundingMode.DOWN);
                totalElectricityAmount = totalElectricityAmount.add(multiply);
            }

            // 如果算出来的电费金额大于总消费金额，则电费金额等于总消费金额
            if (totalElectricityAmount.compareTo(orderAmount) > 0) {
                totalElectricityAmount = orderAmount;
            }
            orderDetail.setTotalElectricityAmount(totalElectricityAmount);
            orderDetail.setTotalServiceAmount(orderAmount.subtract(totalElectricityAmount));
            orderDetail.setTotalUsedElectricity(new BigDecimal(data.getTotalElectricity())); // 总用电量
            orderDetail.setTotalOrderAmount(orderAmount); // 订单总金额
        } catch (Exception e) {
            logger.error("设置订单详情参数发生异常", e);
        }
        return orderDetail;
    }

    /**
     * 通过站点id修改运营商id
     *
     * @param stationId
     * @return
     */
    @Override
    public int updateMerchantByStationId(Long stationId, String newMerchantId) {
        return orderBasicInfoMapper.updateMerchantByStationId(stationId, newMerchantId);
    }

    /**
     * 通过订单编号获取南瑞平台所需要的订单数据信息
     *
     * @param orderCode
     * @return
     */
    @Override
    public JiangSuOrderInfoVO getNROrderInfoByOrderCode(String orderCode) {
        NRQueryOrderDTO dto = new NRQueryOrderDTO();
        dto.setOrderCode(orderCode);
        List<JiangSuOrderInfoVO> jsOrderInfos = orderBasicInfoMapper.getNROrderInfoByOrderCode(dto);
        if (CollectionUtils.isEmpty(jsOrderInfos)) {
            return null;
        }
        // 此方法仅通过订单编号查，因此只有一条数据
        JiangSuOrderInfoVO jsOrderInfoVO = jsOrderInfos.get(0);
        return jsOrderInfoVO;
    }

    /**
     * 通过充电结束时间批量查询
     *
     * @param dto
     * @return
     */
    @Override
    public List<JiangSuOrderInfoVO> getNROrderInfos(NRQueryOrderDTO dto) {
        List<JiangSuOrderInfoVO> nrOrderInfoVOList = orderBasicInfoMapper.getNROrderInfoByOrderCode(dto);
        if (CollectionUtils.isEmpty(nrOrderInfoVOList)) {
            return new ArrayList<>();
        }
        return nrOrderInfoVOList;
    }

    /**
     * 卡状态解锁
     */
    private void cardStatusUnlocked(String logicCard) {
        try {
            // 根据物理卡号查出当前为锁定状态的卡
            PileAuthCard cardInfo = pileAuthCardService.selectSomeStatusCardInfo(CardStatusEnum.START_LOCK.getCode(), logicCard);
            if (cardInfo != null) {
                // 将此卡状态改为正常
                cardInfo.setStatus(CardStatusEnum.NORMAL.getCode());
                pileAuthCardService.updatePileAuthCard(cardInfo);
            }
        } catch (Exception e) {
            logger.error("解锁卡状态 error,", e);
        }
    }

    /**
     * 解锁vin状态
     *
     * @param vinCode
     */
    private void vinStatusUnlocked(String vinCode) {
        try {
            MemberPlateNumberRelation plateInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode);
            if (plateInfo != null && (StringUtils.equals(plateInfo.getVinStatus(), "2"))) {
                plateInfo.setVinStatus("1");
                memberPlateNumberRelationService.updateMemberPlateNumberRelation(plateInfo);
            }
        } catch (Exception e) {
            logger.error("解锁vin状态 error,", e);
        }
    }

    /**
     * 在线支付的订单退款
     */
    private void onlinePaymentOrderRefund(OrderBasicInfo orderBasicInfo) {
        // 订单编号
        String orderCode = orderBasicInfo.getOrderCode();

        // 需要退款的金额
        BigDecimal refundAmount = orderBasicInfo.getRefundAmount();

        // 微信退款逻辑
        ApplyRefundDTO applyRefundDTO = new ApplyRefundDTO();
        applyRefundDTO.setOrderCode(orderCode);
        applyRefundDTO.setRefundType(Constants.ONE);
        applyRefundDTO.setRefundAmount(refundAmount);

        // 查到该笔订单付款金额到哪里了
        MemberTransactionRecord transactionRecord = memberTransactionRecordService.selectByOrderCode(orderCode, ActionTypeEnum.FORWARD.getValue());
        logger.info("查到该笔订单付款金额到哪里了:{}", JSON.toJSONString(transactionRecord));
        if (StringUtils.equals(transactionRecord.getPaymentInstitutions(), PaymentInstitutionsEnum.WECHAT_PAY.getValue())) {
            this.weChatRefund(applyRefundDTO);
        } else if (StringUtils.equals(transactionRecord.getPaymentInstitutions(), PaymentInstitutionsEnum.ADAPAY.getValue())) {
            // 汇付退款需要一级运营商的小程序appId, 否则会退款失败
            String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(orderBasicInfo.getMerchantId());
            if (StringUtils.isNotBlank(wechatAppId)) {
                applyRefundDTO.setWechatAppId(wechatAppId);
            }
            this.refundOrderWithAdapay(applyRefundDTO);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void balancePaymentOrderRefundV2(OrderBasicInfo orderBasicInfo) {
        // 订单编号
        String orderCode = orderBasicInfo.getOrderCode();
        // 订单消费金额
        BigDecimal orderAmount = orderBasicInfo.getOrderAmount();
        // 查支付记录
        List<OrderPayRecord> payRecordList = orderPayRecordService.getOrderPayRecordList(orderCode);

        // Map<String, OrderPayRecord> payRecordMap = payRecordList.stream()
        //         .collect(Collectors.toMap(OrderPayRecord::getPayMode, Function.identity(), (k1, k2) -> k1));
        Map<String, List<OrderPayRecord>> payRecordMap = payRecordList.stream().collect(Collectors.groupingBy(OrderPayRecord::getPayMode));
        // 获取本金支付的记录
        List<OrderPayRecord> orderPayRecordList = payRecordMap.get(Constants.ONE);
        BigDecimal principalPay = orderPayRecordList.stream().map(OrderPayRecord::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 取出本金支付金额
        // BigDecimal principalPay = null;

        // if (principalPayRecord != null) {
        //     principalPay = principalPayRecord.getPayAmount();
        // }

        // 计算需要退回的金额
        Map<String, BigDecimal> returnAmountMap = calculateReturnAmount(principalPay, null, orderAmount);
        logger.info("结算订单:{}, 剩余金额退回余额, 订单消费金额:{}, 本金支付金额:{}, 赠送支付金额:{}, 退回金额map:{}",
                orderCode, orderAmount, principalPay, null, JSON.toJSONString(returnAmountMap));

        // 需要退回本金的金额
        BigDecimal returnPrincipal = returnAmountMap.get("returnPrincipal");

        // 更新会员钱包/余额退回到钱包
        UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder()
                .memberId(orderBasicInfo.getMemberId())
                .type(MemberWalletEnum.TYPE_IN.getValue()) // 进账
                .subType(MemberWalletEnum.SUBTYPE_ORDER_SETTLEMENT_REFUND.getValue()) // 订单结算退款
                .updatePrincipalBalance(returnPrincipal)
                .relatedOrderCode(orderCode)
                .build();
        memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO);

        // 更新order_pay_record, 解冻部分
        AbstractProgramLogic orderLogic = new DelayMerchantProgramLogic();
        List<Map<String, Object>> list = orderLogic.calculateUnfreezeAmount(orderAmount, payRecordList);
        for (Map<String, Object> map : list) {
            String paymentId = (String) map.get("paymentId");
            BigDecimal unfreezeAmount = (BigDecimal) map.get("unfreezeAmount");
            memberAdapayRecordService.unfreezeAmount(paymentId, unfreezeAmount);
        }
    }

    /**
     * 订单分账逻辑
     * orderSplittingOperations
     * 只有开通结算账户的运营商才走分账逻辑
     */
    @Override
    public void orderSplittingOperations(String merchantId, AdapayMemberAccount adapayMemberAccount, List<SettleOrderReport> stationReportList) {
        // 运营商有没有开通结算账户
        if (adapayMemberAccount == null) {
            logger.error("订单分账逻辑error-运营商有没有开通结算账户");
            return;
        }

        if (CollectionUtils.isEmpty(stationReportList)) {
            logger.error("订单分账逻辑error-stationReportList为空");
            return;
        }
        String tradeDate = stationReportList.get(0).getTradeDate();
        logger.info("运营商:{}, 交易日期:{}, 进行分账处理start", adapayMemberAccount, JSON.toJSONString(stationReportList));

        // String merchantId = adapayMemberAccount.getMerchantId();
        String appId = pileMerchantInfoService.queryAppIdByMerchantId(merchantId);

        // 根据运营商id和结算日期查询清分账单
        ClearingBillInfo queryBillInfo = clearingBillInfoService.selectByMerchantIdAndTradeDate(merchantId, tradeDate);

        // 清分账单信息
        ClearingBillInfo clearingBillInfo = new ClearingBillInfo();
        String clearingBillCode = "CLE" + IdUtils.getOrderCode();
        if (queryBillInfo != null) {
            clearingBillInfo.setId(queryBillInfo.getId());
            clearingBillCode = queryBillInfo.getClearingBillCode();
        }
        clearingBillInfo.setBillStatus("1");
        clearingBillInfo.setClearingBillCode(clearingBillCode);
        clearingBillInfo.setClearingTime(DateUtils.getNowDate());
        clearingBillInfo.setMerchantId(merchantId);
        clearingBillInfo.setOrderSource("1");

        // 应收金额
        BigDecimal receivableAmount = BigDecimal.ZERO;
        // 应清分金额
        BigDecimal shouldClearingAmount = BigDecimal.ZERO;
        // 实际清分金额
        BigDecimal actualClearingAmount = BigDecimal.ZERO;
        // 手续费金额
        BigDecimal feeAmount = BigDecimal.ZERO;
        // 可提现金额
        BigDecimal withdrawableAmount = BigDecimal.ZERO;

        // 清分账单详情列表
        List<ClearingBillDetail> billDetailList = Lists.newArrayList();

        for (SettleOrderReport orderReport : stationReportList) {
            String orderCodes = orderReport.getOrderCodes();
            if (StringUtils.isBlank(orderCodes)) {
                logger.info("站点:{}, 日期:{}, 没有查到订单数据", orderReport.getStationId(), orderReport.getTradeDate());
                continue;
            }
            List<String> orderCodeList = Lists.newArrayList(StringUtils.split(orderCodes, ","));
            List<OrderBasicInfo> orderBasicInfos = queryOrderList(orderCodeList);
            if (CollectionUtils.isEmpty(orderBasicInfos)) {
                continue;
            }

            // 执行分账
            for (OrderBasicInfo orderBasicInfo : orderBasicInfos) {
                try {
                    OrderSettleResult orderSettleResult;
                    if (OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue().equals(orderBasicInfo.getPayMode())) {
                        // 余额支付的订单
                        orderSettleResult = doBalancePaymentWithDelay(orderBasicInfo, adapayMemberAccount, appId);
                    } else {
                        // 在线支付，进行支付确认分账
                        orderSettleResult = doPaymentConfirmWithDelay(orderBasicInfo, adapayMemberAccount, appId);
                    }
                    // 记录详情
                    ClearingBillDetail clearingBillDetail = ClearingBillDetail.builder()
                            .clearingBillCode(clearingBillCode)
                            .orderCode(orderBasicInfo.getOrderCode())
                            .createTime(DateUtils.getNowDate())
                            .delFlag(DelFlagEnum.NORMAL.getValue())
                            .build();
                    if (orderSettleResult != null && AdapayStatusEnum.SUCCEEDED.getValue().equals(orderSettleResult.getStatus())) {
                        BigDecimal confirmAmt = new BigDecimal(orderSettleResult.getConfirmAmt());
                        BigDecimal feeAmt = new BigDecimal(orderSettleResult.getFeeAmt());
                        // 应收金额 = 订单结算金额汇总
                        receivableAmount = receivableAmount.add(orderBasicInfo.getSettleAmount());
                        // 应清分金额 = 订单产生的电费+服务费实际消费 汇总
                        shouldClearingAmount = shouldClearingAmount.add(orderBasicInfo.getSettleAmount());
                        // 实际清分金额 = 汇付清分接口返回的清分金额
                        actualClearingAmount = actualClearingAmount.add(confirmAmt);
                        // 手续费金额 = 汇付清分接口返回的手续费金额
                        feeAmount = feeAmount.add(feeAmt);
                        // 可提现金额 = 实际清分金额 - 手续费金额
                        withdrawableAmount = withdrawableAmount
                                .add(confirmAmt)
                                .subtract(feeAmt);
                        clearingBillDetail.setFeeAmt(feeAmt);
                        clearingBillDetail.setConfirmAmt(confirmAmt);
                        billDetailList.add(clearingBillDetail);
                    } else {
                        clearingBillDetail.setFeeAmt(BigDecimal.ZERO);
                        clearingBillDetail.setConfirmAmt(BigDecimal.ZERO);
                        billDetailList.add(clearingBillDetail);
                    }
                } catch (Exception e) {
                    logger.error("订单交易确认失败:{}", orderBasicInfo.getOrderCode(), e);
                }
            }
        }

        clearingBillInfo.setReceivableAmount(receivableAmount);
        clearingBillInfo.setShouldClearingAmount(shouldClearingAmount);
        clearingBillInfo.setFeeAmount(feeAmount);
        clearingBillInfo.setWithdrawableAmount(withdrawableAmount);
        clearingBillInfo.setActualClearingAmount(actualClearingAmount);
        clearingBillInfo.setDelFlag(DelFlagEnum.NORMAL.getValue());
        clearingBillInfo.setBillStatus("2");
        clearingBillInfo.setTradeDate(tradeDate);
        if (StringUtils.equals(adapayMemberAccount.getRemark(), Constants.DEFAULT)) {
            clearingBillInfo.setDelFlag(DelFlagEnum.DELETE.getValue());
        }

        // 保存清分账单
        ClearingBillTransactionDTO dto = new ClearingBillTransactionDTO();
        dto.setClearingBillInfo(clearingBillInfo);
        dto.setBillDetailList(billDetailList);
        transactionService.saveClearingBill(dto);
    }

    /**
     * 处理订单分账
     */
    @Override
    public void orderSplittingOperations(String merchantId, String tradeDate) {
        // 查询运营商有没有开通结算账户
        AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(merchantId);
        if (adapayMemberAccount == null) {
            logger.error("订单分账逻辑error, 运营商id:{}, 未配置结算账户, 使用默认账户", merchantId);
            adapayMemberAccount = adapayMemberAccountService.getDefault();
        }

        // 根据交易日期查询运营商下面所有站点的交易日报
        List<SettleOrderReport> stationReportList = settleOrderReportService.selectByMerchantIdAndDate(merchantId, tradeDate);
        orderSplittingOperations(merchantId, adapayMemberAccount, stationReportList);
    }

    /**
     * 余额支付订单，使用余额分账
     *
     * @param orderBasicInfo      订单信息
     * @param adapayMemberAccount 汇付用户信息
     * @return
     */
    @Override
    public OrderSettleResult doBalancePaymentWithDelay(OrderBasicInfo orderBasicInfo, AdapayMemberAccount adapayMemberAccount, String wechatAppId) throws BaseAdaPayException {
        // 订单结算金额
        BigDecimal settleAmount = orderBasicInfo.getSettleAmount();
        // 订单编号
        String orderCode = orderBasicInfo.getOrderCode();

        BigDecimal confirmAmt = BigDecimal.ZERO; // 消费金额
        BigDecimal feeAmt = BigDecimal.ZERO; // 手续费金额
        String status = null; // 状态

        // 获取余额支付扣除金额 也许存在一笔不够扣，需要扣多笔的情况
        List<BalanceDeductionAmountVO> list = calculateSplitTheBillAmount(orderBasicInfo.getMemberId(), settleAmount);
        // List<String> collect = list.stream().map(BalanceDeductionAmountVO::getPaymentId).collect(Collectors.toList());

        List<OrderPayRecord> orderPayRecordList = orderPayRecordService.getOrderPayRecordList(orderBasicInfo.getOrderCode());
        List<PaymentInfo> paymentInfos = Lists.newArrayList();
        for (OrderPayRecord orderPayRecord : orderPayRecordList) {
            String deductionRecord = orderPayRecord.getDeductionRecord();
            paymentInfos.addAll(orderPayRecordService.parseDeductionRecord(deductionRecord));
        }
        List<String> collect = paymentInfos.stream().map(PaymentInfo::getPaymentId).collect(Collectors.toList());

        // 校验是否分账
        OrderSettleResult result = verifyOrderConfirmAmount(collect, orderCode, settleAmount, wechatAppId);
        if (!AdapayStatusEnum.SUCCEEDED.getValue().equals(result.getStatus())) {
            // 没有分账，执行分账逻辑
            for (BalanceDeductionAmountVO vo : list) {
                String paymentId = vo.getPaymentId();
                BigDecimal deductionAmount = vo.getDeductionAmount();

                // 延时分账，使用确认交易API
                PaymentConfirmResponse paymentConfirmResponse = adapayService.createPaymentConfirmRequest(paymentId,
                        adapayMemberAccount, deductionAmount, orderCode, wechatAppId);

                if (paymentConfirmResponse != null && paymentConfirmResponse.isNotFailed()) {
                    confirmAmt = confirmAmt.add(new BigDecimal(paymentConfirmResponse.getConfirm_amt()));
                    feeAmt = feeAmt.add(new BigDecimal(paymentConfirmResponse.getFee_amt()));
                    status = paymentConfirmResponse.getStatus();
                    memberAdapayRecordService.unfreezeAmountAndUpdateSpendAmount(paymentId, confirmAmt, confirmAmt);
                }
            }

            // 分账接口返回的信息
            result = new OrderSettleResult();
            result.setConfirmAmt(confirmAmt.toString());
            result.setStatus(status);
            result.setFeeAmt(feeAmt.toString());
            result.setOrderCode(orderCode);
            result.setSettleAmt(settleAmount.toString());
        }
        return result;
    }

    /**
     * 计算分账扣除金额
     */
    public List<BalanceDeductionAmountVO> calculateSplitTheBillAmount(String memberId, BigDecimal amount) {
        List<BalanceDeductionAmountVO> resultList = Lists.newArrayList();
        // 查询会员的余额充值记录 按照充值时间正序
        // List<MemberAdapayRecord> memberAdapayRecords = memberAdapayRecordService.selectAvailableBalance(memberId);
        List<MemberAdapayRecord> memberAdapayRecords = memberAdapayRecordService.selectAvailableFreeze(memberId);
        // 定义一个临时金额等于消费金额
        BigDecimal tempAmount = new BigDecimal(amount.toString());
        for (MemberAdapayRecord memberAdapayRecord : memberAdapayRecords) {
            // 该笔支付冻结金额 取出一笔判断是否冻结金额够分账
            BigDecimal freezeAmt = memberAdapayRecord.getFreezeAmt();
            // 该笔支付扣除金额
            BigDecimal deductionAmount;

            // 临时消费金额 = 临时消费金额 - 该笔交易的剩余金额
            tempAmount = tempAmount.subtract(freezeAmt);
            if (tempAmount.compareTo(BigDecimal.ZERO) >= 0) {
                // 计算以后，大于等于0，说明这笔支付剩余金额需要扣完，还要继续扣下一笔
                deductionAmount = freezeAmt;
                BalanceDeductionAmountVO build = BalanceDeductionAmountVO.builder()
                        .memberId(memberId)
                        .paymentId(memberAdapayRecord.getPaymentId())
                        .deductionAmount(deductionAmount)
                        .build();
                resultList.add(build);
            } else {
                // 如果小于0，则说明该笔交易的剩余金额用不完，扣除金额等于临时消费金额，并结束循环
                deductionAmount = freezeAmt.add(tempAmount); // 该笔交易的剩余金额加上一个负数临时消费金额，就是该笔交易扣除金额
                BalanceDeductionAmountVO build = BalanceDeductionAmountVO.builder()
                        .memberId(memberId)
                        .paymentId(memberAdapayRecord.getPaymentId())
                        .deductionAmount(deductionAmount)
                        .build();
                resultList.add(build);
                break;
            }
        }
        return resultList;
    }

    /**
     * 计算余额扣除金额
     *
     * @param memberId 会员id
     * @param amount   消费金额/退款金额
     */
    @Override
    public List<BalanceDeductionAmountVO> calculateTheBalanceDeductionAmount(String memberId, BigDecimal amount) {
        List<BalanceDeductionAmountVO> resultList = Lists.newArrayList();
        // 查询会员的余额充值记录 按照充值时间正序
        List<MemberAdapayRecord> memberAdapayRecords = memberAdapayRecordService.selectAvailableBalance(memberId);

        // 定义一个临时金额等于消费金额
        BigDecimal tempAmount = new BigDecimal(amount.toString());
        for (MemberAdapayRecord memberAdapayRecord : memberAdapayRecords) {
            // 该笔支付剩余金额 取出一笔判断是否剩余金额够支付订单消费吗
            BigDecimal balanceAmt = memberAdapayRecord.getBalanceAmt();
            // 该笔支付扣除金额
            BigDecimal deductionAmount;

            // 临时消费金额 = 临时消费金额 - 该笔交易的剩余金额
            tempAmount = tempAmount.subtract(balanceAmt);
            if (tempAmount.compareTo(BigDecimal.ZERO) >= 0) {
                // 计算以后，大于等于0，说明这笔支付剩余金额需要扣完，还要继续扣下一笔
                deductionAmount = balanceAmt;
                BalanceDeductionAmountVO build = BalanceDeductionAmountVO.builder()
                        .memberId(memberId)
                        .paymentId(memberAdapayRecord.getPaymentId())
                        .deductionAmount(deductionAmount)
                        .build();
                resultList.add(build);
            } else {
                // 如果小于0，则说明该笔交易的剩余金额用不完，扣除金额等于临时消费金额，并结束循环
                deductionAmount = balanceAmt.add(tempAmount); // 该笔交易的剩余金额加上一个负数临时消费金额，就是该笔交易扣除金额
                BalanceDeductionAmountVO build = BalanceDeductionAmountVO.builder()
                        .memberId(memberId)
                        .paymentId(memberAdapayRecord.getPaymentId())
                        .deductionAmount(deductionAmount)
                        .build();
                resultList.add(build);
                break;
            }
        }
        return resultList;
    }

    /**
     * 延迟交易订单 交易确认
     *
     * @param orderBasicInfo      订单
     * @param adapayMemberAccount 结算账户
     */
    public OrderSettleResult doPaymentConfirmWithDelay(OrderBasicInfo orderBasicInfo, AdapayMemberAccount adapayMemberAccount, String wechatAppId) throws BaseAdaPayException {
        // 订单编号
        String orderCode = orderBasicInfo.getOrderCode();
        // 订单结算金额
        BigDecimal settleAmount = orderBasicInfo.getSettleAmount();

        // 查询订单支付记录
        List<OrderPayRecord> orderPayRecordList = orderPayRecordService.getOrderPayRecordList(orderCode);

        // 选出需要分账的支付id
        List<PaymentInfo> paymentInfos = Lists.newArrayList();
        for (OrderPayRecord orderPayRecord : orderPayRecordList) {
            BigDecimal payAmount = orderPayRecord.getPayAmount();
            BigDecimal refundAmount = orderPayRecord.getRefundAmount() == null ? BigDecimal.ZERO : orderPayRecord.getRefundAmount();
            // 如果相减等于0，说明这笔支付单退完了，就不用分账了
            BigDecimal subtract = payAmount.subtract(refundAmount);
            if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                paymentInfos.addAll(orderPayRecordService.parseDeductionRecord(orderPayRecord.getDeductionRecord()));
            }
        }

        List<String> paymentIds = paymentInfos.stream().map(PaymentInfo::getPaymentId).collect(Collectors.toList());

        // 查询该笔订单的支付交易回调
        // AdapayCallbackRecord adapayCallbackRecord = selectAdapayCallbackRecordByPaymentId(paymentInfos.get(0).getPaymentId());

        // 支付id
        String paymentId = paymentInfos.get(0).getPaymentId();

        // 校验订单分账金额
        OrderSettleResult result = verifyOrderConfirmAmount(paymentIds, orderCode, settleAmount, wechatAppId);

        // 校验订单是否分账  状态为非交易完成的时候，进行分账处理
        if (!AdapayStatusEnum.SUCCEEDED.getValue().equals(result.getStatus())) {
            // 调汇付的分账接口 确认交易
            PaymentConfirmResponse paymentConfirmResponse = adapayService.createPaymentConfirmRequest(paymentId,
                    adapayMemberAccount, settleAmount, orderCode, wechatAppId);

            // 分账接口返回的信息
            result = new OrderSettleResult();
            result.setConfirmAmt(paymentConfirmResponse.getConfirm_amt());
            result.setStatus(paymentConfirmResponse.getStatus());
            result.setFeeAmt(paymentConfirmResponse.getFee_amt());
            result.setOrderCode(orderCode);
            result.setSettleAmt(settleAmount.toString());
        }
        return result;
    }

    /**
     * 校验订单分账金额
     *
     * @param paymentIds   支付id集合
     * @param orderCode    订单编号
     * @param settleAmount 结算金额
     */
    private OrderSettleResult verifyOrderConfirmAmount(List<String> paymentIds, String orderCode, BigDecimal settleAmount, String wechatAppId) throws BaseAdaPayException {
        // 分账金额
        BigDecimal totalConfirmAmt = BigDecimal.ZERO;
        // 手续费
        BigDecimal feeAmt = BigDecimal.ZERO;
        // 通过支付id查询分账情况
        for (String paymentId : paymentIds) {
            QueryPaymentConfirmDTO dto = new QueryPaymentConfirmDTO();
            dto.setPaymentId(paymentId);
            dto.setWechatAppId(wechatAppId);
            QueryPaymentConfirmDetailResponse response = adapayService.queryPaymentConfirmList(dto);
            if (response != null) {
                List<QueryPaymentConfirmDetailResponse.PaymentConfirmInfo> confirms = response.getPaymentConfirms();
                if (CollectionUtils.isNotEmpty(confirms)) {
                    for (QueryPaymentConfirmDetailResponse.PaymentConfirmInfo confirm : confirms) {
                        // 校验分账是否撤销
                        if (queryConfirmReverseStatus(confirm.getId(), wechatAppId)) {
                            logger.info("支付确认id:" + confirm.getId() + "撤销了。。。");
                            continue;
                        }
                        JSONObject jsonObject = JSON.parseObject(confirm.getDescription());
                        if (StringUtils.equals(jsonObject.getString("orderCode"), orderCode)) {
                            // 订单号对的上，累计分账金额
                            BigDecimal confirmAmt = new BigDecimal(confirm.getConfirmAmt());
                            BigDecimal confirmedAmt = new BigDecimal(confirm.getConfirmedAmt());
                            BigDecimal orderConfirmedAmt = confirmedAmt.compareTo(BigDecimal.ZERO) == 0
                                    ? confirmedAmt
                                    : confirmAmt;
                            totalConfirmAmt = totalConfirmAmt.add(orderConfirmedAmt);
                            feeAmt = feeAmt.add(new BigDecimal(confirm.getFeeAmt()));
                        }
                    }
                }
            }
        }

        OrderSettleResult result = new OrderSettleResult();
        result.setOrderCode(orderCode);
        result.setSettleAmt(settleAmount.toString());
        result.setConfirmAmt(totalConfirmAmt.toString());
        if (totalConfirmAmt.compareTo(BigDecimal.ZERO) == 0) {
            feeAmt = BigDecimal.ZERO;
        }
        result.setFeeAmt(feeAmt.toString());
        String status;
        // 如果确认金额和结算金额相等，返回succeeded，其他情况返回PENDING
        if (settleAmount.compareTo(totalConfirmAmt) == 0) {
            // 返回succeeded 标识该笔订单已经完成了分账，不要再次执行分账
            status = AdapayStatusEnum.SUCCEEDED.getValue();
        } else {
            status = AdapayStatusEnum.PENDING.getValue();
        }
        result.setStatus(status);
        logger.info("校验订单分账金额-orderCode:{}, 分账结果:{}", orderCode, JSON.toJSONString(result));
        return result;
    }

    /**
     * 查询分账撤销状态
     */
    private boolean queryConfirmReverseStatus(String paymentConfirmId, String wechatAppId) throws BaseAdaPayException {
        boolean result = false;

        QueryConfirmReverseDTO dto = QueryConfirmReverseDTO.builder()
                .paymentConfirmId(paymentConfirmId)
                .wechatAppId(wechatAppId)
                .build();
        ConfirmReverseResponse confirmReverseResponse = adapayService.queryConfirmReverse(dto);
        if (confirmReverseResponse.isSuccess()) {
            result = true;
        }

        return result;
    }

    /**
     * uniApp 发送停止充电订阅消息
     */
    // private void sendMsg(OrderBasicInfo orderBasicInfo) {
    //     try {
    //         WechatSendMsgDTO wechatSendMsgDTO = new WechatSendMsgDTO();
    //         wechatSendMsgDTO.setOrderCode(orderBasicInfo.getOrderCode());
    //         Map<String, String> resultMap = wxAppletRemoteService.stopChargingSendMsg(wechatSendMsgDTO);
    //         logger.info("小程序发送充电停止推送消息 result:{}", JSON.toJSONString(resultMap));
    //     } catch (Exception e) {
    //         logger.error("小程序发送充电停止推送消息 error", e);
    //     }
    // }

    /**
     * 批量查询订单
     *
     * @param orderCodeList
     * @return
     */
    @Override
    public List<OrderBasicInfo> queryOrderList(List<String> orderCodeList) {
        List<OrderBasicInfo> resultList = Lists.newArrayList();
        if (CollectionUtils.isEmpty(orderCodeList)) {
            return resultList;
        }
        return orderBasicInfoMapper.queryOrderList(orderCodeList);
    }

    /**
     * 从redis中取出实时记录保存到表中j
     * 当订单完成的时候调用
     */
    @Override
    public void realTimeMonitorDataRedis2DB(String transactionCode, String orderCode) {
        try {
            if (StringUtils.isBlank(transactionCode) || StringUtils.isBlank(orderCode)) {
                return;
            }
            // 校验有没有保存过
            OrderMonitorData orderMonitorData = orderMonitorDataService.selectByOrderCode(orderCode);
            if (orderMonitorData != null) {
                return;
            }
            List<RealTimeMonitorData> chargingRealTimeData = getChargingRealTimeData(transactionCode);
            if (CollectionUtils.isEmpty(chargingRealTimeData)) {
                return;
            }
            List<RealTimeMonitorData> list = Lists.newArrayList();
            for (RealTimeMonitorData data : chargingRealTimeData) {
                RealTimeMonitorData build = RealTimeMonitorData.builder()
                        .outputCurrent(data.getOutputCurrent())
                        .outputCurrent(data.getOutputCurrent()) // 电流
                        .outputVoltage(data.getOutputVoltage()) // 电压
                        .outputPower(data.getOutputPower())  // 功率
                        .SOC(data.getSOC()) // soc
                        .dateTime(data.getDateTime())  // 时间
                        .batteryMaxTemperature(data.getBatteryMaxTemperature())
                        .chargingAmount(data.getChargingAmount())
                        .chargingDegree(data.getChargingDegree())
                        .sumChargingTime(data.getSumChargingTime())
                        .timeRemaining(data.getTimeRemaining())
                        .gunLineTemperature(data.getGunLineTemperature())
                        .build();
                list.add(build);
            }

            OrderMonitorData record = new OrderMonitorData();
            record.setOrderCode(orderCode);
            record.setTransactionCode(transactionCode);
            record.setMonitorData(JSON.toJSONString(list));
            int insert = orderMonitorDataService.insertSelective(record);
            if (insert > 0) {
                // 删除redis中缓存
                String pileConnectorCode = transactionCode.substring(0, 16);
                String redisKey = CacheConstants.PILE_REAL_TIME_MONITOR_DATA + pileConnectorCode + "_" + transactionCode; // 删除redis中缓存
                redisCache.deleteObject(redisKey);
            }
        } catch (Exception e) {
            logger.info("redis中取出实时记录保存到表发生异常", e);
        }
    }

    /**
     * 余额支付 计算需要退回的金额
     *
     * @param principalPay 本金支付金额
     * @param giftPay      赠送金额支付的金额
     * @param orderAmount  订单消费金额
     * @return
     */
    private Map<String, BigDecimal> calculateReturnAmount(BigDecimal principalPay, BigDecimal giftPay, BigDecimal orderAmount) {
        Map<String, BigDecimal> resultMap = Maps.newHashMap();

        // 消费金额优先使用本金
        BigDecimal returnPrincipal = null; // 退回本金金额
        BigDecimal returnGift = null; // 退回赠送金额

        // 余额支付 有3种情况
        if (principalPay != null && giftPay == null) {
            // 只有本金支付
            BigDecimal subtract = principalPay.subtract(orderAmount);
            if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                returnPrincipal = subtract;
            }
        }
        if (principalPay == null && giftPay != null) {
            // 只有赠送金额支付
            BigDecimal subtract = giftPay.subtract(orderAmount);
            if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                returnGift = subtract;
            }
        }
        if (principalPay != null && giftPay != null) {
            // 本金+赠送支付
            BigDecimal subtract = principalPay.subtract(orderAmount);
            if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                // 本金减掉订单金额后还有剩余，那就把剩余的退回，赠送原封不动退回
                returnPrincipal = subtract;
                returnGift = giftPay;
            } else if (subtract.compareTo(BigDecimal.ZERO) == 0) {
                // 本金刚好够，那赠送金额支付的原封不动退回
                returnGift = giftPay;
            } else {
                returnGift = giftPay.subtract(subtract.negate());
            }
        }

        resultMap.put("returnPrincipal", returnPrincipal);
        resultMap.put("returnGift", returnGift);
        return resultMap;
    }

    /**
     * 结算订单退款和用户余额退款调这个方法
     *
     * @param dto
     */
    @Override
    public void weChatRefund(ApplyRefundDTO dto) {
        // 退款有两种情况 1-订单结算退款  2-用户余额退款
        String refundType = dto.getRefundType();
        if (StringUtils.equals(refundType, "1")) {
            WechatPayRefundResponse response = refundOrderWithWechatPay(dto);
            logger.info("订单结算退款 result:{}", JSON.toJSONString(response));
        } else if (StringUtils.equals(refundType, "2")) {
            WechatPayRefundResponse response = refundBalanceWithWechatPay(dto);
            logger.info("用户余额退款 result:{}", JSON.toJSONString(response));
        } else {
            logger.warn("没有找到退款处理逻辑");
        }
    }

    /**
     * 生成订单编号
     *
     * @return
     */
    private String generateNewOrderCode() {
        while (true) {
            String orderCode = "C" + IdUtils.getOrderCode();
            // 通过orderCode查询是否已经存在
            OrderBasicInfo orderBasicInfo = getOrderInfoByOrderCode(orderCode);
            if (orderBasicInfo == null) {
                return orderCode;
            }
        }
    }

    /**
     * 保存异常订单到订单主表
     *
     * @param data 交易记录数据
     */
    @Override
    public void saveAbnormalOrder(TransactionRecordsData data) {
        OrderAbnormalRecord record = new OrderAbnormalRecord();
        BeanUtils.copyBeanProp(record, data);
        orderAbnormalRecordService.insertOrderAbnormalRecord(record);

        // 保存到订单主表
        // 订单基本信息
        PileInfoVO pileInfoVO = pileBasicInfoService.selectPileInfoBySn(data.getPileSn());
        if (pileInfoVO == null) {
            return;
        }
        String orderCode = generateNewOrderCode();
        OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder().build();
        // 订单编号
        orderBasicInfo.setOrderCode(orderCode);
        // 交易流水号
        orderBasicInfo.setTransactionCode(data.getTransactionCode());
        // 站点id
        String stationId = pileInfoVO.getStationId();
        orderBasicInfo.setStationId(stationId);
        // 运营商id
        PileStationInfo pileStationInfo = pileStationInfoService.selectPileStationInfoById(Long.valueOf(stationId));
        String merchantId = pileStationInfo != null ? String.valueOf(pileStationInfo.getMerchantId()) : "";
        orderBasicInfo.setMerchantId(merchantId);
        // 充电桩编号
        orderBasicInfo.setPileSn(data.getPileSn());
        // 枪口号
        orderBasicInfo.setConnectorCode(data.getConnectorCode());
        // 枪口编号
        orderBasicInfo.setPileConnectorCode(pileInfoVO.getPileSn() + data.getConnectorCode());
        // 启动方式
        String transactionIdentifier = data.getTransactionIdentifier();
        String startMode = null;
        if (StringUtils.equals(transactionIdentifier, "01")) {
            startMode = StartModeEnum.APP.getValue();
            if(StringUtils.isNotBlank(data.getLogicCard())) {
                // 如果卡号不为空，还按照离线卡启动处理
                startMode = StartModeEnum.OFFLINE_CARD.getValue();
                orderBasicInfo.setLogicCard(data.getLogicCard());
            }
        } else if (StringUtils.equals(transactionIdentifier, "02")) {
            // 鉴权卡启动
            startMode = StartModeEnum.AUTH_CARD.getValue();
            orderBasicInfo.setLogicCard(data.getLogicCard());
        } else if (StringUtils.equals(transactionIdentifier, "04")) {
            // 离线卡启动
            startMode = StartModeEnum.OFFLINE_CARD.getValue();
            orderBasicInfo.setLogicCard(data.getLogicCard());
        } else if (StringUtils.equals(transactionIdentifier, "05")) {
            // VIN启动
            startMode = StartModeEnum.VIN_CODE.getValue();
        }
        orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());

        // 卡号
        // if (StringUtils.isNotBlank(data.getLogicCard()) && !StringUtils.equals(Constants.ZERO, data.getLogicCard())) {
        //     startMode = StartModeEnum.OFFLINE_CARD.getValue();
        //     orderBasicInfo.setLogicCard(data.getLogicCard());
        //     // 订单状态 (2023.4.6 要求改成“订单完成”)
        //     orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
        // } else {
        //     // 订单状态 可疑
        //     orderBasicInfo.setOrderStatus(OrderStatusEnum.SUSPICIOUS.getValue());
        // }
        orderBasicInfo.setStartMode(startMode);
        // 支付方式
        orderBasicInfo.setPayMode(null);
        // 支付金额
        orderBasicInfo.setPayAmount(null);
        // 支付状态
        orderBasicInfo.setPayStatus(null);
        // 支付时间
        orderBasicInfo.setPayTime(null);
        // 订单金额
        orderBasicInfo.setOrderAmount(new BigDecimal(data.getConsumptionAmount()));
        // 虚拟金额
        orderBasicInfo.setVirtualAmount(new BigDecimal(data.getConsumptionAmount()));
        // 结算金额
        orderBasicInfo.setSettleAmount(BigDecimal.ZERO);
        // 充电开始时间
        orderBasicInfo.setChargeStartTime(DateUtils.parseDate(data.getStartTime()));
        // 充电结束时间
        orderBasicInfo.setChargeEndTime(DateUtils.parseDate(data.getEndTime()));
        // 停止原因
        orderBasicInfo.setReason(data.getStopReasonMsg());
        // 结算时间
        // orderBasicInfo.setSettlementTime(DateUtils.getNowDate());
        // 创建人
        orderBasicInfo.setCreateBy(data.getLogicCard());

        // 订单详情
        OrderDetail orderDetail = OrderDetail.builder().build();
        // 订单编号
        orderDetail.setOrderCode(orderCode);
        // 订单总金额
        orderDetail.setTotalOrderAmount(new BigDecimal(data.getConsumptionAmount()));
        // 总用电量
        orderDetail.setTotalUsedElectricity(new BigDecimal(data.getTotalElectricity()));
        // 总服务费金额
        // orderDetail.setTotalServiceAmount();
        // 总电费金额
        // orderDetail.setTotalElectricityAmount();

        // 尖时段金额
        orderDetail.setSharpAmount(new BigDecimal(data.getSharpAmount()));
        // 尖时段单价
        orderDetail.setSharpPrice(new BigDecimal(data.getSharpPrice()));

        // 尖时段用电量
        orderDetail.setSharpUsedElectricity(new BigDecimal(data.getSharpUsedElectricity()));

        // 峰时段金额
        orderDetail.setPeakAmount(new BigDecimal(data.getPeakAmount()));
        // 峰时段单价
        orderDetail.setPeakPrice(new BigDecimal(data.getPeakPrice()));

        // 峰时段用电量
        orderDetail.setPeakUsedElectricity(new BigDecimal(data.getPeakUsedElectricity()));

        // 平时段金额
        orderDetail.setFlatAmount(new BigDecimal(data.getFlatAmount()));
        // 平时段单价
        orderDetail.setFlatPrice(new BigDecimal(data.getFlatPrice()));

        // 平时段用电量
        orderDetail.setFlatUsedElectricity(new BigDecimal(data.getFlatUsedElectricity()));

        // 谷时段金额
        orderDetail.setValleyAmount(new BigDecimal(data.getValleyAmount()));
        // 谷时段单价
        orderDetail.setValleyPrice(new BigDecimal(data.getValleyPrice()));

        // 谷时段用电量
        orderDetail.setValleyUsedElectricity(new BigDecimal(data.getValleyUsedElectricity()));

        if (data.getCreateTime() != null) {
            orderBasicInfo.setCreateTime(data.getCreateTime());
            orderDetail.setCreateTime(data.getCreateTime());
        }

        // 查到站点计费模板
        BillingTemplateVO billingTemplate = pileBillingTemplateService.queryUsedBillingTemplate(stationId);
        if (billingTemplate != null) {
            // 尖时段服务费单价
            orderDetail.setSharpServicePrice(billingTemplate.getSharpServicePrice());
            // 尖时段电费单价
            orderDetail.setSharpElectricityPrice(billingTemplate.getSharpElectricityPrice());
            // 峰时段服务费单价
            orderDetail.setPeakServicePrice(billingTemplate.getPeakServicePrice());
            // 峰时段电费单价
            orderDetail.setPeakElectricityPrice(billingTemplate.getPeakElectricityPrice());
            // 平时段服务费单价
            orderDetail.setFlatServicePrice(billingTemplate.getFlatServicePrice());
            // 平时段电费单价
            orderDetail.setFlatElectricityPrice(billingTemplate.getFlatElectricityPrice());
            // 谷时段服务费单价
            orderDetail.setValleyServicePrice(billingTemplate.getValleyServicePrice());
            // 谷时段电费单价
            orderDetail.setValleyElectricityPrice(billingTemplate.getValleyElectricityPrice());
        }

        OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder()
                .orderBasicInfo(orderBasicInfo)
                .orderDetail(orderDetail)
                .build();
        pileTransactionService.doCreateOrder(createOrderTransactionDTO); // 保存异常订单到订单主表
    }

    /**
     * 根据订单编号获取充电实时数据 时间倒序
     * 订单只有在充电中，才会把实时数据保存到redis
     *
     * @param transactionCode 订单编号
     * @return
     */
    @Override
    public List<RealTimeMonitorData> getChargingRealTimeData(String transactionCode) {
        List<RealTimeMonitorData> resultList = Lists.newArrayList();
        if (StringUtils.isBlank(transactionCode)) {
            return resultList;
        }
        String pileConnectorCode = transactionCode.substring(0, 16);
        String redisKey = CacheConstants.PILE_REAL_TIME_MONITOR_DATA + pileConnectorCode + "_" + transactionCode;
        // 拿到所有数据
        Map<Object, Object> map = redisCache.hmget(redisKey);
        if (map != null && !map.isEmpty()) {
            List<String> keyList = map.keySet().stream()
                    .map(x -> (String) x)
                    .sorted(Comparator.reverseOrder()) // 对keyList排序 时间倒序
                    .collect(Collectors.toList());
            for (String s : keyList) {
                Object o = map.get(s);
                RealTimeMonitorData data = JSONObject.parseObject((String) o, RealTimeMonitorData.class);
                resultList.add(data);
            }
        } else {
            logger.debug("redis中没有实时数据了，去数据库查");
            // redis中为空，去查库
            OrderMonitorData orderMonitorData = orderMonitorDataService.selectByTransactionCode(transactionCode);
            if (orderMonitorData != null) {
                String monitorData = orderMonitorData.getMonitorData();
                List<RealTimeMonitorData> dataList = JSON.parseArray(monitorData, RealTimeMonitorData.class);
                resultList.addAll(dataList);
            }
        }
        return resultList;
    }

    /**
     * 首页订单数据展示
     *
     * @param dto 首页信息查询dto
     * @return
     */
    @Override
    public List<IndexOrderInfoVO> getIndexOrderInfo(IndexQueryDTO dto) {
        AuthorizedDeptVO authorizedMap = UserUtils.getAuthorizedMap();
        if (authorizedMap == null) {
            return Lists.newArrayList();
        }
        List<String> stationIdList = Lists.newArrayList();
        List<String> stationDeptIds = authorizedMap.getStationDeptIds();
        if (CollectionUtils.isNotEmpty(stationDeptIds)) {
            // 根据部门id查询站点id
            List<String> list = pileStationInfoService.queryByStationDeptIds(stationDeptIds);
            if (CollectionUtils.isNotEmpty(list)) {
                stationIdList.addAll(list);
            }
        }
        List<String> merchantDeptIds = authorizedMap.getMerchantDeptIds();
        if (CollectionUtils.isNotEmpty(merchantDeptIds)) {
            // 根据运营商部门id查询下面所有站点id
            List<String> list = pileMerchantInfoService.queryByMerchantDeptIds(merchantDeptIds);
            if (CollectionUtils.isNotEmpty(list)) {
                stationIdList.addAll(list);
            }
        }
        dto.setStationIdList(stationIdList);
        // return orderBasicInfoMapper.getIndexOrderInfo(dto);
        List<IndexOrderInfoVO> voList = orderBasicInfoMapper.getIndexOrderInfoV2(dto);

        Map<String, List<IndexOrderInfoVO>> map = voList.stream().collect(Collectors.groupingBy(IndexOrderInfoVO::getDate));

        List<IndexOrderInfoVO> resultList = Lists.newArrayList();
        IndexOrderInfoVO vo;
        for (Map.Entry<String, List<IndexOrderInfoVO>> entry : map.entrySet()) {
            vo = new IndexOrderInfoVO();
            vo.setDate(entry.getKey());

            BigDecimal totalElectricity = BigDecimal.ZERO;
            BigDecimal totalOrderAmount = BigDecimal.ZERO;

            List<String> orderCodeList = Lists.newArrayList();
            for (IndexOrderInfoVO indexOrderInfoVO : entry.getValue()) {
                totalOrderAmount = totalOrderAmount.add(new BigDecimal(indexOrderInfoVO.getTotalOrderAmount()));
                totalElectricity = totalElectricity.add(new BigDecimal(indexOrderInfoVO.getTotalElectricity()));
                orderCodeList.addAll(Lists.newArrayList(StringUtils.split(indexOrderInfoVO.getOrderCodes(), ",")));
            }

            if (CollectionUtils.isNotEmpty(orderCodeList)) {
                // 查询对应数据
                IndexOrderInfoVO detailInfo = orderBasicInfoMapper.getIndexOrderDetail(orderCodeList);
                vo.setTotalOrderAmount(totalOrderAmount.toString());
                vo.setTotalElectricity(totalElectricity.toString());
                if (detailInfo != null) {
                    vo.setTotalPeakUsedElectricity(detailInfo.getTotalPeakUsedElectricity());
                    vo.setTotalFlatUsedElectricity(detailInfo.getTotalFlatUsedElectricity());
                    vo.setTotalSharpUsedElectricity(detailInfo.getTotalSharpUsedElectricity());
                    vo.setTotalValleyUsedElectricity(detailInfo.getTotalValleyUsedElectricity());
                }
                resultList.add(vo);
            }
        }
        resultList = resultList.stream().sorted(Comparator.comparing(IndexOrderInfoVO::getDate)).collect(Collectors.toList());
        return resultList;
    }

    /**
     * 获取超过15分钟的待支付状态订单
     *
     * @return
     */
    @Override
    public List<OrderBasicInfo> getUnpaidOrderListOver15Min() {
        Date now = DateUtils.addMinute(new Date(), -15);
        String nowString = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);
        List<OrderBasicInfo> list = orderBasicInfoMapper.getUnpaidOrderListOver15Min(nowString);
        return CollectionUtils.isNotEmpty(list) ? list : Lists.newArrayList();
    }

    /**
     * 根据orderId批量修改订单状态
     *
     * @param orderIds
     * @param orderStatus
     */
    @Override
    public void updateOrderStatusById(List<String> orderIds, String orderStatus) {
        orderBasicInfoMapper.updateOrderStatusById(orderIds, orderStatus);
    }

    @Override
    public int close15MinutesOfUnpaidOrders() {
        List<OrderBasicInfo> orderList = getUnpaidOrderListOver15Min();
        if (CollectionUtils.isNotEmpty(orderList)) {
            for (OrderBasicInfo orderBasicInfo : orderList) {
                this.cleanCacheByOrderCode(orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode());

                // 通过订单号查询汇付有没有支付单
                checkUnpaidOrder(orderBasicInfo);
            }

            // 订单id集合
            List<String> orderIdList = orderList.stream()
                    .map(x -> String.valueOf(x.getId()))
                    .collect(Collectors.toList());
            // 根据orderIdList修改订单状态
            updateOrderStatusById(orderIdList, OrderStatusEnum.ORDER_CLOSE_TIMEOUT.getValue());
        }
        return orderList.size();
    }

    /**
     * 校验未支付订单
     * 如果存在因为未收到支付回调导致超时关闭的订单，在修改订单状态后，检查一下是否支付过，把支付的金额退款
     *
     * @param orderBasicInfo
     */
    private void checkUnpaidOrder(OrderBasicInfo orderBasicInfo) {
        String orderCode = orderBasicInfo.getOrderCode();
        String memberId = orderBasicInfo.getMemberId();
        String merchantId = orderBasicInfo.getMerchantId();
        String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(merchantId);
        String delayMode = pileMerchantInfoService.getDelayModeByWechatAppId(wechatAppId);

        // 订单总金额
        BigDecimal orderAmount = orderBasicInfo.getOrderAmount() == null ? BigDecimal.ZERO : orderBasicInfo.getOrderAmount();
        if (orderAmount.compareTo(BigDecimal.ZERO) > 0) {
            return;
        }

        // 如果超时关闭的订单，存在支付信息，都退款处理
        Set<PaymentInfo> paymentInfoSet = Sets.newHashSet();
        List<PaymentInfo> paymentInfos1 = orderPayRecordService.queryPaymentInfosByOrderCode(orderCode);
        paymentInfoSet.addAll(paymentInfos1);
        try {
            String redisKey = CacheConstants.ORDER_WECHAT_PAY_PARAMETERS + orderCode;
            String orderNo = redisCache.getCacheObject(redisKey);
            if (StringUtils.isNotBlank(orderNo)) {
                List<PaymentInfo> paymentInfos2 = adapayService.queryPaymentInfosByOrderNo(orderNo, wechatAppId);
                paymentInfoSet.addAll(paymentInfos2);
            }
        } catch (BaseAdaPayException e) {
            throw new RuntimeException(e);
        }
        logger.info("根据订单号:{}, 查询到支付信息:{}", orderCode, JSON.toJSONString(paymentInfoSet));
        if (CollectionUtils.isNotEmpty(paymentInfoSet)) {
            for (PaymentInfo paymentInfo : paymentInfoSet) {
                String paymentId = paymentInfo.getPaymentId();
                BigDecimal payAmt = new BigDecimal(paymentInfo.getAmount());
                if (MerchantDelayModeEnum.DELAY.getMode().equals(delayMode)) {
                    // 延时分账商户，创建交易撤销请求
                    adapayService.createPaymentReverseRequest(paymentId, payAmt, wechatAppId, memberId, ScenarioEnum.ORDER.getValue(), orderCode);
                } else {
                    // 实时分账商户，创建交易退款请求
                    adapayService.createRefundRequest(paymentId, payAmt, wechatAppId, memberId, ScenarioEnum.ORDER.getValue(), orderCode);
                }
            }
        }
    }

    /**
     * 微信支付-订单退款处理逻辑
     */
    @Override
    public WechatPayRefundResponse refundOrderWithWechatPay(ApplyRefundDTO dto) {
        // 查出来原来的支付信息
        WxpayCallbackRecord record = wxpayCallbackRecordService.selectByOrderCode(dto.getOrderCode());
        if (Objects.isNull(record)) {
            logger.error("orderCode:{}, 订单退款处理逻辑, 查询订单微信支付记录为空!", dto.getOrderCode());
            throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_CALLBACK_RECORD_ERROR);
        }

        // 判断支付金额和退款金额
        int refundAmountInt = dto.getRefundAmount().multiply(new BigDecimal("100")).intValue();
        int payerTotalInt = Integer.parseInt(record.getPayerTotal());
        if (refundAmountInt > payerTotalInt) {
            logger.error("订单号:{}, 退款金额:{}(分)，大于可退金额{}(分), 抛出异常", dto.getOrderCode(), refundAmountInt, payerTotalInt);
            throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_AMOUNT_ERROR);
        }

        // 调微信退款接口
        WechatPayRefundRequest request = new WechatPayRefundRequest();
        request.setTransaction_id(record.getTransactionId()); // 微信支付单号
        request.setOut_trade_no(record.getOutTradeNo()); // 商户订单号
        // 生成退款单号
        request.setOut_refund_no(SnowflakeIdWorker.getSnowflakeId()); // 商户退款单号
        request.setNotify_url(WeChatPayParameter.refundNotifyUrl); // 回调接口
        WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount();
        amount.setRefund(refundAmountInt); // 退款金额
        amount.setTotal(payerTotalInt); // 原订单金额
        request.setAmount(amount);
        request.setReason("订单结算退款");
        request.setFunds_account("AVAILABLE");
        try {
            return wechatPayService.ApplyForWechatPayRefundV3(request);
        } catch (JsonProcessingException e) {
            logger.error("调微信退款API发生异常", e);
        }
        return null;
    }

    /**
     * 微信支付-余额退款处理逻辑
     */
    @Override
    public WechatPayRefundResponse refundBalanceWithWechatPay(ApplyRefundDTO dto) {
        // 查会员余额
        MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId());
        if (memberVO == null) {
            throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_NOT_FOUND_ERROR);
        }
        // 校验退款金额
        BigDecimal principalBalance = memberVO.getPrincipalBalance();
        BigDecimal refundAmount = dto.getRefundAmount();
        if (refundAmount.compareTo(principalBalance) > 0) {
            throw new BusinessException(ReturnCodeEnum.CODE_REFUND_MEMBER_BALANCE_ERROR);
        }
        // 退款金额 元转分 123
        int refundTotalCents = refundAmount.multiply(new BigDecimal(100)).intValue();

        // 查询用户充值余额订单 过滤掉已经退款的充值订单 refundableOrder
        List<RefundableWxPayOrderData> recordList = queryRefundableOrder(dto.getMemberId());

        // 也许需要多笔支付订单才够退款
        List<WechatPayRefundRequest> requestList = Lists.newArrayList();
        WechatPayRefundRequest request;
        for (RefundableWxPayOrderData record : recordList) {
            int refundableTotal = record.getRefundableAmount().intValue(); // 该笔支付订单的可退金额，单位分
            int payerTotal = record.getPayerAmount().intValue(); // 该笔支付订单的支付金额，单位分
            // 用户申请退款金额-可退金额
            refundTotalCents = refundTotalCents - refundableTotal; // 123 - 100
            request = new WechatPayRefundRequest();
            request.setTransaction_id(record.getTransactionId()); // 微信支付单号
            request.setOut_trade_no(record.getOutTradeNo()); // 商户订单号
            request.setOut_refund_no(SnowflakeIdWorker.getSnowflakeId()); // 商户退款单号
            request.setNotify_url(WeChatPayParameter.refundNotifyUrl); // 回调接口
            request.setReason("用户余额退款");
            request.setFunds_account("AVAILABLE");
            if (refundTotalCents > 0) {
                // 如果大于0说明，这笔单退完也不够
                WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount();
                amount.setRefund(refundableTotal); // 退款金额
                amount.setTotal(payerTotal); // 原订单金额
                request.setAmount(amount);
                requestList.add(request);
            } else {
                // 如果小于0，这笔单退一部分
                // 生成退款单号
                WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount();
                // 部分退
                int i = refundableTotal + refundTotalCents;
                amount.setRefund(i); // 退款金额
                amount.setTotal(payerTotal); // 原订单金额
                request.setAmount(amount);
                requestList.add(request);
                break;
            }
        }
        // 调微信退款api
        if (CollectionUtils.isNotEmpty(requestList)) {
            for (WechatPayRefundRequest refundRequest : requestList) {
                try {
                    WechatPayRefundResponse wechatPayRefundResponse = wechatPayService.ApplyForWechatPayRefundV3(refundRequest);
                    logger.info("调微信退款API退款====={}", JSON.toJSONString(wechatPayRefundResponse));
                } catch (Exception e) {
                    logger.error("调微信退款API发生异常", e);
                }
            }
        }
        return null;
    }

    private List<RefundableWxPayOrderData> queryRefundableOrder(String memberId) {
        List<RefundableWxPayOrderData> resultList = Lists.newArrayList();
        // 查询最近一年余额充值订单
        List<WxpayCallbackRecord> recordList = wxpayCallbackRecordService.queryBalanceRechargeRecordOfTheLatestYear(memberId);
        if (CollectionUtils.isEmpty(recordList)) {
            return resultList;
        }
        // 拿到微信商户单号list
        List<String> outTradeNoList = recordList.stream()
                .map(WxpayCallbackRecord::getOutTradeNo)
                .collect(Collectors.toList());
        List<WxpayRefundCallback> wxpayRefundCallbacks = wxpayRefundCallbackService.selectWxpayRefundCallbackList(outTradeNoList);
        if (CollectionUtils.isEmpty(wxpayRefundCallbacks)) {
            // 退款记录为空，表示没有一笔退款
            for (WxpayCallbackRecord wxpayCallbackRecord : recordList) {
                resultList.add(
                        RefundableWxPayOrderData.builder()
                                .outTradeNo(wxpayCallbackRecord.getOutTradeNo())
                                .transactionId(wxpayCallbackRecord.getTransactionId())
                                .payerAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal()))
                                .refundableAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal()))
                                .build()
                );
            }
            return resultList;
        }

        // 退款记录转map  key:outTradeNo  value:退款记录
        Map<String, List<WxpayRefundCallback>> refundMap = wxpayRefundCallbacks.stream()
                .collect(Collectors.groupingBy(WxpayRefundCallback::getOutTradeNo));
        for (WxpayCallbackRecord wxpayCallbackRecord : recordList) {
            List<WxpayRefundCallback> refundCallbackList = refundMap.get(wxpayCallbackRecord.getOutTradeNo());
            if (CollectionUtils.isEmpty(refundCallbackList)) {
                // 这笔单没有申请过退款
                resultList.add(
                        RefundableWxPayOrderData.builder()
                                .outTradeNo(wxpayCallbackRecord.getOutTradeNo())
                                .transactionId(wxpayCallbackRecord.getTransactionId())
                                .payerAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal()))
                                .refundableAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal()))
                                .build()
                );
                continue;
            }
            // 支付订单产生过退款
            BigDecimal refundTotal = refundCallbackList.stream()
                    .map(x -> new BigDecimal(x.getAmountRefund()))
                    .reduce(BigDecimal::add)
                    .get();

            // 可退金额
            BigDecimal subtract = new BigDecimal(wxpayCallbackRecord.getPayerTotal()).subtract(refundTotal);
            if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                resultList.add(
                        RefundableWxPayOrderData.builder()
                                .outTradeNo(wxpayCallbackRecord.getOutTradeNo())
                                .transactionId(wxpayCallbackRecord.getTransactionId())
                                .payerAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal()))
                                .refundableAmount(subtract)
                                .build()
                );
            }
        }
        return resultList;
    }

    /**
     * 通过订单号查询订单详情
     *
     * @param orderCode 订单号
     * @return 订单详情
     */
    @Override
    public OrderDetail getOrderDetailByOrderCode(String orderCode) {
        return orderBasicInfoMapper.getOrderDetailByOrderCode(orderCode);
    }

    @Override
    public List<OrderDetail> getOrderDetailList(List<String> orderCodes) {
        return orderBasicInfoMapper.getOrderDetailList(orderCodes);
    }

    /**
     * 通过会员Id和订单状态查询订单信息
     *
     * @param memberId        会员id
     * @param orderStatusList 订单状态集合
     * @return
     */
    @Override
    public List<OrderVO> getListByMemberIdAndOrderStatus(String memberId, List<String> orderStatusList) {
        return getListByMemberIdAndOrderStatus(memberId, orderStatusList, null, null);
    }

    @Override
    public List<OrderVO> getListByMemberIdAndOrderStatus(String memberId, List<String> orderStatusList, LocalDateTime dateTime) {
        return getListByMemberIdAndOrderStatus(memberId, orderStatusList, dateTime, null);
    }

    @Override
    public List<OrderVO> getListByMemberIdAndOrderStatus(String memberId, List<String> orderStatusList, LocalDateTime dateTime, String stationId) {
        return orderBasicInfoMapper.getListByMemberIdAndOrderStatus(memberId, orderStatusList, dateTime, stationId);
    }

    @Override
    public List<OrderVO> getListByOrderCodes(List<String> orderCodes) {
        return orderBasicInfoMapper.getListByOrderCodes(orderCodes);
    }

    /**
     * 个人桩查询充电数据
     *
     * @param dto
     * @return
     */
    @Override
    public List<PersonPileConnectorSumInfoVO> getAccumulativeInfo(QueryPersonPileDTO dto) {
        return orderBasicInfoMapper.getAccumulativeInfo(dto);
    }

    /**
     * 修改订单状态为异常（桩离线时调用）
     *
     * @param pileSn
     */
    @Override
    public void updateOrderStatusAsAbnormal(String pileSn) {
        // 先从redis判断是否有订单再进行查询
        // if (Objects.isNull(redisCache.getCacheObject(CacheConstants.PILE_IS_CHARGING + pileSn))) {
        //     return;
        // }
        // 将此桩正在进行充电的订单状态改为 异常
        List<OrderListVO> orderListVOS = selectChargingOrder(pileSn);
        if (CollectionUtils.isEmpty(orderListVOS)) {
            return;
        }
        for (OrderListVO orderListVO : orderListVOS) {
            if (StringUtils.equals(orderListVO.getOrderStatus(), OrderStatusEnum.IN_THE_CHARGING.getValue())) {
                // 修改数据库订单状态
                OrderBasicInfo info = OrderBasicInfo.builder()
                        .id(Integer.parseInt(orderListVO.getId()))
                        .orderStatus(OrderStatusEnum.ABNORMAL.getValue())
                        .build();
                updateOrderBasicInfo(info);
                logger.info("充电桩:{}退出, 修改充电桩正在充电的订单状态为异常, orderCode: {}", pileSn, orderListVO.getOrderCode());
            }
        }
    }

    @Override
    public List<OrderBasicInfo> getReservedOrder(LocalDateTime dateTime) {
        return orderBasicInfoMapper.getReservedOrder(dateTime);
    }

    /**
     * 生成订单 返回交易流水号
     *
     * @param dto
     * @return
     */
    @Override
    public Map<String, Object> generateOrderByCard(GenerateOrderDTO dto) throws Exception {
        logger.info("充电桩主动申请启动充电生成订单 param:{}", JSON.toJSONString(dto));
        BigDecimal accountBalance;
        String payMode;
        // 判断当前用户是否为平台测试员
        PlatformTesterVO platformTesterVO = memberBasicInfoService.selectPlatformTesterStatus(dto.getMemberId());
        PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(dto.getPileSn());
        PileStationWhitelist pileStationWhitelist = pileStationWhitelistService.queryWhitelistByMemberId(String.valueOf(pileBasicInfo.getStationId()), dto.getMemberId());

        // 运营商id
        String merchantId = pileBasicInfo.getMerchantId() + "";

        if (platformTesterVO != null && StringUtils.equals(Constants.ONE, platformTesterVO.getStatus())) {
            // 是平台测试员
            accountBalance = Constants.WHITELIST_DEFAULT_AMOUNT;
            payMode = OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue();
        } else if (pileStationWhitelist != null) {
            // 站点白名单
            accountBalance = Constants.WHITELIST_DEFAULT_AMOUNT;
            payMode = OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue();
        } else {
            // 通过memberId获取账户余额
            MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId(), merchantId);
            if (memberVO == null) {
                throw new BusinessException(ReturnCodeEnum.CODE_GET_MEMBER_ACCOUNT_AMOUNT_ERROR);
            }
            accountBalance = memberVO.getTotalBalance();
            if (accountBalance.compareTo(BigDecimal.ZERO) <= 0) {
                logger.info("充电桩主动申请启动充电生成订单 余额不足, memberId:{}, MemberVO:{}", dto.getMemberId(), JSON.toJSONString(memberVO));
                throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_IS_INSUFFICIENT);
            }
            BigDecimal defaultAmount = Constants.BALANCE_PAY_MAX_AMOUNT_NEW;
            if (accountBalance.compareTo(defaultAmount) > 0) {
                accountBalance = defaultAmount;
            }
            payMode = OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue();
        }
        dto.setChargeAmount(accountBalance);
        dto.setPayMode(payMode);
        /*
        生成订单
         */
        OrderBasicInfo basicInfo = generateOrder(dto);
        if (basicInfo == null) {
            return null;
        }
        if (StringUtils.equals(StartModeEnum.AUTH_CARD.getValue(), dto.getStartMode())) {
            // 将卡状态改为启动锁定
            PileAuthCard pileAuthCard = PileAuthCard.builder()
                    .id(dto.getPileAuthCardInfo().getId())
                    .logicCard(dto.getPileAuthCardInfo().getLogicCard())
                    .status("2")
                    .build();
            pileAuthCardService.updatePileAuthCard(pileAuthCard);
        } else if (StringUtils.equals(StartModeEnum.VIN_CODE.getValue(), dto.getStartMode())) {
            // 将vin码改成启动锁定 2023.11.4  站点白名单和测试员不需要锁定
            if (!StringUtils.equals(OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue(), dto.getPayMode())) {
                dto.getMemberPlateNumberRelation().setVinStatus("2");
            }
            // 2024.02.06 不再判断锁定状态
            // memberPlateNumberRelationService.updateMemberPlateNumberRelation(dto.getMemberPlateNumberRelation());
        }

        // 组装结果集
        Map<String, Object> map = Maps.newHashMap();
        map.put("orderCode", basicInfo.getOrderCode());
        map.put("transactionCode", basicInfo.getTransactionCode());
        map.put("accountBalance", accountBalance);

        logger.info("生成订单 result:{}", JSON.toJSONString(map));

        // 支付订单
        // PayOrderDTO payOrderDTO = new PayOrderDTO();
        // payOrderDTO.setOrderCode(basicInfo.getOrderCode());
        // payOrderDTO.setPayAmount(accountBalance);
        // payOrderDTO.setPayMode(dto.getPayMode());
        // payOrderDTO.setMemberId(dto.getMemberId());
        // payOrderDTO.setStartMode(dto.getStartMode());
        // payOrderDTO.setRequestSource("");
        // payOrderDTO.setCode();
        // payOrderDTO.setLockValue();
        // payOrderDTO.setOrderBasicInfo(basicInfo);

        PayOrderDTO payOrderDTO = PayOrderDTO.builder()
                .orderCode(basicInfo.getOrderCode())
                .payAmount(accountBalance)
                .payMode(dto.getPayMode())
                .memberId(dto.getMemberId())
                .startMode(dto.getStartMode())
                .build();

        String mode = pileMerchantInfoService.getDelayModeByMerchantId(merchantId);
        // 获取处理逻辑
        AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode);
        orderLogic.payOrder(payOrderDTO); // 充电桩主动申请启动充电生成订单 使用支付

        // 推送小程序启动充电消息
        // 通过memberId查询openId
        MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMemberId(dto.getMemberId());
        WechatSendMsgDTO sendMsgDTO = new WechatSendMsgDTO();
        sendMsgDTO.setOpenId(memberBasicInfo.getOpenId());
        sendMsgDTO.setOrderCode(basicInfo.getOrderCode());

        wxAppletRemoteService.startChargingSendMsg(sendMsgDTO);

        return map;
    }

    /**
     * 联联平台 获取累计数据用
     *
     * @param dto
     * @return
     */
    @Override
    public List<AccumulativeInfoVO> getAccumulativeInfoForLianLian(QueryStationInfoDTO dto) {
        return orderBasicInfoMapper.getAccumulativeInfoForLianLian(dto);
    }

    /**
     * 联联平台生成订单
     *
     * @param dto
     * @return
     */
    @Override
    public Map<String, Object> generateOrderForThirdParty(QueryStartChargeDTO dto) {
        logger.info("联联平台生成订单param:{}", JSON.toJSONString(dto));
        // 获取到第三方平台类型
        String operatorId = dto.getOperatorId();
        String type = ThirdPartyOperatorIdEnum.getTypeByOperatorId(operatorId);
        // 生成订单
        String orderCode = dto.getStartChargeSeq();
        String pileConnectorCode = dto.getConnectorID();
        String pileSn = StringUtils.substring(pileConnectorCode, 0, 14);
        String connectorCode = StringUtils.substring(pileConnectorCode, 14, 16);

        String transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode);

        // 校验充电桩信息
        GenerateOrderDTO generateOrderDTO = new GenerateOrderDTO();
        generateOrderDTO.setPileSn(pileSn);
        generateOrderDTO.setConnectorCode(connectorCode);
        generateOrderDTO.setStartMode(StartModeEnum.THIRD_PARTY_PLATFORM.getValue());

        checkPileInfo(generateOrderDTO);
        // 通过桩号查询所属站点
        PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn);
        Long stationId = pileBasicInfo.getStationId();
        PileStationInfo pileStationInfo = pileStationInfoService.selectPileStationInfoById(stationId);
        String merchantId = pileStationInfo != null ? String.valueOf(pileStationInfo.getMerchantId()) : "";
        // 将此订单信息存入订单表
        // 订单基本信息
        OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder()
                .orderCode(orderCode)
                .transactionCode(transactionCode)
                .orderStatus(OrderStatusEnum.NOT_START.getValue())
                // .memberId(memberVO.getMemberId())  // 会员memberId
                .stationId(String.valueOf(stationId))
                .merchantId(merchantId)
                .pileSn(pileSn)
                .connectorCode(connectorCode)
                .pileConnectorCode(pileConnectorCode)
                // .logicCard(pileAuthCardInfo.getLogicCard())  // 卡号
                .startMode(StartModeEnum.THIRD_PARTY_PLATFORM.getValue()) // 启动方式
                .thirdPartyType(type) // 第三方平台类型
                .payStatus(Constants.ONE)
                .payAmount(dto.getAccountBalance())  // 支付金额
                .payTime(new Date())
                // .payMode()  // 支付方式
                .orderAmount(BigDecimal.ZERO)
                .build();
        if (StringUtils.isNotBlank(dto.getPlateNum())) {
            // 车牌号
            orderBasicInfo.setPlateNumber(dto.getPlateNum());
        }
        if (StringUtils.isNotBlank(dto.getPayMode())) {
            orderBasicInfo.setPayMode(dto.getPayMode());
        }
        // 根据桩编码查询当前计费模板
        BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn);
        // 订单详情
        OrderDetail orderDetail = OrderDetail.builder()
                .orderCode(orderCode)
                .sharpElectricityPrice(billingTemplateVO.getSharpElectricityPrice())
                .sharpServicePrice(billingTemplateVO.getSharpServicePrice())
                .peakElectricityPrice(billingTemplateVO.getPeakElectricityPrice())
                .peakServicePrice(billingTemplateVO.getPeakServicePrice())
                .flatElectricityPrice(billingTemplateVO.getFlatElectricityPrice())
                .flatServicePrice(billingTemplateVO.getFlatServicePrice())
                .valleyElectricityPrice(billingTemplateVO.getValleyElectricityPrice())
                .valleyServicePrice(billingTemplateVO.getValleyServicePrice())
                .build();

        OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder()
                .orderBasicInfo(orderBasicInfo)
                .orderDetail(orderDetail)
                .build();
        pileTransactionService.doCreateOrder(createOrderTransactionDTO); // 联联平台生成订单

        // 组装结果集
        Map<String, Object> resultMap = Maps.newHashMap();
        resultMap.put("orderCode", orderBasicInfo.getOrderCode());
        resultMap.put("transactionCode", orderBasicInfo.getTransactionCode());
        resultMap.put("orderBasicInfo", orderBasicInfo);
        resultMap.put("orderDetail", orderDetail);
        // resultMap.put("accountBalance", totalAccountAmount);
        logger.info("联联平台生成订单result:{}", JSON.toJSONString(resultMap));
        return resultMap;
    }

    @Override
    public List<OrderAmountDetailVO> queryOrderAmountDetail(List<String> orderCodes) {
        List<OrderDetail> orderDetailList = getOrderDetailList(orderCodes);
        if (CollectionUtils.isEmpty(orderDetailList)) {
            return Lists.newArrayList();
        }
        List<OrderAmountDetailVO> resultList = Lists.newArrayList();
        OrderAmountDetailVO vo = null;
        for (OrderDetail orderDetail : orderDetailList) {
            vo = new OrderAmountDetailVO();
            BeanUtils.copyBeanProp(vo, orderDetail);
            resultList.add(vo);
        }
        return resultList;
    }

    /**
     * 订单详情 转换为各个时段的详情
     */
    @Override
    public List<OrderPeriodAmountVO> transformPeriodAmountByOrderDetail(OrderDetail orderDetail) {
        // 尖时段
        OrderPeriodAmountVO sharp = new OrderPeriodAmountVO();
        sharp.setPeriodType(BillingTimeTypeEnum.SHARP.getLabel());
        sharp.setElectricityPrice(orderDetail.getSharpElectricityPrice());
        sharp.setServicePrice(orderDetail.getSharpServicePrice());
        BigDecimal sharpUsedElectricity = orderDetail.getSharpUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getSharpUsedElectricity();
        sharp.setUsedElectricity(sharpUsedElectricity);
        sharp.setElectricityAmount(sharp.getElectricityPrice().multiply(sharp.getUsedElectricity()).setScale(2, RoundingMode.DOWN));
        sharp.setServiceAmount(sharp.getServicePrice().multiply(sharp.getUsedElectricity()).setScale(2, RoundingMode.DOWN));

        // 峰时段
        OrderPeriodAmountVO peak = new OrderPeriodAmountVO();
        peak.setPeriodType(BillingTimeTypeEnum.PEAK.getLabel());
        peak.setElectricityPrice(orderDetail.getPeakElectricityPrice());
        peak.setServicePrice(orderDetail.getPeakServicePrice());
        BigDecimal peakUsedElectricity = orderDetail.getPeakUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getPeakUsedElectricity();
        peak.setUsedElectricity(peakUsedElectricity);
        peak.setElectricityAmount(peak.getElectricityPrice().multiply(peak.getUsedElectricity()).setScale(2, RoundingMode.DOWN));
        peak.setServiceAmount(peak.getServicePrice().multiply(peak.getUsedElectricity()).setScale(2, RoundingMode.DOWN));

        // 平时段
        OrderPeriodAmountVO flat = new OrderPeriodAmountVO();
        flat.setPeriodType(BillingTimeTypeEnum.FLAT.getLabel());
        flat.setElectricityPrice(orderDetail.getFlatElectricityPrice());
        flat.setServicePrice(orderDetail.getFlatServicePrice());
        BigDecimal flatUsedElectricity = orderDetail.getFlatUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getFlatUsedElectricity();
        flat.setUsedElectricity(flatUsedElectricity);
        flat.setElectricityAmount(flat.getElectricityPrice().multiply(flat.getUsedElectricity()).setScale(2, RoundingMode.DOWN));
        flat.setServiceAmount(flat.getServicePrice().multiply(flat.getUsedElectricity()).setScale(2, RoundingMode.DOWN));

        // 谷时段
        OrderPeriodAmountVO valley = new OrderPeriodAmountVO();
        valley.setPeriodType(BillingTimeTypeEnum.VALLEY.getLabel());
        valley.setElectricityPrice(orderDetail.getValleyElectricityPrice());
        valley.setServicePrice(orderDetail.getValleyServicePrice());
        BigDecimal valleyUsedElectricity = orderDetail.getValleyUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getValleyUsedElectricity();
        valley.setUsedElectricity(valleyUsedElectricity);
        valley.setElectricityAmount(valley.getElectricityPrice().multiply(valley.getUsedElectricity()).setScale(2, RoundingMode.DOWN));
        valley.setServiceAmount(valley.getServicePrice().multiply(valley.getUsedElectricity()).setScale(2, RoundingMode.DOWN));

        return Lists.newArrayList(sharp, peak, flat, valley);
    }

    /**
     * 汇付支付-订单退款处理逻辑
     * 汇付支付订单退款
     *
     * @param dto
     */
    @Override
    public void refundOrderWithAdapay(ApplyRefundDTO dto) {
        logger.info("汇付支付订单:{}, 执行退款逻辑 param:{}", dto.getOrderCode(), JSON.toJSONString(dto));
        // 查出来原来的支付信息
        AdapayCallbackRecord callbackRecord = adapayCallbackRecordService.selectByOrderCode(dto.getOrderCode());
        if (Objects.isNull(callbackRecord)) {
            logger.error("汇付支付orderCode:{}, 订单退款处理逻辑, 查询订单微信支付记录为空!", dto.getOrderCode());
            throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_CALLBACK_RECORD_ERROR);
        }

        String paymentId = callbackRecord.getPaymentId();
        // 判断支付金额和退款金额
        BigDecimal refundAmount = dto.getRefundAmount();
        BigDecimal payAmt = callbackRecord.getPayAmt();
        if (refundAmount.compareTo(payAmt) > 0) {
            logger.error("汇付支付订单号:{}, 退款金额:{}(元)，大于付款金额{}(元), 抛出异常", dto.getOrderCode(), refundAmount, payAmt);
            throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_AMOUNT_ERROR);
        }

        // 获取延时分账模式  延时分账的使用撤销方法退款，实时分账的使用退款方法
        String description = callbackRecord.getDescription();
        JSONObject descriptionJsonObject = JSON.parseObject(description);
        String payMode = descriptionJsonObject.getString("payMode");
        BigDecimal refundAmt = null; // 交易退款金额
        if (StringUtils.equalsIgnoreCase(payMode, Constants.ADAPAY_PAY_MODE_DELAY)) {
            // 延迟分账未确认调撤销调撤销接口退款
            PaymentReverseOperation operation = new PaymentReverseOperation();
            operation.setPaymentId(paymentId);
            operation.setReverseAmt(refundAmount);
            operation.setMerchantKey(dto.getWechatAppId());
            operation.setMemberId(dto.getMemberId());
            operation.setScenarioType(ScenarioEnum.ORDER.getValue());
            operation.setOrderCode(dto.getOrderCode());
            PaymentReverseResponse response = adapayService.createPaymentReverseRequest(operation);
            if (response != null && response.isNotFailed()) {
                refundAmt = new BigDecimal(response.getReverse_amt());
                /*
                 不管是撤销还是退款，都需要更新memberAdapayRecord中的金额, 解冻金额就是支付的金额，退款金额就是订单结算后需要退的金额
                 延时分账的，可以部分解冻
                 */
                memberAdapayRecordService.updateRefundAmountFromFreezeAmount(paymentId, refundAmt);
            }
        } else {
            // 实时分账的调退款接口
            RefundResponse refundRequest = adapayService.createRefundRequest(paymentId, refundAmount,
                    dto.getWechatAppId(), dto.getMemberId(), ScenarioEnum.ORDER.getValue(), dto.getOrderCode());
            if (refundRequest != null && refundRequest.isNotFailed()) {
                refundAmt = new BigDecimal(refundRequest.getRefund_amt());
                // 更新此笔交易单的消费金额 = 支付金额 - 撤销金额
                /*
                 不管是撤销还是退款，都需要更新memberAdapayRecord中的金额, 解冻金额就是支付的金额，退款金额就是订单结算后需要退的金额
                 实时分账的，可以全部解冻
                 */
                memberAdapayRecordService.unfreezeAmountAndUpdateSpendAmount(paymentId, payAmt, refundAmt);
            }
        }
    }

    /**
     * 汇付支付余额退款
     *
     * @param dto
     */
    @Override
    public void refundBalanceWithAdapay(ApplyRefundDTO dto) {
        // 做个拦截，如果前一笔退款没有完成，就抛异常
        String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + dto.getMemberId();
        PaymentReverseResponse redisResult = redisCache.getCacheObject(redisKey);
        if (Objects.nonNull(redisResult)) {
            throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_REFUNDS_ARE_IN_PROGRESS_ERROR);
        }

        // 查会员余额
        MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId());
        if (memberVO == null) {
            throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_NOT_FOUND_ERROR);
        }

        // 校验退款金额
        BigDecimal principalBalance = memberVO.getPrincipalBalance();
        BigDecimal refundAmount = dto.getRefundAmount();
        if (refundAmount.compareTo(principalBalance) > 0) {
            throw new BusinessException(ReturnCodeEnum.CODE_REFUND_MEMBER_BALANCE_ERROR);
        }

        // 查询用户充值余额订单 过滤掉已经退款的充值订单
        List<BalanceDeductionAmountVO> list = calculateTheBalanceDeductionAmount(dto.getMemberId(), refundAmount);
        for (BalanceDeductionAmountVO vo : list) {
            String paymentId = vo.getPaymentId();
            BigDecimal deductionAmount = vo.getDeductionAmount();

            // 调汇付的交易撤销接口
            // PaymentReverseResponse paymentReverseRequest = adapayService.createPaymentReverseRequest(paymentId, deductionAmount, dto.getWechatAppId(),
            //         dto.getMemberId(), ScenarioEnum.BALANCE.getValue(), null);

            PaymentReverseOperation operation = new PaymentReverseOperation();
            operation.setPaymentId(paymentId);
            operation.setReverseAmt(deductionAmount);
            operation.setMerchantKey(dto.getWechatAppId());
            operation.setMemberId(dto.getMemberId());
            operation.setScenarioType(ScenarioEnum.BALANCE.getValue());
            PaymentReverseResponse paymentReverseRequest = adapayService.createPaymentReverseRequest(operation);

            if (paymentReverseRequest != null && paymentReverseRequest.isNotFailed()) {
                memberAdapayRecordService.updateRefundAmount(paymentId, deductionAmount);

                // 放缓存
                redisCache.setCacheObject(redisKey, paymentReverseRequest, CacheConstants.cache_expire_time_30m);
            }
        }
    }

    /**
     * 计算站点订单报表
     *
     * @param stationId 站点id
     * @param tradeDate 交易日期
     */
    // @Override
    // public void generateDailyOrderReports(String stationId, String tradeDate) {
    //     // logger.info("线程名===={}", Thread.currentThread().getName());
    //     if (StringUtils.isBlank(stationId)) {
    //         return;
    //     }
    //     if (StringUtils.isBlank(tradeDate)) {
    //         // 日期为空默认昨天
    //         tradeDate = LocalDate.now().plusDays(-1).toString();
    //     }
    //     PileStationVO stationInfo = pileStationInfoService.getStationInfo(stationId);
    //     // 查询站点前一天结算完成的订单
    //     QueryOrderDTO dto = new QueryOrderDTO();
    //     dto.setStationId(stationId);
    //     LocalDate parse = LocalDate.parse(tradeDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    //     String startTime = DateUtils.formatDateTime(LocalDateTime.of(parse, LocalTime.MIN));
    //     String endTime = DateUtils.formatDateTime(LocalDateTime.of(parse, LocalTime.MAX));
    //     dto.setStartSettleTime(startTime);
    //     dto.setEndSettleTime(endTime);
    //     // 查询结算完成的订单
    //     List<OrderListVO> orderListVOS = orderBasicInfoMapper.selectOrderBasicInfoList(dto);
    //     // if (CollectionUtils.isEmpty(orderListVOS)) {
    //     //     logger.info("站点:{}, 在{}-{}没有查询到订单数据", stationInfo.getStationName(), startTime, endTime);
    //     //     return;
    //     // }
    //     List<String> collect = orderListVOS.stream().map(OrderListVO::getOrderCode).collect(Collectors.toList());
    //     logger.info("站点:{}, 在{}-{}查询到订单数据{}条，订单编号:{}", stationInfo.getStationName(), startTime, endTime, orderListVOS.size(), collect);
    //     // 统计出日报信息
    //     BigDecimal useElectricity = BigDecimal.ZERO;
    //     int chargeNum = 0;
    //     long chargeTime = 0L;
    //     BigDecimal totalElectricityAmount = BigDecimal.ZERO;
    //     BigDecimal totalServiceAmount = BigDecimal.ZERO;
    //     BigDecimal totalOrderAmount = BigDecimal.ZERO;
    //     BigDecimal totalVirtualAmount = BigDecimal.ZERO;
    //     BigDecimal totalSettleAmount = BigDecimal.ZERO;
    //     List<String> orderCodeList = Lists.newArrayList();
    //     for (OrderListVO vo : orderListVOS) {
    //         // 统计结算金额大于0的
    //         BigDecimal settleAmount = StringUtils.isBlank(vo.getSettleAmount())
    //                 ? BigDecimal.ZERO
    //                 : new BigDecimal(vo.getSettleAmount());
    //         if (settleAmount.compareTo(BigDecimal.ZERO) <= 0) {
    //             // 只统计用电量大于0的
    //             continue;
    //         }
    //
    //         // 订单消费金额
    //         String orderAmount = vo.getOrderAmount();
    //
    //         // 用电度数
    //         BigDecimal chargingDegree = StringUtils.isBlank(vo.getChargingDegree())
    //                 ? BigDecimal.ZERO
    //                 : new BigDecimal(vo.getChargingDegree());
    //
    //         // 充电度数累计
    //         useElectricity = useElectricity.add(chargingDegree);
    //
    //         // 充电次数
    //         chargeNum += 1;
    //         orderCodeList.add(vo.getOrderCode());
    //
    //         // 充电时间累计
    //         if (StringUtils.isNotBlank(vo.getChargeStartTime()) && StringUtils.isNotBlank(vo.getChargeEndTime())) {
    //             long l = DateUtils.intervalTime(vo.getChargeStartTime(), vo.getChargeEndTime());
    //             chargeTime += l;
    //         }
    //
    //         // 电费金额
    //         BigDecimal e = vo.getTotalElectricityAmount() != null ? vo.getTotalElectricityAmount() : BigDecimal.ZERO;
    //         totalElectricityAmount = totalElectricityAmount.add(e);
    //
    //         // 服务费金额
    //         BigDecimal serviceAmount = vo.getTotalServiceAmount() != null ? vo.getTotalServiceAmount() : BigDecimal.ZERO;
    //         totalServiceAmount = totalServiceAmount.add(serviceAmount);
    //
    //         // 订单金额
    //         totalOrderAmount = totalOrderAmount.add(new BigDecimal(orderAmount));
    //
    //         // 虚拟金额
    //         String virtualAmount = StringUtils.isNotBlank(vo.getVirtualAmount()) ? vo.getVirtualAmount() : Constants.ZERO;
    //         totalVirtualAmount = totalVirtualAmount.add(new BigDecimal(virtualAmount));
    //
    //         // 结算金额
    //         totalSettleAmount = totalSettleAmount.add(settleAmount);
    //     }
    //
    //     // 计算报表
    //     SettleOrderReport settleOrderReport = new SettleOrderReport();
    //     String settleCode = "SETTLE_" + IdUtils.getOrderCode();
    //     settleOrderReport.setSettleCode(settleCode);
    //     settleOrderReport.setMerchantId(stationInfo.getMerchantId());
    //     settleOrderReport.setStationId(stationId);
    //     settleOrderReport.setUseElectricity(useElectricity);
    //     settleOrderReport.setChargeNum(chargeNum + "");
    //     settleOrderReport.setChargeTime(chargeTime + "");
    //     settleOrderReport.setElectricityAmount(totalElectricityAmount);
    //     settleOrderReport.setServiceAmount(totalServiceAmount);
    //     settleOrderReport.setTotalAmount(totalOrderAmount);
    //     settleOrderReport.setVirtualAmount(totalVirtualAmount);
    //     settleOrderReport.setTradeDate(tradeDate);
    //     settleOrderReport.setOrderCodes(Joiner.on(",").join(orderCodeList));
    //     // 计算手续费 = 结算金额 * 0.55%
    //     SplitSettleAmountVO splitSettleAmountVO = splitSettleAmount(totalSettleAmount);
    //     settleOrderReport.setTradeFee(splitSettleAmountVO.getFeeAmount());
    //     settleOrderReport.setTradeAmount(splitSettleAmountVO.getTradeAmount());
    //     // 根据站点id和交易日期查询
    //     SettleOrderReport selectResult = settleOrderReportService.selectByStationIdAndDate(stationId, tradeDate);
    //     if (selectResult != null) {
    //         settleOrderReport.setId(selectResult.getId());
    //     }
    //     // 订单日报 新增或更新
    //     settleOrderReportService.insertOrUpdate(settleOrderReport);
    // }

    /**
     * 通过结算金额，计算客户到账金额和手续费
     *
     * @param settleAmount 需要拆分的结算金额
     * @return
     */
    // private SplitSettleAmountVO splitSettleAmount(BigDecimal settleAmount) {
    //     SplitSettleAmountVO resultVO = new SplitSettleAmountVO();
    //     if (settleAmount == null) {
    //         return resultVO;
    //     }
    //     // 计算手续费 = 结算金额 * 0.55%
    //     BigDecimal fee = settleAmount.multiply(new BigDecimal(Constants.FEE_RATES));
    //     resultVO.setSettleAmount(settleAmount);
    //     resultVO.setFeeAmount(fee);
    //     resultVO.setTradeAmount(settleAmount.subtract(fee));
    //     return resultVO;
    // }

    /**
     * 获取运营商订单列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<MerchantOrderInfoVO> getMerchantOrderInfoList(QueryMerchantOrderDTO dto) {
        int pageNum = dto.getPageNum() == 0 ? 1 : dto.getPageNum();
        int pageSize = dto.getPageSize() == 0 ? 10 : dto.getPageSize();
        String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, DateUtils.addDays(new Date(), -7));

        startTime = dto.getStartTime() == null ? startTime : dto.getStartTime();

        dto.setStartTime(startTime);
        PageUtils.startPage(pageNum, pageSize);
        return orderBasicInfoMapper.getMerchantOrderInfoList(dto);
    }

    @Override
    public OrderBasicInfo generateOrder(GenerateOrderDTO dto) throws ParseException {
        logger.info("generateOrder param:{}", JSON.toJSONString(dto));
        // 处理前端传的参数
        analysisPileParameter(dto);

        // 校验充电桩相关的信息
        checkPileInfo(dto);

        // 保存订单到数据库 saveOrder2Database
        return saveOrder2Database(dto);
    }

    /**
     * 处理前端传的参数
     * pileConnectorCode = pileSn + connectorCode
     *
     * @param dto
     */
    @Override
    public void analysisPileParameter(BasicPileDTO dto) {
        if (StringUtils.isBlank(dto.getPileSn()) || StringUtils.isBlank(dto.getConnectorCode())) {
            // 从pileConnectorCode解析
            String pileConnectorCode = dto.getPileConnectorCode();
            if (StringUtils.isNotEmpty(pileConnectorCode) && pileConnectorCode.length() == Constants.PILE_CONNECTOR_CODE_LENGTH) {
                dto.setPileSn(StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2));
                dto.setConnectorCode(StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length()));
            } else {
                throw new BusinessException(ReturnCodeEnum.CODE_DATA_LENGTH_ERROR);
            }
        } else {
            // 说明pileSn 和 connectorCode前端传了，那就校验一下长度
            if (dto.getPileSn().length() != Constants.PILE_SN_LENGTH || dto.getConnectorCode().length() != Constants.CONNECTOR_CODE_LENGTH) {
                throw new BusinessException(ReturnCodeEnum.CODE_DATA_LENGTH_ERROR);
            }
        }
    }

    /**
     * 支付订单
     *
     * @param dto
     * @return
     */
    // @Override
    // public Map<String, Object> payOrder(PayOrderDTO dto) {
    //     OrderBasicInfo orderInfo = this.getOrderInfoByOrderCode(dto.getOrderCode());
    //     if (orderInfo == null) {
    //         throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_INFO_IS_NULL);
    //     }
    //     if (!StringUtils.equals(orderInfo.getPayStatus(), OrderPayStatusEnum.unpaid.getValue())) {
    //         // 订单已支付
    //         throw new BusinessException(ReturnCodeEnum.CODE_ORDER_IS_NOT_TO_BE_PAID_ERROR);
    //     }
    //     Map<String, Object> resultMap = Maps.newHashMap();
    //     if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) {
    //         // 余额支付
    //         // balancePayOrder(dto);
    //         balancePayOrderV2(dto);
    //     } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) {
    //         // 2023-07-11 全部改为汇付支付
    //         dto.setGoodsTitle("充电费用");
    //         dto.setGoodsDesc("充电桩预付款金额");
    //         dto.setType(ScenarioEnum.ORDER.getValue());
    //         Map<String, Object> weixinMap = adapayService.createPayment(dto);
    //
    //         // 返回微信支付参数
    //         resultMap.put("weixinMap", weixinMap);
    //     } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue())) { // 白名单支付
    //         // 白名单支付可以直接调支付回调方法
    //         dto.setPayAmount(Constants.whitelistDefaultAmount);
    //         whiteListPayOrder(dto);
    //     }
    //     return resultMap;
    // }

    /**
     * 白名单支付订单逻辑
     *
     * @param dto
     */
    // private void whiteListPayOrder(PayOrderDTO dto) {
    //     String orderCode = dto.getOrderCode();
    //     BigDecimal payAmount = dto.getPayAmount();
    //     String payMode = dto.getPayMode();
    //
    //     // 白名单直接算支付成功
    //     PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder()
    //             .orderCode(orderCode)
    //             .payAmount(payAmount)
    //             .payMode(payMode)
    //             .startMode(dto.getStartMode())
    //             .acquirer(AcquirerEnum.LOCAL.getValue())
    //             .build();
    //     payOrderSuccessCallback(callbackDTO); // 白名单直接算支付成功
    // }

    /**
     * 订单支付成功 支付回调
     * 支付成功后掉用这个方法
     * 1. 修改订单支付状态
     * 2. 发送启动充电指令
     */
    @Override
    public void payOrderSuccessCallback(PayOrderSuccessCallbackDTO dto) {
        logger.info("订单:{}支付成功 支付回调", dto.getOrderCode());
        OrderBasicInfo orderInfo = this.getOrderInfoByOrderCode(dto.getOrderCode());
        BigDecimal payAmount = dto.getPayAmount();

        // 是否发送启动指令
        boolean sendStartCharging = true;
        if (StartModeEnum.AUTH_CARD.getValue().equals(dto.getStartMode())) {
            sendStartCharging = false;
        } else if (StartModeEnum.VIN_CODE.getValue().equals(dto.getStartMode())) {
            sendStartCharging = false;
        } else if (StartTypeEnum.RESERVED.getValue().equals(orderInfo.getStartType())) {
            sendStartCharging = false;
        } else if (OrderStatusEnum.STAY_RETROACTIVE_AMOUNT.getValue().equals(orderInfo.getOrderStatus())) {
            sendStartCharging = false;
        }

        // 判断该桩是否对接了类似华为平台的第三方站点
        List<ThirdPartySnRelationVO> list = snRelationService.selectSnRelationListByParams(null, orderInfo.getPileSn(), null);
        if (CollectionUtils.isNotEmpty(list)) {
            for (ThirdPartySnRelationVO vo : list) {
                String startMode = vo.getStartMode();
                if (StringUtils.equals(Constants.ONE, startMode)) {
                    // 无需发送启机指令，在汇付回调中发送
                    sendStartCharging = false;
                }
            }
        }
        // 判断该桩所在的站点是否推送了第三方站点（需要我方平台发送启动指令的，如：华为平台）
        // List<ThirdPartyStationRelationVO> relationInfoList = thirdPartyStationRelationService.getRelationInfoList(orderInfo.getStationId());
        // if (CollectionUtils.isNotEmpty(relationInfoList)) {
        //     for (ThirdPartyStationRelationVO vo : relationInfoList) {
        //         String startMode = vo.getStartMode();
        //         if (StringUtils.equals(Constants.ONE, startMode)) {
        //             // 无需发送启机指令，在汇付回调中发送
        //             sendStartCharging = false;
        //         }
        //     }
        // }

        // 修改订单
        orderInfo.setPayMode(dto.getPayMode());
        orderInfo.setPayStatus(OrderPayStatusEnum.paid.getValue());
        BigDecimal orderPayAmount = orderInfo.getPayAmount() == null ? BigDecimal.ZERO : orderInfo.getPayAmount();
        // 2024年3月25日12点26分 发现重复记录的情况
        if(orderPayAmount.compareTo(payAmount) != 0) {
            orderInfo.setPayAmount(orderPayAmount.add(payAmount));
        }
        orderInfo.setPayTime(new Date());

        if (sendStartCharging) {
            String pileSn = orderInfo.getPileSn();
            // 发送启动充电指令前，再次下发计费模板
            BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn);
            if (billingTemplateVO != null) {
                logger.info("发送启动充电指令前，再次下发计费模板, orderCode:{}, 计费模板:{}", orderInfo.getOrderCode(), JSON.toJSONString(billingTemplateVO));
                pileRemoteService.publishPileBillingTemplate(pileSn, billingTemplateVO);
            }
            // 获取启动金额
            BigDecimal chargeAmount = computeChargeAmount(orderInfo.getMerchantId(), orderInfo.getStationId(), orderInfo.getMemberId(), orderInfo.getPayAmount());
            // 发送启动指令
            pileRemoteService.remoteStartCharging(pileSn, orderInfo.getConnectorCode(), orderInfo.getTransactionCode(), chargeAmount);
            logger.info("订单:{}支付成功, 发送启动指令", dto.getOrderCode());
        }

        /**
         * 异步发送预约充电指令
         */
        // if (StringUtils.equals(orderInfo.getStartType(), StartTypeEnum.RESERVED.getValue())) {
        //     ReservationChargingCommand command = ReservationChargingCommand.builder()
        //             .transactionCode(orderInfo.getTransactionCode())
        //             .pileSn(orderInfo.getPileSn())
        //             .connectorCode(orderInfo.getConnectorCode())
        //             .operation(BytesUtil.bcd2Str(new byte[]{0x01}))
        //             .reservedStartTime(orderInfo.getReservedStartTime())
        //             .reservedEndTime(orderInfo.getReservedEndTime())
        //             .amount(new BigDecimal(Constants.FIVE_HUNDRED))
        //             .build();
        //     // 发送预约充电指令
        //     logger.info("订单:{}支付成功, 发送预约充电指令, command:{}", dto.getOrderCode(), JSON.toJSONString(command));
        //     pileRemoteService.reservationCharging(command);
        // }

        if (OrderStatusEnum.STAY_RETROACTIVE_AMOUNT.getValue().equals(orderInfo.getOrderStatus())) {
            // 如果订单状态是待补缴，表示已经停止充电了，需要补缴费用，补缴完成订单状态改为订单完成，设置结算时间
            orderInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
            orderInfo.setPayStatus(OrderPayStatusEnum.paid.getValue());
            orderInfo.setSettlementTime(new Date());
            BigDecimal remedialAmount = orderInfo.getRemedialAmount();
            orderInfo.setRemedialAmount(remedialAmount.subtract(payAmount));
        }
        this.updateOrderBasicInfo(orderInfo);
    }

    /**
     * 计算启动金额
     * 2024年1月9日10点24分 下发金额不变，由结算时计算优惠金额
     */
    private BigDecimal computeChargeAmount(String merchantId, String stationId, String memberId, BigDecimal payAmount) {
        // 默认折扣100%
        BigDecimal discount = BigDecimal.ONE;

        // TODO 如果member享受会员价，则获取到该会员在此站点的折扣

        // 启动金额 = 支付金额 ➗ 折扣  保留两位小数
        BigDecimal chargeAmount = payAmount.divide(discount, 2, RoundingMode.DOWN);

        return chargeAmount;
    }

    /**
     * 查询订单退款记录
     *
     * @param orderBasicInfo
     * @return
     */
    @Override
    public List<PaymentReverseResponse> queryOrderAdapayRefund(OrderBasicInfo orderBasicInfo) {
        List<PaymentReverseResponse> resultList = Lists.newArrayList();
        // 查到原汇付支付id
        AdapayCallbackRecord adapayCallbackRecord = adapayCallbackRecordService.selectByOrderCode(orderBasicInfo.getOrderCode());
        if (adapayCallbackRecord == null) {
            return resultList;
        }

        // 获取appId
        String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(orderBasicInfo.getMerchantId());

        // 通过支付id查询退款记录
        String paymentId = adapayCallbackRecord.getPaymentId();
        try {
            resultList = adapayService.queryPaymentReverse(paymentId, wechatAppId);
        } catch (BaseAdaPayException e) {
            logger.error("查询支付撤销对象发生异常", e);
        }
        return resultList;
    }

    /**
     * 重试订单退款
     *
     * @param orderCode 订单编号
     * @throws BaseAdaPayException
     */
    @Override
    public void retryRefundOrder(String orderCode) throws BaseAdaPayException {
        // 查询订单信息
        OrderBasicInfo orderBasicInfo = getOrderInfoByOrderCode(orderCode);
        retryRefundOrder(orderBasicInfo);
    }

    @Override
    public void retryRefundOrder(OrderBasicInfo orderBasicInfo) throws BaseAdaPayException {
        String orderCode = orderBasicInfo.getOrderCode();
        // 查询订单信息
        if (orderBasicInfo == null) {
            throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_INFO_IS_NULL);
        }
        // 如果该订单是订单完成状态，并且是微信支付 存在需要退款金额，则进行后续操作
        String orderStatus = orderBasicInfo.getOrderStatus();
        if (!StringUtils.equals(orderStatus, OrderStatusEnum.ORDER_COMPLETE.getValue())) {
            throw new BusinessException("", "订单状态不是完成状态");
        }
        String payMode = orderBasicInfo.getPayMode();
        if (!StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) {
            throw new BusinessException("", "订单不是微信支付");
        }

        String memberId = orderBasicInfo.getMemberId();
        BigDecimal refundAmount = orderBasicInfo.getRefundAmount();

        // 新逻辑
        String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId());
        AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode);
        List<OrderDetailInfoVO.OrderRefundInfo> orderRefundInfoList = orderLogic.getOrderRefundInfoList(orderBasicInfo);

        if (CollectionUtils.isEmpty(orderRefundInfoList)) {
            // 获取appId
            String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(orderBasicInfo.getMerchantId());
            // 如果没有退款过，重新执行一遍退款
            ApplyRefundDTO applyRefundDTO = new ApplyRefundDTO();
            applyRefundDTO.setOrderCode(orderCode);
            applyRefundDTO.setRefundType(Constants.ONE);
            applyRefundDTO.setRefundAmount(refundAmount);
            applyRefundDTO.setWechatAppId(wechatAppId);
            applyRefundDTO.setMemberId(memberId);
            refundOrderWithAdapay(applyRefundDTO);
            // logger.info("重试订单退款response:{}", JSON.toJSONString(response));
        } else {
            BigDecimal reversedAmt = BigDecimal.ZERO;
            for (OrderDetailInfoVO.OrderRefundInfo orderRefundInfo : orderRefundInfoList) {
                if (new BigDecimal(orderRefundInfo.getReverseAmt()).compareTo(reversedAmt) > 0) {
                    reversedAmt = new BigDecimal(orderRefundInfo.getReverseAmt());
                }
            }
            // 如果历史撤销金额 等于 订单退款金额，则提示已经退款请耐心等待
            if (reversedAmt.compareTo(refundAmount) == 0) {
                throw new BusinessException(ReturnCodeEnum.CODE_ORDER_HAS_BEEN_REFUNDED);
            }
        }
    }

    /**
     * 查询余额订单分账信息
     *
     * @param orderCode 订单编号
     * @param memberId  会员id
     */
    // private BigDecimal queryBalanceOrderSettleInfo(String orderCode, String memberId, String wechatAppId) {
    //     BigDecimal resultAmt = BigDecimal.ZERO;
    //     // 查询会员余额支付记录
    //     List<MemberAdapayRecord> recordList = memberAdapayRecordService.selectAdapayRecordList(memberId, ScenarioEnum.BALANCE.getValue());
    //     if (CollectionUtils.isEmpty(recordList)) {
    //         return resultAmt;
    //     }
    //
    //     // 用汇付api查询分账信息
    //     for (MemberAdapayRecord record : recordList) {
    //         QueryPaymentConfirmDTO dto = new QueryPaymentConfirmDTO();
    //         dto.setWechatAppId(wechatAppId);
    //         dto.setPaymentId(record.getPaymentId());
    //         QueryPaymentConfirmDetailResponse response = adapayService.queryPaymentConfirmList(dto);
    //         if (response != null && CollectionUtils.isNotEmpty(response.getPaymentConfirms())) {
    //             for (QueryPaymentConfirmDetailResponse.PaymentConfirmInfo paymentConfirm : response.getPaymentConfirms()) {
    //                 JSONObject jsonObject = JSON.parseObject(paymentConfirm.getDescription());
    //                 if (StringUtils.equals(jsonObject.getString("orderCode"), orderCode)) {
    //                     // 订单号对的上，累计分账金额
    //                     resultAmt = resultAmt.add(new BigDecimal(paymentConfirm.getConfirmAmt()));
    //                 }
    //             }
    //         }
    //     }
    //     return resultAmt;
    // }

    /**
     * 余额支付订单逻辑
     * 去除赠送金额相关的代码
     *
     * @param dto
     */
    // private void balancePayOrder(PayOrderDTO dto) {
    //     // 记录支付流水
    //     List<OrderPayRecord> payRecordList = Lists.newArrayList();
    //     String orderCode = dto.getOrderCode();
    //     BigDecimal chargeAmount = dto.getPayAmount();
    //     // 查询该会员的余额
    //     MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId());
    //     BigDecimal totalAccountAmount = memberVO.getTotalAccountAmount();
    //
    //     if (totalAccountAmount.compareTo(chargeAmount) < 0) {
    //         // 总余额小于充电金额
    //         throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_IS_INSUFFICIENT);
    //     }
    //     BigDecimal principalAmount = memberVO.getPrincipalBalance(); // 会员剩余本金金额
    //     BigDecimal giftAmount = memberVO.getGiftBalance(); // 会员剩余赠送余额
    //
    //     BigDecimal principalPay = null; // 30
    //     BigDecimal giftPay = null; // 10
    //     // 先扣除本金金额，再扣除赠送金额
    //     BigDecimal subtract = principalAmount.subtract(chargeAmount);
    //     if (subtract.compareTo(BigDecimal.ZERO) >= 0) {
    //         principalPay = chargeAmount;
    //     } else {
    //         if (principalAmount.compareTo(BigDecimal.ZERO) > 0) {
    //             principalPay = principalAmount;
    //         }
    //         giftPay = subtract.negate();
    //     }
    //
    //     // 更新会员钱包
    //     UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder()
    //             .memberId(dto.getMemberId())
    //             .type(MemberWalletEnum.TYPE_OUT.getValue())
    //             .subType(MemberWalletEnum.SUBTYPE_PAYMENT_FOR_ORDER.getValue())
    //             .updatePrincipalBalance(principalPay)
    //             .updateGiftBalance(giftPay)
    //             .relatedOrderCode(orderCode)
    //             .build();
    //     memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO);
    //
    //     // 查询余额充值有剩余的记录
    //     List<BalanceDeductionAmountVO> list = calculateTheBalanceDeductionAmount(dto.getMemberId(), chargeAmount);
    //
    //
    //
    //     // 记录流水
    //     if (principalPay != null) {
    //         payRecordList.add(OrderPayRecord.builder()
    //                 .orderCode(orderCode)
    //                 .payMode(OrderPayRecordEnum.PRINCIPAL_BALANCE_PAYMENT.getValue())
    //                 .payAmount(principalPay)
    //                 .acquirer(AcquirerEnum.LOCAL.getValue())
    //                 .createBy(dto.getMemberId())
    //                 .build());
    //     }
    //     if (giftPay != null) {
    //         payRecordList.add(OrderPayRecord.builder()
    //                 .orderCode(orderCode)
    //                 .payMode(OrderPayRecordEnum.GIFT_BALANCE_PAYMENT.getValue())
    //                 .payAmount(giftPay)
    //                 .acquirer(AcquirerEnum.LOCAL.getValue())
    //                 .createBy(dto.getMemberId())
    //                 .build());
    //     }
    //     // 余额支付可以直接调支付回调方法
    //     PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder()
    //             .orderCode(orderCode)
    //             .payAmount(chargeAmount)
    //             .payMode(dto.getPayMode())
    //             .startMode(dto.getStartMode())
    //             .acquirer(AcquirerEnum.LOCAL.getValue())
    //             .build();
    //     payOrderSuccessCallback(callbackDTO);
    //
    //     // 余额支付订单 记录会员交易流水
    //     MemberTransactionRecord record = MemberTransactionRecord.builder()
    //             .orderCode(orderCode)
    //             .scenarioType(ScenarioEnum.ORDER.getValue())
    //             .memberId(memberVO.getMemberId())
    //             .actionType(ActionTypeEnum.FORWARD.getValue())
    //             .payMode(PayModeEnum.PAYMENT_OF_BALANCE.getValue())
    //             .paymentInstitutions(PaymentInstitutionsEnum.LOCAL_ACCOUNTS.getValue())
    //             .amount(dto.getPayAmount()) // 单位元
    //             .build();
    //     memberTransactionRecordService.insertSelective(record);
    //
    //     // 订单支付流水入库
    //     if (CollectionUtils.isNotEmpty(payRecordList)) {
    //         orderPayRecordService.batchInsert(payRecordList);
    //     }
    // }
    @Transactional(rollbackFor = Exception.class)
    public void balancePayOrderV2(PayOrderDTO dto) {
        String orderCode = dto.getOrderCode(); // 订单编号
        BigDecimal chargeAmount = dto.getPayAmount(); // 支付金额
        // 查询该会员的余额
        MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId());
        BigDecimal totalAccountAmount = memberVO.getPrincipalBalance();

        if (totalAccountAmount.compareTo(chargeAmount) < 0) {
            // 总余额小于充电金额
            throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_IS_INSUFFICIENT);
        }
        BigDecimal principalPay = chargeAmount;

        // 更新会员钱包
        UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder()
                .memberId(dto.getMemberId())
                .type(MemberWalletEnum.TYPE_OUT.getValue())
                .subType(MemberWalletEnum.SUBTYPE_PAYMENT_FOR_ORDER.getValue())
                .updatePrincipalBalance(principalPay) // 使用本金支付的金额
                .relatedOrderCode(orderCode)
                .build();
        memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO);

        // 查询余额充值有剩余的记录
        List<BalanceDeductionAmountVO> list = calculateTheBalanceDeductionAmount(dto.getMemberId(), chargeAmount);
        // 记录支订单付流水
        List<OrderPayRecord> payRecordList = Lists.newArrayList();
        for (BalanceDeductionAmountVO balanceDeductionAmountVO : list) {
            String paymentId = balanceDeductionAmountVO.getPaymentId();
            BigDecimal deductionAmount = balanceDeductionAmountVO.getDeductionAmount();
            // JSONObject json = new JSONObject();
            // json.put("paymentId", paymentId);
            // json.put("amount", deductionAmount);
            PaymentInfo paymentInfo = new PaymentInfo();
            paymentInfo.setPaymentId(paymentId);
            paymentInfo.setAmount(deductionAmount.toString());
            // 记录流水
            payRecordList.add(OrderPayRecord.builder()
                    .orderCode(orderCode)
                    .payMode(OrderPayRecordEnum.PRINCIPAL_BALANCE_PAYMENT.getValue())
                    .payAmount(deductionAmount)
                    .acquirer(AcquirerEnum.LOCAL.getValue())
                    .deductionRecord(JSON.toJSONString(paymentInfo))
                    .createBy(dto.getMemberId())
                    .delFlag(DelFlagEnum.NORMAL.getValue())
                    .build());
        }
        // 订单支付流水入库
        if (CollectionUtils.isNotEmpty(payRecordList)) {
            orderPayRecordService.batchInsert(payRecordList);
            for (OrderPayRecord record : payRecordList) {
                String deductionRecord = record.getDeductionRecord();
                JSONObject jsonObject = JSON.parseObject(deductionRecord);
                String paymentId = jsonObject.getString("paymentId");
                BigDecimal amount = jsonObject.getBigDecimal("amount");
                // 余额支付 临时冻结金额
                memberAdapayRecordService.updateFreezeAmount(paymentId, amount);
            }
        }

        // 余额支付可以直接调支付回调方法
        PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder()
                .orderCode(orderCode)
                .payAmount(chargeAmount)
                .payMode(dto.getPayMode())
                .startMode(dto.getStartMode())
                .acquirer(AcquirerEnum.LOCAL.getValue())
                .build();
        payOrderSuccessCallback(callbackDTO); // 余额支付可以直接调支付回调方法

        // 余额支付订单 记录会员交易流水
        MemberTransactionRecord record = MemberTransactionRecord.builder()
                .orderCode(orderCode)
                .scenarioType(ScenarioEnum.ORDER.getValue())
                .memberId(memberVO.getMemberId())
                .actionType(ActionTypeEnum.FORWARD.getValue())
                .payMode(PayModeEnum.PAYMENT_OF_BALANCE.getValue())
                .paymentInstitutions(PaymentInstitutionsEnum.LOCAL_ACCOUNTS.getValue())
                .amount(dto.getPayAmount()) // 单位元
                .build();
        memberTransactionRecordService.insertSelective(record);
    }

    /**
     * 校验充电桩相关的信息
     *
     * @param dto
     */
    @Override
    public void checkPileInfo(GenerateOrderDTO dto) {
        // 查询充电桩状态 是否空闲 枪口是否占用
        PileConnectorDetailVO pileConnector = pileBasicInfoService.queryPileConnectorDetail(dto.getPileSn() + dto.getConnectorCode());
        if (pileConnector == null) {
            logger.error("checkPileInfo充电枪口为空 pileSn:{}, connectorCode:{}", dto.getPileSn(), dto.getConnectorCode());
            throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR);
        }

        // 查询站点状态
        PileStationVO stationInfo = pileStationInfoService.getStationInfo(pileConnector.getStationId());
        if (stationInfo == null || StringUtils.equals(stationInfo.getOpenFlag(), Constants.ZERO)) {
            throw new BusinessException(ReturnCodeEnum.CODE_STATION_IS_NOT_OPEN);
        }

        if (StringUtils.isNotBlank(dto.getAppId())) {
            // 校验启动桩使用的小程序，和充电桩所属一级运营商是否一致
            String merchantIdByAppId = "";
            if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.ALIPAY_LITE.getValue())) {
                // 支付宝小程序
                merchantIdByAppId = pileMerchantInfoService.getDelayModeByAlipayAppId(dto.getAppId());
            }else {
                // 微信小程序
                merchantIdByAppId = pileMerchantInfoService.getFirstLevelMerchantIdByWxAppId(dto.getAppId());
            }
            String merchantIdByMerchantId = pileMerchantInfoService.getFirstLevelMerchantIdByMerchantId(stationInfo.getMerchantId());
            if (!StringUtils.equals(merchantIdByAppId, merchantIdByMerchantId)) {
                throw new BusinessException("", "当前桩运营商与小程序所属运营商不一致");
            }
        }

        // 如果是鉴权卡或者vin启动，不判断枪口状态
        if (!(StringUtils.equals(dto.getStartMode(), StartModeEnum.AUTH_CARD.getValue())
                || StringUtils.equals(dto.getStartMode(), StartModeEnum.VIN_CODE.getValue()))) {

            // 判断枪口状态
            if (!(StringUtils.equals(pileConnector.getConnectorStatus(), PileConnectorDataBaseStatusEnum.FREE.getValue())
                    || StringUtils.equals(pileConnector.getConnectorStatus(), PileConnectorDataBaseStatusEnum.OCCUPIED_NOT_CHARGED.getValue()))) {
                logger.error("checkPileInfo充电枪口状态不正确，当前状态为:{}", pileConnector.getConnectorStatus());
                throw new BusinessException(ReturnCodeEnum.CODE_PILE_CONNECTOR_STATUS_ERROR);
            }
        }
        // 查询充电桩的计费模板
        BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(dto.getPileSn());
        if (billingTemplateVO == null) {
            throw new BusinessException(ReturnCodeEnum.CODE_BILLING_TEMPLATE_NULL_ERROR);
        }
        dto.setPileConnector(pileConnector);
        dto.setBillingTemplate(billingTemplateVO);
    }

    /**
     * 保存订单信息到数据库
     *
     * @param dto
     * @return
     */
    @Override
    public OrderBasicInfo saveOrder2Database(GenerateOrderDTO dto) throws ParseException {
        String orderCode = generateNewOrderCode();
        String transactionCode = IdUtils.generateTransactionCode(dto.getPileSn(), dto.getConnectorCode());

        if (StringUtils.isBlank(dto.getStartType())) {
            dto.setStartType(StartTypeEnum.NOW.getValue());
        }

        String stationId = dto.getPileConnector().getStationId();
        // 查询站点信息
        PileStationInfo pileStationInfo = pileStationInfoService.selectPileStationInfoById(Long.valueOf(stationId));
        String merchantId = pileStationInfo != null ? String.valueOf(pileStationInfo.getMerchantId()) : "";
        String plateNumber = dto.getPlateNumber() != null ? dto.getPlateNumber() : "";
        // 订单基本信息
        OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder()
                .orderCode(orderCode)
                .transactionCode(transactionCode)
                .orderStatus(OrderStatusEnum.NOT_START.getValue())
                .memberId(dto.getMemberId())
                .stationId(stationId)
                .merchantId(merchantId)
                .pileSn(dto.getPileSn())
                .connectorCode(dto.getConnectorCode())
                .pileConnectorCode(dto.getPileSn() + dto.getConnectorCode())
                .startMode(dto.getStartMode())
                .payStatus(Constants.ZERO)
                // .payAmount(dto.getChargeAmount()) // 支付完成后填入支付金额
                .payMode(dto.getPayMode())
                .plateNumber(plateNumber)
                .orderAmount(BigDecimal.ZERO)
                .virtualAmount(BigDecimal.ZERO)
                .settleAmount(BigDecimal.ZERO)
                .startType(dto.getStartType())
                .build();
        if (StringUtils.equals(dto.getStartMode(), StartModeEnum.AUTH_CARD.getValue())) {
            // 鉴权卡启动
            orderBasicInfo.setLogicCard(dto.getPileAuthCardInfo().getLogicCard());
        }
        if (StringUtils.equals(dto.getStartMode(), StartModeEnum.VIN_CODE.getValue())) {
            // vin启动
            MemberPlateNumberRelation memberPlateNumberRelation = dto.getMemberPlateNumberRelation();
            if (memberPlateNumberRelation != null) {
                if (StringUtils.isNotBlank(memberPlateNumberRelation.getVinCode())) {
                    orderBasicInfo.setVinCode(memberPlateNumberRelation.getVinCode());
                }
                if (StringUtils.isNotBlank(memberPlateNumberRelation.getLicensePlateNumber())) {
                    orderBasicInfo.setPlateNumber(memberPlateNumberRelation.getLicensePlateNumber());
                }
            }
            if (StringUtils.isNotBlank(dto.getStartSoc())) {
                orderBasicInfo.setStartSoc(dto.getStartSoc());
            }
        }

        /**
         * 预约时间
         */
        if (StringUtils.equals(dto.getStartType(), StartTypeEnum.RESERVED.getValue())) {
            orderBasicInfo.setReservedStartTime(DateUtils.parseDate(dto.getReservedStartTime(), DateUtils.YYYY_MM_DD_HH_MM_SS));
            orderBasicInfo.setReservedEndTime(DateUtils.parseDate(dto.getReservedEndTime(), DateUtils.YYYY_MM_DD_HH_MM_SS));
        }

        // 订单详情
        BillingTemplateVO billingTemplate = dto.getBillingTemplate();
        logger.info("订单使用的计费模板-orderCode:{}, billingTemplate:{}", orderCode, JSON.toJSONString(billingTemplate));
        BigDecimal sharpElectricityPrice = billingTemplate.getSharpElectricityPrice() != null ? billingTemplate.getSharpElectricityPrice() : BigDecimal.ZERO;
        BigDecimal sharpServicePrice = billingTemplate.getSharpServicePrice() != null ? billingTemplate.getSharpServicePrice() : BigDecimal.ZERO;
        BigDecimal peakElectricityPrice = billingTemplate.getPeakElectricityPrice() != null ? billingTemplate.getPeakElectricityPrice() : BigDecimal.ZERO;
        BigDecimal peakServicePrice = billingTemplate.getPeakServicePrice() != null ? billingTemplate.getPeakServicePrice() : BigDecimal.ZERO;
        BigDecimal flatElectricityPrice = billingTemplate.getFlatElectricityPrice() != null ? billingTemplate.getFlatElectricityPrice() : BigDecimal.ZERO;
        BigDecimal flatServicePrice = billingTemplate.getFlatServicePrice() != null ? billingTemplate.getFlatServicePrice() : BigDecimal.ZERO;
        BigDecimal valleyElectricityPrice = billingTemplate.getValleyElectricityPrice() != null ? billingTemplate.getValleyElectricityPrice() : BigDecimal.ZERO;
        BigDecimal valleyServicePrice = billingTemplate.getValleyServicePrice() != null ? billingTemplate.getValleyServicePrice() : BigDecimal.ZERO;

        OrderDetail orderDetail = OrderDetail.builder()
                .orderCode(orderCode)
                .sharpPrice(sharpElectricityPrice.add(sharpServicePrice))
                .sharpElectricityPrice(sharpElectricityPrice)
                .sharpServicePrice(sharpServicePrice)
                .peakPrice(peakElectricityPrice.add(peakServicePrice))
                .peakElectricityPrice(peakElectricityPrice)
                .peakServicePrice(peakServicePrice)
                .flatPrice(flatElectricityPrice.add(flatServicePrice))
                .flatElectricityPrice(flatElectricityPrice)
                .flatServicePrice(flatServicePrice)
                .valleyPrice(valleyElectricityPrice.add(valleyServicePrice))
                .valleyElectricityPrice(valleyElectricityPrice)
                .valleyServicePrice(valleyServicePrice)
                .build();

        OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder()
                .orderBasicInfo(orderBasicInfo)
                .orderDetail(orderDetail)
                .build();
        pileTransactionService.doCreateOrder(createOrderTransactionDTO);
        return orderBasicInfo;
    }

    /**
     * 根据时间端范围查询订单支付单id
     */
    @Override
    public List<OrderPayDetailVO> queryOrderPayDetail(String startTime, String endTime) {
        return orderBasicInfoMapper.queryOrderPayDetail(startTime, endTime);
    }

    /**
     * 根据车牌号查询订单信息（宁夏交投 用）
     *
     * @param dto
     * @return
     */
    @Override
    public List<OrderVO> getOrderInfoByNXJT(NXJTQueryOrdersInfoDTO dto) {
        return orderBasicInfoMapper.getOrderInfoByNXJT(dto);
    }

    @Override
    public List<OrderBasicInfo> queryRepayOrder(String memberId) {
        return orderBasicInfoMapper.queryRepayOrder(memberId);
    }

    @Override
    public List<OrderDetailInfoVO.OrderRefundInfo> getOrderRefundInfoList(String orderCode) {
        OrderBasicInfo orderBasicInfo = getOrderInfoByOrderCode(orderCode);
        return getOrderRefundInfoList(orderBasicInfo);
    }

    /**
     * 查询该笔订单的退款记录
     * @param orderBasicInfo
     * @return
     */
    @Override
    public List<OrderDetailInfoVO.OrderRefundInfo> getOrderRefundInfoList(OrderBasicInfo orderBasicInfo) {
        if (orderBasicInfo == null) {
            return Lists.newArrayList();
        }
        List<OrderDetailInfoVO.OrderRefundInfo> orderRefundInfoList = Lists.newArrayList();
        OrderDetailInfoVO.OrderRefundInfo refundInfo;
        if (OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue().equals(orderBasicInfo.getPayMode())) {
            // 查新member_wallet_log订单 进账记录
            List<MemberWalletLog> walletLogs = memberWalletLogService.getOrderRecord(orderBasicInfo.getOrderCode(), MemberWalletEnum.TYPE_IN.getValue());
            if (CollectionUtils.isNotEmpty(walletLogs)) {
                for (MemberWalletLog memberWalletLog : walletLogs) {
                    refundInfo = new OrderDetailInfoVO.OrderRefundInfo();
                    refundInfo.setReverseAmt(memberWalletLog.getAmount().abs().toString());
                    refundInfo.setSucceedTime(DateUtils.formatDateTime(memberWalletLog.getCreateTime()));
                    refundInfo.setCreatedTime(DateUtils.formatDateTime(memberWalletLog.getCreateTime()));
                    orderRefundInfoList.add(refundInfo);
                }
            }
        } else if (OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue().equals(orderBasicInfo.getPayMode())) {
            // 新逻辑
            String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId());
            AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode);
            orderRefundInfoList = orderLogic.getOrderRefundInfoList(orderBasicInfo);
        }
        return orderRefundInfoList;
    }

    @Override
    public List<OrderBasicInfo> queryOrderListByGroupCode(String groupCode) {
        return orderBasicInfoMapper.queryOrderListByGroupCode(groupCode);
    }

    /**
     * 根据订单编号查询订单详细信息（包括充电计费明细）
     * @param orderCode
     * @return
     */
    @Override
    public OrderVO getChargeOrderInfoByOrderCode(String orderCode) {
        return orderBasicInfoMapper.getChargeOrderInfoByOrderCode(orderCode);
    }

    /**
     * 查询新电途订单
     */
    public List<OrderBasicInfo> queryXDTOrderList(String merchantId, String stationId, String startDate, String endDate) {
        return orderBasicInfoMapper.queryXDTOrderList(merchantId, stationId, startDate, endDate);
    }

    /**
     * 通过站点id查询订单信息
     * @param stationId
     * @return
     */
    public List<SupStationStatsVO> queryOrderListByStationId(String stationId) {
        List<SupStationStatsVO> orderVOS = orderBasicInfoMapper.queryOrderListByStationId(stationId);
        for (SupStationStatsVO orderVO : orderVOS) {
            if (StringUtils.isNotBlank(orderVO.getStartTime()) && StringUtils.isNotBlank(orderVO.getEndTime())) {
                // 计算每笔订单充电时长(分钟)
                long intervalTime = DateUtils.intervalTime(orderVO.getStartTime(), orderVO.getEndTime());
                orderVO.setChargingTime(Integer.parseInt(String.valueOf(intervalTime)));
            }
        }
        return orderVOS;
    }

    @Override
    public List<OrderListVO> queryOrderByOccupyTime(QueryOrderDTO dto) {
        return orderBasicInfoMapper.queryOrderByOccupyTime(dto);
    }

}

