package com.bonus.core.pay.common.business;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bonus.constant.LeConstants;
import com.bonus.core.account.v3.api.AccBusinessApi;
import com.bonus.core.account.v3.constants.AccExceptionRecordStatusEnum;
import com.bonus.core.account.v3.web.dto.AccAddExceptionRecordDTO;
import com.bonus.core.account.v3.web.dto.AccUpdateExceptionRecordDTO;
import com.bonus.core.common.utils.JacksonUtil;
import com.bonus.core.common.utils.LogUtil;
import com.bonus.core.customer.api.CustInfoApi;
import com.bonus.core.order.mq.constants.OrderMQConstants;
import com.bonus.core.order.utils.LeNumUtil;
import com.bonus.core.pay.api.dto.UnifyPayDTO;
import com.bonus.core.pay.api.dto.UnifyPaySelectDTO;
import com.bonus.core.pay.api.vo.UnifyPaySelectVO;
import com.bonus.core.pay.api.vo.UnifyPayVO;
import com.bonus.core.pay.common.constants.PayCacheConstants;
import com.bonus.core.pay.common.constants.PayStateEnum;
import com.bonus.core.pay.common.dto.ChannelPayDTO;
import com.bonus.core.pay.common.dto.MixPayResultDTO;
import com.bonus.core.pay.common.dto.PayChannelSplitDTO;
import com.bonus.core.pay.common.dto.PaySelectDTO;
import com.bonus.core.pay.common.model.TradeChannel;
import com.bonus.core.pay.common.model.TradeRecord;
import com.bonus.core.pay.common.service.*;
import com.bonus.core.pay.common.vo.*;
import com.bonus.core.pay.custom.PayCustomBusiness;
import com.bonus.i18n.I18n;
import com.bonus.utils.id.Id;
import com.fasterxml.jackson.databind.JsonNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

@Component
public class PayBusiness {
   private static final Logger log = LoggerFactory.getLogger(PayBusiness.class);
   @Resource
   @Lazy
   protected PayCustomBusiness payCustomBusiness;
   @Lazy
   @Resource
   protected ChannelBusiness channelBusiness;
   @Lazy
   @Resource
   protected PayTradeService payTradeService;
   @Lazy
   @Resource
   protected TradeRecordService tradeRecordService;
   @Lazy
   @Resource
   protected PayChannelSelectService payChannelSelectService;
   @Lazy
   @Resource
   protected AccBusinessApi accBusinessApi;
   @Lazy
   @Resource
   protected TradeChannelService tradeChannelService;
   @Resource
   @Lazy
   protected CustInfoApi custInfoApi;


