package cn.freemud.service.impl;

import cn.freemud.adapter.OrderAdapter;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.base.log.ErrorLog;
import cn.freemud.base.util.DateUtil;
import cn.freemud.constant.RedisKeyConstant;
import cn.freemud.constant.ResponseCodeConstant;
import cn.freemud.entities.bo.CheckSvcAmountBo;
import cn.freemud.entities.bo.CheckSvcAmountResponse;
import cn.freemud.entities.dto.SvcComPayRequestDto;
import cn.freemud.entities.dto.SvcComPayResponseDto;
import cn.freemud.entities.dto.order.CreatePrepayRequestDto;
import cn.freemud.entities.dto.order.FacePayRequestDto;
import cn.freemud.entities.dto.order.InvoiceCreateResponse;
import cn.freemud.entities.dto.order.UnifiedPayResponseDto;
import cn.freemud.entities.dto.pay.*;
import cn.freemud.entities.dto.pay.svc.SVCCardAmountRequestDto;
import cn.freemud.entities.dto.pay.svc.SVCCardAmountResponseDto;
import cn.freemud.entities.vo.CreateOrderResponseVo;
import cn.freemud.entities.vo.PaysuccessNoticeMessage;
import cn.freemud.entities.vo.PutRoundRobinVo;
import cn.freemud.entities.vo.order.CreateOrderUnionPayCardVo;
import cn.freemud.entities.vo.order.PlugInParameter;
import cn.freemud.enums.PayChannel;
import cn.freemud.enums.PaySuccessSource;
import cn.freemud.enums.ResponseResult;
import cn.freemud.enums.TradeState;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.management.entities.dto.request.BatchOrderRefundV2Request;
import cn.freemud.management.entities.dto.request.pay.PayRefundRequestDto;
import cn.freemud.management.entities.dto.request.pay.PaymentQueryOrderRequestDto;
import cn.freemud.management.entities.dto.response.pay.OrderRefundResponse;
import cn.freemud.management.entities.dto.response.pay.PayBatchRefundResponse;
import cn.freemud.management.entities.dto.response.pay.PayRefundData;
import cn.freemud.management.entities.dto.response.pay.PaymentQueryOrderResponseDto;
import cn.freemud.management.enums.PaymentRefundStatus;
import cn.freemud.management.thirdparty.MulitiPaymentClient;
import cn.freemud.management.thirdparty.OMSPaymentClient;
import cn.freemud.redis.RedisCache;
import cn.freemud.service.thirdparty.ComPayClient;
import cn.freemud.service.thirdparty.PaymentNewClient;
import cn.freemud.service.thirdparty.SvcAppClient;
import cn.freemud.service.thirdparty.SvcComPayClient;
import cn.freemud.utils.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.freemud.api.assortment.datamanager.entity.db.*;
import com.freemud.api.assortment.datamanager.entity.vo.AssortmentCustomerInfoVo;
import com.freemud.api.assortment.datamanager.manager.*;
import com.freemud.application.sdk.api.base.SDKCommonBaseContextWare;
import com.freemud.application.sdk.api.constant.ResponseResultEnum;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.ordercenter.entities.v1.OrderBeanV1;
import com.freemud.application.sdk.api.ordercenter.entities.v1.ProductBeanV1;
import com.freemud.application.sdk.api.ordercenter.enums.*;
import com.freemud.application.sdk.api.ordercenter.request.OrderCancelReq;
import com.freemud.application.sdk.api.ordercenter.request.OrderExtInfoDto;
import com.freemud.application.sdk.api.ordercenter.request.UpdateOrderReq;
import com.freemud.application.sdk.api.ordercenter.response.orderInfo.OrderPayItemResp;
import com.freemud.application.sdk.api.ordercenter.service.OrderSdkService;
import com.freemud.application.sdk.api.util.ResponseUtils;
import com.freemud.sdk.api.assortment.order.constant.OrderRedisKeyConstant;
import com.freemud.sdk.api.assortment.order.request.order.CancelOrderRequest;
import com.freemud.sdk.api.assortment.order.request.order.MultiOrderRefundRequest;
import com.freemud.sdk.api.assortment.order.request.order.OrderEditRequest;
import com.freemud.sdk.api.assortment.order.request.order.PaymentRequest;
import com.freemud.sdk.api.assortment.order.request.payment.CombPayRequest;
import com.freemud.sdk.api.assortment.order.request.payment.MultiPayRequest;
import com.freemud.sdk.api.assortment.order.response.order.MultiOrderRefundResponse;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class PayServiceImpl {

    @Autowired
    private SvcAppClient svcAppClient;
    @Autowired
    private ComPayClient comPayClient;
    @Autowired
    private SvcComPayClient svcComPayClient;
    @Autowired
    private MulitiPaymentClient mulitiPaymentClient;
    //OMSPaymentClient与PaymentNewClient都是payment-center-api服务，接口不能重复
    @Autowired
    private PaymentNewClient paymentNewClient;
    @Autowired
    private OMSPaymentClient omsPaymentClient;

    @Autowired
    private AssortmentOpenPlatformWxappManager openPlatformWxappManager;
    @Autowired
    private AssortmentOpenPlatformPartnerManager assortmentOpenPlatformPartnerManager;
    @Autowired
    private AssortmentOpenPlatformPartnerConfigManager openPlatformPartnerConfigManager;
    @Autowired
    private AssortmentOpenPlatformIappWxappStoreManager assortmentOpenPlatformIappWxappStoreManager;
    @Autowired
    private AssortmentOpenPlatformPartnerPaymentConfigManager openPlatformPartnerPaymentConfigManager;



    @Autowired
    private OrderQueueService orderQueueService;
    @Autowired
    private OrderSdkService orderSdkService;


    @Autowired
    private OrderAdapterServiceImpl orderAdapterService;
    @Autowired
    private OrderAdapter orderAdapter;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private RedisService redisService;


    @Value("${saas.reverseNotifyiDcUrl}")
    private String reverseNotifyiDcUrl;
    @Value("${collage.pre_order_pay.goods_tag_list}")
    private String collageGoodsTagList;
    @Value("${collage.pre_order_pay.goods_tag}")
    private String collageGoodsTag;

    @Value("${query.pay.order:true}")
    private Boolean queryPayOrder;
    @Value("${use.pay.feign:true}")
    private Boolean usePayFeignClient;
    @Value("${pay.response.error:true}")
    private Boolean printUnifiedPayResponseError;


    private static final Integer MULITI_RESPONSE = 200;
    private static final String SUCCESS = "SUCCESS";
    public static final Integer SUCCESS_RESPONSE_CODE_INT = 100;
    public static final Integer SUCCESS_RESPONSE_101_CODE_INT = 101;
    public static final Integer REFUND_RESPONSE_CODE = 8200305;

    /**
     * 创建预支付订单
     */
    public CreateOrderResponseVo createPrepayOrder(CreatePrepayRequestDto createPrepayRequestDto) {

        CreateOrderResponseVo createOrderResponse;
        OrderPayResponse orderPayResponse = null;
        PaymentRequest paymentRequest = orderBodyConvertToPaymentBody(createPrepayRequestDto.getOpenId(), createPrepayRequestDto.getPartnerId(),
                createPrepayRequestDto.getWxAppId(), createPrepayRequestDto.getPayCode());
        long totalAmount = createPrepayRequestDto.getTotalAmount();
//        String cardCode = createPrepayRequestDto.getCardCode();
        List<String> cardCodes = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(createPrepayRequestDto.getCardCodes())){
            cardCodes = createPrepayRequestDto.getCardCodes();
        }else if(StringUtils.isNotBlank(createPrepayRequestDto.getCardCode())){
            cardCodes.add(createPrepayRequestDto.getCardCode());
        }
        String transId = createPrepayRequestDto.getTransId();
        if (totalAmount < 0) {
            throw new ServiceException(ResponseResult.PAY_AMOUNT_ERROR);
        } else if (totalAmount > 0 && Objects.nonNull(createPrepayRequestDto.getUnionPayCard())) {
            // 电子风味卡支付
            orderPayResponse = uSvcPay(createPrepayRequestDto.getFatherOrderBean(), paymentRequest, transId, LogThreadLocal.getTrackingNo(), createPrepayRequestDto.getUnionPayCard());
//        } else if (totalAmount > 0 && StringUtils.isNotBlank(createPrepayRequestDto.getFaceCode())) {
            //扫脸支付
//            orderPayResponse = facePay(createPrepayRequestDto.getFaceCode(), createPrepayRequestDto.getProductOrderBean(), paymentRequest, LogThreadLocal.getTrackingNo());
        } else if (totalAmount > 0 && CollectionUtils.isEmpty(cardCodes)) {
            //现金线上支付
//            String partnerPayOvertime = this.getPartnerPayOvertime(createPrepayRequestDto.getPartnerId());
            orderPayResponse = getPreOrderPay(createPrepayRequestDto.getFatherOrderBean(), paymentRequest, createPrepayRequestDto.getCardAmount(), transId, createPrepayRequestDto.getOrderExtInfoDTO());
        } else if (totalAmount > 0 && CollectionUtils.isNotEmpty(cardCodes)) {
            //混合支付+svc卡(礼品卡)
//            orderPayResponse = switchSvcOrComb(totalAmount, cardCode, createPrepayRequestDto.getFatherOrderBean(), paymentRequest, transId, createPrepayRequestDto.getChannel());
            //多卡混合支付
            orderPayResponse = multiPay(cardCodes, createPrepayRequestDto.getFatherOrderBean(), paymentRequest, (int)totalAmount, createPrepayRequestDto.getChannel());
        } else {
            // 0元订单如果不需要支付，自定义支付单号
            orderPayResponse = getOrderPayResponse(paymentRequest, createPrepayRequestDto.getFatherOrderBean());
            // 这里如果抖音卖券价格为0元，不能设置支付方式为0元购，否则后面mq送券的判断会走到通用送券逻辑
            if (PayChannelType.TIKTOKPAY.getEbcode().equals(createPrepayRequestDto.getChannel())) {
                orderPayResponse.setPayChannelType(PayChannelType.TIKTOKPAY);
            }
        }
        if (orderPayResponse == null || Objects.isNull(orderPayResponse.getFmId())) {
            BaseResponse baseResponse = failPreOrderPay(LogThreadLocal.getTrackingNo(), createPrepayRequestDto.getProductOrderBean(), cardCodes, createPrepayRequestDto.getOrderClient(),
                    Objects.isNull(orderPayResponse) ? null : orderPayResponse.getMsg());
            // 电子风味卡需要给用户特殊的返回
            if (totalAmount > 0 && Objects.nonNull(createPrepayRequestDto.getUnionPayCard())) {
                baseResponse.setMessage(Objects.nonNull(orderPayResponse) &&
                        (ResponseCodeConstant.PASSWORD_WRONG.equals(orderPayResponse.getPayTransId())
                                || ResponseCodeConstant.NOT_SUFFICIENT_FUND.equals(orderPayResponse.getPayTransId())) ?
                        orderPayResponse.getMsg() : "支付失败");
            }
            throw new ServiceException(baseResponse.getCode(), baseResponse.getMessage());
        }
        createOrderResponse = orderAdapter.convent2CreateFatherSonOrderResponseVo(orderPayResponse, createPrepayRequestDto.getProductOrderBean());
        //更新订单支付信息   多卡支付有多个卡号，不用拓展字段了
//        if (StringUtils.isNotBlank(cardCode)) {
//            if (Objects.nonNull(createPrepayRequestDto.getOrderExtInfoDTO())) {
//                createPrepayRequestDto.getOrderExtInfoDTO().setCardCode(cardCode);
//            }else {
//                OrderExtInfoDto dto = new OrderExtInfoDto();
//                dto.setCardCode(cardCode);
//                createPrepayRequestDto.setOrderExtInfoDTO(dto);
//            }
//        }

        BaseResponse baseEditResponse = this.updateOrderInfo(orderPayResponse, createPrepayRequestDto.getOrderExtInfoDTO(), createPrepayRequestDto.getProductOrderBean(), LogThreadLocal.getTrackingNo());
        if (baseEditResponse != null) {
            throw new ServiceException(baseEditResponse.getCode(), baseEditResponse.getMessage());
        }
        if (totalAmount > 0 && !Objects.equals(PayChannelType.SVC.getEbcode(),orderPayResponse.getPayChannelType().getEbcode()) && Objects.isNull(createPrepayRequestDto.getUnionPayCard())) {
            createOrderResponse.setPaySuccess(false);
        } else if (orderPayResponse.getPayChannelType() != null && PayChannelType.COMB.getEbcode().equals(orderPayResponse.getPayChannelType().getEbcode())) {
            createOrderResponse.setPaySuccess(false);
        } else if (orderPayResponse.getPayChannelType() != null && PayChannelType.SVC.getEbcode().equals(orderPayResponse.getPayChannelType().getEbcode())) {
            createOrderResponse.setPaySuccess(true);
        } else {
            createOrderResponse.setPaySuccess(true);
        }
        if (!createOrderResponse.getPaySuccess()) {
            return createOrderResponse;
        } else {
            //如果是商品券支付0元，调用回调接口
            /**
             *  - 老的svc卡或是0元订单下单成功直接核销 这里不处理
             *  - 混合支付纯svc支付 需要直接内部核销 其他支付方式需依靠外部回调
             */
            PaysuccessNoticeMessage message = new PaysuccessNoticeMessage();
            message.setResult_code(100);
            message.setOut_trade_no(createOrderResponse.getFmId());
            message.setTrans_id(createOrderResponse.getOid());
            message.setTotal_fee(0);
            message.setOpenid(createPrepayRequestDto.getOpenId());
            message.setPlatform_coupon(0);
            message.setMerchant_coupon(0);
            message.setSource(PaySuccessSource.OUTSIDE.getSource());
            message.setSvcPayItems(orderPayResponse.getSvcPayItems());
            orderAdapterService.paySuccessCallback(message);
            return createOrderResponse;
        }
    }



    /**
     * 创建预支付信息 (围餐用)
     * cardCode svc卡号
     */
    // TODO: 21-9-17 待合并
    public CreateOrderResponseVo createPrePaymentOrder(OrderBeanV1 orderBean, AssortmentCustomerInfoVo assortmentCustomerInfoVo, String partnerId, int cardAmount, String cardCode) {
        OrderPayResponse orderPayResponse = null;
        String wxAppId = assortmentCustomerInfoVo.getWxAppId();
        //设置支付信息
        PaymentRequest paymentRequest = new PaymentRequest();
        paymentRequest.setOpenId(assortmentCustomerInfoVo.getOpenId());
        paymentRequest.setWxAppId(wxAppId);
        AssortmentOpenPlatformWxapp wxApp = openPlatformWxappManager.findByPartnerIdAndWxappId(partnerId, wxAppId);
        paymentRequest.setPrincipalName(wxApp.getPrincipalName());
        paymentRequest.setReverseNotifyiDcUrl(reverseNotifyiDcUrl);
        //修改订单信息
        OrderExtInfoDto orderExtInfoDto = JSONObject.parseObject(orderBean.getExtInfo(), OrderExtInfoDto.class) == null ? new OrderExtInfoDto() : JSONObject.parseObject(orderBean.getExtInfo(), OrderExtInfoDto.class);
        if (orderBean.getAmount() > 0 && StringUtils.isEmpty(cardCode)) {
            try {
                String transId = orderBean.getOid() + redisService.increment(RedisUtil.getPaymentTransIdSequenceKey(orderBean.getOid()), 1L, TimeUnit.DAYS);
//                UnifiedOrderRequest request = orderAdapter.convent2UnifiedOrderRequest(orderBean, paymentRequest, orderBean.getAmount(), cardAmount, transId);
                UnifiedOrderCom com = new UnifiedOrderCom(orderBean, paymentRequest, orderBean.getAmount(), cardAmount, transId, "30");
                //支付聚合sdk 请求参数
                UnifiedOrderRequest request = orderAdapter.convent2UnifiedOrderRequest(com);
                if (SDKCommonBaseContextWare.getProfile().equals(SDKCommonBaseContextWare.profiles.DEFAULT.getProfile())
                        || SDKCommonBaseContextWare.getProfile().equals(SDKCommonBaseContextWare.profiles.DEV.getProfile())
                        || SDKCommonBaseContextWare.getProfile().equals(SDKCommonBaseContextWare.profiles.TEST.getProfile())) {
                    request.setAmount(1L);
                }
                AppLogUtil.infoLog("支付transId :{},payRequest:{}", request.getTransId(), JSON.toJSONString(request));
                redisService.savePaymentTransIdOrder(RedisUtil.getPaymentTransIdOrderKey(transId), orderBean.getOid(), 1L, TimeUnit.DAYS);
//                com.freemud.application.sdk.api.base.BaseResponse<UnifiedOrderResponse> responseBase = standardPaymentService.unifiedOrder(request, LogThreadLocal.getTrackingNo());

                //Feign 预支付接口请求参数
                UnifiedOrderRequestDto requestDto = this.convert2UnifiedOrderRequestDto(com);
                // add by miaohui for 拼单群收款判断拼单人数大于1时参与微信平台补贴活动，创建预支付时上送goodsTag，后续抽成促销服务活动时删除此逻辑 start
                if (null != orderBean.getMarketingType() && MarketTypeEnum.COLLAGE.getIndex().byteValue() == orderBean.getMarketingType()) {
                    // 拼单人数大于1人时参加拼单补贴
                    if (null != orderBean.getProductList() && orderBean.getProductList().stream().map(ProductBeanV1::getUserId).distinct().collect(Collectors.toList()).size() > 1) {
                        Map<String, String> goodsTagMap = this.goodsTagMap();
                        String goodsTag = goodsTagMap.get(orderBean.getCompanyId());
                        goodsTag = StringUtils.isBlank(goodsTag) ? collageGoodsTag : goodsTag;
                        request.setGoodsTag(goodsTag);
                        requestDto.setGoodsTag(goodsTag);
                    }
                }
                // add by miaohui for 拼单群收款判断拼单人数大于1时参与微信平台补贴活动，创建预支付时上送goodsTag，后续抽成促销服务活动时删除此逻辑 end
                if (orderExtInfoDto != null && StringUtils.isNotBlank(orderExtInfoDto.getStationId())) {
                    request.setStationId(orderExtInfoDto.getStationId());
                    requestDto.setStationId(orderExtInfoDto.getStationId());
                }

                orderPayResponse = new OrderPayResponse();
                String clientCode = this.getPayCodeByChanel(paymentRequest.getWxAppId(), orderBean.getShopId());
                if (StringUtils.isBlank(clientCode)) {
                    orderPayResponse.setMsg("请先联系相关人员配置商户对应的支付渠道");
//                        return orderPayResponse;
                }
                requestDto.setClientCode(Long.parseLong(clientCode));
//            com.freemud.application.sdk.api.base.BaseResponse<UnifiedPayResponseDto> response = paymentNewClient.unifiedOrder(requestDto);
                com.freemud.application.sdk.api.base.BaseResponse<UnifiedPayResponseDto> response = null;
                //处理超时情况，后续冲正mq正常冲正，同支付sdk逻辑
                try {
                    response = this.unifiedOrder(requestDto);
                } catch (Exception e) {
                    AppLogUtil.errorLog("获取预支付信息异常", JSONObject.toJSONString(requestDto), null, e);
                }
                //预支付接口失败
                if (null == response || !Objects.equals(ResponseCodeConstant.RESPONSE_SUCCESS_STR, response.getCode())
                        || !Objects.equals(ResponseCodeConstant.RESPONSE_SUCCESS, response.getData().getResultCode())) {
                    String errorMessage = "unified fail";
                    if (null != response) {
                        errorMessage = StringUtils.isNotEmpty(response.getMessage()) ? response.getMessage() : response.getData().getResultMsg();
                    }
                    //打印业务异常
                    if (response != null && printUnifiedPayResponseError) {
                        AppLogUtil.errorLog("获取预支付信息失败", JSONObject.toJSONString(requestDto), JSONObject.toJSONString(response), null);
                    }
                    //预支付失败需要把原因进行记录
                    orderPayResponse.setMsg(errorMessage);
                    return null;
                }
                putDelMq(request.getPartnerId(), request.getStoreId(), response.getData().getFmId(), orderBean.getOid(), null);
                this.convent2CreateOrderResponseVo(orderPayResponse, paymentRequest.getWxAppId(), response.getData());
                orderPayResponse.setOpenId(paymentRequest.getOpenId());
                orderPayResponse.setPartnerId(orderBean.getCompanyId());
                orderPayResponse.setOrderId(orderBean.getOid());
                orderPayResponse.setPayChannelType(PayChannelType.WECHAT);
                if (orderPayResponse.getPayOrder() != null && StringUtils.isNotBlank(orderPayResponse.getPayOrder().getAliPayOrder())) {
                    orderPayResponse.setPayChannelType(PayChannelType.ALIPAY);
                }
//                if (!ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(responseBase.getCode())) {
//                    return null;
//                }
//                orderPayResponse = orderAdapter.convent2OrderPayResponse(responseBase.getData());
//                orderPayResponse.setWxAppid(paymentRequest.getWxAppId());
//                orderPayResponse.setOpenId(paymentRequest.getOpenId());
//                orderPayResponse.setPartnerId(orderBean.getCompanyId());
//                orderPayResponse.setOrderId(orderBean.getOid());

                orderExtInfoDto.setPrePayTransId(request.getTransId());
            } catch (Exception e) {
                AppLogUtil.errorLog("getPreOrderPay_error", JSONObject.toJSONString(orderBean), JSONObject.toJSONString(paymentRequest), e);
                //给出支付失败提示
                return null;
            }
        } else if (orderBean.getAmount() > 0 && StringUtils.isNotEmpty(cardCode)) {
            //svc卡支付
            orderPayResponse = svcPay(cardCode, orderBean, paymentRequest, orderBean.getOid());
            orderExtInfoDto.setPrePayTransId(orderPayResponse.getPayTransId());
        } else if (orderBean.getAmount() < 0) {
            throw new ServiceException(ResponseResult.PAY_AMOUNT_ERROR);
        } else {
            String fmId = "SPAY" + ValidationCode.getRandomUuid();
            orderPayResponse = orderAdapter.getOrderPayResponse(orderBean.getCompanyId(), paymentRequest,
                    orderBean.getOid(), fmId);
            orderExtInfoDto.setPrePayTransId(orderPayResponse.getPayTransId());
        }
        CreateOrderResponseVo createOrderResponseVo = orderAdapter.convent2CreateFatherSonOrderResponseVo(orderPayResponse, orderBean);
        orderExtInfoDto.setFmId(createOrderResponseVo.getFmId());
        orderExtInfoDto.setPrePayUserId(assortmentCustomerInfoVo.getMemberId());
        orderExtInfoDto.setPhone(assortmentCustomerInfoVo.getMobile());
        orderExtInfoDto.setAppid(wxAppId);
        UpdateOrderReq updateOrderReq = new UpdateOrderReq();
        updateOrderReq.setPartnerId(orderBean.getCompanyId());
        updateOrderReq.setOrderCode(orderBean.getOid());
        updateOrderReq.setExtInfo(JSONObject.toJSONString(orderExtInfoDto));
        com.freemud.application.sdk.api.ordercenter.response.OrderBaseResp response = orderSdkService.editOrder(updateOrderReq, LogThreadLocal.getTrackingNo());
        if (!ObjectUtils.equals(ResponseCodeConstant.RESPONSE_SUCCESS_STR, response.getCode())) {
            throw new ServiceException(ResponseResult.ORDER_EDIT_ERROR, response.getMessage());
        }
        if (orderBean.getAmount() > 0 && StringUtils.isBlank(cardCode)) {
            createOrderResponseVo.setPaySuccess(false);
        } else {
            createOrderResponseVo.setPaySuccess(true);
        }
        return createOrderResponseVo;
    }

    /**
     * 扫脸支付
     */
    public OrderPayResponse facePay(String cardCode, OrderBeanV1 orderBean, PaymentRequest paymentRequest, String trackingNo) {
        FacePayRequestDto request = new FacePayRequestDto();
        OrderPayResponse orderPayResponse = new OrderPayResponse();
        String partnerId = orderBean.getCompanyId();
        request.setBody(orderBean.getShopName());
        request.setBusinessDate(DateUtil.convert2String(new Date(), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
        request.setCode(cardCode);
        request.setPartnerId(partnerId);
        request.setStoreId(orderBean.getShopId());
        request.setAmount(orderBean.getAmount());
        request.setTransId(orderBean.getOid());
        request.setStationId("1");
        request.setOperatorId("1");
        request.setVer("2");
        //支付服务扫脸付接口
        com.freemud.application.sdk.api.base.BaseResponse<UnifiedPayResponseDto> responseDto = null;
        try {
            responseDto = paymentNewClient.facePay(request);
        } catch (Exception e) {
            AppLogUtil.errorLog("facePay_error", null, null, e);
        }
        if (responseDto == null || !ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(responseDto.getCode()) || responseDto.getData() == null) {
            // 1.9.34 预支付失败需要把原因进行记录
            orderPayResponse.setMsg(Objects.isNull(responseDto) ? "扫脸支付异常" : responseDto.getMessage());
        } else {
            UnifiedPayResponseDto response = responseDto.getData();
            orderPayResponse.setFmId(response.getFmId());
            orderPayResponse.setPayTransId(response.getPayTransId());
            orderPayResponse.setWxAppid(paymentRequest.getWxAppId());
            orderPayResponse.setOpenId(paymentRequest.getOpenId());
            orderPayResponse.setPartnerId(orderBean.getCompanyId());
            orderPayResponse.setOrderId(orderBean.getOid());
        }
        return orderPayResponse;
    }


    /**
     * 查询支付配置
     */
    private PaymentRequest orderBodyConvertToPaymentBody(String openId, String partnerId, String appId, String payCode) {
        //设置支付信息
        PaymentRequest paymentRequest = new PaymentRequest();
        paymentRequest.setOpenId(openId);
        paymentRequest.setWxAppId(appId);
        paymentRequest.setReverseNotifyiDcUrl(reverseNotifyiDcUrl);
        paymentRequest.setPayCode(payCode);
//        if ("2080".equals(partnerId)) {
            //【ID1035981】【蜜雪冰城】订单C端，拼接order_body字段：蜜雪冰城+门店编号
//            paymentRequest.setPrincipalName("蜜雪冰城" + storeId + "店");
//        } else {
            // saas 查询小程序配置
            paymentRequest.setPrincipalName(this.getPaymentPrincipalName(partnerId, appId));
//        }
        return paymentRequest;
    }

    /**
     * 查询支付配置
     */
    public String getPaymentPrincipalName(String partnerId, String appId) {
        String redisKey = MessageFormat.format(OrderRedisKeyConstant.PARTNER_PAYMENT_PRINCIPAL_NAME, partnerId);
        // 先从redis中查询支付商户名称
        String principalName = redisCache.hashGet(redisKey, appId);
        if (StringUtils.isEmpty(principalName)) {
            AssortmentOpenPlatformWxapp wxApp = openPlatformWxappManager.findByPartnerIdAndWxappId(partnerId, appId);
            if (wxApp == null || StringUtils.isEmpty(wxApp.getPrincipalName())) {
                // 小程序如果没有配置支付商户名称，则去商户名称替代
                AssortmentOpenPlatformPartner platformPartner = assortmentOpenPlatformPartnerManager.selectOpenPlatformPartner(partnerId);
                if (null != platformPartner) principalName = platformPartner.getCompanyName();
            } else {
                principalName = wxApp.getPrincipalName();
            }
            if (StringUtils.isEmpty(principalName)) {
                //如果还是没有查到，就用非码代替
                principalName = "上海非码网络科技有限公司";
            }
            // 加载到redis，有效期一天
            redisCache.hashPut(redisKey, appId, principalName);
            redisCache.updateTTL(redisKey, 24, TimeUnit.HOURS);
        }
        return principalName;
    }


    /**
     * 电子风味卡支付
     * unionPay card pay
     */
    public OrderPayResponse uSvcPay(OrderBeanV1 orderBean, PaymentRequest paymentRequest, String transId, String trackingNo, CreateOrderUnionPayCardVo unionPayCard) {
        OrderPayResponse orderPayResponse = new OrderPayResponse();
        if (Objects.isNull(unionPayCard) || StringUtils.isBlank(unionPayCard.getCode()) || StringUtils.isBlank(unionPayCard.getPassword())) {
            orderPayResponse.setMsg("电子风味卡信息缺失");
            return orderPayResponse;
        }
        FacePayRequestDto request = new FacePayRequestDto();
        String partnerId = orderBean.getCompanyId();
        request.setBody(orderBean.getShopName());
        request.setBusinessDate(DateTimeFormatter.ofPattern(DateUtil.FORMAT_YYYY_MM_DD_HHMMSS).format(LocalDateTime.now()));
        // paymentRequest 的 payCode可能为null,不保险
        request.setPayCode(PayChannel.USVCP.getCode());
        // 电子风味卡信息
        request.setCode(unionPayCard.getCode());
        request.setCardPassword(unionPayCard.getPassword());
        request.setPartnerId(partnerId);
        request.setStoreId(orderBean.getShopId());
        request.setAmount(orderBean.getAmount());
        request.setTransId(transId);
        request.setStationId("2");
        request.setOperatorId("2");
        request.setVer("2");
        request.setMerchantDiscount(orderBean.getOriginalAmount().longValue() - orderBean.getAmount());
        com.freemud.application.sdk.api.base.BaseResponse<UnifiedPayResponseDto> responseBase = paymentNewClient.codePay(request);
        if (responseBase == null || !ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(responseBase.getCode()) || responseBase.getData() == null) {
            // 需要把2种特殊情况抛给用户
            if (Objects.nonNull(responseBase) && (ResponseCodeConstant.PASSWORD_WRONG.equals(responseBase.getCode()) || ResponseCodeConstant.NOT_SUFFICIENT_FUND.equals(responseBase.getCode()))) {
                orderPayResponse.setPayTransId(responseBase.getCode());
            }
            orderPayResponse.setMsg(Objects.isNull(responseBase) ? "电子风味卡支付异常" : responseBase.getMessage());
        } else {
            UnifiedPayResponseDto codePayResponse = responseBase.getData();
            orderPayResponse.setFmId(codePayResponse.getFmId());
            orderPayResponse.setPayTransId(codePayResponse.getPayTransId());
            orderPayResponse.setWxAppid(paymentRequest.getWxAppId());
            orderPayResponse.setOpenId(paymentRequest.getOpenId());
            orderPayResponse.setPartnerId(orderBean.getCompanyId());
            orderPayResponse.setOrderId(orderBean.getOid());
            orderPayResponse.setPayChannelType(PayChannelType.USVCP);
        }
        return orderPayResponse;
    }


    /**
     * 获取商户支付超时时间
     */
    public String getPartnerPayOvertime(String partnerId) {
        return Optional.ofNullable(openPlatformPartnerConfigManager.selectPartnerConfigByPartnerKey(partnerId, RedisKeyConstant.PARTNER_PAY_OVERTIME))
                .orElseGet(() -> {
                    AssortmentOpenPlatformPartnerConfig config = new AssortmentOpenPlatformPartnerConfig();
                    config.setPartnerValue("30");
                    openPlatformPartnerConfigManager.addPartnerConfig(partnerId, RedisKeyConstant.PARTNER_PAY_OVERTIME, config);
                    return config;
                }).getPartnerValue();
    }


    /**
     * 现金支付
     */
    public OrderPayResponse getPreOrderPay(OrderBeanV1 orderBean, PaymentRequest paymentRequest, Integer cardAmount, String transId, OrderExtInfoDto orderExtInfoDto) {
        String partnerPayOvertime = this.getPartnerPayOvertime(orderBean.getCompanyId());

        OrderPayResponse orderPayResponse;

        UnifiedOrderCom com = new UnifiedOrderCom(orderBean, paymentRequest, orderBean.getAmount(), cardAmount, transId, partnerPayOvertime);
        //支付聚合sdk 请求参数
        UnifiedOrderRequest request = orderAdapter.convent2UnifiedOrderRequest(com);
        //Feign 预支付接口请求参数
        UnifiedOrderRequestDto requestDto = this.convert2UnifiedOrderRequestDto(com);
        // add by miaohui for 拼单群收款判断拼单人数大于1时参与微信平台补贴活动，创建预支付时上送goodsTag，后续抽成促销服务活动时删除此逻辑 start
        if (null != orderBean.getMarketingType() && MarketTypeEnum.COLLAGE.getIndex().byteValue() == orderBean.getMarketingType()) {
            // 拼单人数大于1人时参加拼单补贴
            if (null != orderBean.getProductList() && orderBean.getProductList().stream().map(ProductBeanV1::getUserId).distinct().collect(Collectors.toList()).size() > 1) {
                Map<String, String> goodsTagMap = this.goodsTagMap();
                String goodsTag = goodsTagMap.get(orderBean.getCompanyId());
                goodsTag = StringUtils.isBlank(goodsTag) ? collageGoodsTag : goodsTag;
                request.setGoodsTag(goodsTag);
                requestDto.setGoodsTag(goodsTag);
            }
        }
        // add by miaohui for 拼单群收款判断拼单人数大于1时参与微信平台补贴活动，创建预支付时上送goodsTag，后续抽成促销服务活动时删除此逻辑 end
        if (orderExtInfoDto != null && StringUtils.isNotBlank(orderExtInfoDto.getStationId())) {
            request.setStationId(orderExtInfoDto.getStationId());
            requestDto.setStationId(orderExtInfoDto.getStationId());
        }
        //使用支付FeignClient
//        if (usePayFeignClient) {
            orderPayResponse = new OrderPayResponse();
            String clientCode = this.getPayCodeByChanel(paymentRequest.getWxAppId(), orderBean.getShopId());
            if (StringUtils.isBlank(clientCode)) {
                orderPayResponse.setMsg("请先联系相关人员配置商户对应的支付渠道");
                return orderPayResponse;
            }
            requestDto.setClientCode(Long.parseLong(clientCode));
//            com.freemud.application.sdk.api.base.BaseResponse<UnifiedPayResponseDto> response = paymentNewClient.unifiedOrder(requestDto);
            com.freemud.application.sdk.api.base.BaseResponse<UnifiedPayResponseDto> response = null;
            //处理超时情况，后续冲正mq正常冲正，同支付sdk逻辑
            try {
                response = this.unifiedOrder(requestDto);
            } catch (Exception e) {
                AppLogUtil.errorLog("获取预支付信息异常", JSONObject.toJSONString(requestDto), null, e);
            }
            //预支付接口失败
            if (null == response || !Objects.equals(ResponseCodeConstant.RESPONSE_SUCCESS_STR, response.getCode())
                    || !Objects.equals(ResponseCodeConstant.RESPONSE_SUCCESS, response.getData().getResultCode())) {
                String errorMessage = "unified fail";
                if (null != response) {
                    errorMessage = StringUtils.isNotEmpty(response.getMessage()) ? response.getMessage() : response.getData().getResultMsg();
                }
                //打印业务异常
                if (response != null && printUnifiedPayResponseError) {
                    AppLogUtil.errorLog("获取预支付信息失败", JSONObject.toJSONString(requestDto), JSONObject.toJSONString(response), null);
                }
                //预支付失败需要把原因进行记录
                orderPayResponse.setMsg(errorMessage);
                return orderPayResponse;
            }
            putDelMq(request.getPartnerId(), request.getStoreId(), response.getData().getFmId(), orderBean.getOid(), null);
            this.convent2CreateOrderResponseVo(orderPayResponse, paymentRequest.getWxAppId(), response.getData());
            orderPayResponse.setOpenId(paymentRequest.getOpenId());
            orderPayResponse.setPartnerId(orderBean.getCompanyId());
            orderPayResponse.setOrderId(orderBean.getOid());
            orderPayResponse.setPayChannelType(PayChannelType.WECHAT);
            if (orderPayResponse.getPayOrder() != null && StringUtils.isNotBlank(orderPayResponse.getPayOrder().getAliPayOrder())
                    && !orderPayResponse.getPayOrder().getAliPayOrder().startsWith("wx")) {
                orderPayResponse.setPayChannelType(PayChannelType.ALIPAY);
            }
            //抖音支付
            if (PayChannelType.TIKTOKPAY.getIndex().toString().equalsIgnoreCase(orderBean.getPayChannelType())) {
                orderPayResponse.setPayChannelType(PayChannelType.TIKTOKPAY);
            }
            return orderPayResponse;
//        }
//        com.freemud.application.sdk.api.base.BaseResponse<UnifiedOrderResponse> responseBase = standardPaymentService.unifiedOrder(request, trackingNo);
//        if (!ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(responseBase.getCode())) {
//            // 1.9.34 预支付失败需要把原因进行记录
//            orderPayResponse = new OrderPayResponse();
//            orderPayResponse.setMsg(responseBase.getMessage());
//        } else {
//            putDelMq(request.getPartnerId(), request.getStoreId(), responseBase.getData().getFmId(), orderBean.getOid(), null);
//            orderPayResponse = orderAdapter.convent2OrderPayResponse(responseBase.getData());
//            orderPayResponse.setWxAppid(paymentRequest.getWxAppId());
//            orderPayResponse.setOpenId(paymentRequest.getOpenId());
//            orderPayResponse.setPartnerId(orderBean.getCompanyId());
//            orderPayResponse.setOrderId(orderBean.getOid());
//            orderPayResponse.setPayChannelType(PayChannelType.WECHAT);
//            if (orderPayResponse.getPayOrder() != null && StringUtils.isNotBlank(orderPayResponse.getPayOrder().getAliPayOrder())) {
//                orderPayResponse.setPayChannelType(PayChannelType.ALIPAY);
//            }
//            //抖音支付
//            if (PayChannelType.TIKTOKPAY.getIndex().toString().equalsIgnoreCase(orderBean.getPayChannelType())) {
//                orderPayResponse.setPayChannelType(PayChannelType.TIKTOKPAY);
//            }
//
//        }
//        return orderPayResponse;
    }


    /**
     * 混合支付
     */
    public OrderPayResponse switchSvcOrComb(Long totalAmount
            , String cardCode
            , OrderBeanV1 orderBean
            , PaymentRequest paymentRequest
            , String transId
            , String channel) {

        OrderPayResponse orderPayResponse = null;
        //混合支付开关
        boolean check = this.checkSvcComPay(orderBean.getCompanyId(), orderBean.getShopId());
        //混合支付
        if (check && StringUtils.isNotBlank(channel)) {
            String partnerPayOvertime = this.getPartnerPayOvertime(orderBean.getCompanyId());
            orderPayResponse = comPayOrder(cardCode, orderBean, paymentRequest, partnerPayOvertime, totalAmount.intValue(), channel, orderBean.getShopId());
        } else {//svc 支付
            orderPayResponse = svcPay(cardCode, orderBean, paymentRequest, transId);
        }
        return orderPayResponse;
    }


    /**
     * 创建混合支付
     */
    public OrderPayResponse comPayOrder(String cardNo
            , OrderBeanV1 orderBean
            , PaymentRequest paymentRequest
            , String partnerPayOvertime
            , Integer totalAmount
            , String channel
            , String storeId) {

        String ebCode = this.getPayCodeByChanel(paymentRequest.getWxAppId(), channel, storeId);
        OrderPayResponse orderPayResponse = new OrderPayResponse();

        if (StringUtils.isBlank(ebCode)) {
            orderPayResponse.setMsg("请先联系相关人员配置商户对应的支付渠道");
            return orderPayResponse;
        }

        CombPayRequest combPayRequest = orderAdapter.convent2CombPayOrderRequest(cardNo, orderBean, paymentRequest, partnerPayOvertime, ebCode, channel, totalAmount);
        CombPayResponse combPayResponse = comPayClient.combPay(combPayRequest, combPayRequest.getPartner_id());
        if (combPayResponse == null || !ResponseCodeConstant.PAYMENT_RESPONSE_SUCCESS.equals(combPayResponse.getCode())) {
            orderPayResponse.setMsg(combPayResponse != null ? "支付：" + combPayResponse.getMsg() : "混合支付忙不过来啦，请稍后再试");
            return orderPayResponse;
        }
        List<CombPayResponse.PayPlatform> payPlatforms = combPayResponse.getData().getPayPlatformResponseList();
        if (payPlatforms.size() == 0) {
            orderPayResponse.setMsg("混合支付:生成预支付失败");
            return orderPayResponse;
        }

        orderPayResponse.setWxAppid(paymentRequest.getWxAppId());
        orderPayResponse.setOpenId(paymentRequest.getOpenId());
        orderPayResponse.setPartnerId(orderBean.getCompanyId());
        orderPayResponse.setOrderId(orderBean.getOid());
        orderPayResponse.setMsg("success");
        orderPayResponse.setPayId("");

        CombPayResponse.PayPlatform cashPay = null;
        for (CombPayResponse.PayPlatform pt : payPlatforms) {
            if (!PayChannelType.SVC.getEbcode().equals(pt.getEbCode())) {
                cashPay = pt;
            }else{
                SvcPayItem payItem = new SvcPayItem();
                payItem.setCardCode(cardNo);
                payItem.setSvcTransId(pt.getPlatformTradeNo());
                payItem.setTransId(pt.getTransId());
                if(CollectionUtils.isEmpty(orderPayResponse.getSvcPayItems())){
                    List<SvcPayItem> svcPayItems = new ArrayList<>();
                    svcPayItems.add(payItem);
                    orderPayResponse.setSvcPayItems(svcPayItems);
                }else{
                    orderPayResponse.getSvcPayItems().add(payItem);
                }
            }
            orderPayResponse.setFmId(pt.getTransId());
            orderPayResponse.setPayTransId(pt.getTransId());
            PayChannelType payChannelType = PayChannelType.getByEbcode(pt.getEbCode());
            if (pt.getCardType() != null && pt.getCardType() == 0) {
                payChannelType = PayChannelType.GIFTCARD;
            }
            orderPayResponse.setPayChannelType(payChannelType);
            orderPayResponse.setPayEbcode(pt.getEbCode());
            OrderPayItemResp payItem = new OrderPayItemResp();
            payItem.setFmTradeNo(pt.getFmTradeNo());
            payItem.setStoreId(storeId);
            payItem.setPayChannelType(payChannelType.getIndex().intValue());
            payItem.setPayChannelName(payChannelType.getName());
            payItem.setTransId(pt.getTransId());
            payItem.setPartnerId(combPayRequest.getPartner_id());
            payItem.setPayAmount(new BigDecimal(pt.getPayAmount()));
            orderPayResponse.getPayItem().add(payItem);
            CombPayResponse.PayPlatform.PayOrderBean payOrderBean = pt.getPayOrder();
            if (null != payOrderBean) {
                OrderPayResponse.PayOrderBean payBean = new OrderPayResponse.PayOrderBean();
                payBean.setAppid(payOrderBean.getAppId());
                payBean.setNonceStr(payOrderBean.getNonceStr());
                payBean.setPackageX(payOrderBean.getPackageX());
                payBean.setSign(payOrderBean.getPaySign());
                payBean.setSignType(payOrderBean.getSignType());
                payBean.setTimestamp(payOrderBean.getTimeStamp());
                payBean.setAliPayOrder(payOrderBean.getAliPayOrder());
                orderPayResponse.setPayOrder(payBean);
            }
        }
        if (payPlatforms.size() > 1) {
            orderPayResponse.setPayChannelType(PayChannelType.COMB);
        }
        //现金线上支付
        if (cashPay != null) {
            String transId = cashPay.getTransId();
            orderPayResponse.setFmId(cashPay.getFmTradeNo());
            orderPayResponse.setEndTransId(cashPay.getEndTransTradeNo());
            redisCache.save(RedisUtil.getPaymentTransIdOrderKey(transId), orderBean.getOid(), 1L, TimeUnit.DAYS);
            //加入轮训队列
            putDelMq(orderBean.getCompanyId(), storeId, orderPayResponse.getFmId(), orderBean.getOid(), PayChannelType.getByEbcode(transId).getIndex().intValue());
        }
        return orderPayResponse;
    }


    /**
     * 纯储值卡或礼品卡支付
     */
    public OrderPayResponse svcPay(String cardCode, OrderBeanV1 orderBean, PaymentRequest paymentRequest, String transId) {
        FacePayRequestDto request = new FacePayRequestDto();
        OrderPayResponse orderPayResponse = new OrderPayResponse();
        String partnerId = orderBean.getCompanyId();
        request.setBody(orderBean.getShopName());
        request.setBusinessDate(DateUtil.convert2String(new Date(), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
        request.setCode(cardCode);
        request.setPartnerId(partnerId);
        request.setStoreId(orderBean.getShopId());
        request.setAmount(orderBean.getAmount());
        request.setTransId(transId);
        request.setStationId("1");
        request.setOperatorId("1");
        request.setVer("2");
        request.setMerchantDiscount(orderBean.getOriginalAmount().longValue() - orderBean.getAmount());
        request.setApplicationType(orderAdapter.getPayApplicationType(orderBean.getOrderClient()));
        SVCCardAmountRequestDto svcRequest = new SVCCardAmountRequestDto();
        svcRequest.setPartnerId(partnerId);
        svcRequest.setCardCodes(Arrays.asList(cardCode));
        //查询svc卡余额
        BaseResponse<SVCCardAmountResponseDto> svcCardAmountResponseBaseResponse = svcAppClient.batchQueryCardAmount(svcRequest);
        if (svcCardAmountResponseBaseResponse == null || !ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(svcCardAmountResponseBaseResponse.getCode())
                || svcCardAmountResponseBaseResponse.getResult() == null || CollectionUtils.isEmpty(svcCardAmountResponseBaseResponse.getResult().getCardSimpleInfos())) {
            orderPayResponse.setMsg(Objects.isNull(svcCardAmountResponseBaseResponse) ? "获取卡余额异常" : svcCardAmountResponseBaseResponse.getMessage());
            return orderPayResponse;
        }
        Integer amount = svcCardAmountResponseBaseResponse.getResult().getCardSimpleInfos().get(0).getAmount();
        Integer vamount = svcCardAmountResponseBaseResponse.getResult().getCardSimpleInfos().get(0).getVamount();
        Integer applyType = svcCardAmountResponseBaseResponse.getResult().getCardSimpleInfos().get(0).getApplyType();
        applyType = applyType == null ? 3 : applyType;
        PayChannelType payChannelType = applyType == 3 ? PayChannelType.SVC : PayChannelType.GIFTCARD;
        if (amount + vamount < orderBean.getAmount()) {
            orderPayResponse.setMsg("卡余额不足");
            return orderPayResponse;
        }
        //svc卡支付
        com.freemud.application.sdk.api.base.BaseResponse<UnifiedPayResponseDto> responseBase = paymentNewClient.codePay(request);
        if (responseBase == null || !ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(responseBase.getCode())
                || responseBase.getData() == null || !Objects.equals(responseBase.getData().getResultCode(), ResponseCodeConstant.RESPONSE_SUCCESS)) {
            // 1.9.34 预支付失败需要把原因进行记录
            orderPayResponse.setMsg(Objects.isNull(responseBase) ? "卡支付异常" : responseBase.getMessage());
        } else {
            UnifiedPayResponseDto codePayResponse = responseBase.getData();
            orderPayResponse.setFmId(codePayResponse.getFmId());
            orderPayResponse.setPayTransId(codePayResponse.getPayTransId());
            orderPayResponse.setWxAppid(paymentRequest.getWxAppId());
            orderPayResponse.setOpenId(paymentRequest.getOpenId());
            orderPayResponse.setPartnerId(orderBean.getCompanyId());
            orderPayResponse.setOrderId(orderBean.getOid());
            orderPayResponse.setPayChannelType(payChannelType);
            orderPayResponse.setSvcPayItems(orderAdapter.convertSvcPayItem(codePayResponse,cardCode));
        }
        return orderPayResponse;
    }

    /**
     * 创建预支付订单，唤起支付
     */
    public com.freemud.application.sdk.api.base.BaseResponse<UnifiedPayResponseDto> unifiedOrder(UnifiedOrderRequestDto request) {
        return paymentNewClient.unifiedOrder(request);
    }

    /**
     * 开订单发票
     */
    public com.freemud.application.sdk.api.base.BaseResponse<InvoiceCreateResponse> createInvoice(InvoiceCreateRequest request){
        return paymentNewClient.createInvoice(request);
    }

    /**
     * 关闭预支付订单
     */
    public com.freemud.application.sdk.api.base.BaseResponse<PaymentCloseUnifiedOrderResponse> cancelNewUnifiedOrder( PaymentCloseUnifiedOrderRequest request){
        return paymentNewClient.cancelNewUnifiedOrder(request);
    }

    /**
     * 支付查询
     */
    public com.freemud.application.sdk.api.base.BaseResponse<PaymentQueryResponseDto> payQuery(PaymentQueryRequestDto request){
        return paymentNewClient.payQuery(request);
    }


    /**
     * 支付退款
     */
    public com.freemud.application.sdk.api.base.BaseResponse<OrderRefundResponse> orderRefund(PayRefundRequestDto orderPayRefundRequest) {
        return orderPayRefund(orderPayRefundRequest);
    }

    /**
     * 混合支付退款接口
     */
    public MultiOrderRefundResponse paymentApplicationRefund(MultiOrderRefundRequest multiOrderRefundRequest, String partnerId) {
        return mulitiPaymentClient.paymentApplicationRefund(multiOrderRefundRequest, partnerId);
    }

    /**
     * 批量支付退款
     */
    public PayBatchRefundResponse batchRefund(BatchOrderRefundV2Request batchOrderRefundV2Request) {
        return mulitiPaymentClient.batchRefund(batchOrderRefundV2Request);
    }


    /**
     * 关闭预支付
     */
    public boolean closePrePay(OrderBeanV1 orderBean) {
        //是否支付成功
        boolean paySuccess = false;
        if (!queryPayOrder) {
            return paySuccess;
        }
        OrderExtInfoDto extInfo = JSONObject.parseObject(orderBean.getExtInfo(), OrderExtInfoDto.class);

        List<OrderPayItemResp> orderPayItemList = orderBean.getOrderPayItem();
        if (null != orderPayItemList && orderPayItemList.size() > 0) {
            Integer partnerId = Integer.valueOf(orderBean.getCompanyId());
            MultiQueryRequest request = new MultiQueryRequest();
            request.setPartnerId(partnerId);
            request.setStoreId(orderBean.getShopId());
            request.setOutOrderNo(orderBean.getOid());
            //查询聚合支付结果
            MultiQueryRespDto response = comPayClient.paymentApplicationQuery(request, partnerId);
            if (response != null && response.getData() != null && Objects.equals(response.getCode(), MULITI_RESPONSE)) {
                List<MultiPaymentRespDto> multiPaymentRespDtoArrayList = response.getData().getQueryList();
                if (null != multiPaymentRespDtoArrayList && multiPaymentRespDtoArrayList.size() > 0) {
                    int successData = 0;
                    for (MultiPaymentRespDto multiPaymentRespDto : multiPaymentRespDtoArrayList) {
                        if (Objects.equals(multiPaymentRespDto.getStatus(), SUCCESS)) {
                            successData++;
                        }
                    }
                    if (successData >= multiPaymentRespDtoArrayList.size()) {
                        paySuccess = true;
                    }
                }
            }
        } else {
            //判断当前订单是否存在预支付订单
            if (extInfo != null && StringUtils.isNotEmpty(extInfo.getFmId())) {
                //订单状态未支付且存在预支付订单：
                // 1.查询预支付订单支付状态
                PaymentQueryRequestDto paymentQueryRequest = new PaymentQueryRequestDto();
                paymentQueryRequest.setPartnerId(orderBean.getCompanyId());
                paymentQueryRequest.setStoreId(orderBean.getShopId());
                paymentQueryRequest.setFmId(extInfo.getFmId());
                paymentQueryRequest.setVer("2");
                com.freemud.application.sdk.api.base.BaseResponse<PaymentQueryResponseDto> queryResponseBaseResponse = this.payQuery(paymentQueryRequest);
                //判断预支付订单状态
                if (ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(), queryResponseBaseResponse.getCode())) {
                    throw new ServiceException(ResponseResult.ORDER_PAY_GETPRE_MESSAGE_ERROR);
                }
                //判断当前预支付订单是否已经支付成功
                if (queryResponseBaseResponse.getData() != null && ObjectUtils.equals(TradeState.SUCCESS.getCode(), queryResponseBaseResponse.getData().getTradeState())) {
                    paySuccess = true;
                }
            }
        }

        if (!paySuccess && extInfo != null && StringUtils.isNotEmpty(extInfo.getFmId())) {
            PaymentCloseUnifiedOrderRequest closeUnifiedOrderRequest = new PaymentCloseUnifiedOrderRequest();
            closeUnifiedOrderRequest.setFmId(extInfo.getFmId());
            closeUnifiedOrderRequest.setVer("2");
            closeUnifiedOrderRequest.setPartnerId(orderBean.getCompanyId());
            closeUnifiedOrderRequest.setStoreId(orderBean.getShopId());
            com.freemud.application.sdk.api.base.BaseResponse<PaymentCloseUnifiedOrderResponse> cancelNewUnifiedOrder = this.cancelNewUnifiedOrder(closeUnifiedOrderRequest);
            if (ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(), cancelNewUnifiedOrder.getCode())) {
                throw new ServiceException(ResponseResult.ORDER_PRE_PAYMENT_CLOSE_FAILED);
            }
        }
        return paySuccess;
    }

    /**
     * 与　closePrePay 待合并
     */
    public void closeHistoryPrePay(OrderBeanV1 orderBean) {

        OrderExtInfoDto extInfo = JSONObject.parseObject(orderBean.getExtInfo(), OrderExtInfoDto.class);
        //判断当前订单是否存在预支付订单
        if (extInfo != null && StringUtils.isNotEmpty(extInfo.getFmId())) {
            //订单状态未支付且存在预支付订单：
            // 1.查询预支付订单支付状态
            PaymentQueryRequestDto paymentQueryRequest = new PaymentQueryRequestDto();
            paymentQueryRequest.setPartnerId(orderBean.getCompanyId());
            paymentQueryRequest.setStoreId(orderBean.getShopId());
            paymentQueryRequest.setFmId(extInfo.getFmId());
            paymentQueryRequest.setVer("2");
            com.freemud.application.sdk.api.base.BaseResponse<PaymentQueryResponseDto> queryResponseBaseResponse = this.payQuery(paymentQueryRequest);
            //判断预支付订单状态
            if (ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(), queryResponseBaseResponse.getCode())) {
                throw new ServiceException(ResponseResult.ORDER_PAY_GETPRE_MESSAGE_ERROR);
            }
            //判断当前预支付订单是否已经支付成功
            if (ObjectUtils.equals(TradeState.SUCCESS.getCode(), queryResponseBaseResponse.getData().getTradeState())) {
                throw new ServiceException(ResponseResult.ORDER_HAS_PAID);
            }
            // 3.取消前一个预支付订单  调用支付取消预支付订单,如果预支付订单已经取消了再调用取消预支付订单接口会报错的
            if (ObjectUtils.equals(TradeState.NOTPAY.getCode(), queryResponseBaseResponse.getData().getTradeState())) {
                PaymentCloseUnifiedOrderRequest closeUnifiedOrderRequest = new PaymentCloseUnifiedOrderRequest();
                closeUnifiedOrderRequest.setFmId(extInfo.getFmId());
                closeUnifiedOrderRequest.setVer("2");
                closeUnifiedOrderRequest.setPartnerId(orderBean.getCompanyId());
                closeUnifiedOrderRequest.setStoreId(orderBean.getShopId());
                com.freemud.application.sdk.api.base.BaseResponse<PaymentCloseUnifiedOrderResponse> cancelNewUnifiedOrder = this.cancelNewUnifiedOrder(closeUnifiedOrderRequest);
                if (ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(), cancelNewUnifiedOrder.getCode())) {
                    throw new ServiceException(ResponseResult.ORDER_PRE_PAYMENT_CLOSE_FAILED);
                }
            }
        }
    }

    /**
     * 编辑订单，保持预支付信息
     */
    public BaseResponse updateOrderInfo(OrderPayResponse orderPayResponse, OrderExtInfoDto orderExtInfo
            , OrderBeanV1 orderBean, String trackingNo) {
        orderExtInfo.setOpenid(orderPayResponse.getOpenId());
        orderExtInfo.setFmId(orderPayResponse.getFmId());
        orderExtInfo.setAppid(orderPayResponse.getWxAppid());
        String prepayId = "";
        OrderPayResponse.PayOrderBean payOrder = orderPayResponse.getPayOrder();
        if (payOrder != null && !StringUtils.isEmpty(payOrder.getPackageX())) {
            String[] prepayIds = payOrder.getPackageX().split("=");
            prepayId = prepayIds.length > 1 ? prepayIds[1] : "";
        }
        //支付宝保存交易流水号发送支付宝模板消息
        if (payOrder != null && !StringUtils.isEmpty(payOrder.getAliPayOrder())) {
            prepayId = payOrder.getAliPayOrder();
        }
        orderExtInfo.setPrepayId(prepayId);

        OrderEditRequest orderEditRequest = new OrderEditRequest(orderPayResponse.getPayTransId(),
                JSONObject.toJSONString(orderExtInfo), orderBean.getCompanyId());
        orderEditRequest.setOrderId(orderBean.getOid());
        orderEditRequest.setTrackingNo(trackingNo);
        if (orderPayResponse.getPayChannelType() != null) {
            orderEditRequest.setPayChannel(orderPayResponse.getPayChannelType().getEbcode());
            orderEditRequest.setPayChannelName(orderPayResponse.getPayChannelType().getName());
            orderEditRequest.setPayChannelType(orderPayResponse.getPayChannelType().getIndex());
        }
        //混合支付项
        if (CollectionUtils.isNotEmpty(orderPayResponse.getPayItem())) {
            orderEditRequest.setOrderPayItem(orderPayResponse.getPayItem());

            //混合支付已经处理好PayChannelType了
            /*if (orderPayResponse.getPayItem().size() == 2) {
                orderEditRequest.setPayChannel(PayChannelType.COMB.getEbcode());
                orderEditRequest.setPayChannelName(PayChannelType.COMB.getName());
                orderEditRequest.setPayChannelType(PayChannelType.COMB.getIndex());
            }*/
        }

        UpdateOrderReq updateOrderReq = new UpdateOrderReq();
        updateOrderReq.setPartnerId(orderBean.getCompanyId());
        updateOrderReq.setOrderCode(orderEditRequest.getOrderId());
        updateOrderReq.setExtInfo(orderEditRequest.getExtInfo());
        updateOrderReq.setOrderPayItem(orderEditRequest.getOrderPayItem());
        updateOrderReq.setPayChannel(orderEditRequest.getPayChannel());
        updateOrderReq.setPayChannelName(orderEditRequest.getPayChannelName());
        updateOrderReq.setPayChannelType(orderEditRequest.getPayChannelType());
        com.freemud.application.sdk.api.ordercenter.response.OrderBaseResp response = orderSdkService.editOrder(updateOrderReq, orderEditRequest.getTrackingNo());
        if (!ObjectUtils.equals(ResponseCodeConstant.RESPONSE_SUCCESS_STR, response.getCode())) {
            CancelOrderRequest cancelOrderRequest = orderAdapter.convent2CancelOrderRequest(orderBean.getOid(), orderBean.getCompanyId(),
                    AfterSalesType.SYSTEM_CANCEL, "编辑订单支付信息失败", trackingNo, null);
            OrderCancelReq request = new OrderCancelReq();
            //商户号必传
            request.setPartnerId(cancelOrderRequest.getPartnerId());
            request.setOrderCode(cancelOrderRequest.getOrderId());
            request.setReqRemark(cancelOrderRequest.getReqRemark());
            //售后单类型 1:其他取消 2:用户取消 3:商户取消 4:未支付超时关单 5:商户接单超时取消 6:商家拒单
            // 7:配送用户拒收 8:用户售后退货/售后退款 9:系统取消 10:客服取消 11:用户统一取消，
            request.setAfterSalesType(cancelOrderRequest.getAfterSalesType().getIndex() == null ? 1 : cancelOrderRequest.getAfterSalesType().getIndex());
            request.setOrderClient(cancelOrderRequest.getOrderClient());
            request.setCancelReason(cancelOrderRequest.getReason());
            request.setAfterSalesReason(cancelOrderRequest.getReason());
            //若为4，默认做【创建】+【同意并退款完成】，售后单状态为【完成】
            request.setCreateEvent(cancelOrderRequest.getCreateEvent());
            request.setAfterSerialNo(cancelOrderRequest.getRefundSerialNo());
            request.setOperator(cancelOrderRequest.getOperator());

            // 【华莱士20210510活动】新增加退款方式字段
            if (Objects.nonNull(cancelOrderRequest.getExtInfoReq())) {
                request.setExtInfo(JSON.toJSONString(cancelOrderRequest.getExtInfoReq()));
            }
            request.setRefundDeliveryAmount(cancelOrderRequest.isRefundDeliveryAmount());
            com.freemud.application.sdk.api.ordercenter.response.OrderBaseResp cancelOrderResponse = orderSdkService.cancelOrder(request, cancelOrderRequest.getTrackingNo());

            //如果编辑订单支付信息失败，冲正
            orderQueueService.backOrdersStatusChange(orderBean.getOid(), orderBean.getStatus(), PayStatusEnum.NOT_PAY.getCode());
            return ResponseUtil.error(response.getCode(), response.getMessage());
        }
        return null;
    }


    /**
     * 拼单参数
     */
    private Map<String, String> goodsTagMap() {
        Map<String, String> map = new HashMap<>();
        try {
            for (String pg : collageGoodsTagList.split(",")) {
                map.put(pg.split(":")[0], pg.split(":")[1]);
            }
        } catch (Exception e) {
            AppLogUtil.errorLog("goodsTag解析失败：", "", "", e);
        }
        return map;
    }


    /**
     * 支付失败处理
     */
    private BaseResponse failPreOrderPay(String trackingNo, OrderBeanV1 orderBean, List<String> cardCodes, OrderClientType orderClient, String msg) {
        List<OrderClientType> notCancelOrderClientList = Lists.newArrayList(OrderClientType.APP);
        if (!notCancelOrderClientList.contains(orderClient)) {
            //失败冲正库存，冲正活动库存，取消订单
            CancelOrderRequest cancelOrderRequest = orderAdapter.convent2CancelOrderRequest(orderBean.getOid(), orderBean.getCompanyId(),
                    AfterSalesType.SYSTEM_CANCEL, StringUtils.join(new String[]{"获取预支付失败", msg}, '-'), trackingNo, null);
            OrderCancelReq request = new OrderCancelReq();
            //商户号必传
            request.setPartnerId(cancelOrderRequest.getPartnerId());
            request.setOrderCode(cancelOrderRequest.getOrderId());
            request.setReqRemark(cancelOrderRequest.getReqRemark());
            //售后单类型 1:其他取消 2:用户取消 3:商户取消 4:未支付超时关单 5:商户接单超时取消 6:商家拒单
            // 7:配送用户拒收 8:用户售后退货/售后退款 9:系统取消 10:客服取消 11:用户统一取消，
            request.setAfterSalesType(cancelOrderRequest.getAfterSalesType().getIndex() == null ? 1 : cancelOrderRequest.getAfterSalesType().getIndex());
            request.setOrderClient(cancelOrderRequest.getOrderClient());
            request.setCancelReason(cancelOrderRequest.getReason());
            request.setAfterSalesReason(cancelOrderRequest.getReason());
            //若为4，默认做【创建】+【同意并退款完成】，售后单状态为【完成】
            request.setCreateEvent(cancelOrderRequest.getCreateEvent());
            request.setAfterSerialNo(cancelOrderRequest.getRefundSerialNo());
            request.setOperator(cancelOrderRequest.getOperator());

            // 【华莱士20210510活动】新增加退款方式字段
            if (Objects.nonNull(cancelOrderRequest.getExtInfoReq())) {
                request.setExtInfo(JSON.toJSONString(cancelOrderRequest.getExtInfoReq()));
            }
            request.setRefundDeliveryAmount(cancelOrderRequest.isRefundDeliveryAmount());
            com.freemud.application.sdk.api.ordercenter.response.OrderBaseResp cancelOrderResponse = orderSdkService.cancelOrder(request, cancelOrderRequest.getTrackingNo());

            // TODO: 2019/9/10 hubowen mq推送变更
            orderQueueService.backOrdersStatusChange(orderBean.getOid(), orderBean.getStatus(), PayStatusEnum.NOT_PAY.getCode());
        }
        //svc 卡支付失败
        if (CollectionUtils.isNotEmpty(cardCodes)) {
            return ResponseUtil.error(ResponseResultEnum.PAY_BACKEND_CONFIG_ERROR.getCode(), StringUtils.isNotBlank(msg) ? msg : ResponseResultEnum.PAY_BACKEND_CONFIG_ERROR.getMessage(), null);
        }
        return ResponseUtil.error(ResponseResultEnum.PAY_UNIFIED_ORDER_ERROR.getCode(), ResponseResultEnum.PAY_UNIFIED_ORDER_ERROR.getMessage(), null);
    }


    /**
     * 通过payCode ->clientCode
     */
    private String getPayCodeByChanel(String wxAppid, String channel, String storeId) {
        if (StringUtils.isBlank(channel)) return "";

        PayChannelType byIndex = PayChannelType.getByIndex(Byte.parseByte(channel));
        if (byIndex.getEbcode() == null) return "";
        AssortmentOpenPlatformIappWxappStore wxAppStore = assortmentOpenPlatformIappWxappStoreManager.selectWxappStoreByWxAppIdAndStoreId(wxAppid
                , storeId
                , byIndex.getEbcode());
        if (wxAppStore != null && StringUtils.isNotBlank(wxAppStore.getClientCode())) {
            return wxAppStore.getClientCode();
        }
        return "";
    }

    /**
     * 通过payCode ->clientCode
     */
    private String getPayCodeByChanel(String wxAppid, String storeId) {

        AssortmentOpenPlatformIappWxappStore wxAppStore = assortmentOpenPlatformIappWxappStoreManager.selectWxappStoreByWxAppIdAndStoreId(wxAppid
                , storeId
                , null);
        if (wxAppStore != null && StringUtils.isNotBlank(wxAppStore.getClientCode())) {
            return wxAppStore.getClientCode();
        }
        return "";
    }

    public String getPayCodeByCondition(String wxAppid, String storeId, String channel) {
        if (channel != null) {
            return this.getPayCodeByChanel(wxAppid, channel, storeId);
        }

        return this.getPayCodeByChanel(wxAppid, storeId);
    }


    /**
     * 获取混合支付是否开启
     */
    private boolean checkSvcComPay(String partnerId, String storeId) {
        SvcComPayRequestDto requestDto = new SvcComPayRequestDto();
        requestDto.setPartnerId(partnerId);
        requestDto.setStoreId(storeId);
        SvcComPayResponseDto query = null;
        for (int i = 0; i < 3; i++) {
            query = svcComPayClient.query(requestDto);
            if (query != null) break;
        }
        if (query == null || !ResponseResult.SUCCESS.getCode().equals(query.getCode())) {
            return false;
        }
        if (query.getResult() != null && query.getResult().getValue()) {
            return true;
        } else {
            return false;
        }
    }


    /**
     * 0元支付参数
     */
    private OrderPayResponse getOrderPayResponse(PaymentRequest paymentRequest, OrderBeanV1 orderBean) {
        OrderPayResponse orderPayResponse;
        String fmId = "SPAY" + ValidationCode.getRandomUuid();
        orderPayResponse = orderAdapter.getOrderPayResponse(orderBean.getCompanyId(), paymentRequest,
                orderBean.getOid(), fmId);
        return orderPayResponse;
    }


    /**
     * 获取预支付成功，将信息放入死心队列，当支付成功没有回掉的时候处理
     */
    public void putDelMq(String partnerId, String storeId, String fmId, String orderId, Integer payChanelType) {
        PaymentMqMessageDto dto = new PaymentMqMessageDto();
        try {
            dto.setFmId(fmId);
            dto.setOrderId(orderId);
            dto.setPartnerId(partnerId);
            dto.setStoreId(storeId);
            dto.setPayChannelType(payChanelType);
            dto.setTrackingNo(LogThreadLocal.getTrackingNo());
            orderQueueService.paymentCallback(dto);
        } catch (Exception e) {
            AppLogUtil.errorLog("paymentQueueService.paymentCallback,orderId:{}", orderId, null, e);
        }
    }


    /**
     * 获取门店支付信息
     * <p>
     * aggregationType 6-会员、7-微商城、8-一键购买 9:积分商城
     */
    public AssortmentOpenPlatformIappWxappStore getIappWxappStoreInfo(String wxAppId, String aggregationType) {
        AssortmentOpenPlatformIappWxappStore wxAppStore = assortmentOpenPlatformIappWxappStoreManager.selectIappWxappStoreByWxAppIdAndAggregationType(wxAppId, aggregationType);
        return wxAppStore;
    }


    public UnifiedOrderRequestDto convert2UnifiedOrderRequestDto(UnifiedOrderCom com) {

        OrderBeanV1 orderBean = com.getOrderBean();
        PaymentRequest paymentRequest = com.getPaymentRequest();
        Long amount = com.getAmount();
        Integer cardAmount = com.getCardAmount();
        String transId = com.getTransId();
        String partnerPayOvertime = com.getPartnerPayOvertime();

        UnifiedOrderRequestDto orderPayDto = new UnifiedOrderRequestDto();
        orderPayDto.setPartnerId(orderBean.getCompanyId());
        orderPayDto.setBody(paymentRequest.getPrincipalName());
        orderPayDto.setNotifyUrl(paymentRequest.getReverseNotifyiDcUrl());
        orderPayDto.setStoreId(orderBean.getShopId());
        orderPayDto.setTransId(transId);
        orderPayDto.setOpenId(paymentRequest.getOpenId());
        String businessDate = DateUtil.convert2String(new Date(), "yyyyMMdd");
        orderPayDto.setBusinessDate(businessDate);
        orderPayDto.setAmount(amount);
        orderPayDto.setUndisAmount(1L);
        orderPayDto.setVipAmount(Long.valueOf(cardAmount));
//        orderPayDto.setAppId(paymentRequest.getWxAppId());
        orderPayDto.setPayTimeOutTime(StringUtils.defaultIfBlank(partnerPayOvertime, "30"));
        List<PayProductDto> productBeans = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(orderBean.getProductList())) {
            orderBean.getProductList().forEach(orderProductBean -> {
                PayProductDto productBean = new PayProductDto();
                productBean.setId(orderProductBean.getProductId());
                productBean.setQuantity(orderProductBean.getNumber());
//                productBean.setSeq(orderProductBean.getSequence());
//                productBean.setSalesType("NORMAL");
                productBean.setPrice(orderProductBean.getPrice());
                productBean.setName(orderProductBean.getProductName());
                productBeans.add(productBean);
            });
        }
        orderPayDto.setProducts(productBeans);
        orderPayDto.setPayCode(paymentRequest.getPayCode());
        //抖音支付的payCode = 10066
        if (OrderClientType.TIKTOKPAY.getIndex().toString().equalsIgnoreCase(orderBean.getOrderClient())) {
            orderPayDto.setPayCode(PayChannelType.TIKTOKPAY.getEbcode());
        }
        orderPayDto.setFoodOrderType(orderAdapter.getFoodOrderType(orderBean.getOrderType()));
