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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tzy.common.utils.Base64Util;
import com.tzy.common.utils.DateUtils;
import com.tzy.common.utils.LogSyncUtil;
import com.tzy.common.utils.StringUtils;
import com.tzy.framework.pay.config.BaofooRechargePayConfig;
import com.tzy.framework.pay.dto.*;
import com.tzy.framework.pay.service.BaofooRechargePayService;
import com.tzy.framework.pay.util.FormatUtil;
import com.tzy.framework.pay.util.bofoo.bank.HttpUtil;
import com.tzy.framework.pay.util.bofoo.bank.RsaCodingUtil;
import com.tzy.framework.pay.util.bofoo.bank.SecurityUtil;
import com.tzy.framework.pay.util.bofoo.bank.SignatureUtils;
import com.tzy.framework.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;


@Slf4j
@Service
public class BaofooRechargePayServiceImpl implements BaofooRechargePayService {

    @Value("${pay.version:dev}")
    private String appversion;

    private String baseUrl = "https://bht.mandao.com/api/";//生产
    private String baseUrlBox = "https://account.baofoo.com/api/";//测试
    private String serviceOrderUrl = "order/{0}/{1}";
    private String serviceTradeUrl = "trade/{0}/{1}";
    private String serviceWalletUrl = "wallet/{0}/{1}";