   @Transactional(
      propagation = Propagation.NOT_SUPPORTED
   )
   public UnifyPayVO unifyPay(UnifyPayDTO unifyPayDTO) {
      LogUtil.info("[统一支付]入参", unifyPayDTO);

      UnifyPayVO globalPayVO;
      try {
         globalPayVO = this.skipPayIfNecessary(unifyPayDTO);
         globalPayVO = this.payCustomBusiness.didSkipPayIfNecessary(unifyPayDTO, globalPayVO);
         if (globalPayVO != null) {
            LogUtil.info("[统一支付]跳过支付结果", globalPayVO);
            return globalPayVO;
         }
      } catch (Exception var17) {
         log.error("[统一支付]跳过支付异常", var17);
      }

      if (!PayCacheConstants.lockTrade(unifyPayDTO.getTradeId())) {
         log.warn("[统一支付]交易锁定失败");
         globalPayVO = UnifyPayVO.newInstance(unifyPayDTO, (List)null);
         globalPayVO.setCode(PayStateEnum.PAY_FAIL.getKey());
         globalPayVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
         return globalPayVO;
      } else {
         TradeRecord tradeRecord;
         try {
            this.payCustomBusiness.willPay(unifyPayDTO);
            tradeRecord = this.insertTradeRecord(unifyPayDTO);
         } catch (Exception var16) {
            log.error("[统一支付]定制埋点与插入记录异常", var16);
            globalPayVO = UnifyPayVO.newInstance(unifyPayDTO, (List)null);
            globalPayVO.setCode(PayStateEnum.PAY_FAIL.getKey());
            globalPayVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
            PayCacheConstants.unlockTrade(unifyPayDTO.getTradeId());
            return globalPayVO;
         }

         try {
            unifyPayDTO.setStartPayTime(LocalDateTime.now());
            globalPayVO = this.startPayFlow(unifyPayDTO, (List)null);
         } catch (Exception var15) {
            log.error("[统一支付]支付异常", var15);
            globalPayVO = UnifyPayVO.newInstance(unifyPayDTO, (List)null);
         }

         try {
            LogUtil.info("[统一支付]结果", globalPayVO);
            this.updateTradeResult(tradeRecord, globalPayVO);
            log.info("[统一支付]更新交易状态完毕");
         } catch (Exception var14) {
            log.error("[统一支付]更新记录异常", var14);
            globalPayVO.setCode(PayStateEnum.PAY_INPROCESS.getKey());
            globalPayVO.setMsg(PayStateEnum.PAY_INPROCESS.getDesc());
         }

         try {
            if (!globalPayVO.isAsyncPay() && PayStateEnum.isPayingState(globalPayVO.getCode())) {
               log.info("[统一支付]支付中，开始定时查询");
               UnifyPaySelectDTO paySelectDTO = new UnifyPaySelectDTO();
               paySelectDTO.setTradeId(tradeRecord.getId());
               paySelectDTO.setSendNoticeMQ(true);
               paySelectDTO.setFromAutoQuery(true);
               this.payTradeService.sendAutoPayResultQuery(paySelectDTO, LocalDateTime.now(), !unifyPayDTO.isDeviceOffline());
            }

            this.payCustomBusiness.didPay(unifyPayDTO, globalPayVO);
         } catch (Exception var12) {
            log.error("[统一支付]埋点异常", var12);
         } finally {
            PayCacheConstants.unlockTrade(unifyPayDTO.getTradeId());
         }

         return globalPayVO;
      }
   }

   protected UnifyPayVO skipPayIfNecessary(UnifyPayDTO unifyPayDTO) {
      if (CollUtil.isEmpty(unifyPayDTO.getPayChannelSplits())) {
         log.warn("[统一支付]支付渠道为空");
         return null;
      } else if (LeConstants.COMMON_YES.equals(unifyPayDTO.getIfTrail())) {
         return this.trailPay(unifyPayDTO);
      } else {
         return LeConstants.COMMON_YES.equals(unifyPayDTO.getIfFastAsyncPay()) ? this.asyncPay(unifyPayDTO) : null;
      }
   }

   protected UnifyPayVO trailPay(UnifyPayDTO unifyPayDTO) {
      UnifyPayVO unifyPayVO = UnifyPayVO.newInstance(unifyPayDTO, (List)null);
      unifyPayVO.setCode(PayStateEnum.PAY_SUCC.getKey());
      unifyPayVO.setIfTrail(LeConstants.COMMON_YES);

      try {
         for(int i = 0; i < unifyPayDTO.getPayChannelSplits().size(); ++i) {
            PayChannelSplitVO splitVO = (PayChannelSplitVO)unifyPayDTO.getPayChannelSplits().get(i);
            TradeChannelVO tradeChannelVO = null;
            BigDecimal needPayAmount = unifyPayVO.calcUnpaidAmount();
            log.info("[渠道支付]开始试算 {} {}", splitVO, needPayAmount);
            ChannelPayDTO channelPayDTO = unifyPayDTO.convertToChannelPayDTO();
            channelPayDTO.setTradeChannelId(i == 0 ? unifyPayDTO.getTradeId() : Id.next());
            channelPayDTO.setPayType(splitVO.getPayType());
            channelPayDTO.setPayChannel(splitVO.getPayChannel());
            channelPayDTO.setAmount(needPayAmount);
            channelPayDTO.setTotalAmount(unifyPayDTO.getAmount());
            channelPayDTO.setPayForMix(CollUtil.size(unifyPayDTO.getPayChannelSplits()) > 1 && i < unifyPayDTO.getPayChannelSplits().size() - 1);
            if (!channelPayDTO.couldSkipChannelPay()) {
               PayService payService = this.channelBusiness.beanOfChannel(channelPayDTO.getPayChannel());
               ChannelPayVO channelPayVO = payService.channelPayTrail(channelPayDTO);
               this.fillVoFields(channelPayVO, channelPayDTO);
               LogUtil.info("[渠道支付]试算结果", channelPayVO);
               unifyPayVO.fillChannelPayVO(channelPayVO);
               tradeChannelVO = TradeChannelVO.of(channelPayVO);
               unifyPayVO.getDetailList().add(tradeChannelVO);
               if (!PayStateEnum.isPaidState(tradeChannelVO.getTradeState())) {
                  log.warn("[渠道支付]试算中断 i={}", i);
                  break;
               }
            }
         }
      } catch (Exception var10) {
         log.error("[渠道支付]试算异常", var10);
         unifyPayVO.setCode(PayStateEnum.PAY_FAIL.getKey());
         unifyPayVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
      }

      LogUtil.info("[统一支付]试算结果", unifyPayVO);
      return unifyPayVO;
   }

