package com.yeejoin.amos.boot.module.hygf.biz.service.impl;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.csii.pp.icbc.util.SM2Utils;
import com.csii.pp.icbc.util.SM4Utils;
import com.csii.pp.icbc.util.UtilIcbc;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.icbc.api.request.*;
import com.icbc.api.response.*;
import com.yeejoin.amos.boot.biz.common.excel.ExcelUtil;
import com.yeejoin.amos.boot.module.hygf.api.dto.*;
import com.yeejoin.amos.boot.module.hygf.api.mapper.HouseholdContractMapper;
import com.yeejoin.amos.boot.module.hygf.api.mapper.PowerStationEngineeringInfoMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.icbc.api.DefaultIcbcClient;
import com.icbc.api.IcbcApiException;
import com.icbc.api.IcbcConstants;
import com.icbc.api.UiIcbcClient;
import com.icbc.api.utils.IcbcSignature;
import com.icbc.api.utils.WebUtils;
import com.yeejoin.amos.boot.module.hygf.api.Enum.IcbcEnum;
import com.yeejoin.amos.boot.module.hygf.api.entity.HygfIcbcRecord;
import com.yeejoin.amos.boot.module.hygf.api.entity.HygfIcbcRequest;
import com.yeejoin.amos.boot.module.hygf.api.entity.PeasantHousehold;
import com.yeejoin.amos.boot.module.hygf.api.mapper.HygfIcbcRecordMapper;
import com.yeejoin.amos.boot.module.hygf.api.mapper.HygfIcbcRequestMapper;
import com.yeejoin.amos.boot.module.hygf.api.service.IHygfIcbcService;

import lombok.extern.slf4j.Slf4j;

/**
 * 并网信息服务实现类
 *
 * @author system_generator
 * @date 2024-01-12
 */
