package com.yc.ship.module.trade.service.ota.impl;


import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.util.DateUtils;
import com.yc.ship.framework.common.exception.ServerException;
import com.yc.ship.framework.common.pojo.CommonResult;
import com.yc.ship.framework.common.util.collection.CollectionUtils;
import com.yc.ship.framework.tenant.core.context.TenantContextHolder;
import com.yc.ship.module.infra.api.config.ConfigApi;
import com.yc.ship.module.ota.api.OtaDistributorApi;
import com.yc.ship.module.ota.api.dto.DistributorProductRespDTO;
import com.yc.ship.module.ota.api.dto.DistributorRespDTO;
import com.yc.ship.module.product.api.ProductApi;
import com.yc.ship.module.product.api.dto.ProductSaleRuleRespDTO;
import com.yc.ship.module.product.api.dto.ProductSpuRespDTO;
import com.yc.ship.module.trade.api.dto.TradeOrderCreateReqDTO;
import com.yc.ship.module.trade.api.dto.TradeOrderRespDTO;
import com.yc.ship.module.trade.controller.admin.order.vo.order.PayOrderReqVO;
import com.yc.ship.module.trade.controller.admin.order.vo.order.PayOrderRespVO;
import com.yc.ship.module.trade.convert.ota.OtaConvert;
import com.yc.ship.module.trade.dal.dataobject.order.TradeDetailDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderDO;
import com.yc.ship.module.trade.enums.ErrorCodeConstants;
import com.yc.ship.module.trade.enums.PayAccountTypeEnum;
import com.yc.ship.module.trade.enums.PayTypeEnum;
import com.yc.ship.module.trade.enums.ota.OtaConstants;
import com.yc.ship.module.trade.enums.ota.QunarAccountConstant;
import com.yc.ship.module.trade.framework.common.ota.DocTypeHandler;
import com.yc.ship.module.trade.framework.common.ota.qunaer.QunarAuthUtil;
import com.yc.ship.module.trade.framework.common.ota.qunaer.QunarReqStruct;
import com.yc.ship.module.trade.framework.common.ota.qunaer.QunarRequestHeader;
import com.yc.ship.module.trade.framework.common.ota.qunaer.QunarResponseHeader;
import com.yc.ship.module.trade.service.notifylog.NotifyLogService;
import com.yc.ship.module.trade.service.order.TradeOrderRepositoryService;
import com.yc.ship.module.trade.service.order.TradeOrderService;
import com.yc.ship.module.trade.service.ota.QuNaErService;
import com.yc.ship.module.trade.service.pay.TradeOrderPayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Base64Util;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;


/**
 * 去哪儿
 */
@Service(value = "ota_QuNaErService")
@Slf4j
public class QuNaErServiceImpl implements QuNaErService {

    @Resource(name = "taskExecutor")
    private ThreadPoolTaskExecutor taskExecutor;
    @Resource
    private OtaDistributorApi otaDistributorApi;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private ProductApi productApi;
    @Resource
    private TradeOrderService tradeOrderService;
    @Resource
    private TradeOrderRepositoryService tradeOrderRepositoryService;
    @Resource
    private ConfigApi configApi;
    @Resource
    private TradeOrderPayService tradeOrderPayService;
    @Resource
    private NotifyLogService notifyLogService;
    @Resource
    private QuNaErService quNaErService;



