package com.clx.performance.service.impl.thirdparty.nbbank;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.clx.performance.config.nbbank.NbBankConfig;
import com.clx.performance.dao.nbbank.NbBankRecordDao;
import com.clx.performance.enums.PerformanceResultEnum;
import com.clx.performance.enums.nbbank.NbBankRecordEnum;
import com.clx.performance.model.nbbank.NbBankRecord;
import com.clx.performance.service.thirdparty.nbbank.NbBankThirdpartyService;
import com.clx.performance.utils.LocalDateTimeUtils;
import com.msl.common.exception.ServiceSystemException;
import com.nbopen.api.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.util.HashMap;
import java.util.Objects;

/**
 * 易付通
 */
@Slf4j
@Service
public class NbBankThirdpartyServiceImpl implements NbBankThirdpartyService {

    @Autowired
    private NbBankConfig nbBankConfig;

    @Autowired
    private NbBankRecordDao nbBankRecordDao;

    @PostConstruct
    public void bankInit() throws IOException {
        File file = new File("/app/nbbank");
        file.mkdir();

        downloadUsingStream(nbBankConfig.getConfigFilePath(), "/app/nbbank/bankConfig.json");
        downloadUsingStream(nbBankConfig.getPublicKeyPath(), "/app/nbbank/bankPubKey.cer");
        downloadUsingStream(nbBankConfig.getPrivateKeyPath(), "/app/nbbank/bankPrivateKey.sm2");

        FileSystemResource resource = new FileSystemResource("/app/nbbank/bankConfig.json");

        InputStream inputStream;
        try {
            inputStream = resource.getInputStream();
            boolean initResult = NBOpenSDK.init(inputStream);
            log.info("宁波银行SDK初始化, 状态:{}", initResult);
            log.info("sdk版本信息:{}", NBOpenSDK.getVersionInfo());
        } catch (IOException e) {
            log.info("宁波银行SDK初始化失败:{}", ExceptionUtils.getStackTrace(e));
        }
    }

    /**
     * 下载
     */
    private static void downloadUsingStream(String urlStr, String file) throws IOException {
        URL url = new URL(urlStr);
        BufferedInputStream bis = new BufferedInputStream(url.openStream());
        FileOutputStream fis = new FileOutputStream(file);
        byte[] buffer = new byte[1024];
        int count=0;
        while((count = bis.read(buffer,0,1024)) != -1)
        {
            fis.write(buffer, 0, count);
        }
        fis.close();
        bis.close();
    }


    /**
     * 下单
     * 5.5转账直连下单
     * 商户号：EFT33021200556315
     * 银行转账：86041110000075918（户名：客户客户）
     * 订单支付：结算账号（86041110000075926（户名：客户客户））
     * 响应结果：
     *{
     *     "data": {
     *         "acctNm": "客户客户",
     *         "acctOpenBankNm": "宁波银行股份有限公司",
     *         "bankId": "313332082914",
     *         "cardNo": "86041110000075918",
     *         "errorCode": "000000",
     *         "errorMsg": "成功",
     *         "signNo": "2976409",
     *         "transSeqNo": "20231129142846065496766yDTQtg2",
     *         "virtualDays": "2024-05-26"
     *     },
     *     "head": {
     *         "rqsJrnlNo": "15543427719351510",
     *         "rspCode": "000000",
     *         "rspDate": "2023-11-29",
     *         "rspMsg": "交易成功",
     *         "rspTime": "14:28:49:600"
     *     }
     * }
     *
     * @Param
     * merSeqNo: 商户流水
     * merId: 商户号
     * amount: 订单金额(分)
     */
    @Override
    public JSONObject directBankTransferOrder(String merSeqNo, String merDtTm, String closeDtTm, Integer amount) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("transId", "IP01");           //交易识别码 必填
            jsonObject.put("merId", nbBankConfig.getMerId());              //商户号 必填

            jsonObject.put("merSeqNo", merSeqNo);        //商户流水 必填
            jsonObject.put("merDtTm", merDtTm);          //商户时间 必填

