package cn.pluss.platform.sxf.pay.impl;

import cn.pluss.platform.api.ResultCode;
import cn.pluss.platform.channel.MerchantAuditService;
import cn.pluss.platform.config.ParameterConfig;
import cn.pluss.platform.constants.Constant;
import cn.pluss.platform.dto.MemberScanPayDTO;
import cn.pluss.platform.dto.MerChantOrderDTO;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.mapper.SubMerchantMapper;
import cn.pluss.platform.merchantOrder.MerchantOrderService;
import cn.pluss.platform.refundOrder.MerchantRefundOrderService;
import cn.pluss.platform.suixingfu.SxfConstants;
import cn.pluss.platform.sxf.SxfService;
import cn.pluss.platform.sxf.pay.SxfPayService;
import cn.pluss.platform.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;

@Slf4j
@Service
@RequiredArgsConstructor
public class SxfPayServiceImpl implements SxfPayService {
    
    private final SxfService sxfService;

    @Setter(onMethod_ = {@Lazy, @Autowired})
    private MerchantRefundOrderService merchantRefundOrderService;

    @Setter(onMethod_ = {@Lazy, @Autowired})
    private MerchantOrderService merchantOrderService;

    @Qualifier("sxfMerchantAuditService")
    private final MerchantAuditService sxfMerchantAuditService;

    private final SubMerchantMapper subMerchantMapper;

    @Resource
    private ExecutorService executorService;


    @Override
    public JSONObject tradePay(MerchantOrder order,MerchantChannelStatus channel,MerchantBaseInfo merchant) {
        Map<String,Object> resultMap = null;
        JSONObject reqData = converParameter(order,channel,merchant);
        log.info("==========>【随行付】支付下单请求，请求参数：{}<==============",reqData);
        merchant.setChannelLimitPay(reqData,channel.getChannel());
        String url = SxfConfg.SXF_JSAPI_SCAN_PAY;
        if(StringUtil.isNotEmpty(order.getScanType()) && "01".equals(order.getScanType())){
            url = SxfConfg.SXF_ACTIVE_SCAN_PAY;
        }
        try {
            Long startTime = System.currentTimeMillis();
            resultMap = sxfService.requestApi(url,reqData);
            Long endTime = System.currentTimeMillis();
            log.info("==========>【随行付】支付下单请求返回，返回参数：{},请求耗时:{}毫秒<==============",resultMap,endTime-startTime);
        } catch (Exception e) {
            log.error("==========>【随行付】支付下单请求异常，异常信息：{}<==============",e.getMessage());
        }
        JSONObject object = checkResultParams(resultMap);
        if(ResultCode.FAIL.code() == object.getInteger("code")){
            return object;
        }
        JSONObject payData = new JSONObject();
        Map<String,Object> respData = (Map<String,Object>) resultMap.get("respData");
        if(!(StringUtil.isNotEmpty(order.getScanType()) && "01".equals(order.getScanType()))){
            if(Constant.PAY_TYPE_ALIPAY.equals(order.getPayTypeCode()) || "sxfPay0".equals(order.getPayTypeCode())){
                payData.put("source",respData.get("source"));
            }else if(Constant.PAY_TYPE_WECHAT.equals(order.getPayTypeCode()) || "sxfPay1".equals(order.getPayTypeCode())){
                payData.put("payAppId",respData.get("payAppId"));
                payData.put("payTimeStamp",respData.get("payTimeStamp"));
                payData.put("paynonceStr",respData.get("paynonceStr"));
                payData.put("payPackage",respData.get("payPackage"));
                payData.put("paySignType",respData.get("paySignType"));
                payData.put("paySign",respData.get("paySign"));
            }else{
                payData.put("redirectUrl",respData.get("redirectUrl"));
            }
        }else{
            payData.put("payUrl",respData.get("payUrl"));
            payData.put("orderNumber",order.getOrderNumber());
            payData.put("mercOrderNo",order.getMercOrderNo());
        }
        payData.put("channel",channel.getChannel());
        order.setTransNo(respData.get("uuid") == null ? "" : respData.get("uuid").toString());
        object.put("payData",payData);
        return object;
    }