   protected UnifyPayVO asyncPay(UnifyPayDTO unifyPayDTO) {
      log.info("[统一支付]异步极速支付开始");
      SupportFastAsyncPayVO customSupport = this.payCustomBusiness.willSupportFastAsyncPay(unifyPayDTO);
      boolean support;
      if (customSupport != null) {
         log.info("[统一支付]定制支持异步极速支付");
         support = customSupport.isSupport();
      } else {
         support = LeNumUtil.isValidId(unifyPayDTO.getCustId()) && unifyPayDTO.getPayChannelSplits().stream().allMatch((splitVO) -> {
            ChannelPayDTO channelPayDTO = unifyPayDTO.convertToChannelPayDTO();
            channelPayDTO.setPayType(splitVO.getPayType());
            channelPayDTO.setPayChannel(splitVO.getPayChannel());
            channelPayDTO.setAmount(unifyPayDTO.getAmount());
            channelPayDTO.setTotalAmount(unifyPayDTO.getAmount());
            PayService payService = this.channelBusiness.beanOfChannel(channelPayDTO.getPayChannel());
            return payService.supportFastAsyncPay(channelPayDTO).isSupport();
         });
      }

      if (!support) {
         log.warn("[统一支付]不支持异步极速支付");
         return null;
      } else {
         UnifyPayVO unifyPayVO = this.trailPay(unifyPayDTO);
         if (!unifyPayVO.enoughPaid()) {
            log.warn("[统一支付]异步极速支付试算金额不足");
            return null;
         } else if (LeNumUtil.isValidId(unifyPayDTO.getCustId()) && !PayCacheConstants.lockTrade(unifyPayDTO.getCustId())) {
            log.warn("[统一支付]异步极速支付人员锁定失败");
            unifyPayVO.setCode(PayStateEnum.PAY_FAIL.getKey());
            unifyPayVO.setMsg("另一笔支付正在进行中，请稍后再试");
            unifyPayVO.setDetailList(CollUtil.newArrayList(new TradeChannelVO[0]));
            return unifyPayVO;
         } else {
            unifyPayVO.setCode(PayStateEnum.PAY_INPROCESS.getKey());
            unifyPayVO.setMsg(PayStateEnum.PAY_INPROCESS.getDesc());
            unifyPayVO.setIfFastAsyncPay(LeConstants.COMMON_YES);
            return unifyPayVO;
         }
      }
   }

   protected TradeRecord insertTradeRecord(UnifyPayDTO payDTO) {
      TradeRecord tradeRecord = payDTO.toTradeRecord();
      this.tradeRecordService.insertTrade(tradeRecord, payDTO.toTradeOrderRechargeList());
      log.info("[统一支付]保存记录结束");
      return tradeRecord;
   }

