package com.liquidnet.service.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.liquidnet.common.sms.constant.SmsEnum;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.adam.dto.vo.AdamEntersVo;
import com.liquidnet.service.base.*;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.service.IDragonOrdersService;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dto.param.*;
import com.liquidnet.service.kylin.dto.vo.KylinAgentVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinIpAreaVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketEntitiesVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.kylin.dto.vo.returns.PayInnerResultVo;
import com.liquidnet.service.kylin.dto.vo.returns.PayResultVo;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.service.IKylinOrderTicketsOrderService;
import com.liquidnet.service.order.utils.*;
import com.taobao.api.TaobaoClient;
import com.taobao.api.request.AlibabaDamaiMevOpenBatchpushticketRequest;
import com.taobao.api.response.AlibabaDamaiMevOpenBatchpushticketResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;


/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-05-20
 */
@Service
@Slf4j
public class KylinOrderTicketsServiceImpl implements IKylinOrderTicketsOrderService {

    @Value("${liquidnet.url-pay.localUrl}")
    private String synUrl;
    @Autowired
    IDragonOrdersService dragonOrdersService;

    @Autowired
    private DataUtils dataUtils;
    @Autowired
    private OrderUtils orderUtils;
    @Autowired
    GoblinOrderUtils goblinOrderUtils;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private MongoConverter mongoConverter;
    @Autowired
    private QueueUtils queueUtils;
    @Autowired
    private TaobaoTicketUtils taobaoTicketUtils;
    @Autowired
    private OrderRefundOvertimeServiceImpl orderRefundsCallbackService;

    ArrayList<Integer> canBuyStatus = new ArrayList() {{
        add(6);
        add(8);
        add(9);
        add(10);
    }};

//    ArrayList<Integer> canBuyTStatus = new ArrayList() {{
//        add(6);
////        add(8);
////        add(9);
////        add(10);
//    }};

    @Override
    public ResponseDto<PayInnerResultVo> checkCanOrder(PayOrderParam payOrderParam) {
        boolean isDownGeneral = false;
        boolean isPay = true;
        boolean useAdvance = false;
        String performanceId = "";
        List<AdamEntersVo> entersVoList = ObjectUtil.cloneArrayListObject();
        String uid = CurrentUtil.getCurrentUid();
        HashMap<String, Object> advanceMap = null;
        try {
            String orderTicketId = IDGenerator.nextSnowId();
            String orderCode = IDGenerator.ticketOrderCode(orderTicketId);
            queueUtils.pushPvUv(uid, KylinTableStatusConst.PvUv.TK_PAY.getKey(), payOrderParam.getPerformanceId(), orderTicketId, orderCode, CurrentUtil.getCliIpAddr());
            if (payOrderParam.getVoucherType() != null && payOrderParam.getVoucherType().equals(3)) {
                isPay = false;
                if (payOrderParam.getNumber() > 1) {
                    return ResponseDto.failure("张数大于1不支持兑换");//参数错误
                }
            }
            KylinPerformanceVo performanceData = dataUtils.getPerformanceVo(payOrderParam.getPerformanceId());
            KylinTicketTimesVo ticketTimesData = null;
            KylinTicketVo ticketData = null;
            for (int x = 0; x < performanceData.getTicketTimeList().size(); x++) {
                KylinTicketTimesVo timeItem = performanceData.getTicketTimeList().get(x);
                if (timeItem.getTimeId().equals(payOrderParam.getTimeId())) {
                    ticketTimesData = timeItem;
                    for (int y = 0; y < ticketTimesData.getTicketList().size(); y++) {
                        KylinTicketVo ticketItem = ticketTimesData.getTicketList().get(y);
                        if (ticketItem.getTicketsId().equals(payOrderParam.getTicketId())) {
                            ticketData = ticketItem;
                            break;
                        }
                    }
                    break;
                }
            }
            performanceId = performanceData.getPerformancesId();
            if (ticketTimesData == null || ticketData == null) {
                return ResponseDto.failure(ErrorMapping.get("20004"));//参数错误
            }
            if (performanceData.getStatusSell() == 0) {
                return ResponseDto.failure(ErrorMapping.get("20010"));//当前不可购买
            }

            if (payOrderParam.getIsExpress().equals(1) && ticketData.getIsExpress().equals(0)) {
                return ResponseDto.failure("票种类型错误");//参数错误
            } else if (payOrderParam.getIsElectronic().equals(1) && ticketData.getIsElectronic().equals(0)) {
                return ResponseDto.failure("票种类型错误");//参数错误
            } else if (payOrderParam.getIsExpress().equals(0) && payOrderParam.getIsElectronic().equals(0)) {
                return ResponseDto.failure("票种类型错误");//参数错误
            }

            if (!ticketData.getTimeId().equals(payOrderParam.getTimeId()) || !ticketTimesData.getPerformanceId().equals(payOrderParam.getPerformanceId())) {
                return ResponseDto.failure(ErrorMapping.get("20004"));//参数错误
            }
            if (payOrderParam.getNumber() % ticketData.getCounts() != 0) {
                return ResponseDto.failure(ErrorMapping.get("20007"));//数量错误
            }
//            //判断代理
//            if (!checkAgent(payOrderParam.getAgentId(), ticketData)) {
//                return ResponseDto.failure(ErrorMapping.get("20008"));//无权购买
//            }
            //校验快递相关参数
            if (payOrderParam.getIsExpress() == 1 && payOrderParam.getExpressType() == 1) {
                if (payOrderParam.getProductCode() == null) {
                    return ResponseDto.failure(ErrorMapping.get("20004"));//参数错误
                }
            }

            String time1 = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(ticketData.getUseStart()), DateUtil.Formatter.MM_dd_zh);
            String time2 = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(ticketData.getUseEnd()), DateUtil.Formatter.MM_dd_zh);
            String useTime = ticketData.getType() == 2 ? time1 + "~" + time2 : time2;
            String content = performanceData.getTitle() + "-" + ticketData.getTitle() + "-" + useTime;

            Integer isStudent = ticketData.getIsStudent();
            //会员时间获取
            String memberTimeStart = ticketData.getMemberTimeStart(); // 会员开售时间
            String timeStart = ticketData.getTimeStart(); // 普通开售时间
            String timeEnd = ticketData.getTimeEnd(); // 购票停售时间
            String timeExpressEnd = ticketData.getTimeEndExpress(); // 快递停售时间
            //获取用户相关
            AddressVo addressesVo = payOrderParam.getAddressesVo();
            boolean isOldMember;
            boolean isMember;
            Integer result = orderUtils.getMember(uid);
            if (result == null) {
                isMember = false;
                isOldMember = false;
            } else if (result.equals(1)) {
                isMember = true;
                isOldMember = false;
            } else if (result.equals(2)) {
                isMember = true;
                isOldMember = true;
            } else {
                isMember = false;
                isOldMember = false;
            }

            if (payOrderParam.getEnterIdList() != null) {
                entersVoList = orderUtils.getEnterList(payOrderParam.getEnterIdList(), uid);
                if (entersVoList.size() != payOrderParam.getEnterIdList().size()) {
                    return ResponseDto.failure(ErrorMapping.get("20016"));//没抢到
                }
            } else {
                entersVoList = ObjectUtil.cloneArrayListObject();
            }
            if (payOrderParam.getIsExpress() == 1) {
                payOrderParam.setAdCode(addressesVo.getCountyId());
            }

            int memberType; //会员状态 不需要判断会员 1判断会员逻辑 2会员专属
            if (DateUtil.compareStrDay(DateUtil.getNowTime(), memberTimeStart) == 1 && DateUtil.compareStrDay(DateUtil.getNowTime(), timeStart) == -1) {//优先时间
                if (payOrderParam.getNumber() > ticketData.getCounts()) {
                    return ResponseDto.failure("优先购时段内，本场演出限购"+ticketData.getCounts()+"张");
                }
                int advanceCount = dataUtils.incrUseMemberCount(uid, performanceData.getPerformancesId());
                if (advanceCount > 1) {//todo
                    dataUtils.decrUseMemberCount(uid, performanceData.getPerformancesId());
                    return ResponseDto.failure("本场演出限用1张优先券，已超出");
                }
            }
            if (ticketData.getIsExclusive() == 1) {
                memberType = 2;
                if (!isMember) {
                    return ResponseDto.failure(ErrorMapping.get("20009"));//没有会员权限
                }
            } else {
                if (DateUtil.compareStrDay(DateUtil.getNowTime(), memberTimeStart) == 1 && DateUtil.compareStrDay(DateUtil.getNowTime(), timeStart) == -1 && ticketData.getIsMember() == 1) {
                    // 会员购买逻辑
                    memberType = 1;
//                    if (!isMember) {
//                        return ResponseDto.failure(ErrorMapping.get("20009"));//没有会员权限
//                    }
                } else {
                    // 普通用户购买逻辑
                    memberType = 0;
                }
            }

