package com.tzy.framework.pay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.tzy.common.utils.*;
import com.tzy.common.utils.http.HttpUtils;
import com.tzy.framework.pay.config.BfPayConfig;
import com.tzy.framework.pay.config.PayConfig;
import com.tzy.framework.pay.dto.*;
import com.tzy.framework.pay.service.BfPayService;
import com.tzy.framework.pay.util.RSA2EncriptUtil;
import com.tzy.framework.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 宝付支付
 */
@Slf4j
@Service
public class BfPayServiceImpl implements BfPayService {

    @Autowired
    private BfPayConfig bfPayConfig;
    @Autowired
    private PayConfig payConfig;

    public static final String MAIN_WX = "DYNAMIC_WECHAT";//宝付-微信-主扫
    public static final String MAIN_ALIPAY = "DYNAMIC_ALPAY";//宝付-支付宝-主扫
    public static final String MAIN_UAC = "DYNAMIC_UNION";//宝付-云闪付-主扫
    public static final String APP_WX = "WECHAT_APPLET";//宝付-微信-APP
    public static final String APP_ALIPAY = "ALI_APPLET";//宝付-支付宝-APP

    public static final String reusePay = "TRUE";//是否支持重复扫码，默认是
    public static String regSpecial = "[`~!@$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）_+|{}‘；：”“’。，、？]";


    private Map<String,Object> init(String appid,String method) {
        BfPayConfig bfPayConfig = (BfPayConfig) payConfig.get(appid);
        if(null == bfPayConfig){
            bfPayConfig = this.bfPayConfig;
        }
        Map<String,Object> publicParam = new HashMap();
        publicParam.put("method", method);// 请求方法
//        publicParam.put("version","1.0");// 版本
//        publicParam.put("format","JSON");// 请求格式
//        publicParam.put("merchantNo","818000802925"); //商户号
//        publicParam.put("signType","RSA2");  //加密方式
        publicParam.put("version",bfPayConfig.getVersion());// 版本
        publicParam.put("format",bfPayConfig.getFormat());// 请求格式
        publicParam.put("merchantNo",bfPayConfig.getAppid()); //商户号
        publicParam.put("signType",bfPayConfig.getSignType());  //加密方式
        return publicParam;
    }
    private String initSignStr(String appid,String method,String signContent ) throws Exception {
        BfPayConfig bfPayConfig = (BfPayConfig) payConfig.get(appid);
        if(null == bfPayConfig){
            bfPayConfig = this.bfPayConfig;
        }
        /**
         * rsa 验签算法流程，当signType为RSA2时
         * 1.先按固定格式拼接
         * 2.RSA签名
         */
//        String signStr = RSA2EncriptUtil.reqSingStr(method,"1.0","JSON","818000802925","RSA2",signContent,"7c16c26a6c5550289ab65e6a69e89ee1");
        String signStr = RSA2EncriptUtil.reqSingStr(method,bfPayConfig.getVersion(),bfPayConfig.getFormat(),bfPayConfig.getAppid(),bfPayConfig.getSignType(),signContent,bfPayConfig.getKey());;
        log.info("[请求]固定格式拼接后明文：{}",signStr);
//        String sign = RSA2EncriptUtil.sign(signStr,"/home/tzy/bf/bfPrivateKey.pfx","880615sandy");
        String sign = RSA2EncriptUtil.sign(signStr,bfPayConfig.getPrivateKeyPath(),bfPayConfig.getPrivatePwd());
        log.info("[请求]RSA加签后内容：{}",sign);
        return sign;
    }

    public boolean verifyCallBack(String appid,String respSign,String sign ){
        BfPayConfig bfPayConfig = (BfPayConfig) payConfig.get(appid);
        if(null == bfPayConfig){
            bfPayConfig = this.bfPayConfig;
        }
        log.info("[响应] 固定格式拼接后：{}",respSign);
//        return RSA2EncriptUtil.verify(respSign , respMap.get("sign").toString() ,"/home/tzy/bf/bfPublicKey.cer");
        return RSA2EncriptUtil.verify(respSign,sign,bfPayConfig.getPublicKeyPath());
    }

    public boolean verify(String appid,Map respMap ){
        BfPayConfig bfPayConfig = (BfPayConfig) payConfig.get(appid);
        if(null == bfPayConfig){
            bfPayConfig = this.bfPayConfig;
        }
//        String respSign = RSA2EncriptUtil.resSingStr(respMap,"7c16c26a6c5550289ab65e6a69e89ee1");
        String respSign = RSA2EncriptUtil.resSingStr(respMap,bfPayConfig.getKey());
        log.info("[响应] 固定格式拼接后：{}",respSign);
//        return RSA2EncriptUtil.verify(respSign , respMap.get("sign").toString() ,"/home/tzy/bf/bfPublicKey.cer");
        return RSA2EncriptUtil.verify(respSign,respMap.get("sign").toString(),bfPayConfig.getPublicKeyPath());
    }