            jsonObject.put("trxAmt", new BigDecimal(amount).movePointLeft(2));      //订单金额 必填
            jsonObject.put("orderDesc", "散煤运输");      //订单详情 必填
            jsonObject.put("productName", "运费");        //商品名称 必填
            jsonObject.put("productId", "001");          //商品编号 必填
            jsonObject.put("productNum", "1");           //商品数量 必填


            jsonObject.put("closeDtTm", closeDtTm);     //关单时间
//            jsonObject.put("mobilePhone", "13000000000");     //手机号

            HashMap<String,String> httpHeader = new HashMap<>();

            RequestApiData requestApiData = new RequestApiData();
            requestApiData.setAppkey(nbBankConfig.getAppKey());
            requestApiData.setData(jsonObject);
            requestApiData.setProductId("YFT");
            requestApiData.setServiceId("directBankTransferOrder");
            requestApiData.setHttpHeader(httpHeader);

            RequestHead requestHead = new RequestHead();
            requestHead.setRqsJrnlNo(NBOpenSDK.getRandom());

            SDKRequest request = new SDKRequest();
            request.setData(requestApiData);
            request.setHead(requestHead);

            log.info("宁波银行, 下单(directBankTransferOrder), 参数: {}", JSON.toJSONString(request));
            SDKResponse response = NBOpenSDK.send(request);
            log.info("宁波银行, 下单(directBankTransferOrder), 结果: {}", JSON.toJSONString(response));

            recordSave(NbBankRecordEnum.Type.DIRECT_BANK_TRANSFER_ORDER.getCode(), request, response);

            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject data = responseJson.getJSONObject("data");

            if (!StringUtils.equals(data.getString("errorCode"), "000000")){
                log.info("宁波银行, 下单失败(directBankTransferOrder), code:{}, msg:{}", data.getString("errorCode"), data.getString("errorMsg"));
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_API_ERROR);
            }

            return data;

        } catch (Exception e) {
            log.info("宁波银行接口异常:{}", ExceptionUtils.getStackTrace(e));
        }

        throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_API_ERROR);
    }

    /**
     * 订单支付收款模式
     * 易付通接口编程-含订单支付
     * 5.13银联订单支付收款模式
     * 商户号：EFT33021200556315
     * 银行转账：86041110000075918（户名：客户客户）
     * 订单支付：结算账号（86041110000075926（户名：客户客户））
     * 86041110000076809:黑玫瑰
     * 响应结果：
     * {
     *     "data": {
     *         "errorCode": "000000",
     *         "errorMsg": "成功",
     *         "frontUrl": "",
     *         "merId": "EFT33021200556315",
     *         "merSeqNo": "20231129133913",
     *         "signData": "",
     *         "transSeqNo": "2023112913391406547689VYvNioNz"
     *     },
     *     "head": {
     *         "rqsJrnlNo": "14414965925389704",
     *         "rspCode": "000000",
     *         "rspDate": "2023-11-29",
     *         "rspMsg": "交易成功",
     *         "rspTime": "13:39:16:035"
     *     }
     * }
     *
     * @Param
     * merSeqNo: 商户流水
     * merId: 商户号
     * amount: 订单金额(分)
     * payAcctOpenBankId: 开户行号
     * payAcctNo: 付款账号
     * payAcctNm: 付款户名
     */
    @Override
    public JSONObject unionPayDirectOrder(String merSeqNo, String merDtTm, Integer amount,
                                          String payAcctOpenBankId, String payAcctNo, String payAcctNm) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("transId", "IP01");           //交易识别码 必填
            jsonObject.put("merId", nbBankConfig.getMerId());              //商户号 必填

            jsonObject.put("merSeqNo", merSeqNo);        //商户流水 必填
            jsonObject.put("merDtTm", merDtTm);          //商户时间 必填

            jsonObject.put("trxAmt", new BigDecimal(amount).movePointLeft(2));     //订单金额 必填
            jsonObject.put("orderDesc", "散煤运输");       //订单详情 必填
            jsonObject.put("productName", "运费");        //商品名称 必填
            jsonObject.put("productId", "001");           //商品编号 必填
            jsonObject.put("productNum", "1");            //商品数量 必填

            jsonObject.put("bankType", "00");                           //账户类型 必填
            jsonObject.put("payAcctOpenBankId", payAcctOpenBankId);     //开户行号 必填
            jsonObject.put("payAcctNo", payAcctNo);                     //付款账号 必填
            jsonObject.put("payAcctNm", payAcctNm);                     //付款户名 必填