            // 获取限购 实名
            int ticketLimit = ticketData.getLimitCount();//普通票种限购
            int ticketMemberLimit = ticketData.getLimitCountMember();//会员票种限购
            int ticketIdCount = ticketData.getIdCount();//实名票种限购
            int performanceLimit = performanceData.getLimitCount();//普通演出限购
            int performanceMemberLimit = 1;//会员演出限购
            int performanceIdCount = performanceData.getIdCount();//实名演出限购
            int isTrueName = ticketData.getIsTrueName();//是否演出实名

            if (!canBuyStatus.contains(performanceData.getAppStatus())) {
                return ResponseDto.failure(ErrorMapping.get("20010"));//当前不可购买
            }

            if (!canBuyStatus.contains(performanceData.getAppStatus())) {
                return ResponseDto.failure(ErrorMapping.get("20010"));//当前不可购买
            }

//            if (!canBuyTStatus.contains(ticketData.getStatus())) {
//                return ResponseDto.failure(ErrorMapping.get("20010"));//当前不可购买
//            }

            //通用判断时间
            if (payOrderParam.getAdvanceCode() != null) {
                if (isOldMember) {

                } else {
                    if (DateUtil.compareStrDay(DateUtil.getNowTime(), memberTimeStart) == 1 && DateUtil.compareStrDay(DateUtil.getNowTime(), timeStart) == -1) {
                        advanceMap = orderUtils.useCoupon(payOrderParam.getAdvanceCode(), "购买 " + performanceData.getTitle(), BigDecimal.ZERO, payOrderParam.getPerformanceId(), payOrderParam.getTimeId(), payOrderParam.getTicketId());
                        if (advanceMap == null) {
                            return ResponseDto.failure("优先券不可用");
                        }
                        Integer typeVoucher = (Integer) advanceMap.get("type");
                        String couponId = (String) advanceMap.get("couponId");
                        if (typeVoucher.equals(-1)) {
                            return ResponseDto.failure("优先券不可用");
                        }
                        if (!orderUtils.judgeRoadShowCanUse(couponId, performanceData.getRoadShowId())) {
                            orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                            return ResponseDto.failure("优先券该演出不可用");
                        }
                        int couponCount = dataUtils.incrUseCouponCount(uid, performanceData.getPerformancesId());
                        useAdvance = true;
                        if (couponCount > 1) {//todo
                            useAdvance = false;
                            dataUtils.decrUseCouponCount(uid, performanceData.getPerformancesId());
                            return ResponseDto.failure("本场演出限用1张优先券，已超出");
                        }
                    }
                }
            }

            if ((isOldMember && memberType == 1) || advanceMap != null) {
                if (DateUtil.compareStrDay(DateUtil.getNowTime(), memberTimeStart) == -1) {
                    orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                    return ResponseDto.failure(ErrorMapping.get("20011"));//未开始
                }
            } else {
                if (DateUtil.compareStrDay(DateUtil.getNowTime(), timeStart) == -1) {
                    orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                    return ResponseDto.failure(ErrorMapping.get("20011"));//未开始
                }
            }
            if (DateUtil.compareStrDay(DateUtil.getNowTime(), timeEnd) == 1) {
                orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                return ResponseDto.failure(ErrorMapping.get("20012"));//已结束
            }

            //快递票判断
            if (payOrderParam.getIsExpress() != null) {
                if (payOrderParam.getIsExpress() == 1 && DateUtil.compareStrDay(DateUtil.getNowTime(), timeExpressEnd) == 1) {
                    orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                    return ResponseDto.failure(ErrorMapping.get("20013"));//快递票不卖
                }
                if (payOrderParam.getIsExpress() == 1 && payOrderParam.getAddressesVo() == null) {
                    orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                    return ResponseDto.failure(ErrorMapping.get("20014"));//快递票未填写收货地址
                }
            }
            //实名判断
            if (isTrueName == 1 && entersVoList.size() == 0) {
                orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                return ResponseDto.failure(ErrorMapping.get("20015"));//需要实名 未实名
            }
            if (isTrueName == 1 && entersVoList.size() != payOrderParam.getNumber()) {
                orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                return ResponseDto.failure(ErrorMapping.get("20015"));//入场人数量错误
            }

            // 判断库存
            int surplusGeneral = orderUtils.changeSurplus(isPay, payOrderParam.getTicketId(), -payOrderParam.getNumber());