    /**
     * 去哪儿-请求
     *
     * @param tenantId
     * @param path
     * @param request
     * @param jsonStr
     * @return
     */
    @Override
    public String doRequest(Long tenantId, String path, HttpServletRequest request, String jsonStr) {
        //心跳监测
        if ("testAlive".equals(path)) {
            log.info("[心跳监测返回String]:alive");
            return "alive";
        }
        if (StringUtils.isEmpty(jsonStr)) {
            log.info("[收到了空请求，直接返回空字符串]");
            return "";
        }
        DistributorRespDTO distributor;
        QunarReqStruct reqObject;
        // 返回
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try {
            TenantContextHolder.setTenantId(tenantId);
            TenantContextHolder.setIgnore(false);
            //1、获取分销商信息
            distributor = this.getServer();

            //2、拆分数据
            reqObject = QunarAuthUtil.handleRequest(JSONUtil.parseObj(jsonStr));

            //3、认证
            if (!QunarAuthUtil.checkSign(reqObject, distributor.getSecret())) {
                log.error("去哪儿：sign校验失败.");
                throw new ServerException(1001,"sign校验失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
            log.info("去哪儿：系统错误." + e.getMessage());
            resultMap.put(OtaConstants.OTA_STATUS, OtaConstants.SYSTEM_ERROR);
            resultMap.put(OtaConstants.MSG, "系统错误");
            return null;
//            return resultMap.toString();
        }

        try {
            String key = "[ota-in]" + distributor.getId();
            RLock lock = redissonClient.getLock(key);
            try {
                if (lock.tryLock(30, TimeUnit.SECONDS)) {
                    try {

                        if ("createOrderForBeforePaySync".equals(path)) {
                            //订单创建 封装数据
                            log.info("[下单请求参数]" + resultMap);
                            return createOrder( request, reqObject, distributor);
                        } else if ("getOrderByQunar".equals(path)) {
                            //订单校验
                            return orderCheck( request, reqObject, distributor);
                        } else if ("payOrderForBeforePaySync".equals(path)) {
                            //订单支付
                            return orderPay( request, reqObject, distributor);
                        } else if ("applyOrderRefundByUser".equals(path)) {
                            //退票申请
                            return applyOrderRefund(request, reqObject, distributor);
                        } else if ("queryOrderInfoByQunar".equals(path)) {
                            //订单查询
                            return qunarOrderQueryReturn( request, reqObject, distributor);
                        } else if ("noticeOrderRefundedByQunar".equals(path)) {
                            //去哪儿：真正退款后的通知 noticeOrderRefundedByQunar[去哪儿->我方]
                            return noticeOrderRefund( request, reqObject, distributor);
                        } else if ("getProductByQunar".equals(path)) {
                            //获取产品信息
                            // 设置分销商  Redis数据分流
                            return queryProduct( request, reqObject, distributor);
                        } else if ("sendOrderEticket".equals(path)) {
                            // Resolver中传递的订单参数
                            return sendOrderEticket( request, reqObject, distributor);
                        } else {
                            // 方法名称错误
                            resultMap.put(OtaConstants.OTA_STATUS, OtaConstants.SYSTEM_ERROR);
                            resultMap.put(OtaConstants.MSG, "方法名错误");
                            return resultMap.toString();
                        }

                    } catch (Exception ex) {
                        log.debug("执行异常");
                        throw ex;
                    } finally {
                        if (lock != null) {
                            lock.unlock();
                        }
                    }
                } else {
                    log.debug("未获取到锁");
                    throw exception(ErrorCodeConstants.OTA_REQUEST_TIMEOUT);
                }
            } catch (Exception ex) {
                throw exception(ErrorCodeConstants.OTA_REQUEST_FAIL);
            }

        } catch (Exception e) {
            resultMap = new HashMap<String, Object>();
            resultMap.put(OtaConstants.OTA_STATUS, OtaConstants.SYSTEM_ERROR);
            resultMap.put(OtaConstants.MSG, "系统错误");
            return null;
        }
    }

    /**
     * 订单校验
     */
    String orderCheck(HttpServletRequest reques, QunarReqStruct reqObject, DistributorRespDTO distributor) {
        String code = "";
        String describe = "";

        JSONObject object = new JSONObject();
        TradeOrderDO order = null;
        String status = "PREPAY_ORDER_NOT_PAYED";
        String qrcode = "";
        String url = distributor.getServerUrl() + "getQrcode.html?qrCode=";
        String useQuantity = "0";

        try {
		/*partnerorderId	orderInfo	订单ID	是	供应商的订单ID
        orderStatus	orderInfo	订单状态	是	供应商的订单状态
		PREPAY_ORDER_BOOK_FAILED 预付：预订失败
		PREPAY_ORDER_NOT_PAYED 预付：预订成功，待支付
		CASHPAY_ORDER_PRINT_FAILED 现付：出票失败
		CASHPAY_ORDER_PRINT_SUCCESS 现付：出票成功
		eticketNo	orderInfo	入园凭证值（现付）	否	如果供应商可以提供则必传，排序提升最大因素*/
            Document doc = DocumentHelper.parseText(reqObject.getXmlData());
            //取的根元素
            Element root = doc.getRootElement();
            // 获取请求头节点
            //QunarRequestHeader hdClass = getRequestHeader(root);
            // 获取body数据
            Element bodyNode = root.element("body");
            String orderNo = bodyNode.elementText("partnerOrderId");
            if (StringUtils.isEmpty(orderNo)) {
                Element orderNode = bodyNode.element("orderInfo");
                orderNo = orderNode.elementText("partnerorderId");
            }
            //4、查询订单信息
             order = tradeOrderRepositoryService.getOrderByNo(orderNo);

            JSONObject sendJson = new JSONObject();

            // 参数传递
            sendJson.put(OtaConstants.ORDER_INFO, order);
            //sendJson.put(OtaConstants.VISTORS, map.get(OtaConstants.VISTORS));
            sendJson.put(OtaConstants.VISTORS, "");

            // 设置Send 无需向票务请求
            sendJson.put(OtaConstants.CONSUMER_ID, "");
            sendJson.put(OtaConstants.TARGEY_URL, "");

            if (null == order) {
                throw new ServerException(1002,"校验失败,订单不存在," + sendJson.getStr(OtaConstants.MSG));
            }
            // 查询成功
            code = "1000";
            describe = "校验成功," + sendJson.getStr(OtaConstants.MSG);
            if (order.getOrderStatus() == 0) {
				/*PREPAY_ORDER_INIT 预付：初始订单
				PREPAY_ORDER_BOOK_FAILED 预付：预订失败
				PREPAY_ORDER_NOT_PAYED 预付：预订成功，待支付
				PREPAY_ORDER_CANCEL 预付：订单已取消
				PREPAY_ORDER_PRINTING 预付：已付款，出票中
				PREPAY_ORDER_PRINT_FAILED 预付：出票失败
				PREPAY_ORDER_PRINT_SUCCESS 预付：出票成功*/
                status = "PREPAY_ORDER_NOT_PAYED";//预付：预订成功，待支付
                //}else if(order.getOrderStatus() == ScenicConstrt.TICKET_NOT_PAY){
            } else if (order.getOrderStatus() == 2) {// 已返码、未验证
                status = "PREPAY_ORDER_PRINT_SUCCESS";// 预付：出票成功
                qrcode = url + order.getOrderNo();//getQrcode();
            } else if (null != order.getOrderStatus() && order.getOrderStatus() == 4) {// 已使用
                List<TradeDetailDO> detailDOList = tradeOrderRepositoryService.queryDetailByOrderId(order.getId());
                useQuantity = String.valueOf(detailDOList.size());
                qrcode = url + order.getOrderNo();//getQrcode();
            } else if (null != order.getOrderStatus() && order.getOrderStatus() == 5) {// 已取消/退款
                status = "PREPAY_ORDER_CANCEL";
            } else if (null != order.getOrderStatus() && order.getOrderStatus() == 6) {// 已过期
                qrcode = url + order.getOrderNo();//getQrcode();
            }

        } catch (ServerException ex) {
            log.error("分销", "去哪儿查询失败", "GetOrderByQunar", ex.getMessage());
            code = "20033";
            describe = ex.getMessage();
        } catch (Exception e) {
            log.error("分销", "去哪儿查询失败", "GetOrderByQunar", e.getMessage());
            code = "20033";
            describe = "去哪儿查询失败";
        }

        QunarResponseHeader head = getHeader("GetOrderByQunar", code, describe);

        String data = Base64Util.encode(responseReturn(head, null, order, status, qrcode, useQuantity));
        object.put("data", data);
        object.put("securityType", "MD5");
        object.put("signed", QunarAuthUtil.generateSign(data, distributor.getSecret()));
        return object.toString();
    }

    /**
     * 重新发码
     */
    String sendOrderEticket(HttpServletRequest reques, QunarReqStruct reqObject, DistributorRespDTO distributor) {
        String code;
        String describe;
        TradeOrderDO order = null;
        JSONObject object = new JSONObject();
        try {

            Document doc = DocumentHelper.parseText(reqObject.getXmlData());
            //取的根元素
            Element root = doc.getRootElement();
            //LogUtil.appLog.info(root.getName());//输出根元素的名称（测试）

            // 获取body数据
            Element bodyNode = root.element("body");

            Element orderInfo = bodyNode.element("orderInfo");
            String orderNo = orderInfo.elementText("partnerorderId");
            String phoneNumber = orderInfo.elementText("phoneNumber");

            //4、查询订单信息
            order = tradeOrderRepositoryService.getOrderByNo(orderNo);
            if (null == order) {
                throw new ServerException(1001,"校验失败,订单不存在。");
            }
            // 查询成功
            code = "1000";
            describe = "校验成功。";

        } catch (ServerException ex) {
            log.error("分销", "去哪儿查询失败", "getOrderByQunar", ex.getMessage());
            code = "20033";
            describe = ex.getMessage();
        } catch (Exception e) {
            log.error("分销", "去哪儿查询失败", "getOrderByQunar", e.getMessage());
            code = "20033";
            describe = "去哪儿查询失败";
        }
        QunarResponseHeader head = getHeader("GetOrderByQunar", code, describe);

        String data = Base64Util.encode(responseReturn(head, null, order, "", "", ""));
        object.put("data", data);
        object.put("securityType", "MD5");
        object.put("signed", QunarAuthUtil.generateSign(data, distributor.getSecret()));
        return object.toString();
    }

    /**
     * 去哪儿和去哪儿创建订单:只创建订单、未支付 1
     */
    String createOrder(HttpServletRequest request, QunarReqStruct reqObject, DistributorRespDTO server) {
        RLock lock = null;
        String code = "";
        String describe = "";
        String orderStatus = "";
        JSONObject object = new JSONObject();
        TradeOrderDO tradeOrderDO = new TradeOrderDO();
        String orderNo ="";
        try {
            //4、封装下单
            TradeOrderCreateReqDTO order = this.parseOrder(reqObject, server);
            String key = order.getExternalOrderNo() + server.getId() ;
            lock = redissonClient.getLock(key);
            if (lock.tryLock(10, TimeUnit.SECONDS)) {
                //5、订单创建 不支付
                Map<String, Object> resMap = quNaErService.savePayOrder(order.getExternalOrderNo(), order, false, server);
                boolean isExist = (boolean) resMap.get("isExist");
                orderNo = MapUtil.getStr(resMap,"orderNo") ;
                tradeOrderDO.setOrderNo(orderNo);
                code = "1000";
                if (!isExist) {
                    describe = "创建订单成功！";
                    orderStatus = "PREPAY_ORDER_NOT_PAYED";
                } else {
                    describe = "订单已存在";
                    orderStatus = "PREPAY_ORDER_NOT_PAYED";
                }
            } else {
                log.info("去哪儿：重复提交");
                throw new ServerException(1011,"重复提交");
            }

        } catch (ServerException ex) {
            log.error("分销", "去哪儿下单", "createOrder", ex.getMessage());
            code = "20033";
            describe = ex.getMessage();
            orderStatus = "PREPAY_ORDER_BOOK_FAILED";
        } catch (Exception e) {
            log.error("分销", "去哪儿下单失败", "getOrderByQunar", e.getMessage());
            code = "20033";
            describe = "下单失败";
            orderStatus = "PREPAY_ORDER_BOOK_FAILED";
        } finally {
            if (lock != null) {
                lock.unlock();
            }
        }
        QunarResponseHeader head = getHeader("CreateOrderForBeforePaySync", code, describe);

        //voucherCode 短信凭证
        String data = Base64Util.encode(responseReturn(head, null, tradeOrderDO, orderStatus, orderNo, "0"));
        object.put("data", data);
        object.put("securityType", "MD5");
        object.put("signed", QunarAuthUtil.generateSign(data, server.getSecret()));
        return object.toString();
    }

    /**
     * 封装下单
     */
    private TradeOrderCreateReqDTO parseOrder(QunarReqStruct reqObject, DistributorRespDTO  distributor) throws DocumentException {
        Long distributorId = distributor.getId();

        Document doc = DocumentHelper.parseText(reqObject.getXmlData());
        //取的根元素
        Element root = doc.getRootElement();
        // 获取请求头节点
        //QunarRequestHeader hdClass = getRequestHeader(root);
        // 获取body数据
        Element bodyNode = root.element("body");
        TradeOrderCreateReqDTO order = new TradeOrderCreateReqDTO();
        List<TradeOrderCreateReqDTO.OrderItem> itemlList = new ArrayList<>();
        List<TradeOrderCreateReqDTO.OrderDetail> detailList = new ArrayList<>();
        if (null != bodyNode) {
            Element orderNode = bodyNode.element("orderInfo");
            order.setExternalOrderNo(orderNode.elementText("orderId"));

            /** 产品信息*/
            Element product = orderNode.element("product");
            String useDate = product.elementText("visitDate");
            Date travelDate = DateUtil.parse(useDate, "yyyy-MM-dd");
            String productId = product.elementText("resourceId");

            TradeOrderCreateReqDTO.OrderProperty orderProperty = OtaConvert.INSTANCE.convert(distributorId.toString(), distributor.getName());
            order.setOrderProperty(orderProperty);
            order.setTravelDate(travelDate);

            String ticketsCount = orderNode.elementText("orderQuantity");

            //2、查询产品
            ProductSpuRespDTO productSpuRespDTO = productApi.getProduct(Long.parseLong(productId)).getCheckedData();
            DistributorProductRespDTO distributorProduct = otaDistributorApi.getDistributorProductByProductAndDistributor(Long.parseLong(productId), distributorId).getCheckedData();

            if (null == distributorProduct || distributorProduct.getIsUse() != 1) {
                log.error("去哪儿：创建订单：产品不存在！id=" + productId);
                throw new ServerException(1005,"产品不存在！");
            }
            /** 取票人、订票人信息*/
            Element contactPerson = orderNode.element("contactPerson");
            //联系人
            TradeOrderCreateReqDTO.OrderUser orderUser = new TradeOrderCreateReqDTO.OrderUser();
            orderUser.setCredentialType(0);
            orderUser.setMobile(contactPerson.elementText("mobile"));
            orderUser.setContactName(contactPerson.elementText("name"));
            order.setOrderUser(orderUser);
            // 单位:元
            BigDecimal ticketPrice = distributorProduct.getSalePrice();
            if (ticketPrice != null) {
                BigDecimal orderAmt = ticketPrice.multiply(new BigDecimal(ticketsCount));
                order.setAmount(orderAmt);
                order.setPayAmount(orderAmt);
            }
            TradeOrderCreateReqDTO.OrderItem orderItem = new TradeOrderCreateReqDTO.OrderItem();
            orderItem.setProductId(productId);
            orderItem.setUseDate(travelDate);
            List<DistributorProductRespDTO.DistributorProjectDTO> distributorProjectDTOS = otaDistributorApi.getProductByDistributor(distributor.getId(),distributorProduct.getProductId(),distributorProduct.getId()).getCheckedData();
            TradeOrderCreateReqDTO.OrderDetail orderDetail = OtaConvert.INSTANCE.convert(distributorProduct, Integer.parseInt(ticketsCount),distributorProjectDTOS,ticketPrice);
            //orderUser.setCardNo(body.getString("idCard"));
            // 姓名拼音contactPerson.elementText("namePinyin");
            // 邮箱contactPerson.elementText("email");
            // 省contactPerson.elementText("province");
            // 市contactPerson.elementText("city");
            // 区contactPerson.elementText("area");
            // 详细地址contactPerson.elementText("address");
            // 邮编contactPerson.elementText("zipCode");

            List<TradeOrderCreateReqDTO.Visitor> visitors = new ArrayList<>();

            Element visitPerson = (Element) orderNode.element("visitPerson");
            List vistors = visitPerson.elements("person");

            // 售票规则验证购票方式(1:实名购票，3：无需实名)
            ProductSaleRuleRespDTO saleRule = productSpuRespDTO.getProductSaleRule();
            if (saleRule != null && saleRule.getIsLimitType() == 1 && CollUtil.isNotEmpty(vistors)) {
                for (Object obj : vistors) {
                    Element visObj = (Element) obj;

                    if (StringUtils.isEmpty(visObj.elementText("credentials"))) {
                        log.error("去哪儿：创建订单：游客身份证为空不能下单.");
                        throw new ServerException(1006,"游客身份证为空不能下单！");
                    }

                    TradeOrderCreateReqDTO.Visitor visitor = new TradeOrderCreateReqDTO.Visitor();
                    visitor.setCredentialNo(visObj.elementText("credentials"));
                    //证件类型
                    String credentialsType = visObj.elementText("credentialsType");
                    credentialsType = DocTypeHandler.changeDocType(OtaConstants.SYS_PRI_KEY_QUNAR, credentialsType);
                    visitor.setCredentialType(Integer.valueOf(credentialsType));
                    visitor.setName(visObj.elementText("name"));
                    visitors.add(visitor);
                }
            }else {
                // 非实名制购票
                if (saleRule != null && saleRule.getIsLimitType() == 0) {
                    visitors = OtaConvert.INSTANCE.convertOtaVisitorList(Integer.parseInt(ticketsCount));
                }
            }
            orderDetail.setVisitorList(visitors);
            detailList.add(orderDetail);
            orderItem.setDetailList(detailList);
            itemlList.add(orderItem);
            order.setItemlList(itemlList);
        }
        return order;
    }

    /**
     * 带事务的创建订单
     *
     * @param otaOrderNo
     * @param order
     * @param isPay
     * @param distributor
     * @return
     */
    @Override
    public Map<String, Object> savePayOrder(String otaOrderNo, TradeOrderCreateReqDTO order, boolean isPay, DistributorRespDTO distributor) {
        Map<String, Object> resMap = new HashMap<>();
        //重复验证
        TradeOrderDO orderDB = tradeOrderRepositoryService.getOrderByOtaAndExternalOrderNo(otaOrderNo, order.getOrderProperty().getSourceId());
        if (orderDB == null) {
            //创建订单
            CommonResult<TradeOrderRespDTO> result = tradeOrderService.createOrder(order);
            if (result.isError()) {
               throw exception(1009,"创建订单失败");
            }
            TradeOrderRespDTO tradeOrderRespDTO = result.getCheckedData();
            //支付订单

            //验证分销商金额是否足够，在创建订单的时候计算订单总额，如果金额不够抛出异常 事务回滚。
            if (isPay) {
                PayOrderReqVO payOrderReqVO = new PayOrderReqVO();
                payOrderReqVO.setAccountId(distributor.getId().toString());
                //ota
                payOrderReqVO.setAccountType(PayAccountTypeEnum.OTA.getType());

                payOrderReqVO.setOrderId(tradeOrderRespDTO.getOrderId());
                payOrderReqVO.setPayAmount(order.getPayAmount());
                //预付款>授信
                Object[] payTypes = distributor.getPayType().split(",");
                if (CollectionUtils.containsAny("1", payTypes)) {
                    payOrderReqVO.setPayType(PayTypeEnum.ADVANCE_PAYMENT.getType());
                } else if (CollectionUtils.containsAny("2", payTypes)) {
                    payOrderReqVO.setPayType(PayTypeEnum.CREDIT_GRANTING.getType());
                }
                //统一支付、扣款、修改订单状态
                CommonResult<PayOrderRespVO> payResult = tradeOrderPayService.payOrder(payOrderReqVO);
                if (payResult.isError()) {
                     throw exception(1010,"支付失败");
                }
            }

            /*//还回订单创建成功
            JSONObject responseBody = new JSONObject();
            responseBody.put("partnerOrderId", MapUtils.getString(map,"orderId"));
            //合作方入园辅助码
            responseBody.put("partnerCode", MapUtils.getString(map,"getTicketNo"));
            //合作二维码链接地址
            responseBody.put("partnerQRCodeAddress", "");
            //场次信息
            responseBody.put("partnerAreaInfo", "");
            */
            resMap.put("orderNo", tradeOrderRespDTO.getOrderNo());
            resMap.put("isExist", false);
        } else {
            resMap.put("orderNo", orderDB.getOrderNo());
            resMap.put("isExist", true);
        }
        return resMap;
    }

    /**
     * 订单支付：美团和去哪儿的创建订单和支付是分开的，该方法只有美团或者去哪儿在调用。 1
     */
    String orderPay(HttpServletRequest request, QunarReqStruct reqObject, DistributorRespDTO distributor) {
        String code = "";
        String describe = "";
        String orderStatus = "";
        JSONObject object = new JSONObject();
        TradeOrderDO order = new TradeOrderDO();
        try {
            //4、查询我方订单信息
            Document doc = DocumentHelper.parseText(reqObject.getXmlData());
            //取的根元素
            Element root = doc.getRootElement();
            // 获取请求头节点
            //QunarRequestHeader hdClass = getRequestHeader(root);
            // 获取body数据
            Element bodyNode = root.element("body");
            Element orderInfo = bodyNode.element("orderInfo");
            String orderNo = orderInfo.elementText("partnerOrderId");//订单号

            order = tradeOrderRepositoryService.getOrderByNo( orderNo);
            // 订单号不存在或已过期
            if (order == null || order.getOrderStatus() == 6) {
                throw new ServerException(1008,"订单号不存在或已过期");
            }
            // 支付成功
            if (0 != order.getOrderStatus()) {
                describe = "已支付！";
            } else {
                describe = "支付成功！";
                //5、增加分销商交易记录、扣除分销商余额
//                service.orderTradeServer(server,order.getOrderAmount(), OtaServerEntity.TRADETYPESUBTRACT, order.getId(), "去哪儿-下单");
                //6、支付
                //支付订单
                PayOrderReqVO payOrderReqVO = new PayOrderReqVO();
                payOrderReqVO.setAccountId(distributor.getId().toString());
                //ota
                payOrderReqVO.setAccountType(PayAccountTypeEnum.OTA.getType());

                payOrderReqVO.setOrderId(order.getId());
                payOrderReqVO.setPayAmount(order.getPayAmount());
                //预付款>授信
                Object[] payTypes = distributor.getPayType().split(",");
                if (CollectionUtils.containsAny("1", payTypes)) {
                    payOrderReqVO.setPayType(PayTypeEnum.ADVANCE_PAYMENT.getType());
                } else if (CollectionUtils.containsAny("2", payTypes)) {
                    payOrderReqVO.setPayType(PayTypeEnum.CREDIT_GRANTING.getType());
                }
                //统一支付、扣款、修改订单状态
                CommonResult<PayOrderRespVO> payResult = tradeOrderPayService.payOrder(payOrderReqVO);
                if (payResult.isError()) {
                    describe = "支付失败！";
                }
            }
            code = "1000";
            orderStatus = "PREPAY_ORDER_PRINT_SUCCESS";
        } catch (ServerException ex) {
            log.error("分销", "去哪儿支付", "PayOrderForBeforePaySync", ex.getMessage());
            code = "20033";
            describe = ex.getMessage();
            orderStatus = "PREPAY_ORDER_PRINT_FAILED";
        } catch (Exception e) {
            log.error("分销", "去哪儿支付失败", "PayOrderForBeforePaySync", e.getMessage());
            code = "20033";
            describe = "支付失败";
            orderStatus = "PREPAY_ORDER_PRINT_FAILED";
        }
        QunarResponseHeader head = getHeader("PayOrderForBeforePaySync", code, describe);
        //voucherCode 短信凭证
        String data = Base64Util.encode(responseReturn(head, null, order, orderStatus, order.getOrderNo(), "0"));
        object.put("data", data);
        object.put("securityType", "MD5");
        object.put("signed", QunarAuthUtil.generateSign(data, distributor.getSecret()));
        return object.toString();
    }

    /**
     * 去哪儿申请退款：去哪儿异步返回用户退款申请结果
     */
    String applyOrderRefund(HttpServletRequest request, QunarReqStruct reqObject, DistributorRespDTO distributor) {
        String code = "15011";
        String describe = "";
        String refundSeq = "";
        String refundQuantity = "";
        JSONObject object = new JSONObject();
        TradeOrderDO order = new TradeOrderDO();

        RLock lock = null;
//        try {
//		/*partnerorderId	orderInfo	订单ID	是	供应商的订单ID
//        orderStatus	orderInfo	订单状态	是	供应商的订单状态
//		PREPAY_ORDER_BOOK_FAILED 预付：预订失败
//		PREPAY_ORDER_NOT_PAYED 预付：预订成功，待支付
//		CASHPAY_ORDER_PRINT_FAILED 现付：出票失败
//		CASHPAY_ORDER_PRINT_SUCCESS 现付：出票成功
//		eticketNo	orderInfo	入园凭证值（现付）	否	如果供应商可以提供则必传，排序提升最大因素*/
//
//            //4、取订单号
//            Document doc = DocumentHelper.parseText(reqObject.getXmlData());
//            //取的根元素
//            Element root = doc.getRootElement();
//            // 获取请求头节点
//            //QunarRequestHeader hdClass = getRequestHeader(root);
//            // 获取body数据
//            Element bodyNode = root.element("body");
//            /**请求参数获取*/
//            /*partnerorderId	orderInfo	订单ID	是	供应商生成的订单ID
//            refundSeq	orderInfo	退款流水号	是	退款流水号，用于标记每一笔退款，由qunar定义
//            orderPrice	orderInfo	订单金额	是	原始订单金额
//            单位：分
//            orderQuantity	orderInfo	订单票数	是	原始订单票数
//            refundQuantity	orderInfo	退款票数	是	退款票数
//            refundReason	orderInfo	退款原因	否	退款原因
//            refundExplain	orderInfo	退款说明	否	退款说明
//            refundCharge	orderInfo	退款手续费	否	订单退款的手续费总额
//            单位：分*/
//            Element orderInfo = bodyNode.element("orderInfo");
//            String orderNo = orderInfo.elementText("partnerorderId");
//            refundSeq = orderInfo.elementText("refundSeq");
//            String orderPrice = orderInfo.elementText("orderPrice");
//            String orderQuantity = orderInfo.elementText("orderQuantity");
//            refundQuantity = orderInfo.elementText("refundQuantity");
//            String refundReason = orderInfo.elementText("refundReason");
//            String refundExplain = orderInfo.elementText("refundExplain");
//            String refundCharge = orderInfo.elementText("refundCharge");
//            //4、查询订单信息
//            order = tradeOrderRepositoryService.getOrderByNo(orderNo);
//            if (order == null) {
//                throw new ServerException(1007,"订单不存在！");
//            }
//            // 查询退款批次
//            RefundEntity refund = refundService.getRefundByOrderId(order.getId());
//            if (refund != null) {
//                // throw new ServerException("退款申请已存在！");
//                describe = "订单已退款";
//                QunarResponseHeader head = getHeader("ApplyOrderRefundByUser", code, describe);
//
//                String data = Base64Util.encode(responseReturn(head, describe, order, "", "", ""));
//                object.put("data", data);
//                object.put("securityType", "MD5");
//                object.put("signed", QunarAuthUtil.generateSign(data, distributor.getSecret()));
//                return object.toString();
//            }
//            lock = redissonClient.getLock(orderNo + distributor.getId() + tenantId);
//            if (lock.tryLock(10, TimeUnit.SECONDS)) {
//                //退单申请
//                RefundTicketForm ticketForm = refundService.refundApply(orderNo, order.getExternalOrderNo(), Integer.valueOf(refundQuantity), 0, null);
//                if (ticketForm != null && StringUtils.isNotEmpty(ticketForm.getBatchId())) {
//                    refundService.orderRefund(request, ticketForm);
//                    code = "1000";
//                    describe = "退款申请成功";
//                    noticeOrderRefundApproveResult(order, distributor, refundSeq, refundQuantity, "同意退款", "APPROVE");
//                } else {
//                    describe = "退款申请失败"; // 退款申请失败
//                    noticeOrderRefundApproveResult(order, distributor, refundSeq, refundQuantity, "拒绝退款", "REJECT");
//                }
//            } else {
//                throw new ServerException("重复提交！");
//            }
//        } catch (ServerException ex) {
//            log.error("分销", "去哪儿退单失败", "ApplyOrderRefundByUser", ex.getMessage());
//            describe = "退款申请失败," + ex.getMessage();
//            noticeOrderRefundApproveResult(order, distributor, refundSeq, refundQuantity, "拒绝退款", "REJECT");
//        } catch (Exception e) {
//            log.error("分销", "去哪儿退单失败", "ApplyOrderRefundByUser", e.getMessage());
//            describe = "去哪儿退单失败";
//        } finally {
//            if (lock !=null && lock.isLocked() && lock.isHeldByCurrentThread()) {
//                lock.unlock();
//            }
//        }
        QunarResponseHeader head = getHeader("ApplyOrderRefundByUser", code, describe);

        String data = Base64Util.encode(responseReturn(head, describe, order, "", "", ""));
        object.put("data", data);
        object.put("securityType", "MD5");
        object.put("signed", QunarAuthUtil.generateSign(data, distributor.getSecret()));
        return object.toString();
    }

//    /**
//     * 供应商通知用户申请退款结果
//     *
//     * @param order
//     * @param distributor
//     * @param refundSeq
//     * @param refundQuantity
//     * @param mark
//     * @param refundResult
//     */
//    public void noticeOrderRefundApproveResult(OrderEntity order, OtaServerEntity distributor, String refundSeq, String refundQuantity, String mark, String refundResult) {
//        // 同意退款
//        if (refundResult.equals("APPROVE")) {
//            taskExecutor.execute(new Runnable() {
//                @Override
//                public void run() {
//                    noticeOrderRefundApprove(order, distributor, refundSeq, refundQuantity, mark, refundResult);
//                }
//            });
//            // 拒绝退款
//        } else {
//            noticeOrderRefundApprove(order, distributor, refundSeq, refundQuantity, mark, refundResult);
//        }
//    }
//
//    public void noticeOrderRefundApprove(OrderEntity order, OtaServerEntity distributor, String refundSeq, String refundQuantity, String mark, String refundResult) {
//        try {
//            if (refundResult.equals("APPROVE")) {
//                Thread.sleep(30000);// 30秒后发送通知
//            }
//            Map<String, Object> ticketParam = new HashMap<>();
//            ticketParam.put("orderId", order.getId());
//            // Map<String, Object> ticketMap = ticketService.queryCountByOrderId(ticketParam);
//            // int refundCount = MapUtils.getIntValue(ticketMap, "refundCount");
//            String sendUrl = "";
//            String param = "";
//
//            JSONObject jsonObject = new JSONObject();
//            QunarRequestHeader head = new QunarRequestHeader(QunarAccountConstant.application,
//                    QunarAccountConstant.processor, QunarAccountConstant.version,
//                    "NoticeOrderRefundApproveResult",
//                    QunarAccountConstant.createUser, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), distributor.getAppid());
//
//            Document doc = DocumentHelper.createDocument();
//            Element root = doc.addElement("request", QunarAccountConstant.xmlRequestSchema);
//
//            /** 设置头部*/
//            root = setRequestHeader(head, root);
//
//            /** 设置body*/
//            Element body = root.addElement("body");
//            body.addAttribute("xsi:type", head.getBodyType());
//            body.addAttribute("xmlns:xsi", QunarAccountConstant.bodyXsi);
//            Element orderInfo = body.addElement("orderInfo");
//                        /*partnerorderId	orderInfo	订单ID	是	供应商生成的订单ID
//                        refundSeq	orderInfo	退款流水号	是	退款流水号，用于标记每一笔退款，由qunar定义
//                        orderQuantity	orderInfo	订单票数	否	原始订单票数
//                        refundQuantity	orderInfo	退款票数	当refundResult=APPROVE时必传	退款票数
//                        refundJudgeMark	orderInfo	退款审核意见	否	退款审核意见
//                        refundResult	orderInfo	退款审核结果	是	退款审核结果
//                        APPROVE：同意退款
//                        REJECT：拒绝退款*/
//
//            orderInfo.addElement("partnerorderId").setText(order.getOrderNo());
//            orderInfo.addElement("refundSeq").setText(refundSeq);
//            orderInfo.addElement("orderQuantity").setText(String.valueOf(order.getTotalTicket()));
//            orderInfo.addElement("refundQuantity").setText(String.valueOf(Integer.valueOf(refundQuantity)));
//
//
//            orderInfo.addElement("refundJudgeMark").setText(mark);
//            orderInfo.addElement("refundResult").setText(refundResult);
//
//            String signData = Base64Util.encode(root.asXML());
//            jsonObject.put("signed", QunarAuthUtil.generateSign(signData, distributor.getSecret()));
//            jsonObject.put("data", signData);
//            jsonObject.put("securityType", "MD5");
//            String serverUrl = distributor.getServerUrl();
//            sendUrl = serverUrl + "?method=noticeOrderRefundApproveResult";
//            Map<String, String> headMap = new HashMap<>();
//            headMap.put("Content-type", "application/x-www-form-urlencoded");
//            // 供应商通知用户申请退款结果
//            param = "method=" + toFirstLowerCase("noticeOrderRefundApproveResult") + "&requestParam=" + jsonObject.toString();
//            log.info("去哪儿：供应商通知用户申请退款结果参数： orderNo=" + order.getOrderNo() + ";param=" + param);
//            String discardJsonStr = SendHttps.sendPost(sendUrl, param, headMap);
//            QunarReqStruct req = QunarAuthUtil.handleRequest(JSONObject.parseObject(discardJsonStr));
//            Map<String, String> result = new HashMap<String, String>(2);
//
//            Document docR = DocumentHelper.parseText(req.getXmlData());
//            //取的根元素
//            Element rootR = docR.getRootElement();
//            //LogUtil.appLog.info(root.getName());//输出根元素的名称（测试）
//
//            // 获取请求头节点
//            QunarResponseHeader hdClass = getResponseHeader(rootR);
//            result.put("code", hdClass.getCode());
//            result.put("describe", hdClass.getDescribe());
//
//            // 获取body数据
//            Element bodyNode = (Element) root.element("body");
//            result.put("message", bodyNode.elementText("message"));
//            String status = result.get("code");
//            String describe = result.get("describe");
//            String message = result.get("message");
//            // 1000成功 其他均为失败
//            if ("1000".equals(status)) {
//                log.info("去哪儿：供应商通知用户申请退款结果： message=" + message + "describe=" + describe);
//            } else {
//                log.info("去哪儿：供应商通知用户申请退款结果： message=" + message + "describe=" + describe);
//            }
//        } catch (Exception e) {
//            log.info("去哪儿：供应商通知用户申请退款结果：通知失败." + e);
//        }
//    }

    public static QunarResponseHeader getResponseHeader(Element root)
            throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        // 获取请求头节点
        Element headerNode = (Element) root.element("header");

        QunarResponseHeader hdClass = new QunarResponseHeader();
        Field[] properties = hdClass.getClass().getDeclaredFields();//获得实例的属性
        //实例的set方法
        Method setmeth;
        for (int j = 0; j < properties.length; j++) {//遍历所有孙子节点
            //实例的set方法
            setmeth = hdClass.getClass().getMethod(
                    "set" + properties[j].getName().substring(0, 1).toUpperCase()
                            + properties[j].getName().substring(1), properties[j].getType());
            //properties[j].getType()为set方法入口参数的参数类型(Class类型)
            //String name = properties[j].getName();
            //Element eleddd =  (Element) headerNode.element(name);
            //String text = eleddd.getText();
            setmeth.invoke(hdClass, headerNode.element(properties[j].getName()).getText());//将对应节点的值存入
        }
        return hdClass;
    }

    /**
     * 订单退款
     */
    String noticeOrderRefund(HttpServletRequest request, QunarReqStruct reqObject, DistributorRespDTO distributor) {
        String code = "15011";
        String describe = "";

        JSONObject object = new JSONObject();
        TradeOrderDO order = new TradeOrderDO();

        String qrcode = "";
//        Lock lock = null;
//        try {
//		/*partnerorderId	orderInfo	订单ID	是	供应商的订单ID
//        orderStatus	orderInfo	订单状态	是	供应商的订单状态
//		PREPAY_ORDER_BOOK_FAILED 预付：预订失败
//		PREPAY_ORDER_NOT_PAYED 预付：预订成功，待支付
//		CASHPAY_ORDER_PRINT_FAILED 现付：出票失败
//		CASHPAY_ORDER_PRINT_SUCCESS 现付：出票成功
//		eticketNo	orderInfo	入园凭证值（现付）	否	如果供应商可以提供则必传，排序提升最大因素*/
//
//            //4、取订单号
//            Document doc = DocumentHelper.parseText(reqObject.getXmlData());
//            //取的根元素
//            Element root = doc.getRootElement();
//            // 获取请求头节点
//            //QunarRequestHeader hdClass = getRequestHeader(root);
//            // 获取body数据
//            Element bodyNode = root.element("body");
//            /**请求参数获取*/
//            /*partnerorderId	orderInfo	订单ID	是	供应商生成的订单ID
//            refundSeq	orderInfo	退款流水号	是	退款流水号，用于标记每一笔退款，由qunar定义
//            orderPrice	orderInfo	订单金额	是	原始订单金额
//            单位：分
//            orderQuantity	orderInfo	订单票数	是	原始订单票数
//            refundQuantity	orderInfo	退款票数	是	退款票数
//            refundReason	orderInfo	退款原因	否	退款原因
//            refundExplain	orderInfo	退款说明	否	退款说明
//            refundCharge	orderInfo	退款手续费	否	订单退款的手续费总额
//            单位：分*/
//        /*partnerorderId	orderInfo	订单ID	是	供应商生成的订单ID
//        refundSeq	orderInfo	退款流水号	是	退款流水号，用于标记每一笔退款，由qunar定义，供应商可以根据此属性信息排除重复的请求。
//        orderQuantity	orderInfo	订单票数	是	原始订单票数
//        refundQuantity	orderInfo	退款票数	否	本次退款票数
//        orderPrice	orderInfo	订单金额	是	原始订单金额 单位：分
//        refundReason	orderInfo	退款原因	否	退款原因
//        refundExplain	orderInfo	退款原因说明	否	退款原因说明
//        refundJudgeMark	orderInfo	退款审核意见	否	退款审核意见
//        orderRefundCharge	orderInfo	退款手续费	否	本次的退款手续费总额  单位：分
//        noticeCanBeIgnored	orderInfo	本次通知是否可忽略	是	取值为true/false。本次通知是否可忽略。（在用户申请退款，供应商审核退款的流程中，在审核时供应商应该已经完成废票动作，本次通知可以忽略；其他场景的通知，有可能不是常规审核流程，要求供应商做废票处理或线下处理，不可忽略）
//        */
//
//            /**请求参数获取*/
//            /*partnerorderId	body	订单ID	是	供应商生成的订单ID*/
//            Element orderInfo = bodyNode.element("orderInfo");
//            String orderNo = orderInfo.elementText("partnerorderId");
//            String refundSeq = orderInfo.elementText("refundSeq");
//            String orderQuantity = orderInfo.elementText("orderQuantity");
//            String refundQuantity = orderInfo.elementText("refundQuantity");
//            String orderPrice = orderInfo.elementText("orderPrice");
//            String refundReason = orderInfo.elementText("refundReason");
//            String refundExplain = orderInfo.elementText("refundExplain");
//            String refundJudgeMark = orderInfo.elementText("refundJudgeMark");
//            String orderRefundCharge = orderInfo.elementText("orderRefundCharge");
//            String noticeCanBeIgnored = orderInfo.elementText("noticeCanBeIgnored");
//            //5、查询订单信息
//            order = orderService.queryByOrderNo(orderNo);
//            if (order == null) {
//                throw new ServerException("订单不存在！");
//            }
//            // 查询退款批次
//            RefundEntity refund = refundService.getRefundByOrderId(order.getId());
//            if (refund != null) {
//                throw new ServerException("订单已退款！");
//            }
//            lock = redisLock.obtain(orderNo + distributor.getId() + tenantId);
//            if (lock.tryLock(10, TimeUnit.SECONDS)) {
//                RefundTicketForm ticketForm = refundService.refundApply(orderNo, order.getExternalOrderNo(), Integer.valueOf(refundQuantity), 1, null); // isForceRefund == 1 强制退票
//                //分销商退单，加上金额
//                //service.orderTradeServer(distributor,refund.getRefundMoney(),OtaServerEntity.TRADETYPEADD, orderNo, "去哪儿-退单" );
//
//                if (ticketForm != null && StringUtils.isNotEmpty(ticketForm.getBatchId())) {
//                    // 确认退单
//                    refundService.orderRefund(request, ticketForm);
//                    code = "1000";
//                    describe = "退款通知成功！";
//                }
//            } else {
//                throw new ServerException("重复提交！");
//            }
//        } catch (ServerException ex) {
//            log.error("分销", "去哪儿退款通知失败", "NoticeOrderRefundedByQunar", ex.getMessage());
//            describe = ex.getMessage();
//        } catch (Exception e) {
//            log.error("分销", "去哪儿退款通知失败", "NoticeOrderRefundedByQunar", e.getMessage());
//            describe = "去哪儿退款通知失败";
//        } finally {
//            if (lock != null) {
//                lock.unlock();
//            }
//        }
        QunarResponseHeader head = getHeader("NoticeOrderRefundedByQunar", code, describe);

        String data = Base64Util.encode(responseReturn(head, describe, order, "", qrcode, ""));
        object.put("data", data);
        object.put("securityType", "MD5");
        object.put("signed", QunarAuthUtil.generateSign(data, distributor.getSecret()));
        return object.toString();
    }

    /**
     * 订单查询接口返回
     */
    String qunarOrderQueryReturn(HttpServletRequest request, QunarReqStruct reqObject, DistributorRespDTO distributor) {
        JSONObject object = new JSONObject();
        String describe = "";
        String code = "";
        try {
            Map<String, Object> result = new HashMap<String, Object>(3);

            Document doc = DocumentHelper.parseText(reqObject.getXmlData());

            //取的根元素
            Element root = doc.getRootElement();


            // 获取body数据
            Element bodyNode = (Element) root.element("body");
            TradeOrderDO orderInfo = new TradeOrderDO();
            if (null != bodyNode) {
                Element orderNode = (Element) bodyNode.element("orderInfo");
                // 获取请求参数
                /** 订单信息*/
                String otaDoc = orderNode.elementText("orderId");// qunar 订单号
                orderInfo.setExternalOrderNo(otaDoc);
                String orderQuantity = orderNode.elementText("orderQuantity");// 订票数量
                String orderPrice = orderNode.elementText("orderPrice");// 订单金额
                String orderCashBackMoney = orderNode.elementText("orderCashBackMoney");// 订单返现总额
                // 去哪儿的订单状态 PREPAY_ORDER_INIT 预付：初始订单 CASHPAY_ORDER_INIT 现付：初始订单
                String orderStatus = orderNode.elementText("orderStatus");// 订单状态
                String orderRemark = orderNode.elementText("orderRemark");// 游客订单备注
                String orderSource = orderNode.elementText("orderSource");// 订单来源
                // 只针对产品的付款类型为景区现付同时电子票类型为Q_CODE时传递。
                String eticketNo = orderNode.elementText("eticketNo");// Qunar电子票串码
                /** 取票人、订票人信息*/
                Element contactPerson = (Element) orderNode.element("contactPerson");
                String name = contactPerson.elementText("name");// 姓名
                String namePinyin = contactPerson.elementText("namePinyin");// 姓名拼音
                String mobile = contactPerson.elementText("mobile");// 电话
                String email = contactPerson.elementText("email");// 邮箱
                String province = contactPerson.elementText("province");// 省
                String city = contactPerson.elementText("city");// 市
                String area = contactPerson.elementText("area");// 区
                String address = contactPerson.elementText("address");// 详细地址
                String zipCode = contactPerson.elementText("zipCode");// 邮编
                /** 产品信息*/
                Element product = (Element) orderNode.element("product");
                // 供应商产品ID
                String resourceId = product.elementText("resourceId");
                String productName = product.elementText("productName");
                // yyyy-MM-dd需提前指定入园时间，如果是有效期为区间的，则不需要传递该值该订单对应的产品的validType=BETWEEN_USE_DATE_AND_N_DAYSAFTER或USE_DATE时必须
                String visitDate = product.elementText("visitDate");
                // Qunar产品售卖单价单位：分
                String sellPrice = product.elementText("sellPrice");
                // 返现金额（每张票）单位：分
                String cashBackMoney = product.elementText("cashBackMoney");
                // 销售类型- B2C:直客（默认）B2B:同行分销
                String saleType = product.elementText("saleType");


                object.put("securityType", "MD5");
                object.put("signed", "1111");
                if (null != orderInfo) {
                    // 查询成功
                    code = "1000";
                    describe = "查询订单成功";
                }

                QunarResponseHeader head = getHeader("queryOrderInfoByQunar", code, describe);

                String data = Base64Util.encode(responseReturn(head, describe, orderInfo, "", "", ""));
                object.put("data", data);
                object.put("securityType", "MD5");
                object.put("signed", QunarAuthUtil.generateSign(data, distributor.getSecret()));
                return object.toString();
            }
        } catch (ServerException ex) {
            log.error("分销", "去哪儿产品查询失败", "QueryOrderInfoByQunar", ex.getMessage());
            describe = ex.getMessage();
        } catch (Exception e) {
            log.error("分销", "去哪儿产品查询失败", "QueryOrderInfoByQunar", e.getMessage());
            describe = "去哪儿产品查询失败";
        }
        QunarResponseHeader head = getHeader("QueryOrderInfoByQunar", code, describe);

        String data = Base64Util.encode(responseReturn(head, describe, null, "", "", ""));
        object.put("data", data);
        object.put("securityType", "MD5");
        object.put("signed", QunarAuthUtil.generateSign(data, distributor.getSecret()));
        return object.toString();
    }

    /**
     * OTA - > 我方 ：查询产品信息
     */
    String queryProduct(HttpServletRequest request, QunarReqStruct reqObject, DistributorRespDTO distributor) {
        JSONObject object = new JSONObject();
        String describe = "";
        try {
            //4、取订单号
            Document doc = DocumentHelper.parseText(reqObject.getXmlData());
            //取的根元素
            Element root = doc.getRootElement();

            // 获取body数据
            Element bodyNode = root.element("body");
            /**订单信息*/
            /*method	body	方法	是	ALL：获取全部产品信息
            SINGLE：获取单个产品信息
            currentPage	body	当前页数	当method=ALL时必传	当前页数
            pageSize	body	每页记录数	当method=ALL时必传	每页记录数
            resourceId	body	供应商产品ID	当method=SINGLE时必传	供应商的产品ID号
            saleType	body	销售类型	当method为SINGLE必传 	ALL: 直客和分销
            B2C：直客
            B2B：同行分销
            method
            currentPage
            pageSize
            resourceId
            saleType*/
            String queryType = bodyNode.elementText("method");// 供应商订单号

            String productId = bodyNode.elementText("resourceId");
            // String saleType = bodyNode.elementText("saleType");
            List<DistributorProductRespDTO> distributorProductList =null;
              // 渠道:OTA
            if ("SINGLE".equals(queryType)) {
                DistributorProductRespDTO distributorProductRespDTO = otaDistributorApi.getDistributorProductByProductAndDistributor(Long.parseLong(productId), distributor.getId()).getCheckedData();
                distributorProductList = new ArrayList<>();
                distributorProductList.add(distributorProductRespDTO);
            } else if ("ALL".equals(queryType)) {
//                 distributorProductList = otaDistributorApi.getProductListByDistributorId(distributor.getId()).getCheckedData();
            }
            //6、封装返回数据
            doc = DocumentHelper.createDocument();
            root = doc.addElement("response", QunarAccountConstant.xmlResponseSchema);
            //Element root = doc.addElement("response", getQunarXmlResponseSchema());

            /** 设置头部*/
            QunarResponseHeader head = getHeader("GetProductByQunar", "1000", "获取产品成功");
            root = setResponseHeader(head, root);

            /** 设置body*/
            Element body = root.addElement("body");
            body.addAttribute("xsi:type", head.getBodyType());
            body.addAttribute("xmlns:xsi", QunarAccountConstant.bodyXsi);
            if (CollUtil.isNotEmpty(distributorProductList)) {
                body.addElement("count").setText(distributorProductList.size() + "");
                Element productInfos = body.addElement("productInfos");
                for (DistributorProductRespDTO distributorProduct : distributorProductList) {
                    ProductSpuRespDTO productSpu = productApi.getProduct(distributorProduct.getProductId()).getCheckedData();
                    // productInfo
                    Element productInfo = productInfos.addElement("productInfo");
                    // baseInfo
                    Element baseInfo = productInfo.addElement("baseInfo");
                    baseInfo.addElement("resourceId").setText(productSpu.getId().toString());
                    baseInfo.addElement("productName").setText(productSpu.getProductName());
                    baseInfo.addElement("saleType").setText("B2C");// B2C：直客（默认）B2B：同行分销
                    Element sights = baseInfo.addElement("sights");
                    Element sight = sights.addElement("sight");
                    sight.addElement("sightName").setText(productSpu.getProductName());// TODO 票务未提供
                    sight.addElement("city").setText(productSpu.getProductName());// TODO 票务未提供
                    // bookConfig
                    Element bookConfig = productInfo.addElement("bookConfig");
                    bookConfig.addElement("paymentType").setText("PREPAY");//PREPAY：在线支付 CASHPAY：景区支付
                    bookConfig.addElement("autoCancelTime").setText("60");// 下单多久后未支付自动取消
                    // 手机号下单限制
                    bookConfig.addElement("hasMaxMobileLimit").setText("FALSE");
                    bookConfig.addElement("mobileLimitTimeScope");
                    bookConfig.addElement("mobileLimitUnit").setText("ORDER");// 限制可预定20份
                    bookConfig.addElement("maxMobileLimit").setText("10");
                    bookConfig.addElement("hasMaxIDCardLimit").setText("FALSE");
                    bookConfig.addElement("idCardLimitTimeScope").setText("10");
                    bookConfig.addElement("idCardLimitUnit").setText("ORDER");
                    bookConfig.addElement("maxIDCardLimit").setText("10");
                    // CONTACT_PERSON：只需要取票人信息（默认）CONTACT_PERSON_AND_VISIT_PERSON：需要游客和取票人信息
                    bookConfig.addElement("bookPersonType").setText("CONTACT_PERSON_AND_VISIT_PERSON");//
                    /** 预定和使用限制 parent-bookConfig*/
                    Element advanceOption = bookConfig.addElement("advanceOption");
                    advanceOption.addElement("bookAdvanceDay").setText("");// 0为当前，空为无限制
                    advanceOption.addElement("bookAdvanceTime").setText("");// 0为当前，空为无限制
                    advanceOption.addElement("useAdvanceHour").setText("");// 使用限制：预定后几小时才能入园
                    bookConfig.addElement("visitPersonRequiredForQuantity").setText("1");//
                    Element visitPersonRequired = bookConfig.addElement("visitPersonRequired");
                    visitPersonRequired.addElement("nameRequired").setText("TRUE");
                    visitPersonRequired.addElement("credentialsRequired").setText("TRUE");
                    visitPersonRequired.addElement("credentialsRequiredTypes").setText("ID_CARD");
                    visitPersonRequired.addElement("namePinYinRequired").setText("FALSE");
                    //visitPersonRequired.addElement("userRequiredDefined1").setText("");
                    //visitPersonRequired.addElement("userRequiredDefined2").setText("");
                    // priceConfig
                    Element priceConfig = productInfo.addElement("priceConfig");
				/*有效期限制：
				USE_DATE :游客选定的游玩日期当天有效
				BETWEEN_USE_DATE_AND_N_DAYSAFTER ：游客选定的游玩日期起_____天内有效
				BETWEEN_BOOK_DATE_AND_N_DAYSAFTER： 游客购买日起_____天内有效
				BETWEEN_USE_DATE_START_AND_END ：游客在使用日期期限内均可使用*/
                    priceConfig.addElement("validType").setText("BETWEEN_USE_DATE_AND_N_DAYSAFTER");// TODO 四种类型都需要考虑
                    // validType=BETWEEN_USE_DATE_AND_N_DAYSAFTER时必须 1为当日
                    priceConfig.addElement("daysAfterUseDateValid").setText("7");//游客选定的游玩日期起x天内有效
                    // validType=BETWEEN_BOOK_DATE_AND_N_DAYSAFTER时必须 1为当日
                    priceConfig.addElement("daysAfterBookDateValid").setText("");//游客购买日起x天内有效
                    priceConfig.addElement("dayUseTimePeriod").setText("08:30-18:00");//可使用时间格式使用：HH:mm-HH:mm 例： 08:00-16:00
                    Element periodPrice = priceConfig.addElement("periodPrice");
                    // 指导价 Qunar产品售卖单价单位：分
                    periodPrice.addElement("sellPrice").setText(distributorProduct.getSalePrice().multiply(new BigDecimal(100)).intValue() + "");
                    // 挂牌价
                    periodPrice.addElement("marketPrice").setText(distributorProduct.getSalePrice().multiply(new BigDecimal(100)).intValue() + "");
                    //分销价
                    periodPrice.addElement("settlePrice").setText(distributorProduct.getSalePrice().multiply(new BigDecimal(100)).intValue() + "");
                    periodPrice.addElement("periodStart").setText(new SimpleDateFormat("yyyy-MM-dd").format(productSpu.getProductBasicRule().getSaleStartDate()));
                    periodPrice.addElement("periodEnd").setText(new SimpleDateFormat("yyyy-MM-dd").format(productSpu.getProductBasicRule().getSaleEndDate()));
                    periodPrice.addElement("sellstock").setText("999");
                    periodPrice.addElement("minimum").setText("1");
                    periodPrice.addElement("maximum").setText("10");
                    periodPrice.addElement("invalidDate").setText("");//不可使用日期
                    periodPrice.addElement("validWeek").setText("1,2,3,4,5,6,7");//星期几有效
                    // 日历价格
                    Element calendarPrices = priceConfig.addElement("calendarPrices");
                    Element calendarPrice = null;
                    //查询日历价
//                    TicketTypeGroupHisEntity ticketTypeGroupHis = typeGroupHisService.queryByTypeId(ticket.getId());
//                    if (ticketTypeGroupHis != null) {
//                        setCalendarPrice(calendarPrice, calendarPrices, ticketTypeGroupHis.getStartTime(), ticketTypeGroupHis.getEndTime(), ticket.getTicketPrintPrice() + "", ticketTypeGroupHis.getTicketPrice() + "", ticketTypeGroupHis.getDayNum());
//                    } else {
//                        setCalendarPrice(calendarPrice, calendarPrices, ticket.getSaleStartDate(), ticket.getSaleEndDate(), ticket.getTicketPrintPrice() + "", ticket.getTicketPrice() + "", ticket.getTotalNum());
//                    }

                    // validType=USE_DATE 或BETWEEN_USE_DATE_AND_N_DAYSAFTER时，不能为空
					/*Element calendarPrice = calendarPrices.addElement("calendarPrice");
						// validType=BETWEEN_USE_DATE_AND_N_DAYSAFTER或USE_DATE时必须
						calendarPrice.addElement("useDate").setText("2017-08-24");
						calendarPrice.addElement("marketPrice").setText(olPrice + "");
						calendarPrice.addElement("sellPrice").setText(sellPrice + "");
						calendarPrice.addElement("settlePrice ").setText(sellPrice + "");
						calendarPrice.addElement("sellstock").setText("999");
						calendarPrice.addElement("minimum").setText("1");
						calendarPrice.addElement("maximum").setText("10");
					Element calendarPrice2 = calendarPrices.addElement("calendarPrice");
						calendarPrice2.addElement("useDate").setText("2017-08-25");
						calendarPrice2.addElement("marketPrice").setText(olPrice + "");
						calendarPrice2.addElement("sellPrice").setText(sellPrice + "");
						calendarPrice2.addElement("settlePrice ").setText(sellPrice + "");
						calendarPrice2.addElement("sellstock").setText("999");
						calendarPrice2.addElement("minimum").setText("1");
						calendarPrice2.addElement("maximum").setText("10");
					Element calendarPrice3 = calendarPrices.addElement("calendarPrice");
						calendarPrice3.addElement("useDate").setText("2017-08-26");
						calendarPrice3.addElement("marketPrice").setText(olPrice + "");
						calendarPrice3.addElement("sellPrice").setText(sellPrice + "");
						calendarPrice3.addElement("settlePrice ").setText(sellPrice + "");
						calendarPrice3.addElement("sellstock").setText("999");
						calendarPrice3.addElement("minimum").setText("1");
						calendarPrice3.addElement("maximum").setText("10");*/
                    // 返现设置
                    Element promoteConfig = productInfo.addElement("promoteConfig");
                    promoteConfig.addElement("cashBackMoney").setText("0");
                    // productDescription
                    Element productDescription = productInfo.addElement("productDescription");
                    productDescription.addElement("remind").setText("【入园凭证】身份证或者二维码扫码入园");
                    productDescription.addElement("feeInfo").setText("【费用包含】无、【费用不含】无");
                    productDescription.addElement("feeInclude").setText("");
                    productDescription.addElement("feeExclude").setText("");
                    productDescription.addElement("pickupTime").setText("取票时间：入园前均有效");
                    productDescription.addElement("pickupAddress").setText("");
                    // 退款信息
                    Element refundOption = productDescription.addElement("refundOption");
                    refundOption.addElement("canRefund").setText("TRUE");// 支持退款
                    // ORDER：按订单收取手续费 QUANTITY：每张票收取手续费
                    refundOption.addElement("refundChargeType").setText("ORDER");// 退款类型
                    refundOption.addElement("refundCharge").setText("0");// 退款手续费
                    // False为整单全退
                    refundOption.addElement("supportPartRefund").setText("FALSE");// 是否支持部分退款
                    refundOption.addElement("refundApplyTimeBeforeValidEndDay").setText("2_22:00");// 最晚有效期前几天几点可退款格式：x_hh:mm
                    refundOption.addElement("refundInfo").setText("【游客申请退款的时间及方式】【是否支持改期】未入园均可退款");// 退款规则

                    // otherConfig
                    Element otherConfig = productInfo.addElement("otherConfig");
                    otherConfig.addElement("eticketType").setText("S_PIC");
                    otherConfig.addElement("telephone").setText("");
                    Element salePeriods = otherConfig.addElement("salePeriods");
                    Element salePeriod = salePeriods.addElement("salePeriod");
                    salePeriod.addElement("saleStartTime").setText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(productSpu.getProductBasicRule().getSaleStartDate()+productSpu.getProductBasicRule().getSaleStartTime()));//产品上架时间-默认为【即刻上架、到期下架】
                    salePeriod.addElement("saleEndTime").setText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(productSpu.getProductBasicRule().getSaleEndDate()+productSpu.getProductBasicRule().getSaleEndTime()));
                    /** 入园设置*/
                    Element enterParkConfig = productInfo.addElement("enterParkConfig");
                    enterParkConfig.addElement("passExchangeVoucherType").setText("UN_KNOWN");// 未知
                    enterParkConfig.addElement("userNameVoucher").setText("");
                    enterParkConfig.addElement("mobileVoucher").setText("");//MOBILE 手机号
                    enterParkConfig.addElement("idCardVoucher").setText("IDCARD");// 身份证
                    // IMMEDIATELY：立即发送 DELAY：延迟发送 CUSTOM：自定义
                    enterParkConfig.addElement("sendVoucherTimeType").setText("IMMEDIATELY");// 发码类型
                    enterParkConfig.addElement("delaySendVoucherMinutes").setText("1");
                    enterParkConfig.addElement("isNeedServiceTime").setText("FALSE");
                    enterParkConfig.addElement("firstNeedServiceTime").setText("08:00:00");
                    enterParkConfig.addElement("secondNeedServiceTime").setText("22:00:00");
                    enterParkConfig.addElement("thirdNeedServiceTime").setText("08:00:00");
                    enterParkConfig.addElement("customSendVoucherTime").setText("");
                    enterParkConfig.addElement("isSupportExpress").setText("FALSE");
                    enterParkConfig.addElement("isSupportTake").setText("TRUE");// 自取
                    // UN_KNOWN：未知 VIRTUAL：凭兑换凭证直接入园(虚拟凭证)  ENTITY：凭兑换凭证换票(实物凭证)
                    enterParkConfig.addElement("passType").setText("VIRTUAL");// 入园方式
                    enterParkConfig.addElement("exchangeAddressList").setText("");// 换票地址
                    enterParkConfig.addElement("passAddressList").setText("");// 入园地址
                }
            }

            String data = Base64Util.encode(root.asXML());
            object.put("data", data);
            object.put("securityType", "MD5");
            object.put("signed", QunarAuthUtil.generateSign(data, distributor.getSecret()));
            return object.toString();
        } catch (ServerException ex) {
            log.error("分销", "去哪儿产品查询失败", "GetProductByQunar", ex.getMessage());
            describe = ex.getMessage();
        } catch (Exception e) {
            log.error("分销", "去哪儿产品查询失败", "GetProductByQunar", e.getMessage());
            describe = "去哪儿产品查询失败";
        }
        QunarResponseHeader head = getHeader("GetProductByQunar", "12001", describe);
        String data = Base64Util.encode(responseReturn(head, describe, null, "", "", ""));
        object.put("data", data);
        object.put("securityType", "MD5");
        object.put("signed", QunarAuthUtil.generateSign(data, distributor.getSecret()));
        return object.toString();
    }

    /**
     * 核销通知
     *
     * @param distributor
     * @param map
     * @return
     */
    @Override
    public boolean consumeNotice(DistributorRespDTO distributor, Map<String, Object> map) {
        String orderNo = MapUtils.getString(map, "orderNo");
        int totalTicket = MapUtils.getIntValue(map, "totalTicket");
        Long orderId = MapUtils.getLong(map, "orderId");

        Map<String, Object> ticketMap = tradeOrderRepositoryService.queryDetailCountByOrderId(orderId);
        int checkCount = MapUtils.getIntValue(ticketMap, "checkCount");
        int partCount = MapUtils.getIntValue(ticketMap, "partCount");
        int outTimeCount = MapUtils.getIntValue(ticketMap, "outTimeCount");
        int useCount = checkCount + partCount + outTimeCount;
        String sendUrl = "";
        String param = "";
        try {

            JSONObject jsonObject = new JSONObject();
            String qunarCreateUser = QunarAccountConstant.createUser;
            qunarCreateUser = new String(qunarCreateUser.getBytes("iso-8859-1"), "UTF-8");
            QunarRequestHeader head = new QunarRequestHeader(QunarAccountConstant.application,
                    QunarAccountConstant.processor, QunarAccountConstant.version,
                    "NoticeOrderConsumed",
                    qunarCreateUser, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), distributor.getAppid());

            Document doc = DocumentHelper.createDocument();
            Element root = doc.addElement("request", QunarAccountConstant.xmlRequestSchema);

            /** 设置头部*/
            root = setRequestHeader(head, root);

            /** 设置body*/
            Element body = root.addElement("body");
            body.addAttribute("xsi:type", head.getBodyType());
            body.addAttribute("xmlns:xsi", QunarAccountConstant.bodyXsi);
            Element orderInfo = body.addElement("orderInfo");
		/*partnerorderId	orderInfo	订单ID	是	供应商生成的订单ID
		orderQuantity	orderInfo	订单票数	否	原始订单总票数
		useQuantity	orderInfo	已消费票数	否	已消费票数，这里指累计消费的票数，如果用户分多次进行消费，每次消费时，这里给出的是累计的消费张数。
		consumeInfo	orderInfo	电子票消费信息	否	电子票消费信息*/

            orderInfo.addElement("partnerorderId").setText(orderNo);
            orderInfo.addElement("orderQuantity").setText(String.valueOf(totalTicket));
            orderInfo.addElement("useQuantity").setText(String.valueOf(useCount));

            orderInfo.addElement("consumeInfo").setText("Empty");

            String signData = Base64Util.encode(root.asXML());
            jsonObject.put("signed", QunarAuthUtil.generateSign(signData, distributor.getSecret()));
            jsonObject.put("data", signData);
            jsonObject.put("securityType", "MD5");
            String serverUrl = distributor.getServerUrl();
//            String sendUrl = "http://openapi.piao.qunar.com/index.php/callback/index/?method=NoticeOrderConsumed";
            sendUrl = serverUrl + "?method=noticeOrderConsumed";
            Map<String, String> headMap = new HashMap<>();
            headMap.put("Content-type", "application/x-www-form-urlencoded");
            // 发送POST请求给 去哪儿
            param = "method=" + toFirstLowerCase("NoticeOrderConsumed") + "&requestParam=" + jsonObject.toString();
            log.info("去哪儿：消费通知接口： orderNo=" + orderNo + ";param=" + param);
//            String discardJsonStr = SendHttps.sendPost(sendUrl, param, headMap);
            String discardJsonStr = HttpUtil.createPost(sendUrl).contentType("application/json")
                    .body(param)
                    .headerMap(headMap,false)
                    .timeout(15000)
                    .execute().body();
            String res = Base64Decoder.decodeStr(discardJsonStr);
            log.info("去哪儿：消费通知接口： orderNo=" + orderNo + ";返回=" + res);
            //处理返回结果
            res = res.substring(res.indexOf("<response"), res.indexOf("</response>") + 11);
            Document resDoc = DocumentHelper.parseText(res);
            Element rootEle = resDoc.getRootElement();
            Element header = rootEle.element("header");
            String code = header.elementText("code");
            //成功
            if ("1000".equals(code)) {
                //记录消费通知
                notifyLogService.saveNotifyLog(map, sendUrl, param, res, 1);
                return true;
            } else {
                notifyLogService.saveNotifyLog(map, sendUrl, param, res, 0);
                return false;
            }
        } catch (Exception e) {
            //记录消费通知
            notifyLogService.saveNotifyLog(map, sendUrl, param, e.getMessage(), 0);
            log.error("去哪儿消费通知失败： orderNo=" + orderNo, e.getMessage());
            return false;
        }
    }

    /**
     * 根据开始和结束时间，设置日历价
     */
    Element setCalendarPrice(Element calendarPrice, Element calendarPrices, Date startTime, Date endTime, String price, String datePrice, Integer dayNum) {
        while (startTime.getTime() < endTime.getTime()) {
            calendarPrice = calendarPrices.addElement("calendarPrice");
            calendarPrice.addElement("useDate").setText(DateUtils.format(startTime, "yyyy-MM-dd"));
            // 挂牌价
            calendarPrice.addElement("marketPrice").setText(String.valueOf(new BigDecimal(price).multiply(new BigDecimal(100)).intValue()));
            // 指导价
            calendarPrice.addElement("sellPrice").setText(String.valueOf(new BigDecimal(price).multiply(new BigDecimal(100)).intValue()));
            //分销价
            calendarPrice.addElement("settlePrice ").setText(String.valueOf(new BigDecimal(datePrice).multiply(new BigDecimal(100)).intValue()));
            //日库存,空表示不限制
            if (dayNum != null) {
                calendarPrice.addElement("sellstock").setText(dayNum + "");
            } else {
                calendarPrice.addElement("sellstock").setText("9999");
            }

            calendarPrice.addElement("minimum").setText("1");
            calendarPrice.addElement("maximum").setText("10");

            startTime=  DateUtil.offsetDay(startTime,1);
        }
        return calendarPrice;
    }


    /**
     * 去哪儿：校验订单return response-data xml封装
     *
     * @param head
     * @param order
     * @param status
     * @param eticketNo
     * @return
     */
    String responseReturn(QunarResponseHeader head, String message, TradeOrderDO order, String status, String eticketNo, String useQuantity) {

        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("response", QunarAccountConstant.xmlResponseSchema);

        /** 设置头部*/
        root = setResponseHeader(head, root);

        /** 设置body*/
        Element body = root.addElement("body");
        body.addAttribute("xsi:type", head.getBodyType());
        body.addAttribute("xmlns:xsi", QunarAccountConstant.bodyXsi);
        if (StringUtils.isNotEmpty(message)) {
            body.addElement("message").setText(message);
            return root.asXML();
        }


        Element orderInfo = body.addElement("orderInfo");

		/*partnerorderId	orderInfo	订单ID	是	供应商生成的订单ID
		orderStatus	orderInfo	订单状态	是	订单状态
		PREPAY_ORDER_INIT 预付：初始订单
		PREPAY_ORDER_BOOK_FAILED 预付：预订失败
		PREPAY_ORDER_NOT_PAYED 预付：预订成功，待支付
		PREPAY_ORDER_CANCEL 预付：订单已取消
		PREPAY_ORDER_PRINTING 预付：已付款，出票中
		PREPAY_ORDER_PRINT_FAILED 预付：出票失败
		PREPAY_ORDER_PRINT_SUCCESS 预付：出票成功
		CASHPAY_ORDER_INIT 现付：初始订单
		CASHPAY_ORDER_PRINTING  现付：出票中
		CASHPAY_ORDER_PRINT_FAILED 现付：出票失败
		CASHPAY_ORDER_PRINT_SUCCESS 现付：出票成功
		CASHPAY_ORDER_CANCEL 现付：订单已取消
		orderQuantity	orderInfo	订单总票数	是	原始订单总票数
		eticketNo	orderInfo	电子票号	否	该订单的电子票信息。如果是qunar电子票，这里是qunar提供的电子票信息，如果是供应商自己生成的，这里是供应商的电子票信息。
		如果该订单为手工发送凭证通知或无法获取电子票信息，可以为空。
		eticketSended	orderInfo	电子票发送状态	是	TRUE：电子票已发送
		FALSE：电子票未发送
		如果没有电子票，则记录实际通知用户后，才能将此设置为true返回。
		useQuantity	orderInfo	已消费票数	是	已消费票数
		consumeInfo	orderInfo	消费信息	是	消费额外信息，相当于消费时的备注。*/
        if (order != null && StringUtils.isNotEmpty(order.getOrderNo())) {
            orderInfo.addElement("partnerorderId").setText(order.getOrderNo());
        }
        orderInfo.addElement("orderStatus").setText(status);// TODO 状态转换
        List<TradeDetailDO> detailDOList = tradeOrderRepositoryService.queryDetailByOrderId(order.getId());
        if (order != null && CollUtil.isNotEmpty(detailDOList)) {
            orderInfo.addElement("orderQuantity").setText(String.valueOf(detailDOList.size()));
        }
        if (StringUtils.isNotEmpty(eticketNo)) {
            orderInfo.addElement("eticketNo").setText(eticketNo);
        }
        orderInfo.addElement("eticketSended").setText("FALSE");// 电子发票未发送
        orderInfo.addElement("useQuantity").setText(useQuantity);
        orderInfo.addElement("consumeInfo").setText("Empty");

        String result = root.asXML();

        return result;
    }

    /**
     * 去哪儿：处理response return header-xml响应头
     *
     * @param head
     * @param root
     * @return
     * @author zhoulonggui
     * @date 2017年5月26日
     * modify history
     */
    Element setResponseHeader(QunarResponseHeader head, Element root) {
        /** 设置头部*/
        Element header = root.addElement("header");
		/*private String application;
		private String processor;
		private String version;
		private String bodyType;
		private String createUser;
		private String createTime;
		private String code;
		private String describe;*/
        Element application = header.addElement("application");
        application.setText(head.getApplication());
        header.addElement("processor").setText(head.getProcessor());
        header.addElement("version").setText(head.getVersion());
        header.addElement("bodyType").setText(head.getBodyType());
        header.addElement("createUser").setText(head.getCreateUser());
        header.addElement("createTime").setText(head.getCreateTime());
        header.addElement("code").setText(head.getCode());
        header.addElement("describe").setText(head.getDescribe());
        return root;
    }

    /**
     * 去哪儿：处理request post header-xml请求头
     *
     * @param head
     * @param root
     * @return
     * @author zhoulonggui
     * @date 2017年5月26日
     * modify history
     */
    private static Element setRequestHeader(QunarRequestHeader head, Element root) {
        /** 设置头部*/
        Element header = root.addElement("header");
		/*private String application;
		private String processor;
		private String version;
		private String bodyType;
		private String createUser;
		private String createTime;
		private String code;
		private String describe;*/
        Element application = header.addElement("application");
        application.setText(head.getApplication());
        header.addElement("processor").setText(head.getProcessor());
        header.addElement("version").setText(head.getVersion());
        header.addElement("bodyType").setText(head.getBodyType());
        header.addElement("createUser").setText(head.getCreateUser());
        header.addElement("createTime").setText(head.getCreateTime());
        header.addElement("supplierIdentity").setText(head.getSupplierIdentity());
        return root;
    }

    /**
     * 首字母小写
     *
     * @param str
     * @return
     */
    private static String toFirstLowerCase(String str) {
        if (StringUtils.isNotEmpty(str)) {
            return str.substring(0, 1).toLowerCase() + str.substring(1);
        }
        return str;
    }

    /**
     * 获取分销商
     */
    DistributorRespDTO getServer() {

        CommonResult<DistributorRespDTO> result = otaDistributorApi.getDistributorByOtaAccount("", OtaConstants.SYS_PRI_KEY_QUNAR_TYPECODE);
        if (result.isError()){
            return null;
        }
        return result.getCheckedData();
    }

    /**
     * 获取header
     */
    QunarResponseHeader getHeader(String method, String code, String describe) {
        return new QunarResponseHeader(QunarAccountConstant.application,
                QunarAccountConstant.processor, QunarAccountConstant.version,
                method,
                QunarAccountConstant.createUser, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), code, describe);

    }
}