//        jsonObject.put("mobilePhone", "13000000000");     //手机号

            HashMap<String,String> httpHeader = new HashMap<>();


            RequestApiData requestApiData = new RequestApiData();
            requestApiData.setAppkey(nbBankConfig.getAppKey());
            requestApiData.setData(jsonObject);
            requestApiData.setProductId("YFT");
            requestApiData.setServiceId("unionPayDirectOrder");
            requestApiData.setHttpHeader(httpHeader);

            RequestHead requestHead = new RequestHead();
            requestHead.setRqsJrnlNo(NBOpenSDK.getRandom());

            SDKRequest request = new SDKRequest();
            request.setData(requestApiData);
            request.setHead(requestHead);

            log.info("宁波银行, 下单(unionPayDirectOrder), 参数: {}", JSON.toJSONString(request));
            SDKResponse response = NBOpenSDK.send(request);
            log.info("宁波银行, 下单(unionPayDirectOrder), 结果: {}", JSON.toJSONString(response));

            recordSave(NbBankRecordEnum.Type.UNION_PAY_DIRECT_ORDER.getCode(), request, response);

            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject data = responseJson.getJSONObject("data");

            if (StringUtils.equals(data.getString("errorCode"), "MER006")){
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_PAY_DISABLE_ERROR);
            }
            else if (StringUtils.equals(data.getString("errorCode"), "BP3233")){
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_ACCOUNT_NOT_FOUND_ERROR);
            }
            else if (StringUtils.equals(data.getString("errorCode"), "MER001")){
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_MERCHANT_STATUS_ERROR);
            }
            else if (StringUtils.equals(data.getString("errorCode"), "BD2103")){
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_AMOUNT_OUT_OF_RANGE_ERROR);
            }
            else if (StringUtils.equals(data.getString("errorCode"), "BP3212")){
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_NAME_BANK_NO_MISSMATCH_ERROR);
            }
            else if (!StringUtils.equals(data.getString("errorCode"), "000000")){
                log.info("宁波银行, 下单失败(unionPayDirectOrder), code:{}, msg:{}", data.getString("errorCode"), data.getString("errorMsg"));
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_API_ERROR);
            }

            return data;

        } catch (Exception e) {
            if (e instanceof ServiceSystemException) {throw (ServiceSystemException)e;}
            log.info("宁波银行接口异常:{}", ExceptionUtils.getStackTrace(e));
        }

        throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_API_ERROR);
    }

    /**
     * 结果查询
     * 6.1交易结果查询
     * 商户号：EFT33021200556315
     * 返回结果： 90:交易不存在
     * {
     *     "data": {
     *         "chargesAmt": "",
     *         "chargesType": "",
     *         "clearDate": "",
     *         "errorCode": "000000",
     *         "errorMsg": "成功",
     *         "merId": "EFT33021200556315",
     *         "merSeqNo": "20231129135754",
     *         "payeeAcctBankName": "",
     *         "payeeAcctBankNo": "",
     *         "payeeAcctName": "",
     *         "payeeAcctNo": "",
     *         "payMethod": "",
     *         "pyerInfList": [
     *             {
     *                 "customerId": "",
     *                 "pyerAcctBankName": "",
     *                 "pyerAcctName": "",
     *                 "pyerAcctNo": "",
     *                 "signNo": "",
     *                 "transAmt": "",
     *                 "transDtTm": ""
     *             }
     *         ],
     *         "realTrxAmt": "",
     *         "transSeqNo": "",
     *         "transStatus": "90",
     *         "trxAmt": ""
     *     },
     *     "head": {
     *         "rqsJrnlNo": "15541586367762936",
     *         "rspCode": "000000",
     *         "rspDate": "2023-11-29",
     *         "rspMsg": "交易成功",
     *         "rspTime": "13:57:54:343"
     *     }
     * }
     * 返回结果： 02:交易已受理
     * {
     *     "data": {
     *         "chargesAmt": "",
     *         "chargesType": "",
     *         "clearDate": "20231129",
     *         "errorCode": "000000",
     *         "errorMsg": "成功",
     *         "merId": "EFT33021200556315",
     *         "merSeqNo": "20231129142845",
     *         "payeeAcctBankName": "宁波银行股份有限公司",
     *         "payeeAcctBankNo": "313332082914",
     *         "payeeAcctName": "客户客户",
     *         "payeeAcctNo": "860411100000759182976409",
     *         "payMethod": "4",
     *         "pyerInfList": [
     *             {
     *                 "customerId": "",
     *                 "pyerAcctBankName": "",
     *                 "pyerAcctName": "",
     *                 "pyerAcctNo": "",
     *                 "signNo": "",
     *                 "transAmt": "",
     *                 "transDtTm": ""
     *             }
     *         ],
     *         "realTrxAmt": "0",
     *         "transSeqNo": "20231129142846065496766yDTQtg2",
     *         "transStatus": "02",
     *         "trxAmt": "1.23"
     *     },
     *     "head": {
     *         "rqsJrnlNo": "15543431902274569",
     *         "rspCode": "000000",
     *         "rspDate": "2023-11-29",
     *         "rspMsg": "交易成功",
     *         "rspTime": "14:28:51:431"
     *     }
     * }
     *
     * transStatus:
     * 00:交易成功
     * 01:交易失败
     * 02:交易已受理
     * 80:订单初始状态
     * 90:交易不存在
     * 99:交易超时,须发起交易结果查询
     */
    @Override
    public JSONObject queryOrder(String orgMerSeqNo) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("transId", "IP01");          //交易识别码 必填
            jsonObject.put("merId", nbBankConfig.getMerId());             //商户号 必填

            jsonObject.put("merSeqNo", orgMerSeqNo);       //商户流水 必填

            HashMap<String,String> httpHeader = new HashMap<>();

            RequestApiData requestApiData = new RequestApiData();
            requestApiData.setAppkey(nbBankConfig.getAppKey());
            requestApiData.setData(jsonObject);
            requestApiData.setProductId("YFT");
            requestApiData.setServiceId("queryOrder");
            requestApiData.setHttpHeader(httpHeader);

            RequestHead requestHead = new RequestHead();
            requestHead.setRqsJrnlNo(NBOpenSDK.getRandom());

            SDKRequest request = new SDKRequest();
            request.setData(requestApiData);
            request.setHead(requestHead);

            log.info("宁波银行, 查询交易结果(queryOrder), 参数: {}", JSON.toJSONString(request));
            SDKResponse response = NBOpenSDK.send(request);
            log.info("宁波银行, 查询交易结果(queryOrder), 结果: {}", JSON.toJSONString(response));

            recordSave(NbBankRecordEnum.Type.QUERY_ORDER.getCode(), request, response);

            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject data = responseJson.getJSONObject("data");

            if (!StringUtils.equals(data.getString("errorCode"), "000000")){
                log.info("宁波银行, 下单失败(queryOrder), code:{}, msg:{}", data.getString("errorCode"), data.getString("errorMsg"));
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_API_ERROR);
            }

            return data;
        } catch (Exception e) {
            log.info("宁波银行接口异常:{}", ExceptionUtils.getStackTrace(e));
        }

        throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_API_ERROR);
    }

    /**
     * 调账
     * 5.10云账簿资金划转
     */
    @Override
    public JSONObject fundTransferOrder(String orgMerSeqNo, String merDtTm, Integer trxAmt,
                                        String customerId, String payCustomerId) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("transId", "IP01");                      //交易识别码 必填 云账簿 CP01, 普通转账 IP01
            jsonObject.put("merId", nbBankConfig.getMerId());       //商户号 必填
            jsonObject.put("merSeqNo", orgMerSeqNo);                   //商户流水 必填

            jsonObject.put("merDtTm", merDtTm);                     //商户交易时间 必填
            jsonObject.put("trxAmt", new BigDecimal(trxAmt).movePointLeft(2));                 //交易金额
            if (StringUtils.isNotBlank(customerId)) {
                jsonObject.put("customerId", customerId);           //云账簿标识_收款方
            }
            if (StringUtils.isNotBlank(payCustomerId)) {
                jsonObject.put("payCustomerId", payCustomerId);     //云账簿标识_付款方
            }