            if (surplusGeneral < 0) {//库存回滚
                orderUtils.changeSurplus(isPay, payOrderParam.getTicketId(), payOrderParam.getNumber());
                orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                return ResponseDto.failure(ErrorMapping.get("20016"));//没抢到
            } else {
                isDownGeneral = true;

                //学生票 判断
                if (isTrueName == 1) {
                    for (AdamEntersVo adamEnters : entersVoList) {
                        if (adamEnters == null) {
                            orderUtils.changeSurplus(isPay, payOrderParam.getTicketId(), payOrderParam.getNumber());
                            orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                            return ResponseDto.failure("入场人数据错误");
                        }
                        if (isStudent == 1) {
                            if (adamEnters.getType() != 1) {
                                orderUtils.changeSurplus(isPay, payOrderParam.getTicketId(), payOrderParam.getNumber());
                                orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                                return ResponseDto.failure(ErrorMapping.get("20031"));//不符合购买条件
                            }
                            int age = IDCard.getAgeByIdCard(adamEnters.getIdCard());
                            if (age > 25) {
                                orderUtils.changeSurplus(isPay, payOrderParam.getTicketId(), payOrderParam.getNumber());
                                orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                                return ResponseDto.failure(ErrorMapping.get("20017"));//年龄超了
                            }
                        }
                    }
                }

                //限购判断 如果实名 则身份证维度限购 如果不实名则数量限购
                if (entersVoList.size() > 0) {
                    for (int i = 0; i < entersVoList.size(); i++) {
                        dataUtils.changeBuyInfo(uid, entersVoList.get(i).getIdCard(), performanceData.getPerformancesId(), ticketData.getTicketsId(), 1);
                        String res1 = orderUtils.judgeOrderLimit(uid, entersVoList.get(i).getIdCard(), payOrderParam.getPerformanceId(), payOrderParam.getTicketId(), performanceLimit, performanceMemberLimit, performanceIdCount, ticketLimit, ticketMemberLimit, ticketIdCount, memberType, isTrueName);
                        if (!res1.equals("")) {
                            for (int x = 0; x <= i; x++) {
                                dataUtils.changeBuyInfo(uid, entersVoList.get(x).getIdCard(), performanceData.getPerformancesId(), ticketData.getTicketsId(), -1);
                            }
                            orderUtils.changeSurplus(isPay, payOrderParam.getTicketId(), payOrderParam.getNumber());
                            orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                            return ResponseDto.failure(res1);//乱七八糟异常
                        }
                    }
                } else {
                    dataUtils.changeBuyInfo(uid, "", performanceData.getPerformancesId(), ticketData.getTicketsId(), payOrderParam.getNumber());
                    String res1 = orderUtils.judgeOrderLimit(uid, "", payOrderParam.getPerformanceId(), payOrderParam.getTicketId(), performanceLimit, performanceMemberLimit, performanceIdCount, ticketLimit, ticketMemberLimit, ticketIdCount, memberType, isTrueName);
                    if (!res1.equals("")) {
                        dataUtils.changeBuyInfo(uid, "", performanceData.getPerformancesId(), ticketData.getTicketsId(), -payOrderParam.getNumber());
                        orderUtils.changeSurplus(isPay, payOrderParam.getTicketId(), payOrderParam.getNumber());
                        orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                        return ResponseDto.failure(res1);//乱七八糟异常
                    }
                }

                ResponseDto<PayInnerResultVo> resultData = order(payOrderParam, uid, isMember, isTrueName, performanceData, ticketData, entersVoList, isStudent, content, useTime, advanceMap, addressesVo, orderTicketId, orderCode);
                isDownGeneral = false;
                return resultData;
            }
        } catch (Exception e) {
            log.error("Kylin Order Pay Error = {}", e);
            if (isDownGeneral) {
                orderUtils.changeSurplus(isPay, payOrderParam.getTicketId(), payOrderParam.getNumber());
                log.error("回滚库存");
                orderUtils.backAdvanceCoupon(payOrderParam.getAdvanceCode(), uid);
                if (useAdvance) {
                    dataUtils.decrUseCouponCount(uid, performanceId);
                }
                for (AdamEntersVo enters : entersVoList) {
                    dataUtils.changeBuyInfo(uid, enters.getIdCard(), payOrderParam.getPerformanceId(), payOrderParam.getTicketId(), -1);
                }
                if (entersVoList.size() == 0) {
                    for (int i = 0; i < payOrderParam.getNumber(); i++) {
                        dataUtils.changeBuyInfo(uid, "", payOrderParam.getPerformanceId(), payOrderParam.getTicketId(), -1);
                    }
                }
            }
            if (e.getMessage() == null) {
                return ResponseDto.failure(ErrorMapping.get("20018"));//乱七八糟异常
            } else if (e.getMessage().equals("券不可用")) {
                return ResponseDto.failure(ErrorMapping.get("20030"));//券不可用
            } else {
                return ResponseDto.failure(ErrorMapping.get("20018"));//乱七八糟异常
            }
        }
    }

    private ResponseDto<PayInnerResultVo> order(PayOrderParam payOrderParam, String uid, boolean isMember, int isTrueName, KylinPerformanceVo performanceData, KylinTicketVo ticketData, List<AdamEntersVo> entersVoList, Integer isStudent, String content, String useTime, HashMap<String, Object> advanceMap, AddressVo addressesVo, String orderTicketId, String orderCode) throws Exception {
        LinkedList<String> sqls = ObjectUtil.cloneLinkedListStr();
        String headerCliSource = CurrentUtil.getHeaderCliSource(), headerCliVersion = CurrentUtil.getHeaderCliVersion();
        String source = headerCliSource == null ? "" : headerCliSource;
        String version = headerCliVersion == null ? "" : headerCliVersion;
        LocalDateTime now = LocalDateTime.now();
        //生成订单 order_ticket
        KylinOrderTickets orderTickets = KylinOrderTickets.getNew();
        orderTickets.setOrderTicketsId(orderTicketId);
        orderTickets.setUserId(uid);
        Map token = CurrentUtil.getTokenClaims();
        orderTickets.setUserName(StringUtils.defaultString(((String) token.get("nickname")), ""));
        orderTickets.setUserMobile(StringUtils.defaultString(((String) token.get("mobile")), ""));
        orderTickets.setPerformanceTitle(performanceData.getTitle());
        orderTickets.setOrderCode(orderCode);
        orderTickets.setPayCode("");
        orderTickets.setQrCode("");
        orderTickets.setOrderType(source);
        orderTickets.setOrderVersion(version);
        orderTickets.setNumber(payOrderParam.getNumber());
        orderTickets.setPrice(ticketData.getPrice());
        orderTickets.setPriceMember(ticketData.getMemberPrice());

        BigDecimal priceExpress = BigDecimal.ZERO;
        if (payOrderParam.getIsExpress() == 1 && payOrderParam.getExpressType() == 1) {
            String productCode = payOrderParam.getProductCode();
            String adCode = payOrderParam.getAdCode();
            priceExpress = orderUtils.getExpressPrice(adCode, productCode);
        }

        if (payOrderParam.getVoucherType() != null) {
            orderTickets.setCouponType(payOrderParam.getVoucherType().equals(3) ? "exchange" : "no");
        } else {
            orderTickets.setCouponType("no");
        }

        if (isMember) {
            orderTickets.setPriceTotal(ticketData.getMemberPrice().multiply(BigDecimal.valueOf(payOrderParam.getNumber())).add(payOrderParam.getIsExpress() == 1 ? priceExpress : BigDecimal.valueOf(0)));
        } else {
            orderTickets.setPriceTotal(ticketData.getPrice().multiply(BigDecimal.valueOf(payOrderParam.getNumber())).add(payOrderParam.getIsExpress() == 1 ? priceExpress : BigDecimal.valueOf(0)));
        }

        orderTickets.setPriceVoucher(BigDecimal.ZERO);
        //券的使用逻辑
        sqls.add(SqlMapping.get("kylin_order_coupon.add"));
        LinkedList<Object[]> sqlsDataE = ObjectUtil.cloneLinkedListObj();
        ArrayList<KylinOrderCoupons> couponsList = new ArrayList();
        if (advanceMap != null) {
            BigDecimal priceVoucher = (BigDecimal) advanceMap.get("voucher");
            Integer typeVoucher = (Integer) advanceMap.get("type");
            KylinOrderCoupons couponsAdvance = KylinOrderCoupons.getNew();
            couponsAdvance.setOrderId(orderTicketId);
            couponsAdvance.setCouponCode(payOrderParam.getAdvanceCode());
            couponsAdvance.setCouponType(101);
            couponsAdvance.setCouponPrice(BigDecimal.ZERO);
            couponsAdvance.setCreatedAt(now);
            couponsList.add(couponsAdvance);
            sqlsDataE.add(new Object[]{
                    orderTicketId, payOrderParam.getAdvanceCode(), typeVoucher, priceVoucher, now, now
            });
        }

        if (payOrderParam.getVoucherCode() != null) {
            HashMap<String, Object> hashMap = orderUtils.useCoupon(payOrderParam.getVoucherCode(), content, orderTickets.getPriceTotal().subtract(priceExpress), payOrderParam.getPerformanceId(), payOrderParam.getTimeId(), payOrderParam.getTicketId());
            if (null != hashMap) {
                BigDecimal priceVoucher = (BigDecimal) hashMap.get("voucher");
                Integer typeVoucher = (Integer) hashMap.get("type");
                if (typeVoucher.equals(-1)) {
                    throw new Exception("券不可用");
                }
                orderTickets.setPriceVoucher(priceVoucher);
                KylinOrderCoupons couponsVoucher = KylinOrderCoupons.getNew();
                couponsVoucher.setOrderId(orderTicketId);
                couponsVoucher.setCouponCode(payOrderParam.getVoucherCode());
                couponsVoucher.setCouponType(typeVoucher);
                couponsVoucher.setCouponPrice(priceVoucher);
                couponsVoucher.setCreatedAt(now);
                couponsList.add(couponsVoucher);
                sqlsDataE.add(new Object[]{
                        orderTicketId, payOrderParam.getVoucherCode(), typeVoucher, priceVoucher, now, now
                });
            }
        }

        if (couponsList.size() > 0) {
            dataUtils.setOrderCoupon(orderTicketId, couponsList);
        }

        BigDecimal finalPrice = orderTickets.getPriceTotal().subtract(orderTickets.getPriceVoucher());
        orderTickets.setPriceActual(finalPrice.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : finalPrice);
        orderTickets.setPriceExpress(priceExpress);
        orderTickets.setPriceRefund(BigDecimal.valueOf(0.0));
        orderTickets.setRefundNumber(0);
        orderTickets.setPayType(payOrderParam.getPayType());
        orderTickets.setPaymentType(null);
        orderTickets.setTimePay(null);
        if (payOrderParam.getIsExpress() == 1) {
            orderTickets.setExpressContacts(addressesVo.getName());
            orderTickets.setExpressAddress(addressesVo.getProvince() + addressesVo.getCity() + addressesVo.getCounty() + addressesVo.getAddress());
            orderTickets.setExpressPhone(addressesVo.getPhone());
            orderTickets.setCity(addressesVo.getCity());
            orderTickets.setProvince(addressesVo.getProvince());
            orderTickets.setCounty(addressesVo.getCounty());
            orderTickets.setGetTicketType("express");
        } else {
            orderTickets.setExpressContacts("");
            orderTickets.setExpressAddress("");
            orderTickets.setExpressPhone("");
            orderTickets.setCity("");
            orderTickets.setProvince("");
            orderTickets.setCounty("");
            orderTickets.setGetTicketType("electronic");
        }
        orderTickets.setGetTicketDescribe("");
        orderTickets.setPayCountdownMinute(performanceData.getPayCountdownMinute());
        orderTickets.setCreatedAt(now);
        orderTickets.setUpdatedAt(null);


        //生成订单 order_ticket_status
        KylinOrderTicketStatus orderTicketStatus = KylinOrderTicketStatus.getNew();
        String orderTicketStatusId = IDGenerator.nextSnowId();
        orderTicketStatus.setOrderTicketStatusId(orderTicketStatusId);
        orderTicketStatus.setOrderId(orderTicketId);
        orderTicketStatus.setExpressType(payOrderParam.getExpressType());
        orderTicketStatus.setTransferStatus(KylinTableStatusConst.ORDER_TRANSFER_STATUS0);
        orderTicketStatus.setStatus(KylinTableStatusConst.ORDER_STATUS0);
        orderTicketStatus.setIsStudent(isStudent);
        orderTicketStatus.setPayStatus(KylinTableStatusConst.ORDER_PAY_STATUS0);
        orderTicketStatus.setProduceCode(payOrderParam.getProductCode());
        orderTicketStatus.setCreatedAt(now);
        orderTicketStatus.setUpdatedAt(null);
        sqls.add(SqlMapping.get("kylin_order_ticket_status.add"));
        LinkedList<Object[]> sqlsDataB = ObjectUtil.cloneLinkedListObj();
        sqlsDataB.add(orderTicketStatus.getAddObject());

        //生成订单 order_ticket_relation
        KylinOrderTicketRelations orderTicketRelations = KylinOrderTicketRelations.getNew();
        String orderTicketRelationId = IDGenerator.nextSnowId();
        orderTicketRelations.setOrderTicketRelationsId(orderTicketRelationId);
        orderTicketRelations.setOrderId(orderTicketId);
        orderTicketRelations.setTransferId("");
        orderTicketRelations.setLiveId("");
        KylinAgentVo agentVo = orderUtils.checkAgent(payOrderParam.getAgentId(), performanceData.getPerformancesId(), ticketData);
        orderTicketRelations.setAgentId(payOrderParam.getAgentId());
        if (agentVo == null) {
            orderTicketRelations.setAgentDistributions(BigDecimal.ZERO);
            orderTicketRelations.setAgentStatus(0);
            orderTicketRelations.setAgentIdMaster("0");
            orderTicketRelations.setAgentDistributionsMaster(BigDecimal.ZERO);
        } else {
            orderTicketRelations.setAgentDistributions(agentVo.getCarry());
            orderTicketRelations.setAgentStatus(agentVo.getIsBlack() == 1 ? 2 : 1);
            orderTicketRelations.setAgentIdMaster(agentVo.getAgentMasterId());
            orderTicketRelations.setAgentDistributionsMaster(agentVo.getExCarry());
        }

        orderTicketRelations.setIsMember(isMember ? 1 : 0);
        orderTicketRelations.setPerformanceId(payOrderParam.getPerformanceId());
        orderTicketRelations.setTimeId(payOrderParam.getTimeId());
        orderTicketRelations.setTicketId(payOrderParam.getTicketId());
        orderTicketRelations.setCreatedAt(now);
        orderTicketRelations.setUpdatedAt(null);
        sqls.add(SqlMapping.get("kylin_order_ticket_relation.add"));
        LinkedList<Object[]> sqlsDataC = ObjectUtil.cloneLinkedListObj();
        sqlsDataC.add(orderTicketRelations.getAddObject());


        //生成票
        KylinOrderTicketEntities orderTicketEntities = KylinOrderTicketEntities.getNew();
        LinkedList<Object[]> sqlsDataD = ObjectUtil.cloneLinkedListObj();
        sqls.add(SqlMapping.get("kylin_order_ticket_entities.add"));
        if (isTrueName == 1) {
            for (AdamEntersVo enters : entersVoList) {
                String orderTicketEntitiesId = IDGenerator.nextSnowId();
                orderTicketEntities.setOrderTicketEntitiesId(orderTicketEntitiesId);
                orderTicketEntities.setOrderId(orderTicketId);
                orderTicketEntities.setTicketId(payOrderParam.getTicketId());
                orderTicketEntities.setUserId(uid);
                orderTicketEntities.setPerformanceId(payOrderParam.getPerformanceId());
                orderTicketEntities.setTimeId(payOrderParam.getTimeId());
                orderTicketEntities.setEnterType(enters.getType());
                orderTicketEntities.setEnterName(enters.getName());
                orderTicketEntities.setEnterMobile(enters.getMobile());
                orderTicketEntities.setEnterIdCode(enters.getIdCard());
                orderTicketEntities.setStatus(KylinTableStatusConst.ENTITIES_STATUS0);
                orderTicketEntities.setSysDamai(ticketData.getSysDamai());
                orderTicketEntities.setCheckClient("");
                orderTicketEntities.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT0);
                orderTicketEntities.setRefundPrice(BigDecimal.valueOf(0.0));
                orderTicketEntities.setComment("");
                orderTicketEntities.setCreatedAt(now);
                orderTicketEntities.setUpdatedAt(null);
                sqlsDataD.add(orderTicketEntities.getAddObject());
                // 生成vo
                KylinOrderTicketEntitiesVo orderTicketEntitiesVo = KylinOrderTicketEntitiesVo.getNew();
                BeanUtils.copyProperties(orderTicketEntities, orderTicketEntitiesVo);
                orderTicketEntitiesVo.setPerformanceTitle(performanceData.getTitle());
                orderTicketEntitiesVo.setTicketTitle(ticketData.getTitle());
                orderTicketEntitiesVo.setUseStart(ticketData.getUseStart());
                orderTicketEntitiesVo.setUseEnd(ticketData.getUseEnd());
                orderTicketEntitiesVo.setCreatedAt(orderTicketEntities.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                orderTicketEntitiesVo.setUpdatedAt(null);
                orderTicketEntitiesVo.setChangeDate(orderTicketEntities.getCreatedAt());
                mongoTemplate.insert(orderTicketEntitiesVo, KylinOrderTicketEntitiesVo.class.getSimpleName());
//                dataUtils.changeBuyInfo(orderTicketEntitiesVo.getUserId(), orderTicketEntitiesVo.getEnterIdCode(), orderTicketEntitiesVo.getPerformanceId(), orderTicketEntitiesVo.getTicketId(), 1);
            }
        } else {
            for (int i = 0; i < payOrderParam.getNumber(); i++) {
                String orderTicketEntitiesId = IDGenerator.nextSnowId();
                orderTicketEntities.setOrderTicketEntitiesId(orderTicketEntitiesId);
                orderTicketEntities.setOrderId(orderTicketId);
                orderTicketEntities.setTicketId(payOrderParam.getTicketId());
                orderTicketEntities.setUserId(uid);
                orderTicketEntities.setPerformanceId(payOrderParam.getPerformanceId());
                orderTicketEntities.setTimeId(payOrderParam.getTimeId());
                orderTicketEntities.setEnterType(0);
                orderTicketEntities.setEnterName("");
                orderTicketEntities.setEnterMobile("");
                orderTicketEntities.setEnterIdCode("");
                orderTicketEntities.setStatus(KylinTableStatusConst.ENTITIES_STATUS0);
                orderTicketEntities.setSysDamai(ticketData.getSysDamai());
                orderTicketEntities.setCheckClient("");
                orderTicketEntities.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT0);
                orderTicketEntities.setComment("");
                orderTicketEntities.setCreatedAt(now);
                orderTicketEntities.setUpdatedAt(null);
                sqlsDataD.add(orderTicketEntities.getAddObject());
                // 生成vo
                KylinOrderTicketEntitiesVo orderTicketEntitiesVo = KylinOrderTicketEntitiesVo.getNew();
                BeanUtils.copyProperties(orderTicketEntities, orderTicketEntitiesVo);
                orderTicketEntitiesVo.setPerformanceTitle(performanceData.getTitle());
                orderTicketEntitiesVo.setTicketTitle(ticketData.getTitle());
                orderTicketEntitiesVo.setUseStart(ticketData.getUseStart());
                orderTicketEntitiesVo.setUseEnd(ticketData.getUseEnd());
                orderTicketEntitiesVo.setCreatedAt(orderTicketEntities.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                orderTicketEntitiesVo.setUpdatedAt(null);
                orderTicketEntitiesVo.setChangeDate(orderTicketEntities.getCreatedAt());
                mongoTemplate.insert(orderTicketEntitiesVo, KylinOrderTicketEntitiesVo.class.getSimpleName());
//                dataUtils.changeBuyInfo(orderTicketEntitiesVo.getUserId(), orderTicketEntitiesVo.getEnterIdCode(), orderTicketEntitiesVo.getPerformanceId(), orderTicketEntitiesVo.getTicketId(), 1);
            }
        }

        //是否免费
        boolean isFree = false;
        PayResultVo payResultVo;

        if (orderTickets.getPriceActual().compareTo(BigDecimal.valueOf(0)) > 0) {
            String name = dataUtils.getTicketPayTxt(ticketData.getTicketsId());
            if (name.equals("")) {
                name = "正在现场";
            }
            // 调用支付
            if (payOrderParam.getPayType().equalsIgnoreCase(DragonConstant.PayChannelEnum.WEPAY.getCode())) {
                if (payOrderParam.getDeviceFrom().equalsIgnoreCase(DragonConstant.DeviceFromEnum.JS.getCode()) || payOrderParam.getDeviceFrom().equalsIgnoreCase(DragonConstant.DeviceFromEnum.APPLET.getCode())) {
                    if (StringUtil.isEmpty(payOrderParam.getOpenId())) {
                        return ResponseDto.failure("微信支付openId不能为空!");
                    }
                }
            }
            DragonPayBaseReqDto dragonPayBaseReqDto = DragonPayBaseReqDto.getNew();
            dragonPayBaseReqDto.setPayType(payOrderParam.getPayType());
            dragonPayBaseReqDto.setDeviceFrom(payOrderParam.getDeviceFrom());
            if (payOrderParam.getDeviceFrom().equals("js") || payOrderParam.getDeviceFrom().equals("applet")) {
                dragonPayBaseReqDto.setOpenId(payOrderParam.getOpenId());
            }
            dragonPayBaseReqDto.setType("TICKET");
            dragonPayBaseReqDto.setPrice(orderTickets.getPriceActual());
            if (StringUtil.isNotNull(name) && name.length() >= 32) {
                name = name.substring(0, 32);
            }
            dragonPayBaseReqDto.setName(name);
            dragonPayBaseReqDto.setDetail("正在现场");
            dragonPayBaseReqDto.setOrderCode(orderTickets.getOrderCode());
            dragonPayBaseReqDto.setClientIp(CurrentUtil.getCliIpAddr());
            dragonPayBaseReqDto.setNotifyUrl(synUrl);
            dragonPayBaseReqDto.setReturnUrl(payOrderParam.getReturnUrl() + orderTicketId);
            dragonPayBaseReqDto.setShowUrl(payOrderParam.getShowUrl() + orderTicketId);
            dragonPayBaseReqDto.setCreateDate(orderTickets.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            dragonPayBaseReqDto.setExpireTime(orderTickets.getPayCountdownMinute() + "");
            ResponseDto<DragonPayBaseRespDto> responseDto = dragonOrdersService.dragonPay(dragonPayBaseReqDto);
            String returnData = JsonUtils.toJson(responseDto);

            log.debug("调用 DRAGON 结果 = " + returnData);
            payResultVo = JsonUtils.fromJson(returnData, PayResultVo.class);
            payResultVo.getData().setOrderId(orderTicketId);
            payResultVo.getData().setPayType(orderTickets.getPayType());
            payResultVo.getData().setPrice(orderTickets.getPriceActual());
            orderTickets.setPayCode(payResultVo.getData().getCode());
            if (payOrderParam.getPayType().equals("alipay") && payOrderParam.getDeviceFrom().equals("wap")) {
                payResultVo.getData().setShowUrl(payOrderParam.getShowUrl() + orderTicketId);
                payResultVo.getData().setReturnUrl(payOrderParam.getReturnUrl() + orderTicketId);
            }
        } else {
            isFree = true;
            orderTickets.setPayType("FREE");
            orderTickets.setPayCode("FREE_PAY_CODE");
            payResultVo = PayResultVo.getNew();
            PayInnerResultVo payInnerResultVo = PayInnerResultVo.getNew();
            payInnerResultVo.setPrice(BigDecimal.valueOf(0));
            payInnerResultVo.setOrderId(orderTickets.getOrderTicketsId());
            payInnerResultVo.setPayType(orderTickets.getPayType());
            payResultVo.setData(payInnerResultVo);
        }

        KylinIpAreaVo vo = dataUtils.getKylinIpAreaVo(CurrentUtil.getCliIpAddr());
        sqls.add(SqlMapping.get("kylin_order_ticket.add"));
        LinkedList<Object[]> sqlsDataA = ObjectUtil.cloneLinkedListObj();
        sqlsDataA.add(orderTickets.getAddObject(CurrentUtil.getCliIpAddr(), vo.getArea(), vo.getProvince(), vo.getCity(), vo.getCounty()));

        // 待支付发送队列
        queueUtils.sendMsgByRedisGoblinStock(orderTickets.getOrderTicketsId(), orderTickets.getCreatedAt(), "TICKET", performanceData.getPayCountdownMinute());
        // 生成vo
        KylinOrderTicketVo orderTicketVo = KylinOrderTicketVo.getNew();
        orderTicketVo.setOrderTicket(orderTickets);
        orderTicketVo.setOrderTicketStatus(orderTicketStatus);
        orderTicketVo.setOrderTicketRelation(orderTicketRelations);
        orderTicketVo.setPerformanceImg(performanceData.getImgPoster());
        orderTicketVo.setTicketTitle(ticketData.getTitle());
        orderTicketVo.setUseStart(ticketData.getUseStart());
        orderTicketVo.setTimeStart(performanceData.getTimeStart());
        orderTicketVo.setOverdueAt(orderTickets.getCreatedAt().plusMinutes(performanceData.getPayCountdownMinute()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        orderTicketVo.setCreatedAt(orderTickets.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        orderTicketVo.setChangeDate(orderTickets.getCreatedAt());
        mongoTemplate.insert(orderTicketVo, KylinOrderTicketVo.class.getSimpleName());

        orderUtils.resetOrderListVo(uid, 1, orderTicketVo.getOrderTicketsId(), orderTicketVo);

        // 执行sql
        String sqlData = SqlMapping.gets(sqls, sqlsDataE, sqlsDataB, sqlsDataC, sqlsDataD, sqlsDataA);
        queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_ORDER_CREATE.getKey(),
                sqlData);
        log.info(UserPathDto.setData("下单(唤起支付)", payOrderParam, payResultVo.getData()));
        if (isFree) {
            SyncOrderParam syncOrderParam = SyncOrderParam.getNew();
            syncOrderParam.setOrderCode(orderTickets.getOrderCode());
            syncOrderParam.setPaymentAt(DateUtil.format(LocalDateTime.now(), DateUtil.Formatter.yyyyMMddHHmmss));
            syncOrderParam.setCode(orderTickets.getPayCode());
            syncOrderParam.setPrice(orderTickets.getPriceActual());
            syncOrderParam.setPaymentId("FREE_PAYMENT_ID");
            syncOrderParam.setPaymentType(orderTickets.getPaymentType());
            syncOrderParam.setStatus(1);
            syncOrder(syncOrderParam);
            return ResponseDto.success(payResultVo.getData());
        } else {
            return ResponseDto.success(payResultVo.getData());
        }
    }

    @Override
    public ResponseDto<PayInnerResultVo> payAgain(PayAgainParam payAgainParam) {
        try {
            String uid = CurrentUtil.getCurrentUid();
            //检查订单时间 是否关闭
            KylinOrderTicketVo orderTicketData = dataUtils.getOrderTicketVo(payAgainParam.getOrderId());
            if (!orderTicketData.getUserId().equals(uid)) {
                return ResponseDto.failure(ErrorMapping.get("20003"));
            }
            if (orderTicketData == null) {
                return ResponseDto.failure(ErrorMapping.get("20024"));
            }

            if (orderTicketData.getStatus() == KylinTableStatusConst.ORDER_STATUS1) {
                return ResponseDto.failure(ErrorMapping.get("20025"));
            } else {
                if (orderTicketData.getStatus() != KylinTableStatusConst.ORDER_STATUS0) {
                    return ResponseDto.failure(ErrorMapping.get("20026"));
                }
            }
            DragonPayOrderQueryRespDto checkVo = dragonOrdersService.checkOrderStatusByCode(orderTicketData.getPayCode());
            if (checkVo.getStatus() == 1) {
                return ResponseDto.failure(ErrorMapping.get("20027"));
            }
            if (!orderTicketData.getPayType().equals("no")) {

                if (orderTicketData.getEntitiesVoList().size() == 0) {
                    return ResponseDto.failure(ErrorMapping.get("20004"));
                }
                String name = dataUtils.getTicketPayTxt(orderTicketData.getTicketId());
                if (name.equals("")) {
                    name = "正在现场";
                }
                if (payAgainParam.getPayType().equalsIgnoreCase(DragonConstant.PayChannelEnum.WEPAY.getCode())) {
                    if (payAgainParam.getDeviceFrom().equalsIgnoreCase(DragonConstant.DeviceFromEnum.JS.getCode()) || payAgainParam.getDeviceFrom().equalsIgnoreCase(DragonConstant.DeviceFromEnum.APPLET.getCode())) {
                        if (StringUtil.isEmpty(payAgainParam.getOpenId())) {
                            return ResponseDto.failure("微信支付openId不能为空!");
                        }
                    }
                }
                DragonPayBaseReqDto dragonPayBaseReqDto = DragonPayBaseReqDto.getNew();
                dragonPayBaseReqDto.setPayType(payAgainParam.getPayType());
                dragonPayBaseReqDto.setDeviceFrom(payAgainParam.getDeviceFrom());
                if (payAgainParam.getDeviceFrom().equals("js") || payAgainParam.getDeviceFrom().equals("applet")) {
                    dragonPayBaseReqDto.setOpenId(payAgainParam.getOpenId());
                }
                dragonPayBaseReqDto.setType("TICKET");
                dragonPayBaseReqDto.setPrice(orderTicketData.getPriceActual());
                if (StringUtil.isNotNull(name) && name.length() >= 32) {
                    name = name.substring(0, 32);
                }
                dragonPayBaseReqDto.setName(name);
                dragonPayBaseReqDto.setDetail("正在现场");
                dragonPayBaseReqDto.setOrderCode(orderTicketData.getOrderCode());
                dragonPayBaseReqDto.setClientIp(CurrentUtil.getCliIpAddr());
                dragonPayBaseReqDto.setNotifyUrl(synUrl);
                dragonPayBaseReqDto.setReturnUrl(payAgainParam.getReturnUrl() + payAgainParam.getOrderId());
                dragonPayBaseReqDto.setShowUrl(payAgainParam.getShowUrl() + payAgainParam.getOrderId());
                dragonPayBaseReqDto.setCreateDate(orderTicketData.getCreatedAt());
                dragonPayBaseReqDto.setExpireTime(orderTicketData.getPayCountdownMinute().toString());
                ResponseDto<DragonPayBaseRespDto> responseDto = dragonOrdersService.dragonPay(dragonPayBaseReqDto);
                String returnData = JsonUtils.toJson(responseDto);


                PayResultVo payResultVo = JsonUtils.fromJson(returnData, PayResultVo.class);
                payResultVo.getData().setOrderId(orderTicketData.getOrderTicketsId());
                payResultVo.getData().setPrice(orderTicketData.getPriceActual());
                if (payAgainParam.getPayType().equals("alipay") && payAgainParam.getDeviceFrom().equals("wap")) {
                    payResultVo.getData().setShowUrl(payAgainParam.getShowUrl());
                    payResultVo.getData().setReturnUrl(payAgainParam.getReturnUrl());
                }

                KylinOrderTickets orderTickets = KylinOrderTickets.getNew();
                orderTickets.setOrderTicketsId(payAgainParam.getOrderId());
                orderTickets.setUpdatedAt(LocalDateTime.now());
                orderTickets.setPayCode(payResultVo.getData().getCode());
                orderTickets.setPayType(payAgainParam.getPayType());

                //改vo
                HashMap<String, Object> map = ObjectUtil.cloneHashMapStringAndObject();
                map.put("payType", payAgainParam.getPayType());
                map.put("payCode", payResultVo.getData().getCode());
                map.put("updatedAt", DateUtil.Formatter.yyyyMMddHHmmss.format(orderTickets.getUpdatedAt()));
                map.put("changeDate", orderTickets.getUpdatedAt());
                mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                        Query.query(Criteria.where("orderTicketsId").is(payAgainParam.getOrderId())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(map))
                );

                LocalDateTime strTime = LocalDateTime.now();
                dataUtils.delOrderTicketRedis(orderTickets.getOrderTicketsId());

                LinkedList<String> sqls = ObjectUtil.cloneLinkedListStr();
                sqls.add(SqlMapping.get("kylin_order_ticket.payAgain"));
                LinkedList<Object[]> sqlsDataA = ObjectUtil.cloneLinkedListObj();
                sqlsDataA.add(orderTickets.getPayAgainObject(strTime, strTime));
                sqls.add(SqlMapping.get("kylin_order_ticket_status.payAgain"));
                LinkedList<Object[]> sqlsDataB = ObjectUtil.cloneLinkedListObj();
                Object[] objectB = ObjectUtil.cloneObjectsArray(4);
                objectB[0] = orderTickets.getUpdatedAt();
                objectB[1] = orderTickets.getOrderTicketsId();
                objectB[2] = strTime;
                objectB[3] = strTime;
                sqlsDataB.add(objectB);
                sqls.add(SqlMapping.get("kylin_order_ticket_relation.payAgain"));
                LinkedList<Object[]> sqlsDataC = ObjectUtil.cloneLinkedListObj();
                Object[] objectC = ObjectUtil.cloneObjectsArray(4);
                objectC[0] = orderTickets.getUpdatedAt();
                objectC[1] = orderTickets.getOrderTicketsId();
                objectC[2] = strTime;
                objectC[3] = strTime;
                sqlsDataC.add(objectC);
                sqls.add(SqlMapping.get("kylin_order_ticket_entities.payAgain"));
                LinkedList<Object[]> sqlsDataD = ObjectUtil.cloneLinkedListObj();
                Object[] objectD = ObjectUtil.cloneObjectsArray(4);
                objectD[0] = orderTickets.getUpdatedAt();
                objectD[1] = orderTickets.getOrderTicketsId();
                objectD[2] = strTime;
                objectD[3] = strTime;
                sqlsDataD.add(objectD);

                String sqlData = SqlMapping.gets(sqls, sqlsDataA, sqlsDataB, sqlsDataC, sqlsDataD);
                queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_ORDER_AGAIN.getKey(), sqlData);
                log.info(UserPathDto.setData("再次支付", payAgainParam, payResultVo.getData()));
                return ResponseDto.success(payResultVo.getData());
            }
            return ResponseDto.failure(ErrorMapping.get("20029"));
        } catch (Exception e) {
            return ResponseDto.failure(ErrorMapping.get("20028"));
        }

    }

    @Override
    public String syncOrder(SyncOrderParam syncOrderParam) {
        try {
            log.debug("SYNC PARAM = " + syncOrderParam.toString());
            //支付时间
            LocalDateTime now = LocalDateTime.now();
            String lock = "order_lock:" + syncOrderParam.getOrderCode();

            String timePay = syncOrderParam.getPaymentAt();
            KylinOrderTicketVo orderTicketData = mongoTemplate.findOne(Query.query(Criteria.where("orderCode").is(syncOrderParam.getOrderCode())), KylinOrderTicketVo.class, KylinOrderTicketVo.class.getSimpleName());
            if (orderTicketData == null) {
                log.error("订单号：" + syncOrderParam.getOrderCode() + " 订单不存在");
                return "fail";//订单不存在
            }

            if (orderTicketData.getStatus() != KylinTableStatusConst.ORDER_STATUS0) {
                if (orderTicketData.getPayCode().equals(syncOrderParam.getCode()) && orderTicketData.getStatus() == KylinTableStatusConst.ORDER_STATUS1) {
                    log.error("订单号：" + syncOrderParam.getOrderCode() + " 已经支付");
                    return "success";//已经支付
                }

                if (!orderTicketData.getPayCode().equals(syncOrderParam.getCode())) {
                    log.error("订单号：" + syncOrderParam.getOrderCode() + " 重复支付");
                    return "fail";//重复支付
                }
            }

            if (orderTicketData.getPriceActual().compareTo(syncOrderParam.getPrice()) != 0) {
                log.error("订单号：" + syncOrderParam.getOrderCode() + " 价格不符");
                return "fail";//价格不符
            }

            LinkedList<String> sqls = ObjectUtil.cloneLinkedListStr();
            LinkedList<Object[]> sqlsDataA = ObjectUtil.cloneLinkedListObj();
            LinkedList<Object[]> sqlsDataB = ObjectUtil.cloneLinkedListObj();
            LinkedList<Object[]> sqlsDataC = ObjectUtil.cloneLinkedListObj();
            LinkedList<Object[]> sqlsDataD = ObjectUtil.cloneLinkedListObj();

            LocalDateTime strTime = LocalDateTime.now().plusSeconds(10);

            KylinOrderTickets orderTickets = KylinOrderTickets.getNew();
            KylinOrderTicketStatus orderTicketStatus = KylinOrderTicketStatus.getNew();
            KylinOrderTicketEntities orderTicketEntities = KylinOrderTicketEntities.getNew();

            if (orderTicketData.getStatus() == 2 && syncOrderParam.getStatus().equals(1)) {
                orderUtils.resetOrderListVo(orderTicketData.getUserId(), 2, orderTicketData.getOrderTicketsId(), null);
                log.error("订单号为 {} 的订单超时支付", syncOrderParam.getOrderCode());
                orderRefundsCallbackService.refundApply(orderTicketData.getOrderTicketsId(), syncOrderParam.getPaymentId(), syncOrderParam.getPaymentType());
                //大麦退款
                refundDamaiOrder(orderTickets.getOrderTicketsId());
            } else if ((orderTicketData.getStatus() == 3 || orderTicketData.getStatus() == 4) && syncOrderParam.getStatus().equals(1)) {
                log.error("订单号为 {} 的订单正在退款 或者已退款", syncOrderParam.getOrderCode());
            } else if (syncOrderParam.getStatus().equals(1)) {
                log.error("订单号为 {} 的订单正常流程", syncOrderParam.getOrderCode());
                orderTickets.setOrderTicketsId(orderTicketData.getOrderTicketsId());
                orderTickets.setPaymentType(syncOrderParam.getPaymentType());
                orderTickets.setPayCode(syncOrderParam.getCode());
                orderTickets.setTimePay(timePay);
                orderTickets.setQrCode(IDGenerator.ticketQrCode(orderTicketData.getOrderTicketsId()));
                orderTickets.setUpdatedAt(now);
                orderTickets.setPaymentId(syncOrderParam.getPaymentId());
                sqls.add(SqlMapping.get("kylin_order_ticket.synPay"));
                sqlsDataA.add(orderTickets.getSynOrderObject(strTime, strTime));

                orderTicketStatus.setOrderId(orderTicketData.getOrderTicketsId());
                orderTicketStatus.setStatus(KylinTableStatusConst.ORDER_STATUS1);
                orderTicketStatus.setPayStatus(syncOrderParam.getStatus());
                orderTicketStatus.setUpdatedAt(orderTickets.getUpdatedAt());
                sqls.add(SqlMapping.get("kylin_order_ticket_status.synPay"));
                sqlsDataB.add(orderTicketStatus.getSynOrderObject(strTime, strTime));

                sqls.add(SqlMapping.get("kylin_order_ticket_relation.synPay"));
                Object[] objectC = ObjectUtil.cloneObjectsArray(4);
                objectC[0] = orderTickets.getUpdatedAt();
                objectC[1] = orderTickets.getOrderTicketsId();
                objectC[2] = strTime;
                objectC[3] = strTime;
                sqlsDataC.add(objectC);

                orderTicketEntities.setOrderId(orderTicketData.getOrderTicketsId());
                orderTicketEntities.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT1);
                orderTicketEntities.setUpdatedAt(orderTickets.getUpdatedAt());
                sqls.add(SqlMapping.get("kylin_order_ticket_entities.synPay"));
                sqlsDataD.add(orderTicketEntities.getSynOrderObject(strTime, strTime));

                //vo
                HashMap<String, Object> orderTicketVo = ObjectUtil.cloneHashMapStringAndObject();
                orderTicketVo.put("paymentType", orderTickets.getPaymentType());
                orderTicketVo.put("payCode", orderTickets.getPayCode());
                orderTicketVo.put("timePay", orderTickets.getTimePay());
                orderTicketVo.put("qrCode", orderTickets.getQrCode());
                orderTicketVo.put("status", KylinTableStatusConst.ORDER_STATUS1);
                orderTicketVo.put("payStatus", orderTicketStatus.getStatus());
                orderTicketVo.put("updatedAt", timePay);
                orderTicketVo.put("changeDate", now);
                mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                        Query.query(Criteria.where("orderTicketsId").is(orderTickets.getOrderTicketsId())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(orderTicketVo))
                );


                HashMap<String, Object> orderTicketEntitiesVo = ObjectUtil.cloneHashMapStringAndObject();
                orderTicketEntitiesVo.put("isPayment", KylinTableStatusConst.ENTITIES_IS_PAYMENT1);
                orderTicketEntitiesVo.put("updatedAt", timePay);
                orderTicketEntitiesVo.put("changeDate", now);
                mongoTemplate.getCollection(KylinOrderTicketEntitiesVo.class.getSimpleName()).updateMany(
                        Query.query(Criteria.where("orderId").is(orderTicketData.getOrderTicketsId())).getQueryObject(),
                        ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(orderTicketEntitiesVo))
                );

                queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_ORDER_CREATE.getKey(),
                        SqlMapping.gets(sqls, sqlsDataA, sqlsDataB, sqlsDataC, sqlsDataD));

                //生成vo redis
                dataUtils.delOrderTicketRedis(orderTickets.getOrderTicketsId());
                orderUtils.resetOrderListVo(orderTicketData.getUserId(), 2, orderTicketData.getOrderTicketsId(), null);

                // 发短信
                KylinPerformanceVo performanceData = dataUtils.getPerformanceVo(orderTicketData.getPerformanceId());
                KylinTicketTimesVo ticketTimesData = null;
                KylinTicketVo ticketData = null;
                for (int x = 0; x < performanceData.getTicketTimeList().size(); x++) {
                    KylinTicketTimesVo timeItem = performanceData.getTicketTimeList().get(x);
                    if (timeItem.getTimeId().equals(orderTicketData.getTimeId())) {
                        ticketTimesData = timeItem;
                        for (int y = 0; y < ticketTimesData.getTicketList().size(); y++) {
                            KylinTicketVo ticketItem = ticketTimesData.getTicketList().get(y);
                            if (ticketItem.getTicketsId().equals(orderTicketData.getTicketId())) {
                                ticketData = ticketItem;
                                break;
                            }
                        }
                        break;
                    }
                }

                String time1 = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(ticketData.getUseStart()), DateUtil.Formatter.yyyy_MM_dd);
                String time2 = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceData.getTimeStart()), DateUtil.Formatter.HHmm);

                SmsEnum.ADTemplate adTemplate = null;
                if (orderTicketData.getGetTicketType().equals("express")) {
                    adTemplate = SmsEnum.ADTemplate.SMS_225995308;
                } else if (orderTicketData.getGetTicketType().equals("electronic")) {
                    adTemplate = ticketData.getIsShowCode() == 1 ? SmsEnum.ADTemplate.SMS_225995308 : SmsEnum.ADTemplate.SMS_225995308;
                }

                if (null != adTemplate) {
                    queueUtils.sendMsgByRedis(MQConst.KylinQueue.SMS_NOTICE.getKey(),
                            SmsMessage.builder().setPhone(orderTicketData.getUserMobile())
                                    .setSignName(SmsEnum.ADSignName.M02.getVal())
                                    .setTemplateCode(adTemplate.name())
                                    .setTemplateParam("name", orderTicketData.getPerformanceTitle())
                                    .setTemplateParam("time", time1 + " " + time2).toJson()
                    );
                }
                //模板消息