   public UnifyPayVO startPayFlow(UnifyPayDTO globalPayDTO, List<TradeChannelVO> existsTradeChannels) {
      LogUtil.infoFieldsX("[渠道支付]继续支付", globalPayDTO, UnifyPayDTO.logFieldsAmount());
      UnifyPayVO globalPayVO = UnifyPayVO.newInstance(globalPayDTO, existsTradeChannels);
      List<PayChannelSplitVO> payChannelSplits = globalPayDTO.getPayChannelSplits();

      try {
         if (CollUtil.isEmpty(payChannelSplits)) {
            payChannelSplits = this.payChannelSelectService.splitChannelDetails(PayChannelSplitDTO.of(globalPayDTO.getPayType(), globalPayDTO.getPayChannel(), globalPayDTO.getCouponId(), globalPayDTO.getCanteenId()));
         }
      } catch (Exception var13) {
         log.error("[渠道支付]拆解支付渠道异常", var13);
         globalPayVO.setCode(PayStateEnum.PAY_FAIL.getKey());
         globalPayVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
         return globalPayVO;
      }

      try {
         if (globalPayDTO.isDeviceOffline() && globalPayVO.getDetailList().isEmpty()) {
            this.createExceptionIfNeed(globalPayDTO, globalPayVO);
         }

         for(int i = 0; i < payChannelSplits.size(); ++i) {
            PayChannelSplitVO splitVO = (PayChannelSplitVO)payChannelSplits.get(i);
            TradeChannelVO tradeChannelVO = null;
            TradeChannelVO exsitsTradeChannelVO = (TradeChannelVO)globalPayVO.getDetailList().stream().filter((s) -> {
               return s.getPayType().equals(splitVO.getPayType()) && s.getPayChannel().equals(splitVO.getPayChannel());
            }).findFirst().orElse((TradeChannelVO) null);
            if (exsitsTradeChannelVO != null) {
               tradeChannelVO = exsitsTradeChannelVO;
               globalPayVO.setCode(exsitsTradeChannelVO.getTradeState());
               globalPayVO.setMsg(exsitsTradeChannelVO.getTradeResult());
            } else {
               BigDecimal needPayAmount = globalPayVO.calcUnpaidAmount();
               log.info("[渠道支付]开始支付 {} {}", splitVO, needPayAmount);
               ChannelPayDTO channelPayDTO = globalPayDTO.convertToChannelPayDTO();
               channelPayDTO.setTradeChannelId(i == 0 ? globalPayDTO.getTradeId() : Id.next());
               channelPayDTO.setPayType(splitVO.getPayType());
               channelPayDTO.setPayChannel(splitVO.getPayChannel());
               channelPayDTO.setAmount(needPayAmount);
               channelPayDTO.setTotalAmount(globalPayDTO.getAmount());
               channelPayDTO.setPayForMix(CollUtil.size(payChannelSplits) > 1 && i < payChannelSplits.size() - 1);
               if (!channelPayDTO.couldSkipChannelPay()) {
                  ChannelPayVO channelPayVO = this.channelPay(channelPayDTO, globalPayDTO.getTradeId());
                  LogUtil.info("[渠道支付]支付结果", channelPayVO);
                  globalPayVO.fillChannelPayVO(channelPayVO);
                  tradeChannelVO = TradeChannelVO.of(channelPayVO);
                  globalPayVO.getDetailList().add(tradeChannelVO);
               }
            }

            if (tradeChannelVO != null && !PayStateEnum.isPaidState(tradeChannelVO.getTradeState())) {
               log.warn("[渠道支付]支付中断 i={}", i);
               break;
            }
         }

         if (globalPayVO.enoughPaid() && CollUtil.isEmpty(globalPayVO.getDetailList())) {
            globalPayVO.setCode(PayStateEnum.PAY_SUCC.getKey());
            globalPayVO.setMsg(PayStateEnum.PAY_SUCC.getDesc());
         }

         if (PayStateEnum.isFinishedState(globalPayVO.getCode())) {
            if (CollUtil.size(payChannelSplits) > 1) {
               this.mixPayResultProcess(globalPayVO, payChannelSplits);
            }

            if (globalPayDTO.isDeviceOffline()) {
               this.updateExceptionIfNeed(globalPayDTO, globalPayVO);
            }

            if (PayStateEnum.isPaidState(globalPayVO.getCode())) {
               globalPayVO.setPayTime(globalPayDTO.getStartPayTime());
            }
         }
      } catch (Exception var12) {
         log.error("[渠道支付]继续支付异常", var12);
      }

      return globalPayVO;
   }

   protected void updateTradeResult(TradeRecord tradeRecord, UnifyPayVO payVO) {
      this.tradeRecordService.updateTradeRecordState(tradeRecord.getId(), payVO);
      tradeRecord.setTradeState(payVO.getCode());
      tradeRecord.setTradeResult(payVO.getMsg());
      tradeRecord.setPayChannel(payVO.getPayChannel());
      tradeRecord.setPayType(payVO.getPayType());
      tradeRecord.setOutTradeNo(payVO.getOutTradeNo());
      tradeRecord.setCustId(payVO.getCustId());
   }