    /**
     * 统一返回参数校验
     * @param resultMap
     * @return
     */
    private JSONObject checkResultParams(Map<String, Object> resultMap) {
        JSONObject result = new JSONObject(10);
        if(resultMap == null){
            result.put("code", ResultCode.FAIL.code());
            result.put("msg","参数为空！");
            return result;
        }
        if(!SxfConfg.SXF_SUCCESS_CODE.equalsIgnoreCase((String)resultMap.get("code"))){
            result.put("code",ResultCode.FAIL.code());
            result.put("msg",resultMap.get("msg"));
            return result;
        }
        Object sign = resultMap.get("sign");
        if(StringUtil.isEmpty(sign)){
            result.put("code",ResultCode.FAIL.code());
            result.put("msg","签名参数为空！");
            return result;
        }
        //验证签名
        resultMap.remove("sign");
        String signStr = SignUtils.getSignContent(JSONObject.parseObject(JSONObject.toJSONString(resultMap)));
        boolean flag = false;
        try {
            flag = RSAUtils.checkSign(SxfConfg.PUBLIC_KEY, signStr, sign.toString());
        } catch (Exception e) {
            log.error("==============>【随行付】签名校验异常<===============");
            e.printStackTrace();
        }
        if(!flag){
            log.info("==============>【随行付】签名校验失败<===============");
            result.put("code",ResultCode.FAIL.code());
            result.put("msg","签名校验失败");
            return result;
        }
        Map<String,Object> respData = (Map<String,Object>)resultMap.get("respData");
        if(!SxfConfg.SXF_SUCCESS_CODE.equalsIgnoreCase((String)respData.get("bizCode")) && !SxfConfg.SXF_REFUND_SUCCESS_CODE.equalsIgnoreCase((String)respData.get("bizCode"))){
            if("3001".equals(respData.get("bizCode"))){
                result.put("code",ResultCode.FAIL.code());
                if(respData.get("bizMsg").toString().contains("使用微信支付")){
                    result.put("msg","云闪付/京东支付失败：同一支付通道下一张身份证最多注册一个小微商户");
                }else if(respData.get("bizMsg").toString().contains("商户需补齐相关资料") || respData.get("bizMsg").toString().contains("微信实名认证")){
                    result.put("msg","D1次日到账：商户未在收银呗APP-商户认证-微信认证内完成授权，暂时无法微信收款");
                }else{
                    result.put("msg",respData.get("bizMsg"));
                }
                return result;
            }
            result.put("code",ResultCode.FAIL.code());
            result.put("msg",respData.get("bizMsg"));
            return result;
        }
        result.put("code",ResultCode.SUCCESS.code());
        result.put("msg",respData.get("bizMsg"));
        return result;
    }