    @Override
    public ResultMap tradeCreate(PaymentRequestDto paymentRequestDto){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        String ipAddr = IpUtils.getIpAddr(request);
        String ipAddr = "127.0.0.1";
        ResultMap resultMap = new ResultMap();
        String method = PayConstants.BF_METHOD_TRADE_MAIN;
        String appScheme = "";
        String payType = "";
        String type = "main";
        switch (paymentRequestDto.getPayWay()){
            case PayConstants.BFPAY_TYPE_MAIN_WX:
                payType= MAIN_WX;
                appScheme = "";
                break;
            case PayConstants.BFPAY_TYPE_MAIN_ALIPAY:
                payType= MAIN_ALIPAY; //支付类型-支付宝
                appScheme = "alipays://platformapi/startapp?appId=20000067&url=";
                break;
            case PayConstants.BFPAY_TYPE_MAIN_UAC:
                payType= MAIN_UAC; //支付类型-云闪付
                appScheme = "";
                break;
            case PayConstants.BFPAY_TYPE_APP_WX:
                payType= APP_WX; //支付类型-微信-app
                appScheme = "";
                type = "app";
                method = PayConstants.BF_METHOD_TRADE_APP;
                break;
            case PayConstants.BFPAY_TYPE_APP_ALIPAY:
                payType= APP_ALIPAY; //支付类型-支付宝-app
                appScheme = "";
                type = "app";
                method = PayConstants.BF_METHOD_TRADE_APP;
                break;
        }
        String url = PayConstants.BF_HOST;
        Map<String,Object> publicParam = init(paymentRequestDto.getAppid(),method);
        /**
         * 业务请求参数
         */
        String msg = Base64Util.subStringByBytes(String.valueOf(paymentRequestDto.getBody()),80).replaceAll(regSpecial," ")+"...";
        JSONObject body = new JSONObject();
//		body.put("subMerchantNo",bfPayConfig.getSubMerchantNo());//门店编号
        body.put("transNo",paymentRequestDto.getMerOrderId());//商户订单号
        body.put("payType",payType); //支付类型
        body.put("orderAmt",paymentRequestDto.getTotalAmount().multiply(new BigDecimal(100)).intValue());        //交易金额
        body.put("goodsInfo",msg);//商品信息摘要
//        body.put("returnUrl","https://m2-dev.hobbystocks.cn/api/bf/paymentBack");//后台回调地址
        body.put("returnUrl",bfPayConfig.getPayNotifyUrl());//后台回调地址
        body.put("requestDate", DateFormatUtils.format(new Date(), "yyyyMMddHHmmss"));//请求时间
        body.put("pageUrl","");//前台跳转地址
//        body.put("pageUrl",bfPayConfig.getPageUrl());//前台跳转地址
        if("main".equals(type))body.put("reusePay",reusePay);//是否支持重复扫码，默认是
        body.put("extend",paymentRequestDto.getPayWay());//原样返回字段
        JSONObject extendmemo = new JSONObject();
//        extendmemo.put("paylimit","balance");//限制卡类型
        extendmemo.put("timeExpire", DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS,new Date(paymentRequestDto.getCreateOrderTime().getTime()+2800*60))); //交易结束时间
        //分账域，分账时必填
//		String shareInfo = "100000178,1";
//		extendmemo.put("shareInfo",shareInfo);
        extendmemo.put("spbillCreateIp",ipAddr); //终端用户IP
//        extendmemo.put("spbillCreateIp",paymentRequestDto.getCreateip()); //终端用户IP
        extendmemo.put("longitude","116.397128");//经度
        extendmemo.put("latitude","39.916527");//纬度
        //以下银联需要上送
//        extendmemo.put("areaInfo","");
//        extendmemo.put("appVersion","");
//        extendmemo.put("deviceType","");
//        extendmemo.put("deviceNo","");
        body.put("memo", extendmemo.toJSONString());
        publicParam.put("signContent",body.toJSONString());
        try {
            String sign = initSignStr(paymentRequestDto.getAppid(),method, body.toJSONString());
            publicParam.put("sign",sign);
            log.info(" 请求参数： {}",publicParam);
            String resp = HttpUtils.httpsRequest(url , "POST", BeanUtil.map2str(publicParam), null);
            log.info("响应] 响应内容：{}",resp);
            Map<String,Object> respMap = (Map<String, Object>) JSONObject.parseObject(resp,Map.class);
            if(verify(paymentRequestDto.getAppid(),respMap)){
                String resResult =  respMap.get("result").toString();
                Map<String,String> result = (Map<String, String>) JSONObject.parseObject(resResult,Map.class);
                log.info("解析结果：{}",result);
                if(result.get("orderStatus").toString().equals("SUCCESS")){
                    log.info("[交易结果]交易成功，成功金额："+result.get("orderAmt").toString()+"分。");
                    Map<String ,String > data = new HashMap<>();
                    data.put("orderNo",paymentRequestDto.getOrderNo());
                    data.put("url",appScheme+result.get("qrCode"));
                    resultMap.put("data",data);
                    return resultMap;
                } else if(result.get("orderStatus").toString().equals("INIT")){
                    log.info("[交易结果]交易未成功,"+result.get("respMsg").toString());
                    Map<String ,String > data = new HashMap<>();
                    data.put("orderNo",paymentRequestDto.getOrderNo());
                    data.put("url",appScheme+result.get("qrCode"));
                    resultMap.put("merOrderId",paymentRequestDto.getMerOrderId());
                    resultMap.put("data",data);
                    return resultMap;
                }else {
                    log.info("[交易结果]交易未成功,"+result.get("respMsg").toString());
                    return ResultMap.error(Integer.parseInt(result.get("respCode")),(String) result.get("respMsg"));
                }
            }
            else{
                log.info("验签失败");
                return ResultMap.error(-1,"验签失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultMap.error(-1,"签名生成异常！");
        }
    }

    @Override
    public PaymentInfoResponseDto queryOrder(String appid ,String payWay, String  orderNo){
        PaymentInfoResponseDto paymentInfoResponseDto = new PaymentInfoResponseDto();
        String method = PayConstants.BF_METHOD_QUERY_MAIN;
        String url = PayConstants.BF_HOST;
        Map<String,Object> publicParam = init(appid,method);
        JSONObject body = new JSONObject();
        body.put("transNo",orderNo);
        body.put("queryType","2");//查询类型 默认：2
        log.info("[请求]业务请求参数：{}",body.toJSONString());
        publicParam.put("signContent",body.toJSONString());
        try {
            String sign = initSignStr(appid,method, body.toJSONString());
            publicParam.put("sign",sign);
            log.info(" 请求参数： {}",publicParam);
            String resp = HttpUtils.httpsRequest(url , "POST", BeanUtil.map2str(publicParam), null);
            log.info("响应] 响应内容：{}",resp);
            Map<String,Object> respMap = (Map<String, Object>) JSONObject.parseObject(resp,Map.class);
            if(verify(appid,respMap)){
                String resResult =  respMap.get("result").toString();
                Map<String,String> result = (Map<String, String>) JSONObject.parseObject(resResult,Map.class);
                log.info("解析结果：{}",result);
                if(result.get("orderStatus").toString().equals("SUCCESS")){
                    log.info("[查询结果]交易成功，金额："+result.get("orderAmt").toString()+"分。");
                    paymentInfoResponseDto.setOrderNo(orderNo);
                    paymentInfoResponseDto.setPayWay(payWay);
                    paymentInfoResponseDto.setPaymentNo(result.get("tradeNo"));
                    paymentInfoResponseDto.setPaymentPrice(new BigDecimal(result.get("orderAmt")).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_FLOOR));
                    paymentInfoResponseDto.setActualPayment(new BigDecimal(result.get("orderAmt")).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_FLOOR));
                    paymentInfoResponseDto.setPaymentSuccessTime(DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, result.get("finishedDate")));
                    paymentInfoResponseDto.setSuccess(true);
                    return paymentInfoResponseDto;
                } else {
                    log.info("[查询结果]交易未成功,"+result.get("respMsg").toString());
                    return PaymentInfoResponseDto.error(Integer.valueOf(result.get("respCode")),(String) result.get("respMsg"));
                }
                /*Object ret = respMap.get("result");
                if(null != ret) {
                    String resResult = respMap.get("result").toString();
                    try {
                        Map<String, String> result = (Map<String, String>) JSONObject.parseObject(resResult, Map.class);
                        log.info("解析结果：{}", result);
                        paymentInfoResponseDto.setOrderNo(orderNo);
                        paymentInfoResponseDto.setPayWay(payWay);
                        paymentInfoResponseDto.setPaymentNo(StringUtils.isNotEmpty(result.get("tradeNo")) ? result.get("tradeNo") : null);
                        String orderAmt = StringUtils.isNotEmpty(result.get("orderAmt")) ? result.get("orderAmt") : "0";
                        paymentInfoResponseDto.setPaymentPrice(new BigDecimal(orderAmt).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_FLOOR));
                        paymentInfoResponseDto.setActualPayment(new BigDecimal(orderAmt).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_FLOOR));
                        Date finishedDate = StringUtils.isNotEmpty(result.get("finishedDate")) ? DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, result.get("finishedDate")) : null;
                        paymentInfoResponseDto.setPaymentSuccessTime(finishedDate);
                        String respCode = StringUtils.isNotEmpty(result.get("respCode")) ? result.get("respCode") : "-1";
                        paymentInfoResponseDto.setCode(Integer.valueOf(respCode));
                        paymentInfoResponseDto.setTradeState(respCode);
                        String respMsg = StringUtils.isNotEmpty(result.get("respMsg")) ? result.get("respCode") : "未找到状态";
                        paymentInfoResponseDto.setMsg(respMsg);
                        paymentInfoResponseDto.setTradeStateDesc(respMsg);
                        if (StringUtils.isNotEmpty(result.get("orderStatus")) && result.get("orderStatus").equals("SUCCESS")) {
                            log.info("[查询结果]交易成功，金额：" + result.get("orderAmt").toString() + "分。");
                        } else {
                            log.info("[查询结果]交易未成功," + result.get("respMsg").toString());
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                        paymentInfoResponseDto = PaymentInfoResponseDto.error(-1,"解析返回数据异常！");
                    }
                }
                return paymentInfoResponseDto;*/
            }
            else{
                log.info("验签失败");
                return PaymentInfoResponseDto.error(-1,"验签失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return PaymentInfoResponseDto.error(-1,"签名生成异常！");
        }
    }