   protected void fillVoFields(ChannelPayVO payVO, ChannelPayDTO payDTO) {
      payVO.setTradeChannelId(payDTO.getTradeChannelId());
      if (payVO.getAmount() == null) {
         payVO.setAmount(payDTO.getAmount());
      }

      if (payVO.getRealAmount() == null && PayStateEnum.isPaidState(payVO.getCode())) {
         payVO.setRealAmount(payVO.getAmount());
      }

      if (payVO.getAccPayResultVO() != null && payVO.getAccPayResultVO().getUnpaidBalance() == null) {
         payVO.getAccPayResultVO().setUnpaidBalance(BigDecimal.ZERO);
      }

      if (payVO.getCustId() == null) {
         payVO.setCustId(payDTO.getCustId());
      }

      if (CharSequenceUtil.isBlank(payVO.getCustName())) {
         payVO.setCustName(payDTO.getCustName());
      }

      if (CharSequenceUtil.isBlank(payVO.getOrgFullName())) {
         payVO.setOrgFullName(payDTO.getOrgFullName());
      }

      if (payVO.getPayChannel() == null) {
         payVO.setPayChannel(payDTO.getPayChannel());
      }

      if (payVO.getPayType() == null) {
         payVO.setPayType(payDTO.getPayType());
      }
   }

   protected void createExceptionIfNeed(UnifyPayDTO globalPayDTO, UnifyPayVO globalPayVO) {
      if (globalPayDTO.isDeviceOffline()) {
         try {
            if (globalPayDTO.isDeviceOffline()) {
               AccAddExceptionRecordDTO exceptionRecordDTO = new AccAddExceptionRecordDTO();
               exceptionRecordDTO.setCustId(globalPayDTO.getCustId());
               exceptionRecordDTO.setAmount(globalPayDTO.getAmount());
               exceptionRecordDTO.setPayChannel(globalPayDTO.getPayChannel());
               exceptionRecordDTO.setRelationId(globalPayDTO.getTradeId());
               exceptionRecordDTO.setSerialNum(globalPayDTO.getSerialNum());
               this.accBusinessApi.addAccExceptionRecord(exceptionRecordDTO);
            }
         } catch (Exception var4) {
            log.error("[渠道支付]离线支付前处理异常", var4);
            globalPayVO.setCode(PayStateEnum.PAY_FAIL.getKey());
            globalPayVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
         }

      }
   }
   protected ChannelPayVO channelPay(ChannelPayDTO channelPayDTO, Long tradeId) {
      ChannelPayVO channelPayVO = new ChannelPayVO();
      channelPayVO.setCode(PayStateEnum.PAY_INPROCESS.getKey());
      channelPayVO.setMsg(PayStateEnum.PAY_INPROCESS.getDesc());
      TradeChannel tradeChannel = channelPayDTO.toTradeRecordChannel(tradeId);
      LocalDateTime now = LocalDateTime.now().withNano(0);
      channelPayDTO.setTradeTime(now);
      tradeChannel.setTradeTime(now);

      try {
         this.payCustomBusiness.willChannelPay(channelPayDTO);
         this.tradeChannelService.insert(tradeChannel);
         log.info("[统一支付]渠道支付开始");
         PayService payService = this.channelBusiness.beanOfChannel(channelPayDTO.getPayChannel());
         channelPayVO = payService.channelPay(channelPayDTO);
         if (channelPayVO.isAsyncPay()) {
            channelPayVO.setCode(PayStateEnum.PAY_INPROCESS.getKey());
            channelPayVO.setMsg(PayStateEnum.PAY_INPROCESS.getDesc());
         }

         this.fillVoFields(channelPayVO, channelPayDTO);
      } catch (Exception var9) {
         log.error("[统一支付]渠道支付异常", var9);
         channelPayVO.setCode(PayStateEnum.PAY_INPROCESS.getKey());
         channelPayVO.setMsg(PayStateEnum.PAY_INPROCESS.getDesc());
      }

      try {
         this.tradeChannelService.updateTradeRecordChannelState(tradeChannel.getTradeChannelId(), channelPayVO.getCode(), channelPayVO.getMsg(), channelPayVO.getOutTradeNo(), channelPayVO.getRealAmount(), channelPayVO.getChannelParam(), (LocalDateTime)null);
      } catch (Exception var7) {
         log.error("[统一支付]渠道支付结果更新异常", var7);
         channelPayVO.setCode(PayStateEnum.PAY_INPROCESS.getKey());
         channelPayVO.setMsg(PayStateEnum.PAY_INPROCESS.getDesc());
      }

      return channelPayVO;
   }
   protected void mixPayResultProcess(UnifyPayVO globalPayVO, List<PayChannelSplitVO> payChannelSplits) {
      LogUtil.info("[混合支付结果]开始处理", globalPayVO, globalPayVO.getDetailList());
      PayChannelSplitVO lastSplitVO = (PayChannelSplitVO)CollUtil.getLast(payChannelSplits);

      for(int i = globalPayVO.getDetailList().size() - 1; i >= 0; --i) {
         TradeChannelVO tradeChannelVO = (TradeChannelVO)globalPayVO.getDetailList().get(i);
         if (tradeChannelVO.getPayType().equals(lastSplitVO.getPayType()) && tradeChannelVO.getPayChannel().equals(lastSplitVO.getPayChannel())) {
            log.info("最后一条渠道跳过结果处理 {}", tradeChannelVO.getTradeChannelId());
         } else {
            MixPayResultDTO mixPayResultDTO = (new MixPayResultDTO()).setTradeChannelId(tradeChannelVO.getTradeChannelId()).setCode(globalPayVO.getCode());
            mixPayResultDTO.setUnpaidBalance(globalPayVO.calcUnpaidAmount());
            MixPayResultVO mixPayResultVO = this.mixPayResultProcess(tradeChannelVO, mixPayResultDTO);
            globalPayVO.fillMixPayResultVO(mixPayResultVO);
         }
      }

      if (globalPayVO.enoughPaid()) {
         globalPayVO.setCode(PayStateEnum.PAY_SUCC.getKey());
         globalPayVO.setMsg(PayStateEnum.PAY_SUCC.getDesc());
      }

   }