@Service
@Slf4j
public class HygfIcbcServiceImpl extends BaseService<HygfIcbcRecordDTO, HygfIcbcRecord, HygfIcbcRecordMapper>

        implements IHygfIcbcService {

    private static final String trxChannel = "05"; // 05表示小程序

    // 正式环境
//    private static  final String APP_ID = "11000000000000028870";
//    private static final String corpNo = "020240710000001169";
//    private static final String MY_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDAlcIeANdqipul3/qAIRlknSacHiFCMzLzUJisGcr9ipm3p2rir8WDsac2MxgtUt+f89SGNoWyjv4q0/QAKQQTd5U3KuGAksCJLBGVibuFe7G7YGYVezUksjvocvp8GIinCIkzq67KL2SOpGXAu3s+282rx8AxdTZA/EhXQvbORbWz5+DamyY+wS7Maa8KmIOb6WZPtiXgENZxDHAafrqW8Gt1BnVfJNf5yS5J9Wl+LcR1EPvi5iH8dSIdn1ZMVupoREjV/DvItSogVehsqTRZWuekAo2xH9YEli1UMG/l3deViRn/A4VmPPzdv0xXpn/yO+OTjWez+KmSmJfAZXBvAgMBAAECggEABRYviWFWTz8X+1qeIDI/nHO2KFt3X2tAxkJztd/8h5PYmYw3e4NPATp5Ayp4UgIlW/ExxNW91EiImBL/F939eJIpA8sDJ8U4hqb+U+fOZyksOZnDOIAHmE+I24vl588yFM9Z6F55gGeeDVJ0SZHqIG/nz8i339aLt02yj3N6V1peQugBP6L9arcD+gVu4F70whkqW+lHBK/WzX1OazqEx3Ip175jqzi9/0vO/h/kqnGGXuMi2VeuAPsa+d0a6lf/FScxqCt3t6dCkJ5DPA1MCj81dPi5ZfCM/vE0N8I6LEV+RyC7bb4YVO/PoicFjb2j8vfLvldOUrsvkNH51dZusQKBgQDpMHacOBpIuVzEFfNtS9SgA96cUV6NCSmHoQppJ/p9xKzY4DpcqoOCIBT4WCvVe6PeN5mrjzt8Q5gJWxiq0tVgIF9k8GjLmuiJ2v4Qh8aUmlRwn0T0DYiX/Y7uzX+pRlkpoKrSktlTOT9vmGwZDGDk0h2+H3hZ3YQEucfA6bhHmQKBgQDTbHrbr1WsUR9lrdLaGi/Uphpl3BXLuCnJXav3yIZOktO5V68MfPZXLP7aaNtbK3n0YHD+Uv8wpHBBSWQYjVYlGdvlniA/W1pr73GZJECFfS1BmmFC4GG3E92D5IkmrcPlUuz8XxKrlwHnfW1F0MoDvhp930vS0tS6u+WYTt9dRwKBgCeEQPVkRIACeYf5OFFTQmsDfNv8pgs8fD8xuTPsxHQ/uhLenMVLWBHbIfKb7oG0/CYSQgZitW/vfHpJZ7q7E9HAaqoOW5P1YmbKJ7fhanOQW7LiKqs5B+bJ30j0piendkCpq4kXvaBu2SMuL1NnV5wvRz8K0jhYY6DxYrp8YPAxAoGAZxWTaZ25tgTvvBHeprzx6Ur7wAJpFiU7KpVjjbLV2WW5mbro/LvJGIQ11qQdn/w4wDBtp3MsPblPimWQSnBPOlO7Zd+NdZbDJbFfv/1vACcic8Qj/AmPW0ZyUSaSwKskwqGGLx7j6Yn9QbNkHhBJDz4XiJvhSm/FjS6kKXj7a20CgYEArnEiPmL5g1Ca/qKK9ql8Q6P9gipIfGGpaFu23y0trbcFpVn8Oos/ic0Jgw4Xiz+rqvb6bW2V6lqBJ+9/kdn0i7zlZxKNpYsW2xFgi04OU3d5HkGL16Y1rpqMYYEhjFaOIn7J8P046UYR99yaybgQd18TE6oFrX8OL5uY8M4ge4Y=";
//    private static final String serviceUrl = "https://gw.open.icbc.com.cn/ui/jft/ui/user/entrustopenacct/submit/V1";
//    private static final String AES_Key = "nuCVNzIxOTHZWv8YjEeYQA==";
//    private static final String CAMS_PUBLIC_KEY = "655CE8706E6ED9A30B92E57D8D645ADDE8C541C27C5C5AFD529C610C4C0B04F9074E3B6E933C50A3316AEA60CEF461BE4C7916D2AF51170D3A2631394A7F3939";
//    private static final String APIGW_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMpjaWjngB4E3ATh+G1DVAmQnIpiPEFAEDqRfNGAVvvH35yDetqewKi0l7OEceTMN1C6NPym3zStvSoQayjYV+eIcZERkx31KhtFu9clZKgRTyPjdKMIth/wBtPKjL/5+PYalLdomM4ONthrPgnkN4x4R0+D4+EBpXo8gNiAFsNwIDAQAB";
//    private static final String OUT_VENDOR_ID = "071301";
//    private static final String PROJECT_ID = "PJ14001401B000160171";

    // 测试环境
    @Value("${hygf.icbc.appId}")
    private String APP_ID;
    @Value("${hygf.icbc.corpNo}")
    private String corpNo;
    @Value("${hygf.icbc.myPrivateKey}")
    private String MY_PRIVATE_KEY;
    @Value("${hygf.icbc.serviceUrl}")
    private String serviceUrl;
    @Value("${hygf.icbc.aesKey}")
    private String AES_Key;
    @Value("${hygf.icbc.camsPublicKey}")
    private String CAMS_PUBLIC_KEY;
    @Value("${hygf.icbc.apigwPublicKey}")
    private String APIGW_PUBLIC_KEY;
    @Value("${hygf.icbc.outVendorId}")
    private String OUT_VENDOR_ID;
    @Value("${hygf.icbc.projectId}")
    private String PROJECT_ID;

    /**
     * 协议总限额
     */
    @Value("${hygf.icbc.protocolLimitAmount:2500000000}")
    private String protocolLimitAmount;
    /**
     * 单笔限额
     */
    @Value("${hygf.icbc.trxLmtAmt:10000000}")
    private String trxLmtAmt;
    /**
     * 日累计限额
     */
    @Value("${hygf.icbc.dayLmtAmt:20000000}")
    private String dayLmtAmt;

    @Value("${hygf.icbc.loanTotalAmt:0}")
    private String loanTotalAmt;
    /**
     * 合作方接收结果通知 URL
     */
    @Value("${hygf.icbc.callbackUrl:}")
    private String callbackUrl;

    @Resource(type = PeasantHouseholdServiceImpl.class)
    private PeasantHouseholdServiceImpl peasantHouseholdService;

    @Resource(type = HygfIcbcRecordMapper.class)
    private HygfIcbcRecordMapper hygfIcbcRecordMapper;

    @Resource(type = HouseholdContractMapper.class)
    private HouseholdContractMapper householdContractMapper;

    @Resource(type = PowerStationEngineeringInfoMapper.class)
    private PowerStationEngineeringInfoMapper powerStationEngineeringInfoMapper;

    @Resource(type = HygfIcbcRequestMapper.class)
    private HygfIcbcRequestMapper hygfIcbcRequestMapper;

    public void icbcRegisterWalletUrl(HttpServletRequest req, HttpServletResponse resp) {
        try {
            UiIcbcClient client = new UiIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY,
                    IcbcConstants.CHARSET_UTF8);

            String userId = req.getParameter("userId");
//            String userId = "071301";

            JftUiUserEntrustopenacctSubmitRequestV1 request = new JftUiUserEntrustopenacctSubmitRequestV1();
            request.setServiceUrl(serviceUrl + "/ui/jft/ui/user/entrustopenacct/submit/V1");

            JftUiUserEntrustopenacctSubmitRequestV1.JftUiUserEntrustopenacctSubmitRequestV1Biz bizContent = new JftUiUserEntrustopenacctSubmitRequestV1.JftUiUserEntrustopenacctSubmitRequestV1Biz();
            bizContent.setAppId(APP_ID);
            bizContent.setCorpNo(corpNo);
            bizContent.setOutUserId(userId); // 用户唯一id
            bizContent.setCorpSerno(UUID.randomUUID().toString());
            bizContent.setTrxChannel(trxChannel);
            bizContent.setSignProtocol("1"); // 是否对接缴费代扣流程
            bizContent.setOutVendorId(OUT_VENDOR_ID); // 企业外系统编号
            bizContent.setProjectId(PROJECT_ID); // 缴费项目编号
            bizContent.setBusiCode(userId); // 缴费编号

            Calendar calendar = Calendar.getInstance();
            Date date = new Date();// 当前时间
            calendar.setTime(date);
            int year = 26;// 26年
            calendar.add(Calendar.YEAR, year);// 在年份增加
            Date newDate = calendar.getTime();
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            String formattedDate = formatter.format(newDate);

            bizContent.setProtocolEndDate(formattedDate); // 协议到期日
            bizContent.setProtocolLimitAmount(protocolLimitAmount); // 协议累计额
            JSONObject templateParams = new JSONObject();
            templateParams.put("prtl_enddate", formattedDate);// 协议到期日
            templateParams.put("loan_total_amt", loanTotalAmt);// 贷款限额（单位：分）
            templateParams.put("trx_lmt_amt", trxLmtAmt);// 单笔限额（单位：分）
            templateParams.put("day_lmt_amt", dayLmtAmt);// 日累计限额（单位：分）
            bizContent.setTemplateParams(templateParams.toJSONString());
            bizContent.setCallbackUrl(callbackUrl);

            bizContent.setCamsPublicKey(CAMS_PUBLIC_KEY);
            request.setBizContent(bizContent);
            // 调用工行 SDK，生成自动提交表单，将用户跳转到收方入驻页面
            log.info("聚富通委托代扣签约同步开户页面接口V1, 入参 => {}", JSON.toJSONString(request));
            //添加上送日志存储
            HygfIcbcRequest hygfIcbcRequest = new HygfIcbcRequest();
            hygfIcbcRequest.setPhase("请求");
            hygfIcbcRequest.setContent(JSONObject.toJSONString(request));
            hygfIcbcRequest.setRecDate(new Date());
            hygfIcbcRequestMapper.insert(hygfIcbcRequest);
            String form = client.buildPostForm(request);
            log.info("聚富通委托代扣签约同步开户页面接口V1, 响应 => {}", form);
            resp.setHeader("Content-Type", "text/html;charset=" + IcbcConstants.CHARSET_UTF8);
            PrintWriter out = resp.getWriter();
            out.write("<html>");
            out.write("<head>");
            out.write("<meta http-equiv=\"Content-Type\" content=\"text/html;charset=" + IcbcConstants.CHARSET_UTF8
                    + "\">");
            out.write("</head>");
            out.write("<body>");
            out.write(form);
            out.write("</body>");
            out.write("</html>");
        } catch (IcbcApiException e) {
            log.error("聚富通委托代扣签约同步开户页面接口V1, error => ", e);
            throw new BadRequest(e.getErrMsg());
        } catch (Exception e) {
            log.error("聚富通委托代扣签约同步开户页面接口V1, error => ", e);
            throw new RuntimeException(e.getMessage());
        }

    }

    public JftApiUserEntrustopenacctQueryResponseV1 getHygfIcbcWalletInfo(String userId) {
        DefaultIcbcClient client = new DefaultIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY,
                IcbcConstants.CHARSET_UTF8, IcbcConstants.FORMAT_JSON, APIGW_PUBLIC_KEY, IcbcConstants.ENCRYPT_TYPE_AES,
                AES_Key, "", "");

        JftApiUserEntrustopenacctQueryRequestV1 request = new JftApiUserEntrustopenacctQueryRequestV1();
        request.setServiceUrl(serviceUrl + "/api/jft/api/user/entrustopenacct/query/V1");
        JftApiUserEntrustopenacctQueryRequestV1.JftApiUserEntrustopenacctQueryRequestV1Biz bizContent = new JftApiUserEntrustopenacctQueryRequestV1.JftApiUserEntrustopenacctQueryRequestV1Biz();
        bizContent.setAppId(APP_ID);
        bizContent.setOutVendorId(OUT_VENDOR_ID);
        bizContent.setOutUserId(userId);
        bizContent.setProjectId(PROJECT_ID);
        bizContent.setBusiCode(userId);
        request.setBizContent(bizContent);
        JftApiUserEntrustopenacctQueryResponseV1 response;
        try {
            log.info("聚富通委托代扣签约同步开户结果查询数据接口V1, => 入参: {}", JSON.toJSONString(request));
            response = client.execute(request, System.currentTimeMillis() + "");
            log.info("聚富通委托代扣签约同步开户结果查询数据接口V1, => 响应: {}", JSON.toJSONString(response));
            if (response.isSuccess()) {
                return response;
            } else {
                // 失败
                throw new BadRequest(response.getReturnMsg());
            }
        } catch (IcbcApiException e) {
            e.printStackTrace();
            log.error("聚富通委托代扣签约同步开户结果查询数据接口V1 error => ", e);
            throw new BadRequest(e.getErrMsg());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("聚富通委托代扣签约同步开户结果查询数据接口V1 error => ", e);
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 户用光伏开户签约异步通知使用
     *
     * @param request  request
     * @param response response
     * @return {@link Object}
     * @throws @author yangyang
     * @date 2024/7/18 20:15
     */
    public Object registerWalletCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("户用光伏开户签约异步通知, => 验签");
        String returnJson;
        // 网关公钥
        Map<String, String> params = new HashMap<>();
        String api = request.getParameter("api");
        String from = request.getParameter("from");
        String app_id = request.getParameter("app_id");
        String charset = request.getParameter("charset");
        String format = request.getParameter("format");
        String encrypt_type = request.getParameter("encrypt_type");
        String timestamp = request.getParameter("timestamp");
        String biz_content = request.getParameter("biz_content");
        String sign_type = request.getParameter("sign_type");
        String sign = request.getParameter("sign");
        params.put("from", from);
        params.put("api", api);
        params.put("app_id", app_id);
        params.put("charset", charset);
        params.put("format", format);
        params.put("encrypt_type", encrypt_type);
        params.put("timestamp", timestamp);
        // params.put("biz_content",
        // "{\"busiCode\":\"11098243\",\"return_msg\":\"success\",\"outUserId\":\"11098243\",\"custName\":\"5p2O5Y2r5Lic\",\"marketingStaffId\":\"\",\"newPayAcc\":\"NjIxNDc2MTUwMjYwMjc5MDc4OQ==\",\"signEntrsutPrtlSucceedFlag\":\"1\",\"certNo\":\"MjI5MDA1MTk3MzEwMjUwMjFY\",\"appId\":\"11000000000000028870\",\"msg_id\":\"20240814190453416\",\"projectId\":\"PJ140014023565102203\",\"openAccoutSucceedFlag\":\"02\",\"return_code\":0}");
        params.put("biz_content", biz_content);
        params.put("sign_type", sign_type);// 目前上行网关签名暂时仅支持RSA
        params.put("sign", sign);
        HygfIcbcRequest hygfIcbcRequest = new HygfIcbcRequest();
        hygfIcbcRequest.setPhase("验签");
        hygfIcbcRequest.setContent(JSONObject.toJSONString(params));
        hygfIcbcRequest.setRecDate(new Date());
        hygfIcbcRequestMapper.insert(hygfIcbcRequest);
        try {
            boolean verifyFlag = verifySignData(request, "/hygf/icbc/notify");
            if (verifyFlag) {
                // 验签成功
                hygfIcbcRequest.setPhase("查询");
                hygfIcbcRequestMapper.updateById(hygfIcbcRequest);

                // String biz_content = request.getParameter("biz_content");
                String decode = URLDecoder.decode(biz_content, "utf-8");
                Map<String, String> data = JSONObject.parseObject(decode, Map.class);
                log.debug("解密后参数:{}", data);// 进行自己的处理,此处默认处理成功，返回通知方成功,return_code=0
                // 其中certNo、custName、newPayAcc字段进行了base64编码，可以调用示例代码中的base64Decode进行解码
                // String custName = base64Decode(data.get("custName"));
                String certNo = base64Decode(data.get("certNo"));
                String newPayAcc = base64Decode(data.get("newPayAcc"));
                String outUserId = data.get("outUserId");
                String projectId = data.get("projectId");
                String openAccoutSucceedFlag = data.get("openAccoutSucceedFlag");
                String signEntrsutPrtlSucceedFlag = data.get("signEntrsutPrtlSucceedFlag");
                JftApiUserEntrustopenacctQueryResponseV1 hygfIcbcWalletInfo = this.getHygfIcbcWalletInfo(outUserId);
                // region 保存数据
                HygfIcbcRecord hygfIcbcRecord = this.lambdaQuery().eq(HygfIcbcRecord::getAmosUserId, outUserId)
                        .last(" limit 1").one();
                if (hygfIcbcRecord == null) {
                    hygfIcbcRecord = new HygfIcbcRecord();
                }
                PeasantHousehold peasantHousehold = peasantHouseholdService.lambdaQuery()
                        .select(PeasantHousehold::getTelephone).eq(PeasantHousehold::getAmosUserId, outUserId)
                        .last("limit 1").one();
                hygfIcbcRecord.setPhone(peasantHousehold != null ? peasantHousehold.getTelephone() : "");
                hygfIcbcRecord.setMediumId(newPayAcc);
                hygfIcbcRecord.setProjectId(projectId);
                hygfIcbcRecord.setOpenAccountStatus(openAccoutSucceedFlag);
                hygfIcbcRecord.setSignEntrsutPrtlStatus(signEntrsutPrtlSucceedFlag);
                hygfIcbcRecord.setCustName(peasantHousehold.getOwnersName());
                hygfIcbcRecord.setIdCard(certNo);
                hygfIcbcRequest.setPhase("组装");
                hygfIcbcRequest.setException(data.get("custName") + " -> " + peasantHousehold.getOwnersName());
                hygfIcbcRequestMapper.updateById(hygfIcbcRequest);

                if (hygfIcbcWalletInfo != null) {
                    hygfIcbcRecord.setCustName(hygfIcbcWalletInfo.getCustName());
                    hygfIcbcRecord.setIdCard(hygfIcbcWalletInfo.getCertNo());
                    hygfIcbcRecord.setProtocolStatus(hygfIcbcWalletInfo.getProtocolStatus());
                    hygfIcbcRecord.setProtocolStartTime(hygfIcbcWalletInfo.getProtocolStartDate());
                    hygfIcbcRecord.setProtocolEndTime(hygfIcbcWalletInfo.getProtocolEndDate());
                    hygfIcbcRecord.setTrxLimitAmount(hygfIcbcWalletInfo.getTrxLimitAmount());
                    hygfIcbcRecord.setDayLimitAmount(hygfIcbcWalletInfo.getDayLimitAmount());
                    hygfIcbcRecord.setProtocolLimitAmount(hygfIcbcWalletInfo.getProtocolLimitAmount());
                    hygfIcbcRecord.setAppId(hygfIcbcWalletInfo.getAppId());
                    hygfIcbcRecord.setOutUserId(hygfIcbcWalletInfo.getOutUserId());
                    hygfIcbcRecord.setOutVendorId(hygfIcbcWalletInfo.getOutVendorId());
                }
                // hygfIcbcRecord.setDiscardStatus();
                hygfIcbcRecord.setAmosUserId(outUserId);
                hygfIcbcRecord.setRecDate(new Date());
                hygfIcbcRecord.setType("二类卡");

                hygfIcbcRequest.setPhase("入库");
                hygfIcbcRequestMapper.updateById(hygfIcbcRequest);

                this.saveOrUpdate(hygfIcbcRecord);
                // endregion
                String copReturnCode = "0";// 通知合作方接收成功的返回码，固定
                String copReturnMsg = "success";// 合作方的返回信息，固定

                hygfIcbcRequest.setPhase("加签返回");
                hygfIcbcRequestMapper.updateById(hygfIcbcRequest);
                returnJson = sign(request, copReturnCode, copReturnMsg);
                log.info("通知响应json结果：{}", returnJson);
                return returnJson;
            } else {// 验签失败
                hygfIcbcRequest.setPhase("验签失败");
                hygfIcbcRequestMapper.updateById(hygfIcbcRequest);

                String copReturnCode = "‐12345";
                String copReturnMsg = "icbc jft sign not pass.";
                returnJson = sign(request, copReturnCode, copReturnMsg);
                log.error("通知响应json结果：{}", returnJson);

            }
        } catch (Exception e) {
            log.error("户用光伏开户签约异步通知, => error:", e);

            hygfIcbcRequest.setException(JSONObject.toJSONString(e));

            hygfIcbcRequestMapper.updateById(hygfIcbcRequest);
            String copReturnCode = "‐1";
            String copReturnMsg = "icbc jft error";
            returnJson = sign(request, copReturnCode, copReturnMsg);
        }
        return returnJson;
    }

    public HygfIcbcRecordDTO getObject(String amosUserId) {
        HygfIcbcRecord hygfIcbcRecord = this.lambdaQuery().eq(HygfIcbcRecord::getAmosUserId, amosUserId).last("limit 1")
                .one();
        HygfIcbcRecordDTO hygfIcbcRecordDTO = new HygfIcbcRecordDTO();
        if (hygfIcbcRecord == null) {
            PeasantHousehold peasantHousehold = peasantHouseholdService.lambdaQuery()
                    .select(PeasantHousehold::getTelephone, PeasantHousehold::getOwnersName,
                            PeasantHousehold::getIdCard)
                    .eq(PeasantHousehold::getAmosUserId, amosUserId).last("limit 1").one();

            hygfIcbcRecordDTO.setCustName(peasantHousehold.getOwnersName());
            hygfIcbcRecordDTO.setIdCard(peasantHousehold.getIdCard());
            hygfIcbcRecordDTO.setPhone(peasantHousehold.getTelephone());
            hygfIcbcRecordDTO.setOpenAccountStatus(IcbcEnum.OpenAccountState.INITIAL.getCode());
            hygfIcbcRecordDTO.setOpenAccountStatusName(IcbcEnum.OpenAccountState.getNameByCode(
                    IcbcEnum.OpenAccountState.INITIAL.getCode(), IcbcEnum.OpenAccountState.INITIAL.getName()));
        } else if (IcbcEnum.OpenAccountState.FAIL.getCode().equals(hygfIcbcRecord.getOpenAccountStatus())) {
            Bean.toModel(hygfIcbcRecord, hygfIcbcRecordDTO);
            PeasantHousehold peasantHousehold = peasantHouseholdService.lambdaQuery()
                    .select(PeasantHousehold::getTelephone, PeasantHousehold::getOwnersName,
                            PeasantHousehold::getIdCard)
                    .eq(PeasantHousehold::getAmosUserId, amosUserId).last("limit 1").one();

            hygfIcbcRecordDTO.setCustName(peasantHousehold.getOwnersName());
            hygfIcbcRecordDTO.setIdCard(peasantHousehold.getIdCard());
            hygfIcbcRecordDTO.setPhone(peasantHousehold.getTelephone());
            hygfIcbcRecordDTO.setOpenAccountStatusName(IcbcEnum.OpenAccountState.getNameByCode(
                    hygfIcbcRecordDTO.getOpenAccountStatus(), IcbcEnum.OpenAccountState.INITIAL.getName()));
            hygfIcbcRecordDTO.setProtocolStatusName(
                    IcbcEnum.ProtocolStatus.getNameByCode(hygfIcbcRecordDTO.getProtocolStatus(), ""));
        } else {
            Bean.toModel(hygfIcbcRecord, hygfIcbcRecordDTO);
            hygfIcbcRecordDTO.setOpenAccountStatusName(IcbcEnum.OpenAccountState.getNameByCode(
                    hygfIcbcRecordDTO.getOpenAccountStatus(), IcbcEnum.OpenAccountState.INITIAL.getName()));
            hygfIcbcRecordDTO.setProtocolStatusName(
                    IcbcEnum.ProtocolStatus.getNameByCode(hygfIcbcRecordDTO.getProtocolStatus(), ""));
        }
        List<String> amosUserIds = Arrays.asList(amosUserId);
        List<PeasantHousehold> peasantHouseholds = peasantHouseholdService.lambdaQuery()
                .in(PeasantHousehold::getAmosUserId, amosUserIds).list();
        Map<String, List<PeasantHousehold>> peasantHouseholdMap = peasantHouseholds.stream()
                .collect(Collectors.groupingBy(PeasantHousehold::getAmosUserId));// 根据农户 ID 分组
        List<PeasantHousehold> peasantHouseholdList = peasantHouseholdMap.get(amosUserId);

        if (peasantHouseholdList != null && peasantHouseholdList.size() > 0) {
            peasantHouseholdList.forEach(e -> {
                if (e.getSurveyInformationId() != null) {
                    e.setScale(householdContractMapper.getHygfCommercialScale(e.getPeasantHouseholdNo()));
                    e.setRealScale(powerStationEngineeringInfoMapper
                            .getRealScaleByPeasantHouseholdNo(e.getPeasantHouseholdNo()));
                }
            });
        }

        hygfIcbcRecordDTO.setPeasantHouseholds(
                Bean.toModels(peasantHouseholdList, HygfIcbcRecordDTO.IcbcPeasantHousehold.class));
        return hygfIcbcRecordDTO;
    }

    public List<HygfIcbcRecordDTO> listObject(HygfIcbcRecordQueryDTO hygfIcbcRecordQueryDTO) {
        List<HygfIcbcRecordDTO> list = hygfIcbcRecordMapper.listObject(hygfIcbcRecordQueryDTO);
        return toModels(list);
    }

    public Map<String, Object> queryForPage(int current, int size, HygfIcbcRecordQueryDTO hygfIcbcRecordQueryDTO) {
        //PageHelper.startPage(current, size);
        List<HygfIcbcRecordDTO> list = hygfIcbcRecordMapper.pageList(hygfIcbcRecordQueryDTO,(current-1)*size,size);
        PageInfo<HygfIcbcRecordDTO> page = new PageInfo(list);
        //PageHelper.startPage(current, Integer.MAX_VALUE);
        List<HygfIcbcRecordDTO> list1 = hygfIcbcRecordMapper.pageList(hygfIcbcRecordQueryDTO,0,Integer.MAX_VALUE);
        double sum = list1.stream().filter(e -> null != e.getPaymentAmount()).mapToDouble(HygfIcbcRecordDTO::getPaymentAmount).sum();

        Page<HygfIcbcRecordDTO> pagenew = new Page<>();
        pagenew.setCurrent(current);
        pagenew.setTotal(list1.size());
        pagenew.setSize(size);
        pagenew.setRecords(toModels(page.getList()));
        Map<String, Object> resultMap = BeanUtil.beanToMap(pagenew);
        resultMap.put("paymentAmountAll", sum);
        return resultMap;

//		======================================================統計錯誤=================================================================
//		// PageHelper.startPage(current, size);
//		Integer total = hygfIcbcRecordMapper.listObjectCount(hygfIcbcRecordQueryDTO);
//		hygfIcbcRecordQueryDTO.setLimit(size);
//		if (current == 1) {
//			hygfIcbcRecordQueryDTO.setOffset(0);
//		} else {
//			// int offset = (current - 1) * size > total ? : (current - 1) * size;
//			hygfIcbcRecordQueryDTO.setOffset((current - 1) * size);
//		}
//		List<HygfIcbcRecordDTO> list = hygfIcbcRecordMapper.listObject(hygfIcbcRecordQueryDTO);
//		Page<HygfIcbcRecordDTO> page = new Page<>();
//		page.setSize(size);
//		page.setCurrent(current);
//		page.setTotal(total);
//		page.setRecords(toModels(list));
//		return page;
    }

    private List<HygfIcbcRecordDTO> toModels(List<HygfIcbcRecordDTO> hygfIcbcRecords) {
        if (CollectionUtils.isEmpty(hygfIcbcRecords)) {
            return Collections.emptyList();
        }
        List<String> amosUserIds = hygfIcbcRecords.stream().map(HygfIcbcRecordDTO::getAmosUserId)
                .collect(Collectors.toList());
        List<PeasantHousehold> peasantHouseholds = peasantHouseholdService.lambdaQuery()
                .select(PeasantHousehold::getAmosUserId, PeasantHousehold::getRegionalCompaniesName,
                        PeasantHousehold::getOwnersName, PeasantHousehold::getIdCard, PeasantHousehold::getTelephone)
                .in(PeasantHousehold::getAmosUserId, amosUserIds).list();
        Map<String, List<PeasantHousehold>> PeasantHouseholdMap = peasantHouseholds.stream()
                .collect(Collectors.groupingBy(PeasantHousehold::getAmosUserId));// 根据农户 ID 分组
        return hygfIcbcRecords.stream().map(hygfIcbcRecordDTO -> {
            hygfIcbcRecordDTO.setOpenAccountStatusName(IcbcEnum.OpenAccountState.getNameByCode(
                    hygfIcbcRecordDTO.getOpenAccountStatus(), IcbcEnum.OpenAccountState.INITIAL.getName()));
            hygfIcbcRecordDTO.setProtocolStatusName(
                    IcbcEnum.ProtocolStatus.getNameByCode(hygfIcbcRecordDTO.getProtocolStatus(), ""));
            List<PeasantHousehold> peasantHouseholdList = PeasantHouseholdMap.get(hygfIcbcRecordDTO.getAmosUserId());
//			if (IcbcEnum.OpenAccountState.FAIL.getCode().equals(hygfIcbcRecordDTO.getOpenAccountStatus())) {
//				hygfIcbcRecordDTO.setCustName(peasantHouseholds.get(0).getOwnersName());
//				hygfIcbcRecordDTO.setIdCard(peasantHouseholds.get(0).getIdCard());
//				hygfIcbcRecordDTO.setPhone(peasantHouseholds.get(0).getTelephone());
//			}
            if (!CollectionUtils.isEmpty(peasantHouseholdList)) {
                // 根据区域经销商名称去重
                List<HygfIcbcRecordDTO.IcbcPeasantHousehold> icbcPeasantHouseholds = Bean.toModels(peasantHouseholdList,
                        HygfIcbcRecordDTO.IcbcPeasantHousehold.class);
                hygfIcbcRecordDTO.setPeasantHouseholds(icbcPeasantHouseholds.stream()
                        .filter(distinctByKey(HygfIcbcRecordDTO.IcbcPeasantHousehold::getRegionalCompaniesName))
                        .collect(Collectors.toList()));
            }
            return hygfIcbcRecordDTO;
        }).collect(Collectors.toList());
    }

    /**
     * 验签方法
     *
     * @param request
     * @param path
     * @return
     * @throws Exception
     */
    private boolean verifySignData(HttpServletRequest request, String path) throws Exception {
        // 网关公钥
        Map<String, String> params = new HashMap<>();
        String api = request.getParameter("api");
        String from = request.getParameter("from");
        String app_id = request.getParameter("app_id");
        String charset = request.getParameter("charset");
        String format = request.getParameter("format");
        String encrypt_type = request.getParameter("encrypt_type");
        String timestamp = request.getParameter("timestamp");
        String biz_content = request.getParameter("biz_content");
        String sign_type = request.getParameter("sign_type");
        String sign = request.getParameter("sign");
        log.info(
                "户用光伏开户签约异步通知, 入参，from：[[{}]], api：[[{}]], app_id：[[{}]], charset：[[{}]], format：[[{}]], encrypt_type：[[{}]], timestamp：[[{}]], biz_content：[[{}]], sign_type：[[{}]], sign：[[{}]]",
                from, api, app_id, charset, format, encrypt_type);
        params.put("from", from);
        params.put("api", api);
        params.put("app_id", app_id);
        params.put("charset", charset);
        params.put("format", format);
        params.put("encrypt_type", encrypt_type);
        params.put("timestamp", timestamp);
        params.put("biz_content", biz_content);
        params.put("sign_type", sign_type);// 目前上行网关签名暂时仅支持RSA
        /********** 验证工行上行网关RSA签名 **********/
        String signStr = WebUtils.buildOrderedSignStr(path, params);
        log.info("验签入参，signStr：[[{}]], sign_type：[[{}]], APIGW_PUBLIC_KEY： [[{}]],charset：[[{}]],sign：[[{}]]", signStr,
                sign_type, APIGW_PUBLIC_KEY, charset, sign);
        boolean flag = IcbcSignature.verify(signStr, sign_type, APIGW_PUBLIC_KEY, charset, sign);
        log.info("验签结果：[[{}]]", flag);
        return flag;
    }

    /**
     * 加签方法
     *
     * @param request
     * @param copReturnCode
     * @param copReturnMsg
     * @return
     * @throws Exception
     */
    private String sign(HttpServletRequest request, String copReturnCode, String copReturnMsg) throws Exception {
        String msg_id = new SimpleDateFormat("yyyyMMdd").format(new Date())
                + new SimpleDateFormat("HHmmss").format(new Date());
        String responseBizContent = "{\"return_code\":\"" + copReturnCode + "\",\"return_msg\":\"" + copReturnMsg + "\""
                + ",\"msg_id\":\"" + msg_id + "\"}";
        String charset = request.getParameter("charset");// 调用过程使用的编码格式
        /**********
         * 商户对消息返回响应进行签名，签名方式需与在API平台登记APP的sign_type保持一致(目前基本都是RSA2)
         **********/
        // String signType = IcbcConstants.SIGN_TYPE_RSA2;
        String signType = IcbcConstants.SIGN_TYPE_RSA;
        String signStr = "\"response_biz_content\":" + responseBizContent + "," + "\"sign_type\":" + "\"" + signType
                + "\"";
        String signParam = IcbcSignature.sign(signStr, signType, MY_PRIVATE_KEY, charset);
        String returnJson = "{\"response_biz_content\":" + responseBizContent + ",\"sign_type\":\"" + signType + "\""
                + ",\"sign\":\"" + signParam + "\"}";
        return returnJson;
    }

    /**
     * base64Decode
     *
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     */
    public String base64Decode(String str) throws UnsupportedEncodingException {
        if (str == null || "".equals(str)) {
            return "";
        }
        char[] ch = str.toCharArray();
        byte[] bt = Base64.getDecoder().decode(String.valueOf(ch));
        return new String(bt, "UTF-8");
    }

    public static <T> Predicate<T> distinctByKey(Function<? super T, Object> distinctField) {
        Map<Object, Boolean> distinctMap = new ConcurrentHashMap<>();
        return object -> distinctMap.putIfAbsent(distinctField.apply(object), Boolean.TRUE) == null;
    }

    public String repair(String userId) {
        JftApiUserEntrustopenacctQueryResponseV1 hygfIcbcWalletInfo = getHygfIcbcWalletInfo(userId);
        PeasantHousehold peasantHousehold = peasantHouseholdService.lambdaQuery().select(PeasantHousehold::getTelephone)
                .eq(PeasantHousehold::getAmosUserId, userId).last("limit 1").one();
        HygfIcbcRecord hygfIcbcRecord = this.lambdaQuery().eq(HygfIcbcRecord::getAmosUserId, userId).last(" limit 1")
                .one();
        if (hygfIcbcRecord == null) {
            hygfIcbcRecord = new HygfIcbcRecord();
        }
        if (hygfIcbcWalletInfo != null) {
            hygfIcbcRecord.setPhone(peasantHousehold != null ? peasantHousehold.getTelephone() : "");
            hygfIcbcRecord.setMediumId(hygfIcbcWalletInfo.getMediumId());
            hygfIcbcRecord.setProjectId("PJ140014023565102203");
            hygfIcbcRecord.setOpenAccountStatus(hygfIcbcWalletInfo.getOpenacctStatus());
            hygfIcbcRecord.setSignEntrsutPrtlStatus("1");
            hygfIcbcRecord.setCustName(hygfIcbcWalletInfo.getCustName());
            hygfIcbcRecord.setIdCard(hygfIcbcWalletInfo.getCertNo());
            hygfIcbcRecord.setProtocolStatus(hygfIcbcWalletInfo.getProtocolStatus());
            hygfIcbcRecord.setProtocolStartTime(hygfIcbcWalletInfo.getProtocolStartDate());
            hygfIcbcRecord.setProtocolEndTime(hygfIcbcWalletInfo.getProtocolEndDate());
            hygfIcbcRecord.setTrxLimitAmount(hygfIcbcWalletInfo.getTrxLimitAmount());
            hygfIcbcRecord.setDayLimitAmount(hygfIcbcWalletInfo.getDayLimitAmount());
            hygfIcbcRecord.setProtocolLimitAmount(hygfIcbcWalletInfo.getProtocolLimitAmount());
            hygfIcbcRecord.setAppId(hygfIcbcWalletInfo.getAppId());
            hygfIcbcRecord.setOutUserId(hygfIcbcWalletInfo.getOutUserId());
            hygfIcbcRecord.setOutVendorId(hygfIcbcWalletInfo.getOutVendorId());
        } else {
            return "开卡信息不存在";
        }
        // hygfIcbcRecord.setDiscardStatus();
        hygfIcbcRecord.setAmosUserId(userId);
        hygfIcbcRecord.setRecDate(new Date());

        this.saveOrUpdate(hygfIcbcRecord);

        return "success";
    }


    public Map<String, Long> exportTotal(String developerCode, String regionalCompaniesCode, String province, String city, String district) {

        List<HygfIcbcRecordExportDTO> dtos = hygfIcbcRecordMapper.exportTotal(developerCode, regionalCompaniesCode, province, city, district);
        Map<String, Long> collect = dtos.stream()
                .collect(Collectors.groupingBy(HygfIcbcRecordExportDTO::getOpenAccountStatus, Collectors.counting()));

        String[] strings = {"开户失败", "开户成功", "未开户"};
        List<String> names = Arrays.asList(strings);
        for (String name : names) {
            if (!collect.keySet().contains(name)) {
                collect.put(name, 0L);
            }
        }


        // 根据 openAccountStatus 分组统计
        return collect;

    }

    public void exportData(HttpServletResponse response, String developerCode, String regionalCompaniesCode, String province, String city, String district) {

        List<HygfIcbcRecordExportDTO> dtos = hygfIcbcRecordMapper.exportTotal(developerCode, regionalCompaniesCode, province, city, district);

        if (CollectionUtil.isNotEmpty(dtos)) {
            ExcelUtil.createTemplate(response, "开卡统计", "开卡统计", dtos, HygfIcbcRecordExportDTO.class, null, false);
        }

    }


    public void exportExcel(HttpServletResponse response, HygfIcbcRecordQueryDTO hygfIcbcRecordQueryDTO) throws ExecutionException, InterruptedException {
        List<HygfIcbcRecordExportDTO> hygfIcbcRecordExportDTOS = hygfIcbcRecordMapper.paymentAmountExport(hygfIcbcRecordQueryDTO);
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        for(HygfIcbcRecordExportDTO dto : hygfIcbcRecordExportDTOS)
        {
            if(dto.getMediumId()!=null&&"二类卡".equals(dto.getType()))
            {
                //并发处理
                CompletableFuture<Void> fan = CompletableFuture.supplyAsync(() -> {
                    SettlementAccountBalanceQueryResponseV1 res= (SettlementAccountBalanceQueryResponseV1) this.balanceQuery(dto.getMediumId());
                    if(res.isSuccess())
                    {
                        dto.setAccountBalance(String.valueOf(Integer.parseInt(res.getAccountBalance())/100.0));
                    }else
                    {
                        dto.setAccountBalance(res.getReturnMsg());
                    }
                    return null;
                });
                futures.add(fan);
            }
        }

        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get();
        if (CollectionUtil.isNotEmpty(hygfIcbcRecordExportDTOS)) {
            ExcelUtil.createTemplate(response, "账号信息", "账号信息", hygfIcbcRecordExportDTOS, HygfIcbcRecordExportDTO.class, null, false);
        }
    }

    public Object signVerifyCode(String phone, String mediumId) {
		PeasantHousehold peasantHousehold=peasantHouseholdService
				.getOne(new LambdaQueryWrapper<PeasantHousehold>().eq(PeasantHousehold::getTelephone,phone).last("LIMIT 1"));
		if(peasantHousehold==null)
		{
           return "农户不存在";
		}
//        PeasantHousehold peasantHousehold = new PeasantHousehold();
//        peasantHousehold.setAmosUserId("890728");
//        peasantHousehold.setOwnersName("吴江");
//        peasantHousehold.setIdCard("61010319890728203X");
        String apiUrl = serviceUrl + "/api/jft/api/user/entrust/send/verify/code/V1";
        DefaultIcbcClient client = new DefaultIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY,
                IcbcConstants.CHARSET_UTF8, IcbcConstants.FORMAT_JSON, APIGW_PUBLIC_KEY, IcbcConstants.ENCRYPT_TYPE_AES,
                AES_Key, "", "");
        JftUserEntrustprtlMobileVerifyRequestV1 request = new
                JftUserEntrustprtlMobileVerifyRequestV1();
        //4、根据测试环境和生产环境替换相应ip和端口
        request.setServiceUrl(apiUrl);
        //5、请对照接口文档用bizContent.setxxx()方法对业务上送数据进行赋值
        JftUserEntrustprtlMobileVerifyRequestV1.JftUserEntrustprtlMobileVerifyRequestV1Biz bizContent = new
                JftUserEntrustprtlMobileVerifyRequestV1.JftUserEntrustprtlMobileVerifyRequestV1Biz();
        bizContent.setAppId(APP_ID);
        bizContent.setOutVendorId(OUT_VENDOR_ID);
        bizContent.setMobile(phone);
        bizContent.setAccountName(peasantHousehold.getOwnersName());
        bizContent.setAccountNo(mediumId);
        bizContent.setIdType("0");
        bizContent.setIdNo(peasantHousehold.getIdCard());
        bizContent.setTrxType("01");
        bizContent.setProjectId(PROJECT_ID);
        bizContent.setTextSerno("09");
        bizContent.setProtocolLimitAmount("20000000");//单位分，不要带小数，非必输
        //bizContent.setSmsNote("自定义备注内容");//短信会显示：XXXXXXXX，备注：自定义备注内容
        request.setBizContent(bizContent);
        JftUserEntrustprtlMobileVerifyResponseV1 response = null;
        try {
            log.info("聚富通委托代扣签约验证码, 入参 => {}", JSON.toJSONString(request));
            response = (JftUserEntrustprtlMobileVerifyResponseV1)
                    client.execute(request, System.currentTimeMillis() + "");
            log.info("聚富通委托代扣签约验证码, 出参 => {}", JSON.toJSONString(response));
            //msgId消息通讯唯一编号，要求每次调用独立生成，APP级唯一
            if (response.isSuccess()) {
                //6、业务成功处理，请根据接口文档用response.getxxx()获取同步返回的业务数据
                System.out.println("ReturnCode:" + response.getReturnCode());
                System.out.println("response:" + response);
            } else {
                //失败
                System.out.println("ReturnCode:" + response.getReturnCode());
                System.out.println("ReturnMsg:" + response.getReturnMsg());
            }
        } catch (IcbcApiException e) {
            e.printStackTrace();
        }
        return response;
    }

    public Object signProtocol(HygfIcbcSignProtocolDTO hygfIcbcSignProtocolDTO) {
		PeasantHousehold peasantHousehold=peasantHouseholdService
				.getOne(new LambdaQueryWrapper<PeasantHousehold>().eq(PeasantHousehold::getTelephone,hygfIcbcSignProtocolDTO.getPhone()).last("LIMIT 1"));
		if(peasantHousehold==null)
		{
           return "农户不存在";
		}
//        PeasantHousehold peasantHousehold = new PeasantHousehold();
//        peasantHousehold.setAmosUserId("890728");
//        peasantHousehold.setOwnersName("吴江");
//        peasantHousehold.setIdCard("61010319890728203X");
        DefaultIcbcClient client = new DefaultIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY,
                IcbcConstants.CHARSET_UTF8, IcbcConstants.FORMAT_JSON, APIGW_PUBLIC_KEY, IcbcConstants.ENCRYPT_TYPE_AES,
                AES_Key, "", "");
        JftUserEntrustprtlMngRequestV1 request = new JftUserEntrustprtlMngRequestV1();
        //4、根据测试环境和生产环境替换相应ip和端口######8
        // 请求示例委托代扣协议签约示例
        //String apiUrl=serviceUrl+"/api/jft/api/vendor/rescind/user/protocol/V1";
        String apiUrl = serviceUrl + "/api/jft/api/user/entrust/protocol/mng/V1";
        request.setServiceUrl(apiUrl);
        //5、请对照接口文档用bizContent.setxxx()方法对业务上送数据进行赋值
        JftUserEntrustprtlMngRequestV1.JftUserEntrustprtlMngRequestV1Biz bizContent = new JftUserEntrustprtlMngRequestV1.JftUserEntrustprtlMngRequestV1Biz();
        bizContent.setAppId(APP_ID);
        bizContent.setOutVendorId(OUT_VENDOR_ID);
        bizContent.setSrVid(hygfIcbcSignProtocolDTO.getSrVid());
        if (hygfIcbcSignProtocolDTO.isCancel())//0签约 2解约
        {
            bizContent.setDealFlag("2");
        } else {
            bizContent.setDealFlag("0");
        }
        bizContent.setProjectId(PROJECT_ID);
        String busiCode = "y"+peasantHousehold.getAmosUserId();
        bizContent.setBusiCode(busiCode);
        bizContent.setBankNo("102");//102默认工行
        bizContent.setAccountNo(hygfIcbcSignProtocolDTO.getMediumId());
        bizContent.setAccountName(peasantHousehold.getOwnersName());
        bizContent.setMobile(hygfIcbcSignProtocolDTO.getPhone());
        bizContent.setVerifyCode(hygfIcbcSignProtocolDTO.getVerifyCode());
        bizContent.setSendNo(hygfIcbcSignProtocolDTO.getSendNo());
        bizContent.setIdType("0");
        bizContent.setIdNo(peasantHousehold.getIdCard());
        LocalDate today = LocalDate.now();
        LocalDate nextYearToday = today.plusYears(25);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formattedDate = nextYearToday.format(formatter);
        bizContent.setProtocolEndDate(formattedDate);
        bizContent.setProtocolLimitAmount("2500000000");
        //bizContent.setCvn2("463");
        //bizContent.setExpired("2002");
        bizContent.setBankFlag("0");//0工行卡 1其他行卡
        //bizContent.setQueryItem1("");
        //bizContent.setQueryItem15("");
        request.setBizContent(bizContent);
        JftUserEntrustprtlMngResponseV1 response = null;
        try {
            response = (JftUserEntrustprtlMngResponseV1) client.execute(request,
                    System.currentTimeMillis() + "");
            //msgId消息通讯唯一编号，要求每次调用独立生成，APP级唯一
            if (response.isSuccess()) {
                //6、业务成功处理，请根据接口文档用response.getxxx()获取同步返回的业务数据
                System.out.println("ReturnCode:" + response.getReturnCode());
                System.out.println("response:" + response);
                if (hygfIcbcSignProtocolDTO.isCancel())//0签约 2解约
                {
                    this.remove(new LambdaQueryWrapper<HygfIcbcRecord>().eq(HygfIcbcRecord::getAmosUserId,peasantHousehold.getAmosUserId()));
                } else {
                    HygfIcbcRecord hygfIcbcRecord = new HygfIcbcRecord();
                    hygfIcbcRecord.setPhone(hygfIcbcSignProtocolDTO.getPhone());
                    hygfIcbcRecord.setMediumId(hygfIcbcSignProtocolDTO.getMediumId());
                    hygfIcbcRecord.setProjectId(PROJECT_ID);
                    hygfIcbcRecord.setOpenAccountStatus("02");
                    hygfIcbcRecord.setSignEntrsutPrtlStatus("1");
                    hygfIcbcRecord.setCustName(peasantHousehold.getOwnersName());
                    hygfIcbcRecord.setIdCard(peasantHousehold.getIdCard());
                    hygfIcbcRecord.setType("一类卡");
                    hygfIcbcRecord.setAppId(APP_ID);
                    hygfIcbcRecord.setOutVendorId(OUT_VENDOR_ID);
                    hygfIcbcRecord.setOutUserId(busiCode);
                    hygfIcbcRecord.setAmosUserId(peasantHousehold.getAmosUserId());
                    this.saveOrUpdate(hygfIcbcRecord);
                    JftUserEntrustprtlQueryResponseV1 prt = (JftUserEntrustprtlQueryResponseV1) signQuery(busiCode);
                    if(prt.isSuccess()&&prt.getReturnCode()==0)
                    {
                        hygfIcbcRecord.setProtocolStatus(prt.getPrtlStatus());
                        hygfIcbcRecord.setProtocolStartTime(prt.getPrtlStartDate());
                        hygfIcbcRecord.setProtocolEndTime(prt.getPrtlEndDate());
                        hygfIcbcRecord.setTrxLimitAmount(String.valueOf(prt.getTrxLmtAmt()));
                        hygfIcbcRecord.setDayLimitAmount(String.valueOf(prt.getDayLmtAmt()));
                        hygfIcbcRecord.setProtocolLimitAmount(String.valueOf(prt.getPrtlLmtAmt()));
                    }
                    this.saveOrUpdate(hygfIcbcRecord);
                }
            } else {
                //失败
                System.out.println("ReturnCode:" + response.getReturnCode());
                System.out.println("ReturnMsg:" + response.getReturnMsg());
            }
        } catch (IcbcApiException e) {
            e.printStackTrace();
        }
        return response;
    }

    public Object signQuery(String busiCode) {
        String apiUrl = serviceUrl + "/api/jft/api/user/entrust/protocol/query/V1";
        DefaultIcbcClient client = new DefaultIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY,
                IcbcConstants.CHARSET_UTF8, IcbcConstants.FORMAT_JSON, APIGW_PUBLIC_KEY, IcbcConstants.ENCRYPT_TYPE_AES,
                AES_Key, "", "");
        JftUserEntrustprtlQueryRequestV1 request = new JftUserEntrustprtlQueryRequestV1();
        //4、根据测试环境和生产环境替换相应ip和端口
        request.setServiceUrl(apiUrl);
        //5、请对照接口文档用bizContent.setxxx()方法对业务上送数据进行赋值
        JftUserEntrustprtlQueryRequestV1.JftUserEntrustprtlQueryRequestV1Biz bizContent = new JftUserEntrustprtlQueryRequestV1.JftUserEntrustprtlQueryRequestV1Biz();
        bizContent.setAppId(APP_ID);
        bizContent.setOutVendorId(OUT_VENDOR_ID);
        bizContent.setChannelType("303");//303-手机，302-pc
        bizContent.setBizZone("00200");//00200（需要和分行人员确定）
        LocalDateTime today = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formattedDate = today.format(formatter);
        bizContent.setTrxDate(formattedDate);
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("HH:mm:ss");
        String formattedTime = today.format(formatter2);
        bizContent.setTrxTime(formattedTime);
        bizContent.setProjectId(PROJECT_ID);
        bizContent.setBusiCode(busiCode);
        //bizContent.setNewPayAcc("9558870200001260273");
        //bizContent.setQueryItem1("");
        //bizContent.setQueryItem15("");
        request.setBizContent(bizContent);
        JftUserEntrustprtlQueryResponseV1 response = null;
        try {
            response = (JftUserEntrustprtlQueryResponseV1)
                    client.execute(request, System.currentTimeMillis() + "");
            //msgId消息通讯唯一编号，要求每次调用独立生成，APP级唯一
            if (response.isSuccess()) {
                //6、业务成功处理，请根据接口文档用response.getxxx()获取同步返回的业务数据
                System.out.println("ReturnCode:" + response.getReturnCode());
                System.out.println("response:" + response);
            } else {//失败
                System.out.println("ReturnCode:" + response.getReturnCode());
                System.out.println("ReturnMsg:" + response.getReturnMsg());
            }
        } catch (IcbcApiException e) {
            e.printStackTrace();
        }
        return response;
    }

    public Object balanceQuery(String mediumId) {


        DefaultIcbcClient client = new DefaultIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY,
                IcbcConstants.CHARSET_UTF8, IcbcConstants.FORMAT_JSON, APIGW_PUBLIC_KEY, IcbcConstants.ENCRYPT_TYPE_AES,
                AES_Key, "", "");
        SettlementAccountBalanceQueryRequestV1 request = new SettlementAccountBalanceQueryRequestV1();
        String apiUrl = serviceUrl + "/api/settlement/account/balance/V1/query";
       // String apiUrl = serviceUrl + "/api/settlement/ /balance/query/V2";
        request.setServiceUrl(apiUrl);
        SettlementAccountBalanceQueryRequestV1.SettlementAccountBalanceQueryRequestV1Biz bizContent = new SettlementAccountBalanceQueryRequestV1.SettlementAccountBalanceQueryRequestV1Biz();
        bizContent.setCorpNo(corpNo);//合作方机构编号
        LocalDateTime today = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formattedDate = today.format(formatter);
        bizContent.setTrxAccDate(formattedDate);
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("HH:mm:ss");
        String formattedTime = today.format(formatter2);
        bizContent.setTrxAccTime(formattedTime);
        bizContent.setCorpSerno(String.valueOf(System.currentTimeMillis()));//合作方交易单号
        bizContent.setCorpDate(formattedDate);//合作方工作日期
        bizContent.setOutServiceCode("querybalance");//外部服务代码
        //String encodedString = Base64.getEncoder().encodeToString(mediumId.getBytes());
        //生成sm4密钥
        //String origSecretKey = UtilIcbc.getNonceStr(16);
        String origSecretKey ="1234567890123456";
        String secretKey = UtilIcbc.getHexString(origSecretKey.getBytes());
        SM4Utils.secretKey = secretKey;
        SM4Utils.hexString = true;
        SM4Utils.iv = "00000000000000000000000000000000";
        //生成sm2加密后的sm4公钥
        String sm4SecretKey = null;
        try {
           sm4SecretKey = SM2Utils.encrypt(UtilIcbc.hexToByte("04"+CAMS_PUBLIC_KEY), origSecretKey.getBytes());
          //  sm4SecretKey = SM2Utils.encrypt(UtilIcbc.hexToByte(SM2_PUBLIC_KEY), origSecretKey.getBytes());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  sm4SecretKey= Sm2Util.encryptBase64(origSecretKey,"04"+CAMS_PUBLIC_KEY);
        //私钥解密
        //String des =  Sm2Util.decryptBase64(sm4SecretKey,SM2_PRIVATE_KEY);
        //涉密信息如身份证号，姓名，卡号都需要用sm4密钥进行加密
        bizContent.setMediumId(SM4Utils.encryptData_CBC(mediumId)); //工行联名卡号
        bizContent.setCcy(1); //币种,1
        bizContent.setSecretKey(sm4SecretKey);
        request.setBizContent(bizContent);
        SettlementAccountBalanceQueryResponseV1 response = null;
        try {
            log.info("工行卡查询余额, 入参 => {}", JSON.toJSONString(request));
            response = client.execute(request, "msgId");
            if (response.isSuccess() && response.getReturnCode() == 0) {
                //业务成功处理
                System.out.println(response.getAccountBalance());//
                System.out.println(response.getHoldBalance());//
            } else {
                // 失败
                System.err.println(response.getReturnCode());//
                System.err.println(response.getReturnMsg());//
            }
        } catch (IcbcApiException e) {
            throw new RuntimeException(e);
        }
        return response;
    }

    public Object balanceQueryByUserId(String id)
    {
        HygfIcbcRecord hygfIcbcRecord = this.getOne(new LambdaQueryWrapper<HygfIcbcRecord>().eq(HygfIcbcRecord::getOutUserId,id));
        if(hygfIcbcRecord!=null)
        {
            SettlementAccountBalanceQueryResponseV1 response = (SettlementAccountBalanceQueryResponseV1) balanceQuery(hygfIcbcRecord.getMediumId());
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(response));
            jsonObject.put("custName",hygfIcbcRecord.getCustName());
            jsonObject.put("mediumId",hygfIcbcRecord.getMediumId());
            jsonObject.put("accountBalanceYuan",String.valueOf(Integer.parseInt(response.getAccountBalance())/100.0));
            return jsonObject;
        }else
        {
            return null;
        }
    }

    public Object delRecordByUserId(String id)
    {
      return this.remove(new LambdaQueryWrapper<HygfIcbcRecord>().eq(HygfIcbcRecord::getOutUserId,id));
    }
}