    /**
     * 随行付主扫逻辑
     * @param merchantOrderDTO
     * @param order
     * @param
     * @return
     */
    @Override
    public JSONObject tradePay(MerChantOrderDTO merchantOrderDTO, MerchantOrder order){
        JSONObject reqData = new JSONObject();
        reqData.put("mno",merchantOrderDTO.getChannelNo());
        reqData.put("ordNo",order.getOrderNumber());
        reqData.put("authCode",merchantOrderDTO.getAuthCode());
        reqData.put("amt",order.getConsumeFee());
        if("sxfPay1".equals(order.getPayTypeCode())){
            reqData.put("payType","WECHAT");
        }else if("sxfPay0".equals(order.getPayTypeCode())){
            reqData.put("payType","ALIPAY");
        }else{
            reqData.put("payType","UNIONPAY");
        }
        if(merchantOrderDTO.getMerchantBaseInfo() != null){
            merchantOrderDTO.getMerchantBaseInfo().setChannelLimitPay(reqData,1);
        }
        reqData.put("subject",merchantOrderDTO.getMerchantName());
        reqData.put("tradeSource","01");
        //商家ip
        reqData.put("trmIp","127.0.0.1");
        // TODO ParametersUtil.domain获取不到ip,先写死
        reqData.put("notifyUrl", ParametersUtil.domain+"/wap/notify/sxfCallBack");
        Map<String,Object> resultMap = null;
        try {
            Long startTime = System.currentTimeMillis();
            log.info("==========>【随行付】主扫支付下单请求参数，返回参数：{},请求耗时:{}毫秒<==============",reqData);
            resultMap = sxfService.requestApi(SxfConfg.SXF_REVERSE_SCAN_PAY, reqData);
            Long endTime = System.currentTimeMillis();
            log.info("==========>【随行付】主扫支付下单请求返回，返回参数：{},请求耗时:{}毫秒<==============",resultMap,endTime-startTime);
        } catch (Exception e) {
            log.error("==========>【随行付】主扫支付下单请求异常，异常信息：{}<==============",e.getMessage());
        }
        JSONObject object = checkResultParams(resultMap);
        if(ResultCode.FAIL.code() == object.getInteger("code")){
            return object;
        }

        JSONObject result = new JSONObject();
        Map<String,Object> respData = (Map<String,Object>)resultMap.get("respData");
        String bizCode = (String)respData.get("bizCode");
        //通道交易流水号 支付宝或微信交易流水号
        result.put("channelOrderNo",respData.get("transactionId"));
        result.put("transNo",respData.get("uuid"));

        order.setThirdTransNo(respData.get("transactionId") == null ? "" : respData.get("transactionId").toString());
        order.setTransNo(respData.get("uuid") == null ? "" : respData.get("uuid").toString());
        order.setMercUserId(respData.get("buyerId") == null ? "" : respData.get("buyerId").toString());
        if(SxfConfg.SXF_REFUND_SUCCESS_CODE.equals(bizCode)){
            result.put("code",ResultCode.TRANSUNKNOW.code());
            result.put("msg","等待支付中...");
            //订单状态待确认
            result.put("payStatus","7");
        }else{
            result.put("code",ResultCode.SUCCESS.code());
            result.put("payStatus","1");
            result.put("msg","请求成功！");
            String payTime = (String)respData.get("payTime");
            result.put("payTime",DateUtils.parse(payTime,"yyyyMMddHHmmss"));
        }
        Object drType = respData.get("drType");
        order.setDrType(drType == null ? "" : drType.toString());
        order.setChannelRate(SxfConstants.CHANNEL_WECHAT_ALIPAY_BANK_COST_RATE.multiply(new BigDecimal(10000)));
        order.setChannelFee(new BigDecimal(String.valueOf(order.getConsumeFee())).multiply(SxfConstants.CHANNEL_WECHAT_ALIPAY_BANK_COST_RATE).setScale(2,BigDecimal.ROUND_HALF_UP));
        if("sxfPay2".equals(order.getPayTypeCode()) && order.getConsumeFee() > 1000.0d){
            if("1".equals(drType)){
                order.setChannelRate(SxfConstants.DEBIT_CARD_BANK_RATE_LARGE.multiply(new BigDecimal(10000)));
                BigDecimal fee = new BigDecimal(String.valueOf(order.getConsumeFee())).multiply(SxfConstants.DEBIT_CARD_BANK_RATE_LARGE).setScale(2,BigDecimal.ROUND_HALF_UP);
                if(fee.compareTo(SxfConstants.DEBIT_CARD_BANK_RATE_LARGE_MAX_FEE) > -1){
                    order.setChannelFee(SxfConstants.DEBIT_CARD_BANK_RATE_LARGE_MAX_FEE);
                }else{
                    order.setChannelFee(fee.setScale(2,BigDecimal.ROUND_HALF_UP));
                }
            }else if("2".equals(drType)){
                order.setChannelRate(SxfConstants.CREDIT_CARD_BANK_RATE_LARGE.multiply(new BigDecimal(10000)));
                BigDecimal fee = new BigDecimal(String.valueOf(order.getConsumeFee())).multiply(SxfConstants.CREDIT_CARD_BANK_RATE_LARGE).setScale(2,BigDecimal.ROUND_HALF_UP);
                order.setChannelFee(fee);
            }
        }
        return result;
    }