//                try {
//                    String fieldName = performanceData.getFieldName();
//                    Integer number = orderTicketData.getNumber();
//                    String useTime = orderTicketData.getUseStart();
//                    String performanceName = performanceData.getTitle();
//                    SweetOpenSendMsgParam param = SweetOpenSendMsgParam.getNew();
//                    param.setSendTargetType(1);
//                    param.setTemplateId("glzgM9PLgchlaenpXN5H3N9JDwV69a52R8H6z95hzrA");
//                    TemplateOrderParam templateOrderParam = TemplateOrderParam.getNew();
//                    templateOrderParam.setFirst("您已购票成功");
//                    templateOrderParam.setKeyword1(performanceName);
//                    templateOrderParam.setKeyword2(number.toString());
//                    templateOrderParam.setKeyword3(useTime);
//                    templateOrderParam.setKeyword4(fieldName);
//                    templateOrderParam.setRemark("点击详情 查看更多票务信息");
//                    param.setTemplateData(JSON.toJSONString(templateOrderParam));
//                    param.setJumpType(4);
//                    param.setJumpUrl("http://m.zhengzai.tv/#/order/ticket/orderdetail?id=" + orderTicketData.getOrderTicketsId());
//                    param.setJumpAppletPagePath("/pages/webview?query=orderDetail&id=" + orderTicketData.getOrderTicketsId());
//                    param.setJumpAppletUsePath(false);
//                    param.setPhone(orderTicketData.getUserMobile());
//                    queueUtils.sendMsgByRedis(MQConst.SweetQueue.SWEET_TEMPLATE_MSG.getKey(),
//                            JsonUtils.toJson(param));
//                }catch (Exception e){
//                    log.info("下单消息模版错误",e);
//                }
                //加分
                goblinOrderUtils.integral(orderTicketData.getUserId(), orderTicketData.getPriceActual(), "购买演出:".concat(orderTicketData.getPerformanceTitle()), 1);
                //