//            jsonObject.put("notifyAction", 0);                  //是否通知

            HashMap<String,String> httpHeader = new HashMap<>();

            RequestApiData requestApiData = new RequestApiData();
            requestApiData.setAppkey(nbBankConfig.getAppKey());
            requestApiData.setData(jsonObject);
            requestApiData.setProductId("YFT");
            requestApiData.setServiceId("fundTransferOrder");
            requestApiData.setHttpHeader(httpHeader);

            RequestHead requestHead = new RequestHead();
            requestHead.setRqsJrnlNo(NBOpenSDK.getRandom());

            SDKRequest request = new SDKRequest();
            request.setData(requestApiData);
            request.setHead(requestHead);

            log.info("宁波银行, 调账接口(fundTransferOrder), 参数: {}", JSON.toJSONString(request));
            SDKResponse response = NBOpenSDK.send(request);
            log.info("宁波银行, 调账接口(fundTransferOrder), 结果: {}", JSON.toJSONString(response));

            recordSave(NbBankRecordEnum.Type.FUND_TRANSFER_ORDER.getCode(), request, response);

            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject data = responseJson.getJSONObject("data");

            if (!StringUtils.equals(data.getString("errorCode"), "PAY888")){
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_NO_MONEY_ERROR);
            }
            else if (!StringUtils.equals(data.getString("errorCode"), "000000")){
                log.info("宁波银行, 调账接口(fundTransferOrder), code:{}, msg:{}", data.getString("errorCode"), data.getString("errorMsg"));
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_API_ERROR);
            }

            return data;
        } catch (Exception e) {
            if (e instanceof ServiceSystemException) {throw (ServiceSystemException)e;}

            log.info("宁波银行接口异常:{}", ExceptionUtils.getStackTrace(e));
        }

        throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_API_ERROR);
    }

    /**
     * 退款
     * 5.2退款
     * {
     *     "data": {
     *         "clearDate": "20240131",
     *         "errorCode": "PAY013",
     *         "errorMsg": "原支付订单非成功状态，无法退款",
     *         "merId": "EFT33021200247909",
     *         "merSeqNo": "7158282384029478912",
     *         "transSeqNo": "2024013110183508603395pEiLj8Kd",
     *         "transStatus": "01",
     *         "trxAmt": "0.01"
     *     },
     *     "head": {
     *         "rqsJrnlNo": "20971617100330682",
     *         "rspCode": "000000",
     *         "rspDate": "2024-01-31",
     *         "rspMsg": "交易成功",
     *         "rspTime": "10:18:35:131"
     *     }
     * }
     * @Param type: 1普通退款 2银行转账退款 3银联订单支付撤单
     * @return
     */
    @Override
    public JSONObject refund(Integer type, String merSeqNo, String merDtTm,
                             Integer amount,
                             String orgMerSeqNo, String coreSeqNo) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("transId", getRefundTransId(type));                     //交易识别码 必填
            jsonObject.put("merId", nbBankConfig.getMerId());                      //商户号 必填

            jsonObject.put("merSeqNo", merSeqNo);           //商户流水 必填
            jsonObject.put("merDtTm", merDtTm);             //商户时间 必填

            jsonObject.put("trxAmt", new BigDecimal(amount).movePointLeft(2));     //订单金额 必填
            jsonObject.put("orgMerSeqNo", orgMerSeqNo);     //原订单流水号 必填
            if (StringUtils.isNotBlank(coreSeqNo)) {
                jsonObject.put("coreSeqNo", coreSeqNo);     //核心流水号 必填
            }

            HashMap<String,String> httpHeader = new HashMap<>();

            RequestApiData requestApiData = new RequestApiData();
            requestApiData.setAppkey(nbBankConfig.getAppKey());
            requestApiData.setData(jsonObject);
            requestApiData.setProductId("YFT");
            requestApiData.setServiceId("refund");
            requestApiData.setHttpHeader(httpHeader);

            RequestHead requestHead = new RequestHead();
            requestHead.setRqsJrnlNo(NBOpenSDK.getRandom());

            SDKRequest request = new SDKRequest();
            request.setData(requestApiData);
            request.setHead(requestHead);

            log.info("宁波银行, 退款(refund), 参数: {}", JSON.toJSONString(request));
            SDKResponse response = NBOpenSDK.send(request);
            log.info("宁波银行, 退款(refund), 结果: {}", JSON.toJSONString(response));

            recordSave(NbBankRecordEnum.Type.REFUND.getCode(), request, response);

            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject data = responseJson.getJSONObject("data");

            if (!StringUtils.equals(data.getString("errorCode"), "000000")){
                log.info("宁波银行, 退款失败(refund), code:{}, msg:{}", data.getString("errorCode"), data.getString("errorMsg"));
                throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_API_ERROR);
            }

            return data;

        } catch (Exception e) {
            log.info("宁波银行接口异常:{}", ExceptionUtils.getStackTrace(e));
        }

        throw new ServiceSystemException(PerformanceResultEnum.NB_BANK_API_ERROR);
    }

    @Override
    public void recordSave(Integer type, SDKRequest request, SDKResponse response) {

        if (Objects.equals(type, NbBankRecordEnum.Type.DIRECT_BANK_TRANSFER_ORDER.getCode())) {
            RequestApiData requestData = (RequestApiData) (request.getData());
            JSONObject requestDataJson = (JSONObject) (requestData.getData());

            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject responseDataJson = responseJson.getJSONObject("data");
            if (responseDataJson == null) {responseDataJson = new JSONObject();}

            recordSave(type
                    , requestDataJson.getString("merId")
                    , requestDataJson.getString("merSeqNo")
                    , requestDataJson.getString("merDtTm")
                    , responseDataJson.getString("transSeqNo")
                    , requestDataJson.getBigDecimal("trxAmt").movePointRight(2).intValue()
                    , JSON.toJSONString(request)
                    , JSON.toJSONString(response)
                    , responseDataJson.getString("errorCode")
                    , responseDataJson.getString("errorMsg")
                    , null
            );
        }
        else if (Objects.equals(type, NbBankRecordEnum.Type.UNION_PAY_DIRECT_ORDER.getCode())) {
            RequestApiData requestData = (RequestApiData) (request.getData());
            JSONObject requestDataJson = (JSONObject) (requestData.getData());

            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject responseDataJson = responseJson.getJSONObject("data");
            if (responseDataJson == null) {responseDataJson = new JSONObject();}

            recordSave(type
                    , requestDataJson.getString("merId")
                    , requestDataJson.getString("merSeqNo")
                    , requestDataJson.getString("merDtTm")
                    , responseDataJson.getString("transSeqNo")
                    , requestDataJson.getBigDecimal("trxAmt").movePointRight(2).intValue()
                    , JSON.toJSONString(request)
                    , JSON.toJSONString(response)
                    , responseDataJson.getString("errorCode")
                    , responseDataJson.getString("errorMsg")
                    , null
            );
        }
        else if (Objects.equals(type, NbBankRecordEnum.Type.QUERY_ORDER.getCode())) {
            RequestApiData requestData = (RequestApiData) (request.getData());
            JSONObject requestDataJson = (JSONObject) (requestData.getData());

            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject responseDataJson = responseJson.getJSONObject("data");
            if (responseDataJson == null) {responseDataJson = new JSONObject();}

            recordSave(type
                    , requestDataJson.getString("merId")
                    , requestDataJson.getString("merSeqNo")
                    , null
                    , responseDataJson.getString("transSeqNo")
                    , responseDataJson.getBigDecimal("trxAmt")==null? null : responseDataJson.getBigDecimal("trxAmt").movePointRight(2).intValue()
                    , JSON.toJSONString(request)
                    , JSON.toJSONString(response)
                    , responseDataJson.getString("errorCode")
                    , responseDataJson.getString("errorMsg")
                    , responseDataJson.getString("transStatus")
            );
        }
        else if (Objects.equals(type, NbBankRecordEnum.Type.NOTIFY_MERCHANT.getCode())) {
            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject responseDataJson = responseJson.getJSONObject("data");
            if (responseDataJson == null) {responseDataJson = new JSONObject();}

            recordSave(type
                    , responseDataJson.getString("merId")
                    , responseDataJson.getString("merSeqNo")
                    , null
                    , responseDataJson.getString("transSeqNo")
                    , responseDataJson.getBigDecimal("trxAmt")==null? null : responseDataJson.getBigDecimal("trxAmt").movePointRight(2).intValue()
                    , JSON.toJSONString(request)
                    , JSON.toJSONString(response)
                    , null
                    , null
                    , responseDataJson.getString("transStatus")
            );
        }
        else if (Objects.equals(type, NbBankRecordEnum.Type.FUND_TRANSFER_ORDER.getCode())) {
            RequestApiData requestData = (RequestApiData) (request.getData());
            JSONObject requestDataJson = (JSONObject) (requestData.getData());

            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject responseDataJson = responseJson.getJSONObject("data");
            if (responseDataJson == null) {responseDataJson = new JSONObject();}

            recordSave(type
                    , requestDataJson.getString("merId")
                    , requestDataJson.getString("merSeqNo")
                    , requestDataJson.getString("merDtTm")
                    , responseDataJson.getString("transSeqNo")
                    , requestDataJson.getBigDecimal("trxAmt").movePointRight(2).intValue()
                    , JSON.toJSONString(request)
                    , JSON.toJSONString(response)
                    , responseDataJson.getString("errorCode")
                    , responseDataJson.getString("errorMsg")
                    , responseDataJson.getString("transStatus")
            );
        }
        else if (Objects.equals(type, NbBankRecordEnum.Type.REFUND.getCode())) {
            RequestApiData requestData = (RequestApiData) (request.getData());
            JSONObject requestDataJson = (JSONObject) (requestData.getData());

            JSONObject responseJson = JSON.parseObject(JSON.toJSONString(response));
            JSONObject responseDataJson = responseJson.getJSONObject("data");
            if (responseDataJson == null) {responseDataJson = new JSONObject();}

            recordSave(type
                    , requestDataJson.getString("merId")
                    , requestDataJson.getString("merSeqNo")
                    , requestDataJson.getString("merDtTm")
                    , requestDataJson.getString("transSeqNo")
                    , requestDataJson.getBigDecimal("trxAmt").movePointRight(2).intValue()
                    , JSON.toJSONString(request)
                    , JSON.toJSONString(response)
                    , responseDataJson.getString("errorCode")
                    , responseDataJson.getString("errorMsg")
                    , responseDataJson.getString("transStatus")
            );
        }

    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void recordSave(Integer type,
                           String merId, String merSeqNo, String merDtTm, String transSeqNo,
                           Integer amount,
                           String param, String result,
                           String errorCode, String errorMsg,
                           String transStatus
                           ){
        NbBankRecord record = new NbBankRecord();
        record.setType(type);
        record.setMerId(merId);
        record.setMerSeqNo(merSeqNo);
        record.setMerDtTm(StringUtils.isBlank(merDtTm)? null : LocalDateTimeUtils.parseTime(merDtTm));
        record.setTransSeqNo(transSeqNo);
        record.setAmount(amount);
        record.setParam(param);
        record.setResult(result);
        record.setErrorCode(errorCode);
        record.setErrorMsg(errorMsg);
        record.setTransStatus(transStatus);

        nbBankRecordDao.saveEntity(record);
    }

    /**
     * 获取退款交易识别码
     */
    private String getRefundTransId(Integer type){
        if (type == 1) {return "TK01";}
        if (type == 2) {return "TK02";}
        return "CD01";

    }
}