    /**
     * 随行付退款
     * @param order
     * @return
     */
    @Override
    public Map<String,Object> refundPay(MerchantOrder order,String mchNo) {
        Map<String,Object> result = new HashMap<>(4);
        JSONObject reqRefundData = new JSONObject();
        String refundNo = "SXFR"+StringUtil.getBillno();
        reqRefundData.put("ordNo",refundNo);
        reqRefundData.put("mno",mchNo);//随行付测试商户号
        reqRefundData.put("origOrderNo",order.getOrderNumber());
        reqRefundData.put("amt",StringUtil.isNotEmpty(order.getRefundType()) && order.getRefundType() == 2 ? order.getRefundAmt() : order.getConsumeFee());
        reqRefundData.put("notifyUrl",ParametersUtil.domain + "/wap/notify/sxfCallBack");
        if(StringUtil.isNotEmpty(order.getRemark())){
            reqRefundData.put("refundReason",order.getRemark());
        }
        result.put("refundNo",refundNo);
        result.put("status","3");
        result.put("code",ResultCode.FAIL.code());
        try {
            Map<String, Object> resultMap = sxfService.requestApi(SxfConfg.SXF_REFUND_PAY, reqRefundData);
            if(resultMap == null){
                result.put("msg","退款失败！");
                return result;
            }
            if(!SxfConfg.SXF_SUCCESS_CODE.equals(resultMap.get("code"))){
                result.put("msg",resultMap.get("msg"));
                return result;
            }
            Map<String,Object> respData = (Map<String,Object>)resultMap.get("respData");
            //0000 和 2002 都表示退款中
            if(SxfConfg.SXF_SUCCESS_CODE.equals(respData.get("bizCode")) || SxfConfg.SXF_REFUND_SUCCESS_CODE.equals(respData.get("bizCode"))){
                result.put("msg","退款成功！");
                result.put("data",respData);
                result.put("status","1");
                result.put("code",ResultCode.SUCCESS.code());
                return result;
            }
            result.put("msg",respData.get("bizMsg"));
            return result;
        } catch (Exception e) {
            log.error("==============>【随行付】退款异常，异常信息:{}<==================",e.getMessage());
            result.put("msg","退款异常");
            return result;
        }
    }

    @Override
    public JSONObject tradeQuery(MerchantOrder order,String mchId) {

        JSONObject result = new JSONObject(6);
        log.info("==============>【随行付】交易订单查询，查询单号：{}<==================",order.getOrderNumber());
        JSONObject reqData = new JSONObject();
        reqData.put("mno",mchId);//随行付测试商户号
        reqData.put("ordNo",order.getOrderNumber());
        try {
            log.info("==============>【随行付】交易订单查询，请求业务参数reqData：{}<==================",reqData);
            Map<String, Object> resultMap = sxfService.requestApi(SxfConfg.SXF_TRADE_QUERY_PAY, reqData);
            log.info("==============>【随行付】交易订单查询，返回参数：{}<==================",resultMap);
            if(resultMap == null){
                log.error("==============>【随行付】交易订单查询失败<==================");
                result.put("code",ResultCode.FAIL.code());
                result.put("msg","订单查询异常");
                return result;
            }
            if(!SxfConfg.SXF_SUCCESS_CODE.equals(resultMap.get("code"))){
                result.put("code",ResultCode.FAIL.code());
                result.put("msg",resultMap.get("msg"));
                return result;
            }
            String sign = (String)resultMap.get("sign");
            resultMap.remove(sign);
            String signContent = SignUtils.getSignContent(JSONObject.parseObject(JSON.toJSONString(resultMap)));
            boolean flag = RSAUtils.checkSign(SxfConfg.PUBLIC_KEY, signContent, sign);
            if(!flag){
                log.error("==============>【随行付】交易订单查询签名校验失败：{}<==================");
                result.put("code",ResultCode.FAIL.code());
                result.put("msg","签名校验失败");
                return result;
            }
            Map<String,String> respData = (Map<String,String>)resultMap.get("respData");
            if(!SxfConfg.SXF_SUCCESS_CODE.equals(respData.get("bizCode"))){
                result.put("code",ResultCode.FAIL.code());
                result.put("msg","查询失败");
                return result;
            }
            String tranSts = respData.get("tranSts");
            if("SUCCESS".equalsIgnoreCase(tranSts)){
                //交易成功
                String uuid = respData.get("uuid");
                String payTime = respData.get("payTime");
                String transactionId = respData.get("transactionId");//支付渠道单号
                String buyerId = respData.get("buyerId");
                result.put("channelOrderNo",transactionId);
                result.put("payTime",DateUtils.parse(payTime,"yyyyMMddHHmmss"));
                result.put("transNo",uuid);
                result.put("code", ResultCode.SUCCESS.code());
                result.put("payStatus", "1");
                result.put("msg", "查询成功！");
                result.put("buyerId", buyerId);
                return result;
            }else if("FAIL".equalsIgnoreCase(tranSts) || "CLOSED".equalsIgnoreCase(tranSts) || "CANCELED".equalsIgnoreCase(tranSts)){
                result.put("code", ResultCode.SUCCESS.code());
                result.put("payStatus", "0");
                result.put("msg", "查询成功");
                result.put("remark",tranSts);
                return result;
            }
            result.put("code", ResultCode.SUCCESS.code());
            result.put("payStatus", "5");
            result.put("msg", "查询成功");
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("==============>【随行付】交易订单查询异常，异常信息：{}<==================",e.getMessage());
            result.put("code",ResultCode.FAIL.code());
            result.put("msg","查询异常！");
            return result;
        }
    }