//                innerService.reportO(orderTicketData, "摩登天空");
                //大麦回调
                sycDamaiOrder(orderTickets.getOrderTicketsId(), orderTicketData.getIsMember());
            }
            log.info(UserPathDto.setData("订单支付成功回调", syncOrderParam, ""));
            return "success";
        } catch (Exception e) {
            log.error("SYNCE ORDER E = ", e);
            e.printStackTrace();
            return "fail";
        }
    }

    @Override
    public ResponseDto<HashMap<String,Object>> checkOrderResult(String orderId) {
        String uid = CurrentUtil.getCurrentUid();
        KylinOrderTicketVo orderTicketData = dataUtils.getOrderTicketVo(orderId);
        if (orderTicketData == null) {
            return ResponseDto.failure(ErrorMapping.get("20024"));
        } else {
            if (!orderTicketData.getUserId().equals(uid)) {
                ResponseDto.failure(ErrorMapping.get("20003"));
            }
            DragonPayOrderQueryRespDto data = dragonOrdersService.checkOrderStatusByCode(orderTicketData.getPayCode());
            SyncOrderParam syncOrderDtoParam = SyncOrderParam.getNew();
            syncOrderDtoParam.setCode(data.getCode());
            syncOrderDtoParam.setOrderCode(data.getOrderCode());
            syncOrderDtoParam.setPaymentAt(data.getPaymentAt());
            syncOrderDtoParam.setPaymentId(data.getPaymentId());
            syncOrderDtoParam.setPaymentType(data.getPaymentType());
            syncOrderDtoParam.setPrice(data.getPrice());
            syncOrderDtoParam.setStatus(data.getStatus());
            syncOrderDtoParam.setType(data.getType());
            HashMap<String, Object> map = CollectionUtil.mapStringObject();
            map.put("performanceId", orderTicketData.getPerformanceId());
            if (syncOrderDtoParam.getStatus() == 1) {
                //处理订单
                syncOrder(syncOrderDtoParam);
                map.put("status", 1);
            } else {
                map.put("status", 0);
            }
            return ResponseDto.success(map);
        }
    }

    /**
     * 同步 退款大麦订单
     *
     * @param orderId
     * @return
     */
    private boolean refundDamaiOrder(String orderId) {
        try {
            KylinOrderTicketVo orderData = dataUtils.getOrderTicketVo(orderId);
            KylinPerformanceVo vo = dataUtils.getPerformanceVo(orderData.getPerformanceId());
            int isSysDamai = 0;
            for (int x = 0; x < vo.getTicketTimeList().size(); x++) {
                KylinTicketTimesVo timeItem = vo.getTicketTimeList().get(x);
                for (int y = 0; y < timeItem.getTicketList().size(); y++) {
                    KylinTicketVo ticketItem = timeItem.getTicketList().get(y);
                    if (ticketItem.getTicketsId().equals(orderData.getTicketId())) {
                        isSysDamai = ticketItem.getSysDamai();
                        break;
                    }
                }
            }
            if (isSysDamai == 1) {
                List<KylinOrderTicketEntitiesVo> listData = orderData.getEntitiesVoList();
                for (int i = 0; i < listData.size(); i++) {
                    KylinOrderTicketEntitiesVo item = listData.get(i);
                    long ticketTimesKey;
                    if (item.getTicketId().length() > 13) {
                        ticketTimesKey = Long.valueOf(IDGenerator.getDamaiCode(item.getTimeId()));
                    } else {
                        ticketTimesKey = Long.parseLong(item.getTimeId());
                    }

                    long orderTicketEntitiesKey;
                    if (orderData.getIsMember() == 1) {
                        orderTicketEntitiesKey = Long.valueOf(IDGenerator.getDamaiCode(item.getOrderTicketEntitiesId()).toString().concat("010"));
                    } else {
                        orderTicketEntitiesKey = Long.valueOf(IDGenerator.getDamaiCode(item.getOrderTicketEntitiesId()).toString().concat("020"));
                    }
                    taobaoTicketUtils.withdrawDamaiOrder(ticketTimesKey, orderTicketEntitiesKey);
                }
                return true;
            }
            return true;
        } catch (Exception e) {
            log.info("REFUND DAMAI ERROR = {}", e);
            return false;
        }
    }

    /**
     * 同步大麦订单
     *
     * @param orderId
     * @return
     */
    private boolean sycDamaiOrder(String orderId, Integer isMember) {
        try {
            KylinOrderTicketVo orderData = dataUtils.getOrderTicketVo(orderId);
            KylinPerformanceVo vo = dataUtils.getPerformanceVo(orderData.getPerformanceId());
            TaobaoClient client = taobaoTicketUtils.initTaobaoClient();
            int isSysDamai = 0;
            for (int x = 0; x < vo.getTicketTimeList().size(); x++) {
                KylinTicketTimesVo timeItem = vo.getTicketTimeList().get(x);
                for (int y = 0; y < timeItem.getTicketList().size(); y++) {
                    KylinTicketVo ticketItem = timeItem.getTicketList().get(y);
                    if (ticketItem.getTicketsId().equals(orderData.getTicketId())) {
                        isSysDamai = ticketItem.getSysDamai();
                        break;
                    }
                }
            }
            if (isSysDamai == 1) {
                List<KylinOrderTicketEntitiesVo> listData = orderData.getEntitiesVoList();
                AlibabaDamaiMevOpenBatchpushticketRequest req = new AlibabaDamaiMevOpenBatchpushticketRequest();
                List<AlibabaDamaiMevOpenBatchpushticketRequest.ThirdTicketPushOpenParam> list2 = new ArrayList<>();
                for (int i = 0; i < listData.size(); i++) {
                    KylinOrderTicketEntitiesVo item = listData.get(i);
                    AlibabaDamaiMevOpenBatchpushticketRequest.ThirdTicketPushOpenParam obj3 = new AlibabaDamaiMevOpenBatchpushticketRequest.ThirdTicketPushOpenParam();
                    obj3.setUserName(item.getEnterName());//用户名 入场人姓名
                    obj3.setCertificateNo(item.getEnterIdCode());//证件号 入场人身份证
                    obj3.setOrderUserMobile(item.getEnterMobile());//用户手机号 入场人手机号
                    obj3.setCertificateType(item.getEnterType().longValue());//证件内容 入场人证件type
                    obj3.setPayTime(DateUtil.parse(orderData.getTimePay(), "yyyy-MM-dd HH:mm:ss"));//支付时间

                    long ticketTimesKey;
                    if (item.getTicketId().length() > 13) {
                        ticketTimesKey = Long.valueOf(IDGenerator.getDamaiCode(item.getTimeId()));
                    } else {
                        ticketTimesKey = Long.parseLong(item.getTimeId());
                    }

                    long ticketIdKey;
                    if (item.getTicketId().length() > 13) {
                        ticketIdKey = Long.valueOf(IDGenerator.getDamaiCode(item.getTicketId()));
                    } else {
                        ticketIdKey = Long.valueOf(item.getTicketId());
                    }

                    long orderIdKey;
                    if (orderData.getOrderTicketsId().length() > 13) {
                        orderIdKey = Long.valueOf(IDGenerator.getDamaiCode(orderData.getOrderTicketsId()));
                    } else {
                        orderIdKey = Long.valueOf(orderData.getOrderTicketsId());
                    }

                    long orderTicketEntitiesKey;
                    if (item.getOrderTicketEntitiesId().length() > 13) {
                        if (isMember == 1) {
                            orderTicketEntitiesKey = Long.valueOf(IDGenerator.getDamaiCode(item.getOrderTicketEntitiesId()).toString().concat("010"));
                            obj3.setExt("登登登VIP");
                            obj3.setTicketItemId(Long.valueOf(ticketIdKey + "".concat("010")));
                        } else {
                            orderTicketEntitiesKey = Long.valueOf(IDGenerator.getDamaiCode(item.getOrderTicketEntitiesId()).toString().concat("020"));
                            obj3.setExt("");
                            obj3.setTicketItemId(ticketIdKey);
                        }
                    } else {
                        orderTicketEntitiesKey = Long.valueOf(item.getOrderTicketEntitiesId());//票单号 入场人id
                    }
                    obj3.setPerformId(ticketTimesKey);//场次id
                    obj3.setVoucherId(orderTicketEntitiesKey);//票单号 入场人id
                    obj3.setQrCode("http://m.zhengzai.tv?c=" + IDGenerator.ticketQrCode(item.getOrderTicketEntitiesId()));
                    obj3.setOrderId(orderIdKey);//订单id orderId
                    obj3.setMediumType(orderData.getGetTicketType().equals("express") ? 1L : 2L);//票类型 快递 电子
                    obj3.setSupplierSecret(taobaoTicketUtils.getSupplierSecret());
                    obj3.setSystemId(taobaoTicketUtils.getSystemId());
                    obj3.setSeatType(1L);
                    obj3.setTicketType(1L);//票类型
                    list2.add(obj3);
                }
                req.setThirdTicketSetOpenParamList(list2);
                if (list2.size() == 0) {
                    log.info("error data = success");
                    return true;
                } else {
                    AlibabaDamaiMevOpenBatchpushticketResponse rsp = client.execute(req);
                    log.info("success data =" + rsp.getBody());
                    return rsp.getResult().getSuccess();
                }
            }
            return true;
        } catch (Exception e) {
            log.info("error data =", e);
            return false;
        }
    }
}