   protected MixPayResultVO mixPayResultProcess(TradeChannelVO tradeChannelVO, MixPayResultDTO mixPayResultDTO) {
      MixPayResultVO processResultVO = MixPayResultVO.newDefaultInstance();

      try {
         LogUtil.info("[混合支付结果]处理", mixPayResultDTO);
         PayService payService = this.channelBusiness.beanOfChannel(tradeChannelVO.getPayChannel());
         processResultVO = payService.mixPayResultHandler(mixPayResultDTO, tradeChannelVO);
         LogUtil.info("[混合支付结果]处理结果", processResultVO);
         if (processResultVO.isNeedUpdateTradeChannel()) {
            tradeChannelVO.fillMixPayResultVO(processResultVO);
            this.tradeChannelService.updateTradeRecordChannelState(tradeChannelVO.getTradeChannelId(), tradeChannelVO.getTradeState(), tradeChannelVO.getTradeResult(), (String)null, tradeChannelVO.getAmount(), (JsonNode)null, (LocalDateTime)null);
         }
      } catch (Exception var5) {
         log.error("[混合支付结果]处理异常", var5);
      }

      return processResultVO;
   }
   protected void updateExceptionIfNeed(UnifyPayDTO globalPayDTO, UnifyPayVO globalPayVO) {
      if (globalPayDTO.isDeviceOffline()) {
         if (!PayStateEnum.isPayingState(globalPayVO.getCode())) {
            if (this.accBusinessApi.existExceptionRecordByRelatedId(globalPayVO.getTradeId(), AccExceptionRecordStatusEnum.FAIL.getKey())) {
               log.warn("[渠道支付]离线支付结果已处理过");
            } else {
               try {
                  Integer recordStatus = AccExceptionRecordStatusEnum.FIRST_SUCC.getKey();
                  if (PayStateEnum.PAY_FAIL.getKey().equals(globalPayVO.getCode())) {
                     recordStatus = AccExceptionRecordStatusEnum.FAIL.getKey();
                     globalPayVO.setCode(PayStateEnum.PART_PAY.getKey());
                     globalPayVO.setRealAmount(globalPayVO.getAmount());
                  }

                  AccUpdateExceptionRecordDTO updateExceptionRecordDTO = new AccUpdateExceptionRecordDTO();
                  updateExceptionRecordDTO.setRecordStatus(recordStatus);
                  updateExceptionRecordDTO.setRelationId(globalPayVO.getTradeId());
                  updateExceptionRecordDTO.setRemark(globalPayVO.getMsg());
                  this.accBusinessApi.updateAccExceptionRecord(updateExceptionRecordDTO);
               } catch (Exception var5) {
                  log.error("[渠道支付]离线支付后处理异常", var5);
               }

            }
         }
      }
   }