    @Override
    public JSONObject refundQuery(MerchantRefundOrder order) {
       JSONObject result = new JSONObject(3);
        log.info("==============>【随行付】退款订单查询，查询单号：{}<==================",order.getRefundNo());
        JSONObject reqData = new JSONObject();
        reqData.put("mno",order.getChannelMercNo());
        reqData.put("ordNo",order.getRefundNo());
        try {
            Map<String, Object> resultMap = sxfService.requestApi(SxfConfg.SXF_TRADE_QUERY_PAY, reqData);
            log.info("==============>【随行付】退款订单查询，返回参数：{}<==================",resultMap);
            if(resultMap == null){
                log.error("==============>【随行付】退款订单查询失败<==================");
                result.put("code","0");
                result.put("msg","退款查询异常");
                return result;
            }
            if(!SxfConfg.SXF_SUCCESS_CODE.equals(resultMap.get("code"))){
                result.put("code","0");
                result.put("msg",resultMap.get("msg"));
                return result;
            }
            String sign = (String)resultMap.get("sign");
            resultMap.remove(sign);
            String signContent = SignUtils.getSignContent(JSONObject.parseObject(JSON.toJSONString(resultMap)));
            boolean flag = RSAUtils.checkSign(SxfConfg.PUBLIC_KEY, signContent, sign);
            if(!flag){
                log.error("==============>【随行付】退款订单查询签名校验失败：{}<==================");
                result.put("code","0");
                result.put("msg","签名校验失败");
                return result;
            }
            result.put("code","1");
            result.put("msg","查询成功！");
            result.put("data",resultMap.get("respData"));
            return result;
        } catch (Exception e) {
            log.error("==============>【随行付】退款订单查询异常，异常信息：{}<==================",e.getMessage());
            result.put("code","0");
            result.put("msg","查询异常！");
            return result;
        }

    }