//        orderPayDto.setMerchantDiscount(orderBean.getOriginalAmount().longValue()-orderBean.getAmount());

        return orderPayDto;
    }


    public void convent2CreateOrderResponseVo(OrderPayResponse createOrderResponseVo, String appId, UnifiedPayResponseDto response) {
        createOrderResponseVo.setWxAppid(appId);
        createOrderResponseVo.setFmId(response.getFmId());
        createOrderResponseVo.setEndTransId(response.getEndTransId());
        createOrderResponseVo.setChannelPayId(response.getChannelPayId());
//        createOrderResponseVo.setPaySuccess(false);
        String payOrderDto = response.getPayOrder();
        PayOrderDto payOrderBean = JSONObject.parseObject(payOrderDto, PayOrderDto.class);
        if (null != payOrderBean) {
            OrderPayResponse.PayOrderBean payBean = new OrderPayResponse.PayOrderBean();
            payBean.setAppid(payOrderBean.getAppid());
            payBean.setNonceStr(payOrderBean.getNonceStr());
            payBean.setPackageX(payOrderBean.getPackageX());
            payBean.setSign(payOrderBean.getPaySign());
            payBean.setSignType(payOrderBean.getSignType());
            payBean.setTimestamp(payOrderBean.getTimestamp());
            payBean.setAliPayOrder(payOrderBean.getAliPayOrder());
            createOrderResponseVo.setPayOrder(payBean);
            createOrderResponseVo.setThirdOrderId(payOrderBean.getThirdPartTradeNo());
            createOrderResponseVo.setThirdOrderToken(payOrderBean.getBizContent());
        }
    }

    /**
     * 1元捐插件需要参数
     */
    public PlugInParameter getPlugInParameter(String partnerId, String appId) {
        PlugInParameter plugInParameter = new PlugInParameter();
        List<AssortmentOpenPlatformPartnerPaymentConfig> openPlatformPartnerPaymentConfigs = openPlatformPartnerPaymentConfigManager.queryPartnerPaymentConfigs(partnerId, appId);
        if (CollectionUtils.isNotEmpty(openPlatformPartnerPaymentConfigs)) {
            plugInParameter.setMchCode(openPlatformPartnerPaymentConfigs.get(0).getUnitMchId());
            plugInParameter.setSubMchCode(openPlatformPartnerPaymentConfigs.get(0).getSubMchid());
        }
        return plugInParameter;
    }

    /**
     * 周周惠插件需要参数
     */
    public PlugInParameter getPlugInParameter(String partnerId, String appId,String storeId) {
        PlugInParameter plugInParameter = new PlugInParameter();
        List<AssortmentOpenPlatformPartnerPaymentConfig> openPlatformPartnerPaymentConfigs = openPlatformPartnerPaymentConfigManager.queryPartnerPaymentConfigs(partnerId, appId);
        if (CollectionUtils.isEmpty(openPlatformPartnerPaymentConfigs)) {
            return plugInParameter;
        }

        AssortmentOpenPlatformPaymentStore assortmentOpenPlatformPaymentStore = openPlatformPartnerPaymentConfigManager.queryPlatformPaymentStore(openPlatformPartnerPaymentConfigs.get(0).getId().toString(), storeId);
        if (assortmentOpenPlatformPaymentStore == null || assortmentOpenPlatformPaymentStore.getStatus() != 1) {
            return plugInParameter;
        }
        AssortmentOpenPlatformPartnerPaymentAuth assortmentOpenPlatformPartnerPaymentAuth = openPlatformPartnerPaymentConfigManager.queryPartnerPaymentAuth(openPlatformPartnerPaymentConfigs.get(0).getAuthId());
        if (assortmentOpenPlatformPartnerPaymentAuth == null) {
            return plugInParameter;
        }

        String applyMchid = openPlatformPartnerPaymentConfigs.get(0).getSubMchid();
        String signMchid = assortmentOpenPlatformPartnerPaymentAuth.getSp_mchid();
        String thirdStoreId = assortmentOpenPlatformPaymentStore.getThirdStoreId();
        plugInParameter.setApplyMchid(applyMchid);
        plugInParameter.setSignMchid(signMchid);
        plugInParameter.setStoreId(thirdStoreId);

        String encryptKey = assortmentOpenPlatformPartnerPaymentAuth.getSignKey();
        String message = "apply_mchid="+applyMchid+"&sign_mchid="+signMchid+"&store_id="+thirdStoreId + "&key="+encryptKey;

        String sign = HMacSHA256.encrypt(message,encryptKey);
        plugInParameter.setSign(sign);

        return plugInParameter;
    }


    /**
     * 退款从sdk 剥离
     */
    public com.freemud.application.sdk.api.base.BaseResponse<OrderRefundResponse> orderPayRefund(PayRefundRequestDto refundRequest) {

        PaymentQueryOrderRequestDto paymentQueryOrderRequest = new PaymentQueryOrderRequestDto();

        paymentQueryOrderRequest.setPartnerId(refundRequest.getPartnerId());
        paymentQueryOrderRequest.setStoreId(refundRequest.getStoreId());
        paymentQueryOrderRequest.setFrontTransId(refundRequest.getOrgTransId());
       com.freemud.application.sdk.api.base.BaseResponse<PaymentQueryOrderResponseDto> payQueryOrderResponse = null;
        try {
            payQueryOrderResponse = omsPaymentClient.payQueryOrder(paymentQueryOrderRequest);
        }catch (Exception e){
            cn.freemud.base.log.ErrorLog.errorConvertJson(this.getClass(), "paymentcenter/queryOrder error", e);
        }
        if(payQueryOrderResponse == null){
            return null;
        }
        Long vipAmount = 0L;
        String payCode = null;
        if (Objects.equals(payQueryOrderResponse.getCode(), "100") && payQueryOrderResponse.getData() != null) {
            if ((payQueryOrderResponse.getData()).getVipAmount() != null && (payQueryOrderResponse.getData()).getVipAmount() != 0) {
                vipAmount = (long) (payQueryOrderResponse.getData()).getVipAmount();
            }

            refundRequest.setTotalAmount((payQueryOrderResponse.getData()).getAmount());
            payCode = payQueryOrderResponse.getCode();
        }

        if (refundRequest.getTotalAmount() == null || refundRequest.getTotalAmount() == 0L) {
            refundRequest.setTotalAmount(refundRequest.getRefundAmount());
        }

        AssortmentOpenPlatformIappWxappStore wxAppStore = this.assortmentOpenPlatformIappWxappStoreManager.selectWxappStoreByWxAppIdAndStoreId(refundRequest.getAppId(), refundRequest.getStoreId(), payCode);
        PayRefundRequestDto request = new PayRefundRequestDto();
        request.setStoreId(refundRequest.getStoreId());
        request.setStationId(refundRequest.getStationId());
        request.setOperatorId(refundRequest.getOperatorId());
        request.setTransId(refundRequest.getOrgTransId());
        request.setBusinessDate(refundRequest.getBusinessDate());
        request.setFmId(refundRequest.getOrgPayFmId());
        request.setTotalAmount(refundRequest.getTotalAmount());
        request.setRefundAmount(refundRequest.getRefundAmount());
        request.setRefundId(refundRequest.getRefundId().toString());
        request.setRefundDesc(refundRequest.getRefundDesc());
        request.setNotifyUrl(refundRequest.getNotifyUrl());
        request.setPartnerId(refundRequest.getPartnerId());
        request.setVer(2);
        request.setExtendParams(refundRequest.getExtendParams());
        com.freemud.application.sdk.api.base.BaseResponse<OrderRefundResponse> checkParam = this.checkParam(refundRequest.getPartnerId(), refundRequest.getStoreId(), refundRequest.getRefundAmount(), wxAppStore);
        if (!Objects.equals(checkParam.getCode(), "100")) {
            return checkParam;
        } else {
            com.freemud.application.sdk.api.base.BaseResponse<PayRefundData>  refundNewResponse = null;
            try {
                refundNewResponse = omsPaymentClient.payRefund(request);
            }catch (Exception e){
                ErrorLog.errorConvertJson(this.getClass(), "paymentcenter/refund error", e);
            }
            if(refundNewResponse == null){
                return null;
            }
            AppLogUtil.infoLog("paymentcenter/refund",JSONObject.toJSONString(request),JSONObject.toJSONString(refundNewResponse));
            if (Objects.equals(refundNewResponse.getCode(), "100")) {
                PayRefundData refundData = refundNewResponse.getData();
                if (null != refundData ) {
                    OrderRefundResponse refundResponse = new OrderRefundResponse();
                    refundResponse.setStatusCode(refundData.getResultCode());
                    refundResponse.setMsg(refundData.getResultMsg());
                    refundResponse.setRefundAmount(refundData.getRefundAmount());
                    refundResponse.setTotalAmount(refundData.getTotalAmount());
                    refundResponse.setRefundStatus(this.getRefundStatus(refundData.getResultCode()));
                    refundResponse.setRefundTradeNo(refundData.getRefundTradeNo());
                    refundResponse.setTradeNo(refundData.getRefundTradeNo());
                    refundResponse.setThirdPartRefundTradeNo(refundData.getThirdPartRefundTradeNo());
                    refundResponse.setThirdPartTradeNo(refundData.getThirdPartTradeNo());
                    refundResponse.setTotalAmount(refundData.getTotalAmount());

                    return ResponseUtils.success(refundResponse);
                }
            }

            if (!Arrays.asList("8200201", "8200202", "8200203", "8200204", "8200205").contains(refundNewResponse.getCode())) {
//                this.emailAlertService.sendEmailAlert("支付退款失败", "请求json:" + JSONObject.toJSONString(request) + "返回msg:" + refundNewResponse.getMessage());
            }

            return ResponseUtils.error(refundNewResponse.getCode(), refundNewResponse.getMessage());
        }

    }

    public Integer getRefundStatus(Integer resultCode) {
        if (Objects.equals(resultCode, SUCCESS_RESPONSE_CODE_INT)) {
            return PaymentRefundStatus.PAYMENT_REFUND_STATUS_1.getCode();
        } else if (Objects.equals(resultCode, SUCCESS_RESPONSE_101_CODE_INT)) {
            return PaymentRefundStatus.PAYMENT_REFUND_STATUS_1.getCode();
        } else {
            return Objects.equals(resultCode, REFUND_RESPONSE_CODE) ? PaymentRefundStatus.PAYMENT_REFUND_STATUS_4.getCode() : PaymentRefundStatus.PAYMENT_REFUND_STATUS_2.getCode();
        }
    }


    public com.freemud.application.sdk.api.base.BaseResponse<OrderRefundResponse> checkParam(String partnerId, String storeId, Long amount, AssortmentOpenPlatformIappWxappStore wxAppStore) {
        if (StringUtils.isBlank(partnerId)) {
            return ResponseUtils.error("501", "商户号不能为空");
        } else if (StringUtils.isBlank(storeId)) {
            return ResponseUtils.error("501", "门店号不能为空");
        } else if (amount == null) {
            return ResponseUtils.error("501", "金额不能为空");
        } else {
            return wxAppStore == null ? ResponseUtils.error("500", "支付信息没有配置") : ResponseUtils.success();
        }
    }

    /**
     * 校验五单收银　储值卡余额，返回储值支付金额与现金支付金额
     */
    public CheckSvcAmountResponse checkSvcAmount(CheckSvcAmountBo checkSvcAmountBo) {

        CheckSvcAmountResponse checkSvcAmountResponse = new CheckSvcAmountResponse();

        String partnerId = checkSvcAmountBo.getPartnerId();
        String storeId = checkSvcAmountBo.getStoreCode();
        String cardCode = checkSvcAmountBo.getCardCode();
        Long orderAmount = checkSvcAmountBo.getOrderAmount();

        //混合支付开关
        boolean combPaySwitch = this.checkSvcComPay(partnerId, storeId);

        SVCCardAmountRequestDto svcRequest = new SVCCardAmountRequestDto();
        svcRequest.setPartnerId(partnerId);
        svcRequest.setCardCodes(Arrays.asList(cardCode));
        //查询svc卡余额
        BaseResponse<SVCCardAmountResponseDto> svcCardAmountResponseBaseResponse = svcAppClient.batchQueryCardAmount(svcRequest);
        if (svcCardAmountResponseBaseResponse == null || !ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(svcCardAmountResponseBaseResponse.getCode())
                || svcCardAmountResponseBaseResponse.getResult() == null || CollectionUtils.isEmpty(svcCardAmountResponseBaseResponse.getResult().getCardSimpleInfos())) {
            checkSvcAmountResponse.setMsg(Objects.isNull(svcCardAmountResponseBaseResponse) ? "获取卡余额异常" : svcCardAmountResponseBaseResponse.getMessage());
            return checkSvcAmountResponse;
        }
        Integer amount = svcCardAmountResponseBaseResponse.getResult().getCardSimpleInfos().get(0).getAmount();
        Integer vamount = svcCardAmountResponseBaseResponse.getResult().getCardSimpleInfos().get(0).getVamount();

        Integer svcAmount = amount + vamount;
        if (!combPaySwitch && svcAmount < orderAmount) {
            checkSvcAmountResponse.setMsg("卡余额不足");
            return checkSvcAmountResponse;
        }

        //储值卡支付金额（分）
        Long svcPayAmount;
        //微信或支付宝 支付金额（分）
        Long payAmount;
        if (svcAmount < orderAmount) {
            svcPayAmount = svcAmount.longValue();
            payAmount = orderAmount - svcAmount.longValue();
        } else {
            svcPayAmount = orderAmount;
            payAmount = 0L;
        }
        checkSvcAmountResponse.setSvcPayAmount(svcPayAmount);
        checkSvcAmountResponse.setPayAmount(payAmount);

        return checkSvcAmountResponse;
    }


    public void putRoundRobin(PutRoundRobinVo putRoundRobinVo) {
        //加入轮训队列
        this.putDelMq(putRoundRobinVo.getPartnerId(),
                putRoundRobinVo.getStoreId(),
                putRoundRobinVo.getFmId(),
                putRoundRobinVo.getOrderCode(),
                (int) putRoundRobinVo.getIndex());


    }

    /**
     * 创建多卡支付
     */
    public OrderPayResponse multiPay(List<String> cardNos
            , OrderBeanV1 orderBean
            , PaymentRequest paymentRequest
            , Integer totalAmount
            , String channel) {

        //  统一走多卡支付Ka2.0.76-0427-0504
        String partnerPayOvertime = this.getPartnerPayOvertime(orderBean.getCompanyId());
        String storeId = orderBean.getShopId();
        String ebCode = this.getPayCodeByChanel(paymentRequest.getWxAppId(), channel, storeId);
        OrderPayResponse orderPayResponse = new OrderPayResponse();

        if (StringUtils.isBlank(ebCode)) {
            orderPayResponse.setMsg("请先联系相关人员配置商户对应的支付渠道");
            return orderPayResponse;
        }

        MultiPayRequest combPayRequest = orderAdapter.convent2MultiPayOrderRequest(cardNos, orderBean, paymentRequest, partnerPayOvertime, ebCode, channel, totalAmount);
        MultiPayResponse multiPayResponse = comPayClient.multiPay(combPayRequest, combPayRequest.getPartner_id());
        if (multiPayResponse == null || !ResponseCodeConstant.PAYMENT_RESPONSE_SUCCESS.equals(multiPayResponse.getCode())) {
            orderPayResponse.setMsg(multiPayResponse != null ? "支付：" + multiPayResponse.getMsg() : "混合支付忙不过来啦，请稍后再试");
            return orderPayResponse;
        }
        List<MultiPayResponse.PayPlatform> payPlatforms = multiPayResponse.getData().getPayPlatformResponseList();
        if (payPlatforms.size() == 0) {
            orderPayResponse.setMsg("混合支付:生成预支付失败");
            return orderPayResponse;
        }

        orderPayResponse.setWxAppid(paymentRequest.getWxAppId());
        orderPayResponse.setOpenId(paymentRequest.getOpenId());
        orderPayResponse.setPartnerId(orderBean.getCompanyId());
        orderPayResponse.setOrderId(orderBean.getOid());
        orderPayResponse.setMsg("success");
        orderPayResponse.setPayId("");

        MultiPayResponse.PayPlatform cashPay = null;
        boolean allCardPay = true;//是否纯储值卡支付
        for (MultiPayResponse.PayPlatform pt : payPlatforms) {
            if (!PayChannelType.SVC.getEbcode().equals(pt.getEbCode())) {
                cashPay = pt;
                allCardPay = false;
            }else{
                SvcPayItem payItem = new SvcPayItem();
                payItem.setCardCode(pt.getCardCode());
                payItem.setSvcTransId(pt.getPlatformTradeNo());
                payItem.setTransId(pt.getTransId());
                if(CollectionUtils.isEmpty(orderPayResponse.getSvcPayItems())){
                    List<SvcPayItem> svcPayItems = new ArrayList<>();
                    svcPayItems.add(payItem);
                    orderPayResponse.setSvcPayItems(svcPayItems);
                }else{
                    orderPayResponse.getSvcPayItems().add(payItem);
                }
            }
            orderPayResponse.setFmId(pt.getTransId());
            orderPayResponse.setPayTransId(pt.getTransId());
            PayChannelType payChannelType = PayChannelType.getByEbcode(pt.getEbCode());
            if (pt.getCardType() != null && pt.getCardType() == 0) {
                payChannelType = PayChannelType.GIFTCARD;
            }
            orderPayResponse.setPayChannelType(payChannelType);
            orderPayResponse.setPayEbcode(pt.getEbCode());
            OrderPayItemResp payItem = new OrderPayItemResp();
            payItem.setFmTradeNo(pt.getFmTradeNo());
            payItem.setStoreId(storeId);
            payItem.setPayChannelType(payChannelType.getIndex().intValue());
            payItem.setPayChannelName(payChannelType.getName());
            payItem.setTransId(pt.getTransId());
            payItem.setPartnerId(combPayRequest.getPartner_id());
            payItem.setPayAmount(new BigDecimal(pt.getPayAmount()));
            payItem.setCardCode(pt.getCardCode());
            orderPayResponse.getPayItem().add(payItem);
            MultiPayResponse.PayPlatform.PayOrderBean payOrderBean = pt.getPayOrder();
            if (null != payOrderBean) {
                OrderPayResponse.PayOrderBean payBean = new OrderPayResponse.PayOrderBean();
                payBean.setAppid(payOrderBean.getAppId());
                payBean.setNonceStr(payOrderBean.getNonceStr());
                payBean.setPackageX(payOrderBean.getPackageX());
                payBean.setSign(payOrderBean.getPaySign());
                payBean.setSignType(payOrderBean.getSignType());
                payBean.setTimestamp(payOrderBean.getTimeStamp());
                payBean.setAliPayOrder(payOrderBean.getAliPayOrder());
                orderPayResponse.setPayOrder(payBean);
            }
        }
        if (!allCardPay && payPlatforms.size() > 1) {
            orderPayResponse.setPayChannelType(PayChannelType.COMB);
        }
        //现金线上支付
        if (cashPay != null) {
            String transId = cashPay.getTransId();
            orderPayResponse.setFmId(cashPay.getFmTradeNo());
            orderPayResponse.setEndTransId(cashPay.getEndTransTradeNo());
            redisCache.save(RedisUtil.getPaymentTransIdOrderKey(transId), orderBean.getOid(), 1L, TimeUnit.DAYS);
            //加入轮训队列
            putDelMq(orderBean.getCompanyId(), storeId, orderPayResponse.getFmId(), orderBean.getOid(), PayChannelType.getByEbcode(transId).getIndex().intValue());
        }
        return orderPayResponse;
    }

}