   @Transactional(
           propagation = Propagation.NOT_SUPPORTED
   )
   public UnifyPaySelectVO unifyPaySelect(UnifyPaySelectDTO unifyPaySelectDTO) {
      LogUtil.info("[支付查询]入参", unifyPaySelectDTO);
      this.payCustomBusiness.willPaySelectV2(unifyPaySelectDTO);
      TradeRecord tradeRecord = unifyPaySelectDTO.getTradeId() != null ? this.tradeRecordService
              .getTradeRecordById(unifyPaySelectDTO.getTradeId()) : this.tradeRecordService.getTradeRecordByOrderRechargeId(unifyPaySelectDTO.getOrderRechargeId());
      if (ObjectUtil.isNull(tradeRecord)) {
         log.info("[查询支付结果]交易记录不存在，orderRechargeId:{}", unifyPaySelectDTO.getOrderRechargeId());
         return UnifyPaySelectVO.of(PayStateEnum.PAY_FAIL.getKey(), I18n.getMessage("pay.trade-not-exist", new Object[0]));
      } else {
         UnifyPaySelectVO unifyPaySelectVO;
         if (!PayCacheConstants.lockTrade(tradeRecord.getId())) {
            log.warn("[支付查询]交易锁定失败");
            unifyPaySelectVO = UnifyPaySelectVO.of(PayStateEnum.PAY_INPROCESS.getKey(), PayStateEnum.PAY_INPROCESS.getDesc());
            unifyPaySelectVO.setTradeId(tradeRecord.getId());
            return unifyPaySelectVO;
         } else {
            try {
               if (!PayStateEnum.isPaidState(tradeRecord.getTradeState()) && (unifyPaySelectDTO.isFromAutoQuery() || !tradeRecord.getCreateTime().plusSeconds((long) OrderMQConstants.PAY_QUERY_MAX_SECOND).isAfter(LocalDateTime.now()))) {
                  UnifyPayVO payVO = this.selectAndStartPayFlow(tradeRecord);
                  LogUtil.info("[支付查询]支付结果", payVO);
                  UnifyPaySelectVO var4;
                  if (PayStateEnum.isPayingState(payVO.getCode())) {
                     var4 = UnifyPaySelectVO.of(payVO);
                     return var4;
                  }

                  this.tradeRecordService.updateTradeRecordState(tradeRecord.getId(), payVO);
                  if (unifyPaySelectDTO.isSendNoticeMQ()) {
                     this.payTradeService.sendResultMq(tradeRecord.getId());
                  }

                  var4 = this.payCustomBusiness.didPaySelectV2(unifyPaySelectDTO, UnifyPaySelectVO.of(payVO));
                  return var4;
               }

               if (unifyPaySelectDTO.isSendNoticeMQ()) {
                  this.payTradeService.sendResultMq(tradeRecord.getId());
               }

               unifyPaySelectVO = this.payCustomBusiness.didPaySelectV2(unifyPaySelectDTO, UnifyPaySelectVO.of(tradeRecord));
            } finally {
               PayCacheConstants.unlockTrade(tradeRecord.getId());
            }

            return unifyPaySelectVO;
         }
      }
   }