    @Override
    public Map<String, Object> closeOrder(String orderNumber, String channelNo) {
        Map<String,Object> result = new HashMap<>(3);
        JSONObject reqData = new JSONObject();
        reqData.put("origOrderNo",orderNumber);
        reqData.put("mno",channelNo);
        log.info("==============>【随行付】订单关闭接口调用，调用请求业务参数：{}<==================",reqData);
        Map<String, Object> resultMap = sxfService.requestApi(SxfConfg.SXF_CANCEL_ORDER, reqData);
        log.info("==============>【随行付】订单关闭接口调用，返回参数：{}<==================",resultMap);
        if(resultMap == null){
            log.error("==============>【随行付】订单关闭接口调用失败<==================");
            result.put("code",ResultCode.FAIL.code());
            result.put("msg","订单关闭失败");
            return result;
        }
        if(!SxfConfg.SXF_SUCCESS_CODE.equals(resultMap.get("code"))){
            result.put("code",ResultCode.FAIL.code());
            result.put("msg",resultMap.get("msg"));
            return result;
        }
        String sign = (String)resultMap.get("sign");
        resultMap.remove(sign);
        String signContent = SignUtils.getSignContent(JSONObject.parseObject(JSON.toJSONString(resultMap)));
        boolean flag = false;
        try {
            flag = RSAUtils.checkSign(SxfConfg.PUBLIC_KEY, signContent, sign);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(!flag){
            log.error("==============>【随行付】退款订单查询签名校验失败：{}<==================");
            result.put("code",ResultCode.FAIL.code());
            result.put("msg","签名校验失败");
            return result;
        }
        Map<String,String> respData = (Map<String,String>)resultMap.get("respData");
        if(!SxfConfg.SXF_SUCCESS_CODE.equals(respData.get("bizCode"))){
            result.put("code",ResultCode.FAIL.code());
            result.put("msg",respData.get("bizMsg"));
            return result;
        }
        result.put("code",ResultCode.SUCCESS.code());
        result.put("msg","关单成功！");
        return result;
    }

    private JSONObject converParameter(MerchantOrder order,MerchantChannelStatus channel,MerchantBaseInfo merchant) {
        JSONObject reqData = new JSONObject();
        reqData.put("ordNo",order.getOrderNumber());
        reqData.put("mno",channel.getMerchantId());
        reqData.put("amt",order.getConsumeFee());
        if("wechatPay".equalsIgnoreCase(order.getPayTypeCode()) || "sxfPay1".equalsIgnoreCase(order.getPayTypeCode())){
            reqData.put("payType","WECHAT");
        }else if("aliPay".equalsIgnoreCase(order.getPayTypeCode()) || "sxfPay0".equalsIgnoreCase(order.getPayTypeCode())){
            reqData.put("payType","ALIPAY");
        }else if("bank".equalsIgnoreCase(order.getPayTypeCode()) || "sxfPay2".equalsIgnoreCase(order.getPayTypeCode())){
            reqData.put("payType","UNIONPAY");
            reqData.put("customerIp","127.0.0.1");
        }
        if(StringUtil.isNotEmpty(order.getSubject())){
            reqData.put("subject",order.getSubject());
        }else{
            reqData.put("subject",order.getMerchantName());
        }
        if(!(StringUtil.isNotEmpty(order.getScanType()) && "01".equals(order.getScanType()))){
            if(("9".equals(order.getOrderType()) ||  "3".equals(order.getOrderType()) || "10".equals(order.getOrderType())) &&
                    "WECHAT".equals(reqData.getString("payType"))){
                String defaultSupAppId = ParametersUtil.APPLETS_APPID;
                if(StringUtil.isNotEmpty(merchant.getSubAppId())){
                    defaultSupAppId = merchant.getSubAppId();
                }
                reqData.put("subAppid",defaultSupAppId);
                reqData.put("payWay","03");
            }else{
                reqData.put("payWay","02");
            }
            reqData.put("userId",order.getMercUserId());
        }
        reqData.put("trmIp","127.0.0.1");
        reqData.put("timeExpire",15);
        reqData.put("tradeSource","01");
        //前台通知地址
        reqData.put("outFrontUrl", ParametersUtil.domain + "/wap/merchant/jumpUrl?orderNumber=" + order.getOrderNumber());
        //前台失败通知地址
        reqData.put("outFrontFailUrl", ParametersUtil.domain + "/wap/merchant/jumpUrl?orderNumber=" + order.getOrderNumber());
        //支付成功回调接口
        reqData.put("notifyUrl", ParametersUtil.domain + "/wap/notify/sxfCallBack");
        if(StringUtil.isNotEmpty(order.getExtendParam())){
            reqData.put(Constant.SXF_PAY_ECHO_KEY_NAME,order.getExtendParam());
        }
        return reqData;
    }

    /**
     * 辅助接口获取用户WXOpenID
     * @param memberScanPayDTO
     * @return
     */
    @Override
    public Map<String, Object> getWxOpenId(MemberScanPayDTO memberScanPayDTO,MerchantChannelStatus channel) throws Exception{

        QueryWrapper<SubMerchant> subQueryMrapper = new QueryWrapper<SubMerchant>().eq("merchantId",channel.getMerchantId())
                .eq("subMchType","WX").eq("status","01");
        SubMerchant subMerchant = subMerchantMapper.selectOne(subQueryMrapper);
        String wxCildNo = null;
        if(subMerchant == null){
            Map<String,Object> map = new HashMap<String,Object>(1);
            map.put("merchantId",channel.getMerchantId());
            JSONObject object = sxfMerchantAuditService.merchantAuditResult(map);
            wxCildNo = object.getString("wxCildNo");
        }else{
            wxCildNo = subMerchant.getSubMchId();
        }
        JSONObject reqData = new JSONObject();
        reqData.put("mno",channel.getMerchantId());
        reqData.put("subMchId",wxCildNo);
        reqData.put("subAppId",ParametersUtil.APPID);
        reqData.put("authCode",memberScanPayDTO.getMemberCode());

        log.info("==============>【随行付】辅助接口获取微信openId，调用请求业务参数：{}<==================",reqData);
        long startTime = System.currentTimeMillis();
        Map<String, Object> resultMap = sxfService.requestApi(SxfConfg.SXF_GET_WX_OPENID, reqData);
        long endTime = System.currentTimeMillis();
        log.info("==============>【随行付】辅助接口获取微信openId，返回参数：{},请求耗时：{}<==================",resultMap,endTime-startTime);
        JSONObject object = checkResultParams(resultMap);
        if(ResultCode.FAIL.code() == object.getInteger("code")){
            return object;
        }
        Map<String,Object> respData = (Map<String,Object>)resultMap.get("respData");
        Map<String,Object> result = new HashMap<>(2);
        result.put("data",respData);
        result.put("code","1");
        result.put("msg","获取成功");
        return result;
    }

    /**
     *
     * @param userAuthCode
     * @param paymentApp
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> getUnionInfo(String userAuthCode, String paymentApp,String merchantId) throws Exception {
        if(StringUtil.isEmpty(userAuthCode)){
            throw new MsgException("授权码不能为空！");
        }
        if(StringUtil.isEmpty(paymentApp)){
            throw new MsgException("银联标识不能为空！");
        }
        JSONObject reqData = new JSONObject(2);
        reqData.put("userAuthCode",userAuthCode);
        reqData.put("paymentApp",paymentApp);
        Map<String,Object> resultMap  = sxfService.requestApi(SxfConfg.SXF_GET_UNION_USERID, reqData);

        JSONObject object = checkResultParams(resultMap);
        if(ResultCode.FAIL.code() == object.getInteger("code")){
            return object;
        }
        Map<String,Object> respData = (Map<String,Object>)resultMap.get("respData");
        Map<String,Object> result = new HashMap<>(2);
        result.put("data",respData);
        result.put("code","1");
        result.put("msg","获取成功");
        return result;
    }

    /**
     *
     * @param transfer
     * @param
     * @return
     * @throws Exception
     */
//    @Override
//    public Map<String, Object> orgTransfer(MerchantTransfer transfer) throws Exception {
//        JSONObject reqData = new JSONObject(5);
//        reqData.put("mno",transfer.getChannelNo());
//        reqData.put("investor","01");//服务商出资
//        reqData.put("orderNo",transfer.getOrderNo());
//        reqData.put("amount",transfer.getAmount());
//        reqData.put("content",transfer.getContent());
//        Map<String,Object> resultMap  = sxfService.requestApi(SxfConfg.SXF_ORG_TRANS_FER, reqData);
//        return checkResultParams(resultMap);
//    }

    /**
     * @description:随行付支付回调处理
     * @date: 2021/8/19 18:41
     * @param map:
     * @return java.util.Map<java.lang.String,java.lang.String>
     */

    @Override
    public Map<String, String> payNotifyCallBack(Map<String, String> map) {
        Map<String,String> result = new HashMap<>(2);
        result.put("code","fail");
        result.put("msg","失败");

        //TODO 去掉签名测试用
        //if(!checkSign(map))return result;
        //随行付交易流水号，32位
        String uuid = map.get("uuid");
        //商户编号
        //String mno = map.get("mno");
        //商户订单号
        String ordNo = map.get("ordNo");
        //交易金额
        //String amt = map.get("amt");
        //交易时间 yyyyMMddHHmmss
        String payTime = map.get("payTime");
        //支付渠道 WECHAT:微信,ALIPAY:支付宝,UNIONPAY:银联
        //String payType =  map.get("payType");
        String bizCode =  map.get("bizCode");
        String buyerId = map.get("buyerId");
        String origOrdNo = map.get("origOrdNo");
        String origUuid = map.get("origUuid");
        String drType = map.get("drType");
        //渠道订单号
        String channelOrderNo = map.get("transactionId");
        //支付成功
        if(SxfConfg.SXF_SUCCESS_CODE.equals(bizCode)){
            //退款通知
            Date payDate = new Date();
            try {
                payDate = new SimpleDateFormat("yyyyMMddHHmmss").parse(payTime);
            } catch (ParseException e) {
                log.info("====================>【随行付】回调时间格式化异常，待转换的时间格式:{}<====================",payTime);
            }
            if(StringUtil.isNotEmpty(origOrdNo) && StringUtil.isNotEmpty(origUuid)){
                log.info("====================>【随行付】退款成功回调，我方原订单号：{}，随行付原订单号：{}<====================",origOrdNo,origUuid);
                QueryWrapper<MerchantRefundOrder> queryWrapper = new QueryWrapper<MerchantRefundOrder>().eq("orderNumber",origOrdNo).eq("channelNo",origUuid);
                queryWrapper.eq("status","2");
                MerchantRefundOrder refundOrder = merchantRefundOrderService.getOne(queryWrapper);
                if(refundOrder == null){
                    log.error("====================>【随行付】退款成功回调，我方原订单号：{}，随行付原订单号：{}，查询出的退款订单为空！<====================",origOrdNo,origUuid);
                }else{
                    refundOrder.setRefundTime(payDate);
                    refundOrder.setStatus("1");
                    refundOrder.setFailMsg(map.get("bizMsg"));
                    executorService.execute(() -> merchantRefundOrderService.updateOrderAndSendNotify(refundOrder));
                }
            }else{
                QueryWrapper<MerchantOrder> queryWrapper = new QueryWrapper<MerchantOrder>().eq("orderNumber",ordNo);
                MerchantOrder order = merchantOrderService.getOne(queryWrapper);
                if(order == null){
                    log.error("====================>【随行付】支付成功回调订单号查询，查询的订单为空：订单号：{}<====================",ordNo);
                    result.put("code","success");
                    result.put("msg","成功");
                    return result;
                }
                order.setTransNo(uuid);
                order.setTransDt(payDate);
                order.setStatus("1");
                order.setDrType(drType);
                order.setThirdTransNo(channelOrderNo);
                if(StringUtil.isEmpty(order.getMercUserId())){
                    order.setMercUserId(buyerId);
                }
                executorService.execute(() -> merchantOrderService.updateOrderAndCreateProfit(order));
            }
        }
        result.put("code","success");
        result.put("msg","成功");
        return result;
    }

    /**
     * @description:校验签名
     * @date: 2021/8/23 10:00
     * @return java.lang.Boolean
     */
    private Boolean checkSign(Map<String,String> map) {
        String sign = map.get("sign");
        map.remove("sign");
        JSONObject params = JSONObject.parseObject(JSONObject.toJSONString(map));
        String signContent = SignUtils.getSignContent(params);
        boolean flag = false;
        try {
            flag = RSAUtils.checkSign(SxfConfg.PUBLIC_KEY,signContent,sign);
        } catch (Exception e) {
            log.info("=========================>【随行付】校验签名异常，异常信息:{}<=====================",e.getMessage());
            e.printStackTrace();
        }
        return flag;
    }

    @Override
    public String tradePayWap(MerchantOrder order, MerchantChannelStatus channel) {
        return null;
    }

    @Override
    public JSONObject getUnionAccountUrl(JSONObject reqData) {
        return null;
    }

    @Override
    public JSONObject jftPay(JftReceiptOrder order, JftMercBaseInfo jftMerc, JftMercPaymentChannel jftChannel) {
        return null;
    }
}