    @Override
    public ResultMap refund(String appid , String orderNo, BigDecimal orderPrice, BigDecimal refundPrice, String refundMsg){
        String method = PayConstants.BF_METHOD_REFUND_MAIN;
        String url = PayConstants.BF_HOST;
        Map<String,Object> publicParam = init(appid,method);
        JSONObject body = new JSONObject();
        String refundNo = RandomUtil.getRandom(RandomUtil.REFUND_NO);
        body.put("transNo",refundNo);//商户订单号
        body.put("refundType","2");//退款类型
        body.put("origTransNo",orderNo);//原商户订单号
        body.put("origOrderAmt",orderPrice.multiply(new BigDecimal(100)).intValue());//原交易金额 单位： 分
        body.put("orderAmt", refundPrice.multiply(new BigDecimal(100)).intValue());//退款金额 单位： 分
        body.put("requestDate",DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS,new Date()));//交易日期
        body.put("refundReason",refundMsg); //退款原因
        body.put("returnUrl",bfPayConfig.getRefundNotifyUrl());//回调地址
        body.put("extend",orderNo); //扩展字段
        publicParam.put("signContent",body.toJSONString());
        try {
            String sign = initSignStr(appid,method, body.toJSONString());
            publicParam.put("sign",sign);
            log.info(" 请求参数： {}",publicParam);
            String resp = HttpUtils.httpsRequest(url , "POST", BeanUtil.map2str(publicParam), null);
            log.info("响应] 响应内容：{}",resp);
            Map<String,Object> respMap = (Map<String, Object>) JSONObject.parseObject(resp,Map.class);
            if(verify(appid,respMap)){
                String resResult =  respMap.get("result").toString();
                Map<String,String> result = (Map<String, String>) JSONObject.parseObject(resResult,Map.class);
                log.info("解析结果：{}",result);
                if(result.get("orderStatus").equals("SUCCESS")|| result.get("orderStatus").equals("PROCESSING")){
                    log.info("[申请退款结果]交易成功，金额："+result.get("orderAmt")+"分。");
                    Map<String, String> stringStringMap = new HashMap<>();
                    stringStringMap.put("out_refund_no", refundNo);
                    stringStringMap.put("refund_id", result.get("tradeNo"));
                    stringStringMap.put("refund_fee", result.get("orderAmt"));
                    stringStringMap.put("fund_change", "Y");
                    stringStringMap.put("finishedDate", result.get("finishedDate"));
                    return ResultMap.ok(result.get("respMsg"))
                            .put("data",stringStringMap)
                            ;
                }else {
                    log.info("[申请退款结果]交易未成功,"+result.get("respMsg").toString());
                    return ResultMap.error(Integer.parseInt(result.get("respCode")),(String) result.get("respMsg"));
                }
            }
            else{
                log.info("验签失败");
                return ResultMap.error(-1,"验签失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultMap.error(-1,"签名生成异常！");
        }
    }

    @Override
    public ResultMap refundQuery( String appid ,String outRefundNo){
        String method = PayConstants.BF_METHOD_REFUND_QUERY_MAIN;
        String url = PayConstants.BF_HOST;
        Map<String,Object> publicParam = init(appid,method);
        JSONObject body = new JSONObject();
        body.put("transNo",outRefundNo);//商户订单号
        publicParam.put("signContent",body.toJSONString());
        try {
            String sign = initSignStr(appid,method, body.toJSONString());
            publicParam.put("sign",sign);
            log.info(" 请求参数： {}",publicParam);
            String resp = HttpUtils.httpsRequest(url , "POST", BeanUtil.map2str(publicParam), null);
            log.info("响应] 响应内容：{}",resp);
            Map<String,Object> respMap = (Map<String, Object>) JSONObject.parseObject(resp,Map.class);
            if(verify(appid,respMap)){
                String resResult =  respMap.get("result").toString();
                Map<String,String> result = (Map<String, String>) JSONObject.parseObject(resResult,Map.class);
                log.info("解析结果：{}",result);
                if(result.get("orderStatus").equals("SUCCESS")){
                    log.info("[申请退款结果]交易成功，金额："+result.get("orderAmt")+"分。");
                    Map<String, String> stringStringMap = new HashMap<>();
                    stringStringMap.put("out_refund_no", outRefundNo);
                    stringStringMap.put("refund_id", result.get("tradeNo"));
                    stringStringMap.put("refund_fee", result.get("orderAmt"));
                    stringStringMap.put("fund_change", "Y");
                    stringStringMap.put("finishedDate", result.get("finishedDate"));
                    return ResultMap.ok()
                            .put("data",stringStringMap)
                            ;
                }else {
                    log.info("[申请退款结果]交易未成功,"+result.get("respMsg").toString());
                    return ResultMap.error(Integer.parseInt(result.get("respCode")),(String) result.get("respMsg"));
                }
            }
            else{
                log.info("验签失败");
                return ResultMap.error(-1,"验签失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultMap.error(-1,"签名生成异常！");
        }
    }



    public static void main(String[] args) {
        BfPayService bfPaymentService = new BfPayServiceImpl();
        PaymentRequestDto p = new PaymentRequestDto();
//        p.setPayWay("wxpay-main-bf");
//        p.setPayWay("alipay-main-bf");
        p.setPayWay(PayConstants.BFPAY_TYPE_MAIN_ALIPAY);
        p.setBody("测试");
        p.setOrderNo(RandomUtil.getRandomOld(RandomUtil.GROUP_USER_ORDER));
        p.setTotalAmount(new BigDecimal(0.01));
        p.setCreateOrderTime(new Date());
        p.setCreateip("192.168.1.1");
        log.info(" 统一下单结果：{} ",bfPaymentService.tradeCreate(p));
//        String orderNo = "GU202205061137016431";
//        log.info(" 统一下单结果：{} ",bfPaymentService.queryOrder("alipay-main-bf",orderNo));
    }

    /****************************新支付逻辑*******************************/

    /**
     * new
     * @param bfPayConfig
     * @param method
     * @return
     */
    private Map<String,Object> init(BfPayConfig bfPayConfig,String method) {
        if(null == bfPayConfig){
            return new HashMap<>();
        }
        Map<String,Object> publicParam = new HashMap();
        publicParam.put("method", method);// 请求方法
        publicParam.put("version",bfPayConfig.getVersion());// 版本
        publicParam.put("format",bfPayConfig.getFormat());// 请求格式
        publicParam.put("merchantNo",bfPayConfig.getAppid()); //商户号
        publicParam.put("signType",bfPayConfig.getSignType());  //加密方式
        return publicParam;
    }
    /**
     * new
     * @param bfPayConfig
     * @param method
     * @param signContent
     * @return
     * @throws Exception
     */
    private String initSignStr(BfPayConfig bfPayConfig,String method,String signContent ) throws Exception {
        if(null == bfPayConfig){
            return null;
        }
        /**
         * rsa 验签算法流程，当signType为RSA2时
         * 1.先按固定格式拼接
         * 2.RSA签名
         */
        String signStr = RSA2EncriptUtil.reqSingStr(method,bfPayConfig.getVersion(),bfPayConfig.getFormat(),bfPayConfig.getAppid(),bfPayConfig.getSignType(),signContent,bfPayConfig.getKey());;
        log.info("[请求]固定格式拼接后明文：{}",signStr);
        String sign = RSA2EncriptUtil.sign(signStr,bfPayConfig.getPrivateKeyPath(),bfPayConfig.getPrivatePwd());
        log.info("[请求]RSA加签后内容：{}",sign);
        return sign;
    }

    /**
     * new
     * @param bfPayConfig
     * @param respSign
     * @param sign
     * @return
     */
    public boolean verifyCallBackNew(BfPayConfig bfPayConfig,String respSign,String sign ){
        if(null == bfPayConfig){
            return false;
        }
        log.info("[响应] 固定格式拼接后：{}",respSign);
        return RSA2EncriptUtil.verify(respSign,sign,bfPayConfig.getPublicKeyPath());
    }
    /**
     * new
     * @param bfPayConfig
     * @param respMap
     * @return
     */
    public boolean verify(BfPayConfig bfPayConfig,Map respMap ){
        if(null == bfPayConfig){
            return false;
        }
//        String respSign = RSA2EncriptUtil.resSingStr(respMap,"7c16c26a6c5550289ab65e6a69e89ee1");
        String respSign = RSA2EncriptUtil.resSingStr(respMap,bfPayConfig.getKey());
        log.info("[响应] 固定格式拼接后：{}",respSign);
//        return RSA2EncriptUtil.verify(respSign , respMap.get("sign").toString() ,"/home/tzy/bf/bfPublicKey.cer");
        return RSA2EncriptUtil.verify(respSign,respMap.get("sign").toString(),bfPayConfig.getPublicKeyPath());
    }

    /**
     * 新支付逻辑
     * @param paymentRequestDto
     * @return
     */
    @Override
    public ResultMap tradeCreateNew(PaymentRequestDto paymentRequestDto){
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        String ipAddr = IpUtils.getIpAddr(request);
        BfPayConfig bfPayConfig = (BfPayConfig) paymentRequestDto.getPayConfigByClass(BfPayConfig.class);
        String ipAddr = "127.0.0.1";
        ResultMap resultMap = new ResultMap();
        String method = PayConstants.BF_METHOD_TRADE_MAIN;
        String appScheme = "";
        String payType = "";
        String type = "main";
        switch (paymentRequestDto.getPayWay()){
            case PayConstants.BFPAY_TYPE_MAIN_WX:
                payType= MAIN_WX;
                appScheme = "";
                break;
            case PayConstants.BFPAY_TYPE_MAIN_ALIPAY:
                payType= MAIN_ALIPAY; //支付类型-支付宝
                appScheme = "alipays://platformapi/startapp?appId=20000067&url=";
                break;
            case PayConstants.BFPAY_TYPE_MAIN_UAC:
                payType= MAIN_UAC; //支付类型-云闪付
                appScheme = "";
                break;
            case PayConstants.BFPAY_TYPE_APP_WX:
                payType= APP_WX; //支付类型-微信-app
                appScheme = "";
                type = "app";
                method = PayConstants.BF_METHOD_TRADE_APP;
                break;
            case PayConstants.BFPAY_TYPE_APP_ALIPAY:
                payType= APP_ALIPAY; //支付类型-支付宝-app
                appScheme = "";
                type = "app";
                method = PayConstants.BF_METHOD_TRADE_APP;
                break;
        }
        String url = PayConstants.BF_HOST;
//        Map<String,Object> publicParam = init(paymentRequestDto.getAppid(),method);
        Map<String,Object> publicParam = init(bfPayConfig,method);
        /**
         * 业务请求参数
         */
        String msg = String.valueOf(paymentRequestDto.getBody());
        msg = Base64Util.subStringByBytes(msg,80).replaceAll(regSpecial," ")+"...";
        JSONObject body = new JSONObject();
//		body.put("subMerchantNo",bfPayConfig.getSubMerchantNo());//门店编号
        body.put("transNo",paymentRequestDto.getOrderNo());//商户订单号
        body.put("payType",payType); //支付类型
        body.put("orderAmt",paymentRequestDto.getTotalAmount().multiply(new BigDecimal(100)).intValue());        //交易金额
        body.put("goodsInfo",msg);//商品信息摘要
//        body.put("returnUrl","https://m2-dev.hobbystocks.cn/api/bf/paymentBack");//后台回调地址
        body.put("returnUrl",bfPayConfig.getPayNotifyUrl());//后台回调地址
        body.put("requestDate", DateFormatUtils.format(new Date(), "yyyyMMddHHmmss"));//请求时间
        body.put("pageUrl","");//前台跳转地址
//        body.put("pageUrl",bfPayConfig.getPageUrl());//前台跳转地址
        if("main".equals(type))body.put("reusePay",reusePay);//是否支持重复扫码，默认是
        body.put("extend",paymentRequestDto.getPayWay());//原样返回字段
        JSONObject extendmemo = new JSONObject();
//        extendmemo.put("paylimit","balance");//限制卡类型
        String expireTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,paymentRequestDto.getExpireTime());
        extendmemo.put("timeExpire", expireTime); //交易结束时间
        //分账域，分账时必填
//		String shareInfo = "100000178,1";
//		extendmemo.put("shareInfo",shareInfo);
        extendmemo.put("spbillCreateIp",ipAddr); //终端用户IP
//        extendmemo.put("spbillCreateIp",paymentRequestDto.getCreateip()); //终端用户IP
        extendmemo.put("longitude","116.397128");//经度
        extendmemo.put("latitude","39.916527");//纬度
        //以下银联需要上送
//        extendmemo.put("areaInfo","");
//        extendmemo.put("appVersion","");
//        extendmemo.put("deviceType","");
//        extendmemo.put("deviceNo","");
        body.put("memo", extendmemo.toJSONString());
        publicParam.put("signContent",body.toJSONString());
        try {
//            String sign = initSignStr(paymentRequestDto.getAppid(),method, body.toJSONString());
            String sign = initSignStr(bfPayConfig,method, body.toJSONString());
            publicParam.put("sign",sign);
            log.info(" 请求参数： {}",publicParam);
            String resp = HttpUtils.httpsRequest(url , "POST", BeanUtil.map2str(publicParam), null);
            log.info("响应] 响应内容：{}",resp);
            Map<String,Object> respMap = (Map<String, Object>) JSONObject.parseObject(resp,Map.class);
//            if(verify(paymentRequestDto.getAppid(),respMap)){
            if(verify(bfPayConfig,respMap)){
                String resResult =  respMap.get("result").toString();
                Map<String,String> result = (Map<String, String>) JSONObject.parseObject(resResult,Map.class);
                log.info("解析结果：{}",result);
                if(result.get("orderStatus").toString().equals("SUCCESS")){
                    log.info("[交易结果]交易成功，成功金额："+result.get("orderAmt").toString()+"分。");
                    Map<String ,String > data = new HashMap<>();
                    data.put("orderNo",paymentRequestDto.getOrderNo());
                    data.put("url",appScheme+result.get("qrCode"));
                    resultMap.put("data",data);
                    return resultMap;
                } else if(result.get("orderStatus").toString().equals("INIT")){
                    log.info("[交易结果]交易未成功,"+result.get("respMsg").toString());
                    Map<String ,String > data = new HashMap<>();
                    data.put("orderNo",paymentRequestDto.getOrderNo());
                    data.put("url",appScheme+result.get("qrCode"));
                    resultMap.put("data",data);
                    return resultMap;
                }else {
                    log.info("[交易结果]交易未成功,"+result.get("respMsg").toString());
                    return ResultMap.error(Integer.parseInt(result.get("respCode")),(String) result.get("respMsg"));
                }
            }
            else{
                log.info("验签失败");
                return ResultMap.error(-1,"验签失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultMap.error(-1,"签名生成异常！");
        }
    }

    @Override
    public PaymentInfoResponseDto queryOrder(PaymentRequestDto paymentRequestDto){
        PaymentInfoResponseDto paymentInfoResponseDto = new PaymentInfoResponseDto();
        String orderNo = paymentRequestDto.getOrderNo();
        String payWay = paymentRequestDto.getPayWay();
        BfPayConfig bfPayConfig = (BfPayConfig) paymentRequestDto.getPayConfigByClass(BfPayConfig.class);

        String method = PayConstants.BF_METHOD_QUERY_MAIN;
        String url = PayConstants.BF_HOST;
//        Map<String,Object> publicParam = init(appid,method);
        Map<String,Object> publicParam = init(bfPayConfig,method);
        JSONObject body = new JSONObject();
        body.put("transNo",orderNo);
        body.put("queryType","2");//查询类型 默认：2
        log.info("[请求]业务请求参数：{}",body.toJSONString());
        publicParam.put("signContent",body.toJSONString());
        try {
//            String sign = initSignStr(appid,method, body.toJSONString());
            String sign = initSignStr(bfPayConfig,method, body.toJSONString());
            publicParam.put("sign",sign);
            log.info(" 请求参数： {}",publicParam);
            String resp = HttpUtils.httpsRequest(url , "POST", BeanUtil.map2str(publicParam), null);
            log.info("响应] 响应内容：{}",resp);
            Map<String,Object> respMap = (Map<String, Object>) JSONObject.parseObject(resp,Map.class);
//            if(verify(appid,respMap)){
            if(verify(bfPayConfig,respMap)){
                String resResult =  respMap.get("result").toString();
                Map<String,String> result = (Map<String, String>) JSONObject.parseObject(resResult,Map.class);
                log.info("解析结果：{}",result);
                paymentInfoResponseDto.setOrderNo(orderNo);
                paymentInfoResponseDto.setPayWay(payWay);
                paymentInfoResponseDto.setPaymentNo(StringUtils.isNotEmpty(result.get("tradeNo")) ? result.get("tradeNo") : null);
                String orderAmt = StringUtils.isNotEmpty(result.get("orderAmt")) ? result.get("orderAmt") : "0";
                paymentInfoResponseDto.setPaymentPrice(new BigDecimal(orderAmt).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_FLOOR));
                paymentInfoResponseDto.setActualPayment(new BigDecimal(orderAmt).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_FLOOR));
                Date finishedDate =StringUtils.isNotEmpty(result.get("finishedDate")) ? DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, result.get("finishedDate")) : null;
                paymentInfoResponseDto.setPaymentSuccessTime(finishedDate);
                if(StringUtils.isNotEmpty(result.get("orderStatus")) && result.get("orderStatus").equals("SUCCESS")){
                    log.info("[查询结果]交易成功，金额："+result.get("orderAmt").toString()+"分。");
                    paymentInfoResponseDto.setSuccess(true);
                    return paymentInfoResponseDto;
                } else {
                    log.info("[查询结果]交易未成功,"+result.get("respMsg").toString());
                    return PaymentInfoResponseDto.error(Integer.valueOf(result.get("respCode")),(String) result.get("respMsg"));
                }
            }
            else{
                log.info("验签失败");
                return PaymentInfoResponseDto.error(-1,"验签失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return PaymentInfoResponseDto.error(-1,"签名生成异常！");
        }
    }

    @Override
    public ResultMap refund(RefundRequestDto refundRequestDto){
        String method = PayConstants.BF_METHOD_REFUND_MAIN;
        String url = PayConstants.BF_HOST;
        BfPayConfig bfPayConfig = (BfPayConfig) refundRequestDto.getPayConfigByClass(BfPayConfig.class);
        String orderNo = refundRequestDto.getOrderNo();
        BigDecimal orderPrice = refundRequestDto.getOrderPrice();
        BigDecimal refundPrice = refundRequestDto.getRefundAmount();
        String refundMsg = refundRequestDto.getRefundMsg();

        Map<String,Object> publicParam = init(bfPayConfig,method);
        JSONObject body = new JSONObject();
        String refundNo = RandomUtil.getRandom(RandomUtil.REFUND_NO);
        body.put("transNo",refundNo);//商户订单号
        body.put("refundType","2");//退款类型
        body.put("origTransNo",orderNo);//原商户订单号
        body.put("origOrderAmt",orderPrice.multiply(new BigDecimal(100)).intValue());//原交易金额 单位： 分
        body.put("orderAmt", refundPrice.multiply(new BigDecimal(100)).intValue());//退款金额 单位： 分
        body.put("requestDate",DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS,new Date()));//交易日期
        body.put("refundReason",refundMsg); //退款原因
//        String returnUrl = "https://www.merchant.com"; //回调地址
        body.put("returnUrl",bfPayConfig.getRefundNotifyUrl());
        body.put("extend",refundRequestDto.getPayWay()); //扩展字段
        publicParam.put("signContent",body.toJSONString());
        try {
            String sign = initSignStr(bfPayConfig,method, body.toJSONString());
            publicParam.put("sign",sign);
            log.info(" 请求参数： {}",publicParam);
            String resp = HttpUtils.httpsRequest(url , "POST", BeanUtil.map2str(publicParam), null);
            log.info("响应] 响应内容：{}",resp);
            Map<String,Object> respMap = (Map<String, Object>) JSONObject.parseObject(resp,Map.class);
            if(verify(bfPayConfig,respMap)){
                String resResult =  respMap.get("result").toString();
                Map<String,String> result = (Map<String, String>) JSONObject.parseObject(resResult,Map.class);
                log.info("解析结果：{}",result);
                if(result.get("orderStatus").equals("SUCCESS") || result.get("orderStatus").equals("PROCESSING")){
                    log.info("[申请退款结果]交易成功，金额："+result.get("orderAmt")+"分。");
                    Map<String, String> stringStringMap = new HashMap<>();
                    stringStringMap.put("out_refund_no", refundNo);
                    stringStringMap.put("refund_id", result.get("tradeNo"));
                    stringStringMap.put("refund_fee", result.get("orderAmt"));
                    stringStringMap.put("fund_change", "Y");
                    stringStringMap.put("finishedDate", result.get("finishedDate"));
                    return ResultMap.ok(result.get("respMsg"))
                            .put("data",stringStringMap)
                            ;
                } else {
                    log.info("[申请退款结果]交易未成功,"+result.get("respMsg").toString());
                    return ResultMap.error(Integer.parseInt(result.get("respCode")),(String) result.get("respMsg"));
                }
            }
            else{
                log.info("验签失败");
                return ResultMap.error(-1,"验签失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultMap.error(-1,"签名生成异常！");
        }
    }

    @Override
    public ResultMap refundQuery(RefundRequestDto refundRequestDto){
        String method = PayConstants.BF_METHOD_REFUND_QUERY_MAIN;
        String url = PayConstants.BF_HOST;
        BfPayConfig bfPayConfig = (BfPayConfig) refundRequestDto.getPayConfigByClass(BfPayConfig.class);
        String outRefundNo= refundRequestDto.getRefundNo();
        Map<String,Object> publicParam = init(bfPayConfig,method);
        JSONObject body = new JSONObject();
        body.put("transNo",outRefundNo);//商户订单号
        publicParam.put("signContent",body.toJSONString());
        try {
            String sign = initSignStr(bfPayConfig,method, body.toJSONString());
            publicParam.put("sign",sign);
            log.info(" 请求参数： {}",publicParam);
            String resp = HttpUtils.httpsRequest(url , "POST", BeanUtil.map2str(publicParam), null);
            log.info("响应] 响应内容：{}",resp);
            Map<String,Object> respMap = (Map<String, Object>) JSONObject.parseObject(resp,Map.class);
            if(verify(bfPayConfig,respMap)){
                String resResult =  respMap.get("result").toString();
                Map<String,String> result = (Map<String, String>) JSONObject.parseObject(resResult,Map.class);
                log.info("解析结果：{}",result);
                if(result.get("orderStatus").equals("SUCCESS")){
                    log.info("[申请退款结果]交易成功，金额："+result.get("orderAmt")+"分。");
                    Map<String, String> stringStringMap = new HashMap<>();
                    stringStringMap.put("out_refund_no", outRefundNo);
                    stringStringMap.put("refund_id", result.get("tradeNo"));
                    stringStringMap.put("refund_fee", result.get("orderAmt"));
                    stringStringMap.put("fund_change", "Y");
                    stringStringMap.put("finishedDate", result.get("finishedDate"));
                    return ResultMap.ok()
                            .put("data",stringStringMap)
                            ;
                }else {
                    log.info("[申请退款结果]交易未成功,"+result.get("respMsg").toString());
                    return ResultMap.error(Integer.parseInt(result.get("respCode")),(String) result.get("respMsg"));
                }
            }
            else{
                log.info("验签失败");
                return ResultMap.error(-1,"验签失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultMap.error(-1,"签名生成异常！");
        }
    }


}