    public static void main(String[] args) {
        Date createTime = new Date();
        BaofooRechargePayServiceImpl service = new BaofooRechargePayServiceImpl();
        RechargeUserInfoDto rechargeUserInfoDto = new RechargeUserInfoDto();
        rechargeUserInfoDto.setLoginNo("1000000002");//1000000002//lsz-3
        rechargeUserInfoDto.setUserName("邓力");//3177000000478634//邓力
        rechargeUserInfoDto.setCertificateNo("360902200005081816");//360902200005081816 //lsz-3177000000478764
        rechargeUserInfoDto.setAgreementNo("312023052400000006288");
        PaymentRequestDto payRequestBody = new PaymentRequestDto();
        payRequestBody.setPayConfig(JSONObject.parseObject(JSONObject.toJSONString(new BaofooRechargePayConfig())));
        payRequestBody.setRechargeUserInfoDto(rechargeUserInfoDto);
        payRequestBody.setBody("个人充值测试！");
        payRequestBody.setOrderNo(RandomUtil.getRandomOld(RandomUtil.GROUP_USER_ORDER));
        payRequestBody.setTotalAmount(new BigDecimal(0.01));//
//        log.info(" log-个人充值：{} ",service.recharge(payRequestBody));//20000193620230524551801797116449
        rechargeUserInfoDto.setCallType("WALLET_PAY");
        payRequestBody.setRechargeUserInfoDto(rechargeUserInfoDto);
//        log.info(" log-个人钱包：{} ",service.wallet(payRequestBody));//
        payRequestBody.setPaySubWay("BALANCE");
//        log.info(" log-分账支付：{} ",service.paymentSplitApi(payRequestBody));//
        payRequestBody.setCreateOrderTime(createTime);
        payRequestBody.setExpireTime(DateUtils.addCalendar(createTime,DateUtils.minute,3));// 3分钟后过期
        payRequestBody.setPaySubWay("ALIPAY_NATIVE");//  ALIPAY_NATIVE ALIPAY_ALXCX
//        log.info(" log-聚合支付：{} ",service.payment(payRequestBody));//
        //退款
        RefundRequestDto refundRequestDto = new RefundRequestDto();
        refundRequestDto.setRechargeUserInfoDto(rechargeUserInfoDto);
        refundRequestDto.setPayConfig(JSONObject.parseObject(JSONObject.toJSONString(new BaofooRechargePayConfig())));
        refundRequestDto.setTradeNo("20000193620230525041710415212733");
        refundRequestDto.setRefundAmount(new BigDecimal(0.01));
        refundRequestDto.setRefundMsg("退款测试");
//        log.info(" log-聚合支付：{} ",service.profitShareRefundApply(refundRequestDto));//

    }
    /**
     * 2.1.1 个人充值-API
     * 暂时不用
     *
     * @param payRequestBody
     * @return
     * @throws Exception
     */
    public ResultMap recharge(PaymentRequestDto payRequestBody) {
        try {
            RechargeUserInfoDto rechargeUserInfoDto = payRequestBody.getRechargeUserInfoDto();
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) payRequestBody.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            String amount = payRequestBody.getTotalAmount().multiply(new BigDecimal(100)).intValue()+"";
            String agreementNo = rechargeUserInfoDto.getAgreementNo();
            String notifyUrl = payConfig.getPayNotifyUrl();
            String outOrderNo = getMerchantOrderId(payConfig);
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            SendData.put("outOrderNo", outOrderNo);
            SendData.put("amount", amount);
            agreementNo = SecurityUtil.Base64Encode(agreementNo);
            agreementNo = RsaCodingUtil.encryptByPubCerFile(agreementNo, payConfig.getPublicKey());
            SendData.put("agreementNo", agreementNo);
            SendData.put("notifyUrl", notifyUrl);
            String OsignData = FormatUtil.formatVerify(
                    "orgNo|merchantNo|terminalNo|loginNo|requestDate|outOrderNo|amount|agreementNo", SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String PostString = HttpUtil.requestPostByType(getServiceOrderUrl("v3.0.0","recharge"), SendData,
                    "application/json");
            if (null == PostString || PostString.isEmpty()) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                // 自行处理
                String result = jsonObject.getString("result");
                log.info("密码链接-->" + result);
                return ResultMap.ok()
                        .put("merOrderId",outOrderNo)
                        .put("orderNo",payRequestBody.getOrderNo())
                        .put("redirectUrl",result)
                        ;
            } else {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(" 下单失败：{} ",e);
        }
        return ResultMap.error("下单失败");
    }
    /**
     * 2.2.1 个人提现-API
     * 暂时不用
     * @param refundRequestDto
     * @return
     * @throws Exception
     */
    public ResultMap withdraw(RefundRequestDto refundRequestDto) {
        String errMsg = "";
       try {
           RechargeUserInfoDto rechargeUserInfoDto = refundRequestDto.getRechargeUserInfoDto();
           BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) refundRequestDto.getPayConfigByClass(BaofooRechargePayConfig.class);
           String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
           String amount = refundRequestDto.getRefundAmount().multiply(new BigDecimal(100)).intValue()+"";
           String agreementNo = rechargeUserInfoDto.getAgreementNo();
           String notifyUrl = payConfig.getRefundNotifyUrl();
           Map<String, Object> SendData = new HashMap<String, Object>();
           String outOrderNo = getMerchantOrderId(payConfig);
           SendData.put("orgNo", payConfig.getMid());
           SendData.put("merchantNo", payConfig.getMid());
           SendData.put("terminalNo", payConfig.getTid());
           SendData.put("loginNo", loginNo);
           SendData.put("requestDate", DateUtils.dateTimeNow());
           SendData.put("outOrderNo", outOrderNo);
           SendData.put("amount", amount);
           agreementNo = SecurityUtil.Base64Encode(agreementNo);
           agreementNo = RsaCodingUtil.encryptByPubCerFile(agreementNo, payConfig.getPublicKey());
           SendData.put("agreementNo", agreementNo);
           SendData.put("notifyUrl", notifyUrl);
           String OsignData = FormatUtil.formatVerify(
                   "orgNo|merchantNo|terminalNo|loginNo|requestDate|outOrderNo|amount|agreementNo", SendData);
           log.info("签名拼接参数：" + OsignData);
           String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
           log.info("签名结果：" + Sign);
           SendData.put("signData", Sign);// 签名结果。
           String PostString = HttpUtil.requestPostByType(getServiceOrderUrl("v3.0.0","withdraw"), SendData,
                   "application/json");
           if (null == PostString || PostString.isEmpty()) {
               log.info("PostString  为空");
               return ResultMap.error(-1,"返回出错【404】");
           }
           JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
           if (!jsonObject.containsKey("success")) {
               return ResultMap.error(-1,jsonObject.getString("errorMsg"));
           }
           if (jsonObject.getBoolean("success")) {
               // 自行处理
               String result = jsonObject.getString("result");
               log.info("密码链接-->" + result);
               return ResultMap.ok()
                       .put("merOrderId",outOrderNo)
                       .put("orderNo",refundRequestDto.getOrderNo())
                       .put("redirectUrl",result)
                       ;
           } else {
               return ResultMap.error(-1,jsonObject.getString("errorMsg"));
           }
       }catch (Exception e){
           e.printStackTrace();
           log.error(" 退款请求失败：{} ",e);
           errMsg = "退款请求失败";
       }
        return ResultMap.error(-2,errMsg);
    }

    /**
     * H5页面统一唤起接口，根据唤起类型区分交易，返回redirectUrl链接10分钟内有效
     * 暂时不用
     * @param payRequestBody
     * @return
     * @throws Exception
     */
    public ResultMap wallet(PaymentRequestDto payRequestBody)  {
        try {
            RechargeUserInfoDto rechargeUserInfoDto = payRequestBody.getRechargeUserInfoDto();
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) payRequestBody.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            String callType = rechargeUserInfoDto.getCallType();// 唤起类型
            log.info("H5页面唤起类型：" + callType);
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("callType", callType);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            Map<String, Object> DC = new HashMap<String, Object>();
            String outOrderNo = getMerchantOrderId(payConfig);
            String body = payRequestBody.getBody();
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(body) ){
                body = Base64Util.subStringByBytes(body,80)+"...";
            }
            int totalPrice = payRequestBody.getTotalAmount().multiply(new BigDecimal(100)).intValue();
            String dataContent = "";
            /*if (callType.equals("EXPENSE_RECHARGE") || callType.equals("EXPENSE_PAYMENT") || callType.equals("ASSURE_PAY")
                    || callType.equals("EXPENSE_RECHARGE") || callType.equals("PAYMENT_SPLIT")
                    || callType.equals("BM_PAYMENT_SPLIT") || callType.equals("B_PAYMENT_SPLIT")
                    || callType.equals("WALLET_ASSURE_PAY")) {
                DC.put("goodsName", body);// 商品名
                DC.put("amount", totalPrice);// 订单金额
                DC.put("outOrderNo", outOrderNo);// 商户订单号
                DC.put("notifyUrl", payConfig.getPayNotifyUrl());// 异步通知地址
                DC.put("expireDate", payRequestBody.getExpireTime());// 设置订单失效时间

                if (callType.equals("EXPENSE_PAYMENT")) {
                    DC.put("oldOutOrderNo", request.getParameter("oldOutOrderNo"));
                }
                if (callType.equals("EXPENSE_RECHARGE")|| callType.equals("WALLET_ASSURE_PAY")) {
                    DC.put("validDate", request.getParameter("validDate"));
                }

                if (callType.equals("ASSURE_PAY") || callType.equals("EXPENSE_PAYMENT") || callType.equals("PAYMENT_SPLIT")
                        || callType.equals("BM_PAYMENT_SPLIT") || callType.equals("B_PAYMENT_SPLIT")
                        || callType.equals("WALLET_ASSURE_PAY")) {
                    String SplitInfoList = request.getParameter("SplitInfoList");
                    log.info(SplitInfoList);
                    if ("[]".equals(SplitInfoList)) {// 分账信息不能为空
                        return "分账信息不能为空，请检查";
                    }
                    JSONArray js = JSONArray.fromObject(SplitInfoList);
                    for (int i = 0; i < js.size(); i++) {
                        JSONObject jo = js.getJSONObject(i);
                        jo.put("subOutOrderNo", DC.get("outOrderNo") + "_" + i);
                    }
                    DC.put("splitInfoList", js);// 放入分账参数
                }
                JSONObject DCString = JSONObject.parseObject(JSONObject.toJSONString(DC));
                SendData.put("dataContent", DCString.toString());
            } else*/ if (callType.equals("PAYMENT") || callType.equals("B_PAYMENT") || callType.equals("BM_PAYMENT")) {
                String str = body + "||" + totalPrice + "||" + outOrderNo + "||" + payConfig.getPayNotifyUrl();
                SendData.put("dataContent", str);
            } else if (callType.equals("B_WITHDRAW")) {
                DC.put("amount", totalPrice);
                DC.put("outOrderNo", outOrderNo);
                DC.put("notifyUrl", payConfig.getPayNotifyUrl());
                JSONObject DCString = JSONObject.parseObject(JSONObject.toJSONString(DC));
                SendData.put("dataContent", DCString.toString());
            } else if (callType.equals("WALLET_PAY")) {
                DC.put("notifyUrl", payConfig.getPayNotifyUrl());
                JSONObject DCString = JSONObject.parseObject(JSONObject.toJSONString(DC));
                SendData.put("dataContent", DCString.toString());
            } else {
                SendData.put("dataContent", dataContent);
            }
            String OsignData = FormatUtil
                    .formatVerify("orgNo|merchantNo|terminalNo|callType|loginNo|requestDate|dataContent", SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String PostString = HttpUtil.requestPostByType(getServiceWalletUrl("v3.0.0","login"), SendData,
                    "");
            log.info("后端请求表单：" + PostString);
            if (StringUtils.isEmpty(PostString)) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("retCode")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            String redirectUrl = "";
            if (jsonObject.getString("retCode").toString().equals("SUCCESS")) {
                if (jsonObject.containsKey("redirectUrl")) {
                    redirectUrl = jsonObject.getString("redirectUrl");
                    log.info("返回地址值：" + redirectUrl);
                }
                return ResultMap.ok()
                        .put("redirectUrl",redirectUrl)
                        ;
            } else {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        } catch (Exception e) {
            log.error(" 支付异常{} ",e);
        }
        return ResultMap.error(-1,"支付异常！");
    }
    /**
     * 3.3 修改分账信息
     * @param payRequestBody
     * @return
     * @throws Exception
     */
    public ResultMap updateSplitInfo(PaymentRequestDto payRequestBody) {
        try {
            RechargeUserInfoDto rechargeUserInfoDto = payRequestBody.getRechargeUserInfoDto();
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) payRequestBody.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            int totalPrice = payRequestBody.getTotalAmount().multiply(new BigDecimal(100)).intValue();
            String oldOutOrderNo = payRequestBody.getMerOrderId();
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            Map<String, Object> JSONDataContent = new HashMap<String, Object>();
            JSONDataContent.put("oldOutOrderNo", oldOutOrderNo);
            JSONDataContent.put("amount", totalPrice);
            //设置分账参数
            JSONObject splitInfo = new JSONObject();
            splitInfo.put("oldSubOutOrderNo",oldOutOrderNo);//原分账子订单号。
            splitInfo.put("contractNo",payConfig.getMid());//客户类型为ORG时传机构/平台号
            splitInfo.put("customerType","ORG");//ORG-机构/平台 PERSON-个人账户 B_ACCOUNT-B端账户
            splitInfo.put("splitAmount",totalPrice); //单位：分；分账金额总和不能超过订单金额
            splitInfo.put("sellerFlag","0");//0-不是卖家(如参与分账的平台) 1-是卖家(一笔担保交易只能有一个卖家)
            JSONArray js = new JSONArray();
            js.add(splitInfo);
            JSONDataContent.put("splitInfoList", js);
            JSONObject jo = JSONObject.parseObject(JSONObject.toJSONString(JSONDataContent));
            SendData.put("dataContent", jo.toString());
            String OsignData = FormatUtil.formatVerify("orgNo|merchantNo|loginNo|terminalNo|requestDate|dataContent",
                    SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String PostString = HttpUtil.requestPostByType(getServiceWalletUrl("v3.0.0","updateSplitInfo"),
                    SendData, "application/json");
            if (null == PostString || PostString.isEmpty()) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                // 自行处理
                //如果修改成功则进行确认分账
                return ResultMap.ok()
                        ;
            }else{
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        }catch (Exception e){
            log.error(" 分账失败请重试：{} ",e);
        }
        return ResultMap.error(-1,"分账失败");
    }

    /**
     * 2.1.1 余额和卡-API
     *
     * @param payRequestBody
     * @return
     * @throws Exception
     */
    @Override
    public ResultMap paymentSplitApi(PaymentRequestDto payRequestBody) {
        try {
            log.info(" 宝付钱包支付请求参数:{} ",payRequestBody);
            String version = "v3.0.0";
            String method = "paymentSplitApi" ;
            RechargeUserInfoDto rechargeUserInfoDto = payRequestBody.getRechargeUserInfoDto();
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) payRequestBody.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            int totalPrice = payRequestBody.getTotalAmount().multiply(new BigDecimal(100)).intValue();
            String outOrderNo = getMerchantOrderId(payConfig);
            String paidType = payRequestBody.getPaySubWay(); //BALANCE 余额支付 CARD 银行卡支付
            String notifyUrl = payConfig.getPayNotifyUrl();
            String agreementNo = rechargeUserInfoDto.getAgreementNo();//银行卡协议号 (如果是银行卡支付)
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            SendData.put("outOrderNo", outOrderNo);
            SendData.put("amount", totalPrice+"");
            SendData.put("paidType", paidType);
            SendData.put("pwdPayExpTime", DateUtils.differentSecond(DateUtils.getNowDate(),payRequestBody.getExpireTime()));
            if(StringUtils.isNotEmpty(agreementNo)){
                agreementNo = RsaCodingUtil.encryptByPubCerFile(SecurityUtil.Base64Encode(agreementNo), payConfig.getPublicKey());
                SendData.put("agreementNo", agreementNo);
            }
            SendData.put("notifyUrl", notifyUrl);
            JSONArray js = new JSONArray();
            //计算分账金额
            int merchantPrice = totalPrice;
            int appPrice = 0;
            if(StringUtils.isNotEmpty(payRequestBody.getAccountType()) && "merchant".equals(payRequestBody.getAccountType())) {
                //如果是商家  平台30%
                appPrice = payRequestBody.getTotalAmount().multiply(new BigDecimal(100)).multiply(new BigDecimal(70)).divide(new BigDecimal(100)).intValue();
                if (appPrice > 0 && totalPrice > appPrice) {
                    merchantPrice = totalPrice - appPrice;
                }
            } else { //默认 平台
                merchantPrice = totalPrice - appPrice;
            }
            if(appPrice > 0) {
                //设置分账参数-平台
                JSONObject splitInfo = new JSONObject();
                splitInfo.put("subOutOrderNo", outOrderNo + "P1");//分账订单号-平台。
                splitInfo.put("contractNo", payConfig.getMid());//客户类型为ORG时传机构/平台号
                splitInfo.put("customerType", "ORG");//ORG-机构/平台 PERSON-个人账户 B_ACCOUNT-B端账户
                splitInfo.put("splitAmount", appPrice); //单位：分；分账金额总和不能超过订单金额
                splitInfo.put("sellerFlag", "0");//0-不是卖家(如参与分账的平台) 1-是卖家(一笔担保交易只能有一个卖家)
                js.add(splitInfo);
            }
            //设置分账参数-商家
            JSONObject merchantSplitInfo = new JSONObject();
            merchantSplitInfo.put("subOutOrderNo",outOrderNo+"M1");//分账订单号-商家。
            merchantSplitInfo.put("contractNo",payRequestBody.getContractNo());//商家编号
            merchantSplitInfo.put("customerType","B_ACCOUNT");//ORG-机构/平台 PERSON-个人账户 B_ACCOUNT-B端账户
            merchantSplitInfo.put("splitAmount",merchantPrice); //单位：分；分账金额总和不能超过订单金额
            merchantSplitInfo.put("sellerFlag","1");//0-不是卖家(如参与分账的平台) 1-是卖家(一笔担保交易只能有一个卖家)
            js.add(merchantSplitInfo);
            SendData.put("splitInfoList", JSONObject.toJSONString(js));
            String OsignData = FormatUtil.formatVerify(
                    "orgNo|merchantNo|terminalNo|loginNo|requestDate|outOrderNo|amount|paidType|splitInfoList", SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            LogSyncUtil.logSync("宝付钱包支付 下单,交易编号:{},请求参数:{}",payRequestBody.getOrderNo(),SendData);
            String PostString = HttpUtil.requestPostByType(getServiceOrderUrl(version,method), SendData, "application/json");
            LogSyncUtil.logSync("宝付钱包支付 下单,交易编号:{},返回结果:{}",payRequestBody.getOrderNo(),PostString);
            if (StringUtils.isEmpty(PostString)) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                // 自行处理
                String link = jsonObject.getString("result");
                log.info("密码链接-->" + link);
                SendData.remove("signData");
                JSONObject data = new JSONObject();
                data.put("url",link);
                return ResultMap.ok()
                        .put("merOrderId",outOrderNo)
                        .put("data",data)
                        .put("payParam",SendData)
                        ;
            } else {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        }catch (Exception e){
            log.error(" 支付异常{} ",e);
        }
        return ResultMap.error(-1,"支付异常！");
    }

    /**
     * 3.1.3 个人-绑卡、余额支付API下单
     *
     * @param payRequestBody
     * @return
     * @throws Exception
     */
    public ResultMap assurePaymentSplit(PaymentRequestDto payRequestBody) {
        try {
            log.info(" 宝付钱包支付请求参数:{} ",payRequestBody);
            String version = "v3.0.0";
            String method = "assurePaymentSplit" ;
            RechargeUserInfoDto rechargeUserInfoDto = payRequestBody.getRechargeUserInfoDto();
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) payRequestBody.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            int totalPrice = payRequestBody.getTotalAmount().multiply(new BigDecimal(100)).intValue();
            String paidType = payRequestBody.getPaySubWay(); //BALANCE 余额支付 CARD 银行卡支付
            String notifyUrl = payConfig.getPayNotifyUrl();
            String agreementNo =  rechargeUserInfoDto.getAgreementNo();//银行卡协议号 (如果是银行卡支付)
            String outOrderNo = getMerchantOrderId(payConfig);
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            SendData.put("validDate", DateUtils.dateTimeNow(DateUtils.YYYYMMDD));
            SendData.put("expireDate", DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS,payRequestBody.getExpireTime()));
            SendData.put("outOrderNo", outOrderNo);
            SendData.put("amount",  totalPrice+"");
            SendData.put("paidType", paidType);
            agreementNo = SecurityUtil.Base64Encode(agreementNo);
            agreementNo = RsaCodingUtil.encryptByPubCerFile(agreementNo, payConfig.getPublicKey());
            SendData.put("agreementNo", agreementNo);
            SendData.put("notifyUrl", notifyUrl);
            JSONArray js = new JSONArray();
            //计算分账金额
            int merchantPrice = totalPrice;
            int appPrice = 0;
            if(StringUtils.isNotEmpty(payRequestBody.getAccountType()) && "merchant".equals(payRequestBody.getAccountType())) {
                //如果是商家  平台30%
                appPrice = payRequestBody.getTotalAmount().multiply(new BigDecimal(100)).multiply(new BigDecimal(70)).divide(new BigDecimal(100)).intValue();
                if (appPrice > 0 && totalPrice > appPrice) {
                    merchantPrice = totalPrice - appPrice;
                }
            } else { //默认 平台
                merchantPrice = totalPrice - appPrice;
            }
            if(appPrice > 0) {
                //设置分账参数-平台
                JSONObject splitInfo = new JSONObject();
                splitInfo.put("subOutOrderNo", outOrderNo + "P1");//分账订单号-平台。
                splitInfo.put("contractNo", payConfig.getMid());//客户类型为ORG时传机构/平台号
                splitInfo.put("customerType", "ORG");//ORG-机构/平台 PERSON-个人账户 B_ACCOUNT-B端账户
                splitInfo.put("splitAmount", appPrice); //单位：分；分账金额总和不能超过订单金额
                splitInfo.put("sellerFlag", "0");//0-不是卖家(如参与分账的平台) 1-是卖家(一笔担保交易只能有一个卖家)
                js.add(splitInfo);
            }
            //设置分账参数-商家
            JSONObject merchantSplitInfo = new JSONObject();
            merchantSplitInfo.put("subOutOrderNo",outOrderNo+"M1");//分账订单号-商家。
            merchantSplitInfo.put("contractNo",payRequestBody.getContractNo());//客户类型为ORG时传机构/平台号
            merchantSplitInfo.put("customerType","B_ACCOUNT");//ORG-机构/平台 PERSON-个人账户 B_ACCOUNT-B端账户
            merchantSplitInfo.put("splitAmount",merchantPrice); //单位：分；分账金额总和不能超过订单金额
            merchantSplitInfo.put("sellerFlag","1");//0-不是卖家(如参与分账的平台) 1-是卖家(一笔担保交易只能有一个卖家)
            js.add(merchantSplitInfo);
            SendData.put("splitInfoList", JSONObject.toJSONString(js));
            String OsignData = FormatUtil.formatVerify(
                    "orgNo|merchantNo|terminalNo|loginNo|requestDate|outOrderNo|amount|paidType|splitInfoList", SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String PostString = HttpUtil.requestPostByType(getServiceOrderUrl(version,method), SendData, "application/json");
            if (null == PostString || PostString.isEmpty()) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                // 自行处理
                String link = jsonObject.getString("result");
                log.info("密码链接-->" + link);
                return ResultMap.ok()
                        .put("redirectUrl",link)
                        ;
            } else {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        }catch (Exception e){
            log.error(" 支付异常{} ",e);
        }
        return ResultMap.error(-1,"支付异常！");
    }
    /**
     * 聚合支付下单API
     *
     * @param payRequestBody
     * @return
     */
    @Override
    public ResultMap payment(PaymentRequestDto payRequestBody) {
        try {
            RechargeUserInfoDto rechargeUserInfoDto = payRequestBody.getRechargeUserInfoDto();
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) payRequestBody.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            String totalPrice = payRequestBody.getTotalAmount().multiply(new BigDecimal(100)).intValue()+"";
            String outOrderNo = getMerchantOrderId(payConfig);
            String paidType = payRequestBody.getPaySubWay();// 支付类型
            String notifyUrl = payConfig.getPayNotifyUrl();
            String validDate = DateUtils.parseDateToStr(DateUtils.YYYYMMDD,DateUtils.addCalendar(payRequestBody.getCreateOrderTime(),DateUtils.day,1));// 担保有效日期 (1天)
            Map<String, Object> SendData = new HashMap<String, Object>();
            String body = payRequestBody.getBody();
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(body) ){
                body = Base64Util.subStringByBytes(body,80)+"...";
            }
            String alipaySimid = payConfig.getAlipaySimid();
            String appid = payConfig.getAppid();
            String chanalId = "";
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            SendData.put("callType", "PAYMENT_SPLIT");//聚合支付
            SendData.put("chanalId", chanalId);// 微信支付(公众号、小程序)需填公众号授权获取微信用户openid，支付宝支付(生活号、小程序)需填生活号授权获取支付宝用户userid
            SendData.put("simId", "");
            SendData.put("appId", "");
            SendData.put("isRaw", "0");
            //分账明细
            Map<String, Object> dataContent = new HashMap<String, Object>();// 分账明细数据1
            dataContent.put("goodsName", body);// 商品名称
            dataContent.put("amount", totalPrice);// 订单金额
            dataContent.put("outOrderNo", outOrderNo);// 商户订单号
            dataContent.put("paidType", paidType);// 支付类型
            dataContent.put("notifyUrl", notifyUrl);// 回调通知地址
            dataContent.put("expireDate", DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS,payRequestBody.getExpireTime()));// 订单支付有效期，默认不填写
            dataContent.put("validDate", validDate);// 担保到期日
            dataContent.put("remark", payRequestBody.getPayWay());// 备注
            //设置分账信息
            //平台
            JSONArray js = new JSONArray();
            JSONObject splitInfo = new JSONObject();
            splitInfo.put("subOutOrderNo",outOrderNo);//分账订单号。
            splitInfo.put("contractNo",payConfig.getMid());//客户类型为ORG时传机构/平台号
            splitInfo.put("customerType","ORG");//ORG-机构/平台 PERSON-个人账户 B_ACCOUNT-B端账户
            splitInfo.put("splitAmount",totalPrice); //单位：分；分账金额总和不能超过订单金额
            splitInfo.put("sellerFlag","0");//0-不是卖家(如参与分账的平台) 1-是卖家(一笔担保交易只能有一个卖家)