   protected UnifyPayVO selectAndStartPayFlow(TradeRecord tradeRecord) {
      List<TradeChannelVO> tradeChannels = this.tradeChannelService.listChannelDetailByTradeId(tradeRecord.getId());
      UnifyPayDTO unifyPayDTO = UnifyPayDTO.of(tradeRecord);
      TradeChannelVO lastTradeChannelVO = (TradeChannelVO)CollUtil.getLast(tradeChannels);
      if (lastTradeChannelVO != null && PayStateEnum.isPayingState(lastTradeChannelVO.getTradeState())) {
         PaySelectDTO paySelectDTO = new PaySelectDTO();
         this.fillPaySelectDTO(paySelectDTO, unifyPayDTO);
         AndroidPayVO androidPayVO = this.channelPaySelect(lastTradeChannelVO, paySelectDTO);
         if (PayStateEnum.isPayingState(androidPayVO.getCode())) {
            return UnifyPayVO.of(tradeRecord, tradeChannels);
         }

         lastTradeChannelVO.setTradeState(androidPayVO.getCode());
         lastTradeChannelVO.setTradeResult(androidPayVO.getMsg());
         if (LeNumUtil.isValidId(androidPayVO.getCustId()) && !LeNumUtil.isValidId(unifyPayDTO.getCustId())) {
            unifyPayDTO.fillCustInfo(this.custInfoApi.getCustInfoByCustId(androidPayVO.getCustId()));
         }

         unifyPayDTO.fillCustInfoIfNecessary(androidPayVO);
      }

      tradeChannels = this.tradeChannelService.listChannelDetailByTradeId(tradeRecord.getId());
      return this.startPayFlow(unifyPayDTO, tradeChannels);
   }

   protected void fillPaySelectDTO(PaySelectDTO paySelectDTO, UnifyPayDTO unifyPayDTO) {
      paySelectDTO.setCanteenId(unifyPayDTO.getCanteenId());
      paySelectDTO.setMachineSn(unifyPayDTO.getMachineSn());
      paySelectDTO.setCouponId(unifyPayDTO.getCouponId());
      paySelectDTO.setPayType(unifyPayDTO.getPayType());
      paySelectDTO.setOrderRechargeId(CollUtil.isNotEmpty(unifyPayDTO.getOrderList()) ? ((UnifyPayDTO.Order)unifyPayDTO.getOrderList().get(0)).getOrderId() : null);
      paySelectDTO.setMacOrderId(unifyPayDTO.getMacOrderId());
   }

   protected AndroidPayVO channelPaySelect(TradeChannelVO tradeChannel, PaySelectDTO paySelectDTO) {
      paySelectDTO.setPayType(tradeChannel.getPayType());
      paySelectDTO.setTradeChannelId(tradeChannel.getTradeChannelId());
      paySelectDTO.setTradeTime(tradeChannel.getTradeTime());
      paySelectDTO.setAmount(tradeChannel.getAmount());
      paySelectDTO.setOutTradeNo(tradeChannel.getOutTradeNo());
      AndroidPayVO androidPayVO = new AndroidPayVO();

      try {
         PayService payService = this.channelBusiness.beanOfChannel(tradeChannel.getPayChannel());
         androidPayVO = payService.paySelect(paySelectDTO);
      } catch (Exception var5) {
         log.error("[支付查询]异常", var5);
         androidPayVO.setCode(PayStateEnum.PAY_INPROCESS.getKey());
         androidPayVO.setMsg(PayStateEnum.PAY_INPROCESS.getDesc());
      }

      log.info("[支付查询]返回结果：{}", JacksonUtil.writeValueAsStringIgnoreNull(androidPayVO));
      this.fillVoFields(androidPayVO, tradeChannel);
      if (PayStateEnum.PAY_INPROCESS.getKey().equals(androidPayVO.getCode())) {
         return androidPayVO;
      } else {
         this.tradeChannelService.updateTradeRecordChannelState(androidPayVO.getTradeChannelId(), androidPayVO.getCode(), androidPayVO.getMsg(), androidPayVO.getOutTradeNo(), androidPayVO.getRealAmount(), (JsonNode)null, (LocalDateTime)null);
         return androidPayVO;
      }
   }

   protected void fillVoFields(AndroidPayVO payVO, TradeChannelVO channelVO) {
      payVO.setTradeId(channelVO.getTradeChannelId());
      payVO.setTradeChannelId(channelVO.getTradeChannelId());
      payVO.setAmount(channelVO.getAmount());
      if (payVO.getRealAmount() == null && PayStateEnum.isPaidState(payVO.getCode())) {
         payVO.setRealAmount(payVO.getAmount());
      }

      if (payVO.getUnpaidBalance() == null) {
         payVO.setUnpaidBalance(BigDecimal.ZERO);
      }

      if (payVO.getPayChannel() == null) {
         payVO.setPayChannel(channelVO.getPayChannel());
      }

      if (payVO.getPayType() == null) {
         payVO.setPayType(channelVO.getPayType());
      }

   }

}