//            js.add(splitInfo);
            //卖家
            JSONObject splitInfo1 = new JSONObject();
            splitInfo1.put("subOutOrderNo",outOrderNo);//分账订单号。
            splitInfo1.put("contractNo", "3177000000478764");//客户类型为ORG时传机构/平台号
            splitInfo1.put("customerType","PERSON");//ORG-机构/平台 PERSON-个人账户 B_ACCOUNT-B端账户
            splitInfo1.put("splitAmount",totalPrice); //单位：分；分账金额总和不能超过订单金额
            splitInfo1.put("sellerFlag","1");//0-不是卖家(如参与分账的平台) 1-是卖家(一笔担保交易只能有一个卖家)
            js.add(splitInfo1);
            dataContent.put("splitInfoList", js);
            JSONObject dc = JSONObject.parseObject(JSONObject.toJSONString(dataContent));
            SendData.put("dataContent", dc.toString());
            String OsignData = FormatUtil
                    .formatVerify("orgNo|merchantNo|terminalNo|callType|loginNo|requestDate|dataContent", SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String version = "v3.0.0";
            String method = "payment" ;
            LogSyncUtil.logSync("宝付聚合支付 下单,交易编号:{},请求参数:{}",payRequestBody.getOrderNo(),SendData);
            String PostString = HttpUtil.requestPostByType(getServiceWalletUrl(version,method), SendData, "application/json");
            LogSyncUtil.logSync("宝付聚合支付 下单,交易编号:{},返回结果:{}",payRequestBody.getOrderNo(),PostString);
//            String PostString = HttpUtil.requestPostByType(getServiceWalletUrl("v3.0.0","payment"), SendData, "application/json");
            if (StringUtils.isEmpty(PostString)) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                // 自行处理
                String result = jsonObject.getString("result");
                String retStr = SecurityUtil.Base64Decode(result);
                log.info("result==>" + retStr);
                return ResultMap.ok()
                        .put("merOrderId",outOrderNo)
                        .put("orderNo",payRequestBody.getOrderNo())
                        .put("appPayRequest",jsonObject.getJSONObject("appPayRequest"))
                        .put("data",JSONObject.parseObject(retStr))
                        ;
            } else {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        }catch (Exception e){

        }
        return ResultMap.error(-1,"支付异常！");
    }
    /**
     * 5.2.1 退款申请
     *
     * @param refundRequestDto
     * @return
     * @throws Exception
     */
    @Override
    public ResultMap profitShareRefundApply(RefundRequestDto refundRequestDto) {
        try {
            RechargeUserInfoDto rechargeUserInfoDto = refundRequestDto.getRechargeUserInfoDto();
            if(null == rechargeUserInfoDto ){
                return ResultMap.error("无法获取支付数据,请联系管理员确认!");
            }
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) refundRequestDto.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            String orgTradeId = refundRequestDto.getOrderNo();// 原支付订单号
            int refundAmount = refundRequestDto.getRefundAmount().multiply(new BigDecimal(100)).intValue();
            JSONArray js = new JSONArray();
            if(StringUtils.isEmpty(loginNo)){
                JSONObject payJson = JSONObject.parseObject(rechargeUserInfoDto.getPayParam());
                JSONObject sendData = payJson.getJSONObject("payParam");
                loginNo = sendData.getString("loginNo");
                //获取分账参数
                String splitInfoStr = sendData.getString("splitInfoList");
                JSONArray splitInfoArray = JSONArray.parseArray(splitInfoStr);
                final int[] refundPrice = {refundAmount};
                if(null != splitInfoArray){
                    for (Object item : splitInfoArray) {
                        JSONObject sp = (JSONObject) item;
                        int splitAmount = sp.getIntValue("splitAmount");
                        if (refundPrice[0] > 0) {
                            refundPrice[0] = refundPrice[0] - splitAmount;
                            if (refundPrice[0] < 0) {
                                splitAmount = splitAmount + refundPrice[0];
                            }
                            JSONObject refundSplitInfo = new JSONObject();
                            refundSplitInfo.put("orgSubOutOrderNo", sp.getString("subOutOrderNo"));
                            refundSplitInfo.put("refundAmount", splitAmount+"");
                            js.add(refundSplitInfo);
                        }
                        if(refundPrice[0] < 0){
                            break;
                        }
                    }
                }
            }
            String refundReason = refundRequestDto.getRefundMsg();
            String refundTradeId = getMerchantOrderId(payConfig);// 退款请求订单号
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("refundTradeId", refundTradeId);// 退款请求订单号
            SendData.put("refundTradeType", "REFUND_APPLY");
            SendData.put("orgTradeId", orgTradeId);// 退款原始支付订单号
            SendData.put("refundAmount", refundAmount+"");
            SendData.put("refundReason", refundReason);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            SendData.put("remark",refundRequestDto.getPayWay());
            SendData.put("refundSplitInfoList", js);
            String OsignData = FormatUtil.formatVerify(
                    "orgNo|merchantNo|terminalNo|loginNo|requestDate|refundTradeId|orgTradeId|refundAmount|refundSplitInfoList",
                    SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String version = "v3.0.0";
            String method = "profitShareRefundApply" ;
            LogSyncUtil.logSync("宝付聚合，钱包支付 退款申请,交易编号:{},请求参数:{}",orgTradeId,SendData);
            String PostString = HttpUtil.requestPostByType(getServiceTradeUrl(version,method), SendData, "application/json");
            LogSyncUtil.logSync("宝付聚合，钱包支付 退款申请,交易编号:{},返回结果:{}",orgTradeId,PostString);
//            String PostString = HttpUtil.requestPostByType(getServiceTradeUrl("v3.0.0","profitShareRefundApply"), SendData, "json");
            if (StringUtils.isEmpty(PostString)) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                //判断结果
//                String result = jsonObject.getString("result");
//                JSONObject resultJson = JSONObject.parseObject(result);
//                String refundOrderId = resultJson.getString("refundOrderId");
//                String refundAmountStr = resultJson.getString("refundAmount");
//                JSONArray refundSplitResultList = resultJson.getJSONArray("refundSplitResultList");
                //如果成功则调用确认退款接口
                rechargeUserInfoDto.setLoginNo(loginNo);
                refundRequestDto.setRechargeUserInfoDto(rechargeUserInfoDto);
                refundRequestDto.setRefundNo(refundTradeId);
                return profitShareRefundConfirm(refundRequestDto);
            } else if("NOT_EXIT_ASSURE_SPLIT_INFO".equals(jsonObject.getString("errorCode"))){
                //子单未确认分账不能进行分账后退款
                //进行分帐前退款
                log.info(" -----不能进行分帐后退款， 调用分帐前退款操作： {} ",orgTradeId);
                return refundRequest(refundRequestDto);
            } else {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(" 退款请求失败：{} ",e);
        }
        return ResultMap.error(-1,"退款异常！");
    }

    /**
     * 5.2.2 退款确认
     *
     * @param refundRequestDto
     * @return
     * @throws Exception
     */
    private ResultMap profitShareRefundConfirm(RefundRequestDto refundRequestDto) {
        try {
            RechargeUserInfoDto rechargeUserInfoDto = refundRequestDto.getRechargeUserInfoDto();
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) refundRequestDto.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            String orgTradeId = refundRequestDto.getOrderNo();// 原支付订单号
            String refundTradeId = refundRequestDto.getRefundNo();// refundTradeId
            String notifyUrl = payConfig.getRefundNotifyUrl();
            String refundAmount = refundRequestDto.getRefundAmount().multiply(new BigDecimal(100)).intValue()+"";
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            SendData.put("refundTradeId", refundTradeId);
            SendData.put("refundTradeType", "REFUND_CONFIRM");
            SendData.put("orgTradeId", orgTradeId);// 退款原始支付订单号
            SendData.put("refundAmount", refundAmount);
            SendData.put("notifyUrl", notifyUrl);// 地址根据商户自定议，接收方法可参考【notifyUrl】
            String OsignData = FormatUtil
                    .formatVerify("orgNo|merchantNo|terminalNo|loginNo|requestDate|refundTradeId|refundAmount", SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String version = "v3.0.0";
            String method = "profitShareRefundConfirm" ;
            LogSyncUtil.logSync("宝付聚合，钱包支付 退款确认,交易编号:{},请求参数:{}",orgTradeId,SendData);
            String PostString = HttpUtil.requestPostByType(getServiceTradeUrl(version,method), SendData, "application/json");
            LogSyncUtil.logSync("宝付聚合，钱包支付 退款确认,交易编号:{},返回结果:{}",orgTradeId,PostString);
//            String PostString = HttpUtil.requestPostByType(getServiceTradeUrl("v3.0.0","profitShareRefundConfirm") , SendData, "application/json");
            if (StringUtils.isEmpty(PostString)) {
                log.info("PostString  为空");
                ResultMap resultMap = profitShareRefundCancel(refundRequestDto);
                log.info(" 退款撤回操作111：{} ",resultMap);
                return ResultMap.error(-1,"退款失败[401]");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                ResultMap resultMap = profitShareRefundCancel(refundRequestDto);
                log.info(" 退款撤回操作2222：{} ",resultMap);
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                String result = jsonObject.getString("result");
                log.info(" 退款结果：{} ",result);
                JSONObject resultJson = JSONObject.parseObject(result);
                String refundStatus = resultJson.getString("refundStatus");
                Map<String, String> stringStringMap = new HashMap<>();
                String refundOrderId = resultJson.getString("refundOrderId");
                String refundTradeIdRet = resultJson.getString("refundTradeId");
                String refundMoney = resultJson.getString("refundMoney");
                if("S".equals(refundStatus)){//成功
                    stringStringMap.put("out_refund_no", refundTradeIdRet);
                    stringStringMap.put("refund_id", refundOrderId);
                    stringStringMap.put("refund_fee", String.valueOf(Double.parseDouble(refundMoney)));
                    stringStringMap.put("fund_change", "Y");
                    stringStringMap.put("refund_status",refundStatus);
                    return  ResultMap.ok()
                            .put("data",stringStringMap)
                            ;
                } else if ("P".equals(refundStatus)) {
                    stringStringMap.put("out_refund_no", refundTradeIdRet);
                    stringStringMap.put("refund_id", refundOrderId);
                    stringStringMap.put("refund_fee", String.valueOf(Double.parseDouble(refundMoney)));
                    stringStringMap.put("fund_change", "P");
                    stringStringMap.put("refund_status",refundStatus);
                    return  ResultMap.ok()
                            .put("data",stringStringMap)
                            ;
                }else{
                    ResultMap resultMap = profitShareRefundCancel(refundRequestDto);
                    log.info(" 退款撤回操作3333：{} ",resultMap);
                    return ResultMap.error(-1,resultJson.getString("message"));
                }
            }else {
                ResultMap resultMap = profitShareRefundCancel(refundRequestDto);
                log.info(" 退款撤回操作44444：{} ",resultMap);
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(" 确认退款异常：{} ",e);
        }
        return ResultMap.error(-1,"退款失败[403]");
    }

    /**
     * 5.2.3 退款撤销
     *
     * @param refundRequestDto
     * @return
     * @throws Exception
     */
    private ResultMap profitShareRefundCancel(RefundRequestDto refundRequestDto) {
        try {
            RechargeUserInfoDto rechargeUserInfoDto = refundRequestDto.getRechargeUserInfoDto();
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) refundRequestDto.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            String refundTradeId = refundRequestDto.getRefundNo();// 原支付订单号
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            SendData.put("refundTradeId", refundTradeId);
            SendData.put("refundTradeType", "REFUND_CANCEL");
            String OsignData = FormatUtil.formatVerify("orgNo|merchantNo|terminalNo|loginNo|requestDate|refundTradeId",
                    SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData,  payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String version = "v3.0.0";
            String method = "profitShareRefundCancel" ;
            LogSyncUtil.logSync("宝付聚合，钱包支付 退款确认,交易编号:{},请求参数:{}",refundTradeId,SendData);
            String PostString = HttpUtil.requestPostByType(getServiceTradeUrl(version,method), SendData, "application/json");
            LogSyncUtil.logSync("宝付聚合，钱包支付 退款确认,交易编号:{},返回结果:{}",refundTradeId,PostString);
//            String PostString = HttpUtil.requestPostByType(getServiceTradeUrl("v3.0.0","profitShareRefundCancel"), SendData, "application/json");
            if (null == PostString || PostString.isEmpty()) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                /**
                 * 省略
                 */
                return ResultMap.ok("退款撤回成功！");
            }else{
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(" 撤回退款异常：{} ",e);
        }
        return ResultMap.error(-2,"退款撤回异常！");
    }

    /**
     * 5.1 分账前退款
     *
     * @param refundRequestDto
     * @return
     * @throws Exception
     */
    public ResultMap refundRequest(RefundRequestDto refundRequestDto)  {
        try {
            log.info(" 分帐前退款--refundRequest--  ");
            RechargeUserInfoDto rechargeUserInfoDto = refundRequestDto.getRechargeUserInfoDto();
            if(null == rechargeUserInfoDto ){
                return ResultMap.error("无法获取支付数据,请联系管理员确认!");
            }
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) refundRequestDto.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            String orgTradeId = refundRequestDto.getOrderNo();// 原支付订单号
            int refundAmount = refundRequestDto.getRefundAmount().multiply(new BigDecimal(100)).intValue();
            JSONArray js = new JSONArray();
            if(StringUtils.isEmpty(loginNo)){
                JSONObject payJson = JSONObject.parseObject(rechargeUserInfoDto.getPayParam());
                JSONObject sendData = payJson.getJSONObject("payParam");
                loginNo = sendData.getString("loginNo");
                //获取分账参数
                String splitInfoStr = sendData.getString("splitInfoList");
                JSONArray splitInfoArray = JSONArray.parseArray(splitInfoStr);
                final int[] refundPrice = {refundAmount};
                if(null != splitInfoArray){
                    for (Object item : splitInfoArray) {
                        JSONObject sp = (JSONObject) item;
                        int splitAmount = sp.getIntValue("splitAmount");
                        if (refundPrice[0] > 0) {
                            refundPrice[0] = refundPrice[0] - splitAmount;
                            if (refundPrice[0] < 0) {
                                splitAmount = splitAmount + refundPrice[0];
                            }
                            JSONObject refundSplitInfo = new JSONObject();
                            refundSplitInfo.put("oldSubOutOrderNo", sp.getString("subOutOrderNo"));
                            refundSplitInfo.put("splitRefundAmount", splitAmount+"");
                            js.add(refundSplitInfo);
                        }
                        if(refundPrice[0] < 0){
                            break;
                        }
                    }
                }
            }
            String refundTradeId = getMerchantOrderId(payConfig);// 退款请求订单号
            String notifyUrl = payConfig.getRefundNotifyUrl();
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("refundTradeId", refundTradeId);// 退款请求订单号
            SendData.put("orgTradeId", orgTradeId);// 退款原始支付订单号
            SendData.put("refundMoney", refundAmount+"");// 单位分
            SendData.put("refundReason",refundRequestDto.getRefundMsg());
            SendData.put("notifyUrl", notifyUrl);// 地址根据商户自定议，接收方法可参考【notifyUrl】
            SendData.put("requestDate", DateUtils.dateTimeNow());
            SendData.put("remark",refundRequestDto.getPayWay());
            SendData.put("refundSplitInfoList", js);
            String OsignData = FormatUtil.formatVerify(
                    "orgNo|merchantNo|terminalNo|requestDate|refundTradeId|orgTradeId|refundMoney|refundReason|notifyUrl",
                    SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String PostString = HttpUtil.requestPostByType(getServiceTradeUrl("v3.0.0","refundRequest"), SendData, "application/json");
            if (null == PostString || PostString.isEmpty()) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                String result = jsonObject.getString("result");
                log.info(" 退款结果：{} ",result);
                JSONObject resultJson = JSONObject.parseObject(result);
                String refundStatus = resultJson.getString("refundStatus");
                Map<String, String> stringStringMap = new HashMap<>();
                String refundOrderId = resultJson.getString("refundOrderId");
                String refundTradeIdRet = resultJson.getString("refundTradeId");
                String refundMoney = resultJson.getString("refundMoney");
                stringStringMap.put("out_refund_no", refundTradeIdRet);
                stringStringMap.put("refund_id", refundOrderId);
                stringStringMap.put("refund_fee", String.valueOf(Double.parseDouble(refundMoney)));
                stringStringMap.put("refund_status",refundStatus);
                if("S".equals(refundStatus)){//成功
                    stringStringMap.put("fund_change", "Y");
                    return  ResultMap.ok()
                            .put("data",stringStringMap)
                            ;
                } else if ("P".equals(refundStatus)) {
                    stringStringMap.put("fund_change", "P");
                    return  ResultMap.ok()
                            .put("data",stringStringMap)
                            ;
                }else{
                    return ResultMap.error(-1,resultJson.getString("message"));
                }
//                return ResultMap.ok()
//                        .put("jsonObject",jsonObject)
//                        ;
            } else {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        }catch (Exception e){

        }
        return ResultMap.error(-1,"退款异常！");
    }

    /**
     * 5.10 交易订单信息查询
     *
     * @param payRequestBody
     * @return
     * @throws Exception
     */
    @Override
    public ResultMap queryOrder(PaymentRequestDto payRequestBody)  {
        String errMsg = "";
        try {
            String tradeId = payRequestBody.getOrderNo();// 支付订单号/退款单号
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) payRequestBody.getPayConfigByClass(BaofooRechargePayConfig.class);
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("tradeId", tradeId);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            String OsignData = FormatUtil.formatVerify("orgNo|merchantNo|terminalNo|requestDate|tradeId", SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String version = "v3.0.0";
            String method = "queryOrder" ;
            LogSyncUtil.logSync("宝付聚合，钱包支付 查询,交易编号:{},请求参数:{}",tradeId,SendData);
            String PostString = HttpUtil.requestPostByType(getServiceWalletUrl(version,method), SendData, "application/json");
            LogSyncUtil.logSync("宝付聚合，钱包支付 查询,交易编号:{},返回结果:{}",tradeId,PostString);
//            String PostString = HttpUtil.requestPostByType(getServiceWalletUrl("v3.0.0","queryOrder"), SendData, "application/json");
            if (StringUtils.isEmpty(PostString)) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                if (jsonObject.containsKey("result")) {
                    JSONObject ResultObject = (JSONObject) jsonObject.get("result");
                    log.info("结果值：" + ResultObject.getString("contractNo"));
                    //判断交易状态
                    if(ResultObject.getString("status").contains(PayConstants.SUCCESS) ||
                            ResultObject.getString("status").contains("FINISH")
                    ) {
                        if(ResultObject.getString("tradeType").equals("RECHARGE") || ResultObject.getString("tradeType").equals("ASSURE_RECHARGE")) {
                            //支付，充值
                            return ResultMap.ok()
                                    .put("orderNo",payRequestBody.getOrderNo())
                                    .put("payWay",payRequestBody.getPayWay())
                                    .put("paymentNo",ResultObject.getString("transactionId"))
                                    .put("paymentPrice",new BigDecimal(ResultObject.getString("amount")).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN))
                                    .put("actualPayment",new BigDecimal(ResultObject.getString("amount")).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN))
                                    .put("paymentSuccessTime",DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, ResultObject.getString("finishDate")))
                                    ;
                        }else if(ResultObject.getString("tradeType").equals("REFUND") || ResultObject.getString("tradeType").equals("WITHDRAW")){
                            //提现退款
                            Map<String, String> stringStringMap = new HashMap<>();
                            stringStringMap.put("out_refund_no", tradeId);
                            stringStringMap.put("refund_id", ResultObject.getString("transactionId"));
                            stringStringMap.put("refund_fee", new BigDecimal(ResultObject.getString("amount")).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN).toString());
                            stringStringMap.put("fund_change", "Y");
                            return ResultMap.ok()
                                    .put("data",stringStringMap)
                                    ;
                        }
                    }else{
                        errMsg = ResultObject.getString("status");
                    }
                }
            }else{
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(" 查询异常{} ",e);
            errMsg = "下单失败";
        }
        return ResultMap.error(-2,errMsg);
    }

    /**
     * 3.4 确认分账
     *
     * @Description 消费担保支付需确认才能进行分账
     * @param payRequestBody
     * @return
     * @throws Exception
     */
    public ResultMap confirmAssurePay(PaymentRequestDto payRequestBody) {
        try {
            RechargeUserInfoDto rechargeUserInfoDto = payRequestBody.getRechargeUserInfoDto();
            if(null == rechargeUserInfoDto ){
                return ResultMap.error("无法获取支付数据,请联系管理员确认!");
            }
            BaofooRechargePayConfig payConfig = (BaofooRechargePayConfig) payRequestBody.getPayConfigByClass(BaofooRechargePayConfig.class);
            String loginNo = rechargeUserInfoDto.getLoginNo();// 登录号
            String notifyUrl = payConfig.getPayNotifyUrl();// 通知地址
            int totalPrice = payRequestBody.getTotalAmount().multiply(new BigDecimal(100)).intValue();// 总金额
            String oldOutOrderNo = payRequestBody.getOrderNo();// 原担保支付/消费充值单号
            String outOrderNo = getMerchantOrderId(payConfig);
            Map<String, Object> SendData = new HashMap<String, Object>();
            SendData.put("orgNo", payConfig.getMid());
            SendData.put("merchantNo", payConfig.getMid());
            SendData.put("terminalNo", payConfig.getTid());
            SendData.put("loginNo", loginNo);
            SendData.put("requestDate", DateUtils.dateTimeNow());
            SendData.put("notifyUrl", notifyUrl);
            Random random = new Random();
            Map<String, Object> DC = new HashMap<String, Object>();
            DC.put("amount", totalPrice+"");// 订单金额
            DC.put("outOrderNo", outOrderNo);// 商户订单号
            DC.put("oldOutOrderNo", oldOutOrderNo);// 原商户订单号
            JSONArray js = new JSONArray();
            if(StringUtils.isEmpty(loginNo)){
                JSONObject payJson = JSONObject.parseObject(rechargeUserInfoDto.getPayParam());
                JSONObject sendData = payJson.getJSONObject("payParam");
                //获取分账参数
                String splitInfoStr = sendData.getString("splitInfoList");
                JSONArray splitInfoArray = JSONArray.parseArray(splitInfoStr);
                if(null != splitInfoArray){
                    for (Object item : splitInfoArray) {
                        JSONObject sp = (JSONObject) item;
                        int splitAmount = sp.getIntValue("splitAmount");
                        JSONObject refundSplitInfo = new JSONObject();
                        refundSplitInfo.put("oldSubOutOrderNo", sp.getString("subOutOrderNo"));
                        refundSplitInfo.put("splitAmount", splitAmount+"");
                        js.add(refundSplitInfo);
                    }
                }
            }
            DC.put("assureConfirmSplitInfoList", js);// 放入分账参数
            JSONObject DCString = JSONObject.parseObject(JSONObject.toJSONString(DC));
            SendData.put("dataContent", DCString.toString());
            String OsignData = FormatUtil.formatVerify("orgNo|merchantNo|loginNo|terminalNo|requestDate|dataContent", SendData);
            log.info("签名拼接参数：" + OsignData);
            String Sign = SignatureUtils.encryptByRSA(OsignData, payConfig.getPrivateKey(), payConfig.getPrivateKeyPwd());
            log.info("签名结果：" + Sign);
            SendData.put("signData", Sign);// 签名结果。
            String PostString = HttpUtil.requestPostByType(getServiceWalletUrl("v3.0.0","confirmAssurePay"), SendData, "application/json");
            if (null == PostString || PostString.isEmpty()) {
                log.info("PostString  为空");
                return ResultMap.error(-1,"返回出错【404】");
            }
            JSONObject jsonObject = JSONObject.parseObject(PostString.trim());
            if (!jsonObject.containsKey("success")) {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
            if (jsonObject.getBoolean("success")) {
                /**
                 * 省略
                 */
                return ResultMap.ok("操作成功，等待分账结果通知！");
            }else {
                return ResultMap.error(-1,jsonObject.getString("errorMsg"));
            }
        }catch (Exception e){
            log.error(" 确认分账异常{} ",e);
        }
        return ResultMap.error(-1,"确认分账异常！");
    }

    private String getServiceOrderUrl(String version ,String method){
        String url = baseUrlBox + serviceOrderUrl ;
        if(StringUtils.isNotEmpty(appversion) && "prod".equals(appversion) ){
            url = baseUrl+serviceOrderUrl ;
        }
        return MessageFormat.format(url,version,method);
    }
    private String getServiceTradeUrl(String version ,String method){
        String url = baseUrlBox + serviceTradeUrl ;
        if(StringUtils.isNotEmpty(appversion) && "prod".equals(appversion) ){
            url = baseUrl+serviceTradeUrl ;
        }
        return MessageFormat.format(url,version,method);
    }
    private String getServiceWalletUrl(String version ,String method){
        String url = baseUrlBox + serviceWalletUrl ;
        if(StringUtils.isNotEmpty(appversion) && "prod".equals(appversion) ){
            url = baseUrl+serviceWalletUrl ;
        }
        return MessageFormat.format(url,version,method);
    }

    public  String getMerchantOrderId(BaofooRechargePayConfig payConfig){
        return payConfig.getMsgSrcId()+ DateUtils.parseDateToStr("yyyyMMddmmHHssSSS",new Date())+ RandomUtil.random(4);
    }

}
