const system = require("../../system");
var settings = require("../../../config/settings");
const ServiceBase = require("../sve.base");
const logCtl = system.getObject("web.oplogCtl");

const moment = require('moment');
const crypto = require('crypto');
const cryptoJS = require("crypto-js");
const md5 = require("MD5");

class EcontractService extends ServiceBase {
    constructor() {
        super(ServiceBase.getDaoName(EcontractService));
        this.etemplateSve = system.getObject("service.etemplateSve");
        this.etemplateDao = system.getObject("db.etemplateDao");
        this.ecompanyDao = system.getObject("db.ecompanyDao");
        this.usereaccountDao = system.getObject("db.usereaccountDao")
        this.utilesignbaoSve = system.getObject("service.utilesignbaoSve");
        this.ejobapplyDao = system.getObject("db.ejobapplyDao");
        this.emessageDao = system.getObject("db.emessageDao");
        this.ecompanybusiDao = system.getObject("db.ecompanybusiDao");
        this.userDao = system.getObject("db.userDao");

        this.bankthreelogDao = system.getObject("db.bankthreelogDao");

        this.esealSve = system.getObject("service.esealSve");

        this.ejobapplySve = system.getObject("service.ejobapplySve");

        this.restClient = system.getObject("util.restClient");
        this.maindict = system.getObject("util.maindict");

        this.eSignBaoRedirectBossUrl = settings.apiconfig.eSignBaoRedirectBossUrl();

        this.redisClient = system.getObject("util.redisClient");

        this.utillbwSve = system.getObject("service.utillbwSve");

        this.idauthlogDao  = system.getObject("db.idauthlogDao")

        this.ydCompanyIds = [
            10173,
            10174,
            10175,
            10207,
            10868
        ];
    }

    async saveOffline(obj) {
        var ecompanyName = obj.ecompanyName;
        var ecompany_id = obj.ecompany_id;
        var userName = obj.userName;
        var mobile = obj.mobile;
        var personsSign = obj.personsSign;
        var bankno = obj.bankno;
        var fileurl = obj.fileurl;

        // 创建account
        var account = await this.usereaccountDao.findOne({
            personsSign: personsSign
        }) || {};
        account.userName = userName;
        account.mobile = mobile;
        account.bankno = bankno;
        account.personsSign = personsSign;
        if (account.id) {
            await account.save();
        } else {
            account.user_id = 0;
            account = await this.usereaccountDao.create(account);
        }

        var now = moment();
        var end = moment().add(1, "years");


        // 创建合同
        var contract = {
            name: ecompanyName,
            fileurl: fileurl,
            eflowstatusname: "已完成",
            eflowstatus: "2",
            begin_at: now,
            completed_at: now,
            user_id: account.user_id,
            usereaccount_id: account.id,
            etemplate_id: 0,
            ecompany_id: ecompany_id,
            end_at: end,
        }

        contract = await this.create(contract);
        this.syncContract(contract.id);
        return contract.id;
    }

    async autoSaveOffline(obj) {
        var ecompany = {};
        //获取模板相关的信息
        var etemplate = await this.etemplateSve.getInfo(obj.etemplate_id);
        var ecompany = await this.ecompanyDao.findById(etemplate.ecompany_id);
        var ecompanyName = ecompany.name || "";
        var ecompany_id = ecompany.id || 0;

        var now = moment();
        var end = moment().add(1, "years");

        var errorItems = [];
        // 循环上传的excle4要素集合
        for (var item in obj.autoExcel) {
            try {
                var userName = obj.autoExcel[item]['name'];
                var mobile = obj.autoExcel[item]['phone'];
                var personsSign = obj.autoExcel[item]['id_card'];
                var bankno = obj.autoExcel[item]['bank_no'];

                // 根据身份证号，获取相应的account
                var account = await this.usereaccountDao.findOne({
                    personsSign: personsSign
                }) || {};

                //是否需要电子签约
                var isNeedCreate = true;
                if (account) {
                    isNeedCreate = !account.eaccountid || userName != account.userName || account.mobile != mobile || account.bankno != bankno;
                }

                account.userName = userName;
                account.mobile = mobile;
                account.bankno = bankno;
                account.personsSign = personsSign;
                if (account.id) {
                    // 验证是否已经签约过
                    var signdContract = await this.dao.findOne({
                        usereaccount_id: account.id,
                        etemplate_id: etemplate.id,
                        eflowstatus: '2'
                    });
                    if (signdContract) {
                        errorItems.push(userName + "-已签约");
                        continue;
                    }
                } else {
                    // TODO 创建p_user
                    account.user_id = 0;
                    account = await this.usereaccountDao.create(account);
                }

                let banklog = await this.bankthreelogDao.findOne({
                    userName: account.userName,
                    userIdNo: account.personsSign,
                    userBankNo: account.bankno,
                    result: 1,
                });
                if (!banklog) {
                    var bankthreeParams = {
                        name: account.userName,
                        idno: account.personsSign,
                        cardno: account.bankno
                    };

                    var threeResult = await this.utilesignbaoSve.bankthree(bankthreeParams, "bankinfoAuth");
                    // {"code":-110,"message":"手机号格式错误","data":{}}
                    //1成功,-110提示验证信息有误，-120亲，提供的信息不正确，请验证后再试！
                    console.log("threeResult-----------------------------", threeResult);
                    if (!threeResult || threeResult.code == -120) {
                        return this.returnjson(-1, "银行三要素（姓名、身份证、银行卡号）验证失败");
                    }
                    if (threeResult.code == -110) {
                        return this.returnjson(-1, "银行三要素验证失败");
                    }
                }

                // isNeedCreate = false;
                if (isNeedCreate) {
                    var uidStr = await this.getUidStr(8, 36);
                    var thirdId = etemplate.id + "_" + account.id + uidStr;

                    //2.创建e签宝account 5.2.1 , 创建后save()
                    var params = {
                        thirdId: thirdId,
                        name: userName,
                        idNo: personsSign,
                        idType: 19,
                        mobile: mobile
                    };
                    var getAccount = await this.utilesignbaoSve.createAccountId(params, "econtractSve");
                    if (getAccount && getAccount.code == 1 && getAccount.data) {
                        account.eaccountid = getAccount.data.accountId;
                        await account.save();
                    } else {
                        errorItems.push(userName + "-e签宝账户创建失败");
                        continue;
                    }
                }

                //3.设置静默签署授权 5.2.5
                if (!account.isGrantAuto) {
                    var paramsGrant = {
                        grantAccountId: account.eaccountid
                    };
                    var grantAuto = await this.utilesignbaoSve.grantAuthorization(paramsGrant, "econtractSve");
                    if (grantAuto.code != 1) {
                        errorItems.push(userName + "-静默签署设置失败");
                        continue;
                    }
                    account.isGrantAuto = true;
                    await account.save();
                }

                //------------------------------------------------
                var resultAll = {
                    code: 1,
                    message: "success",
                    data: {}
                };

                // 创建合同   fileurl、esignUrl 怎么赋值????????????
                var contract = {
                    name: ecompanyName,
                    eflowstatusname: "签约中",
                    eflowstatus: "1",
                    // begin_at: now,
                    // completed_at: now,
                    user_id: account.user_id,
                    usereaccount_id: account.id,
                    etemplate_id: obj.etemplate_id,
                    ecompany_id: ecompany_id,
                    // end_at: end,
                }
                contract = await this.create(contract);

                // 创建印章id
                var sealId = "";
                var eseal = await this.esealSve.findOne({
                    nameA: etemplate.nameA
                });
                // TODO 生产环境需要打开
                if (!eseal) {
                    var rs = await this.utilesignbaoSve.creatEntSignet(settings.apiconfig.companyAccountId(), etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
                    if (rs && rs.code == 1) {
                        sealId = rs.data.sealId;
                        await this.esealSve.create({
                            nameA: etemplate.nameA,
                            sealId: sealId,
                        });
                    } else {
                        errorItems.push(userName + "-生成印章错误");
                        continue;
                    }
                } else {
                    sealId = eseal.sealId;
                }

                let today = new Date().Format("yyyy-MM-dd");
                var signParams = {
                    templateId: etemplate.templateid, //模板id，由创建模板接口调用返回的templateId 必填
                    name: ecompany.name, //合同模板名称 必填
                    simpleFormFields: {
                        nameA: etemplate.nameA, //甲方 必填
                        nameB: account.userName, //乙方 必填
                        unit: ecompany.name, //合作单位（国美） 必填---------------------------超出长度风险---目前不知多少长度
                        signDateA: today, //甲方签约日期 必填
                        signDateB: today //乙方签约日期 必填
                    }
                }
                var ebaoAccountId = account.eaccountid; //签署人账户id-- 必填
                var thirdOrderNo = contract.id; //第三方流水号，通知回调使用---选填
                var eBaoRedirectBossUrl = "";

                var tt = await this.utilesignbaoSve.userAutoSignContractNoTemplate(signParams, ebaoAccountId, thirdOrderNo, eBaoRedirectBossUrl, "econtractSve", sealId);
                if (tt && tt.data && tt.code == 1) {
                    contract.eflowid = tt.data.flowId;
                    contract.edocid = tt.data.docId;
                    contract.eflowstatus = '2';
                    contract.eflowstatusname = "已完成";

                    var signTime = new Date();
                    contract.completed_at = signTime;
                    contract.begin_at = signTime;
                    var end_at = new Date();
                    end_at.setFullYear(end_at.getFullYear() + 1);
                    contract.end_at = end_at;

                    contract.save();
                    // TODO DOWNLOAD OK
                    this.redisClient.rpushBCD({id: contract.id, sve: "e"});
                    // }

                }

            } catch (error) {
                console.log(error.message);
                continue;
            }
        }

        if (errorItems.length > 0) {
            var errors = "";
            for (var item of errorItems) {
                errors += item + "、";
            }


            return system.getErrResult2(errors.substr(0, errors.length - 1));
        }

        return resultAll;
    }

    async getCount(params) {
        var where = {};
        if (params.ecompanyIds) {
            where.ecompany_id = {
                [this.db.Op.in]: params.ecompanyIds
            };
        }
        let contractCount = await this.findCount(where);
        return contractCount
    }

    async pageByCondition(params) {
        var currentPage = Number(params.currentPage || 0);
        var pageSize = Number(params.pageSize || 10);

        var where = {};

        if (params.ecompanyIds) {
            where.ecompany_id = {
                [this.db.Op.in]: params.ecompanyIds
            };
        }

        if (params.etemplateIds) {
            where.etemplate_id = {
                [this.db.Op.in]: params.etemplateIds
            };
        }

        if (params.ecompany_id) {
            where.ecompany_id = params.ecompany_id;
        }

        if (params.eflowstatusList) {
            where.eflowstatus = {
                [this.db.Op.in]: params.eflowstatusList
            };
        }

        if (params.accountName || params.accountMobile || params.accountIdno) {
            var accountIds = await this.usereaccountDao.idsByCondition({
                userName: params.accountName || "",
                mobile: params.accountMobile || "",
                personsSign: params.accountIdno || "",
            });

            if (!accountIds || accountIds.length == 0) {
                return {
                    total: 0,
                    rows: []
                };
            }

            where.usereaccount_id = {
                [this.db.Op.in]: accountIds
            };
        }
        this.addWhereTime(where, 'completed_at', params.signBegin, params.signEnd, true);

        var orderby = [
            ["id", 'desc']
        ];

        var attributes = [`id`, `fileurl`, `etemplate_id`, `eflowstatus`, `eflowstatusname`, `completed_at`, `end_at`, `user_id`, `usereaccount_id`, `ecompany_id`];

        var page = await this.getPageList(currentPage, pageSize, where, orderby, attributes);
        if (page && page.rows) {
            for (var row of page.rows) {
                this.handleDate(row, ["completed_at", "end_at"], null);
            }
            await this.setEaccount(page.rows);
            await this.setCompany(page.rows);
            await this.setEtemplate(page.rows);
        }
        return page;
    }

    async setEaccount(list) {
        if (!list || list.length == 0) {
            return;
        }

        var ids = [];
        for (var item of list) {
            ids.push(item.usereaccount_id);
        }
        var attrs = " `id`, `mobile`, `userName`, `personsSign`, `bankno` ";
        var accountMap = await this.usereaccountDao.findMapByIds(ids, attrs);

        for (var item of list) {
            item.eaccount = accountMap["id_" + item.usereaccount_id];
        }
    }

    async setCompany(list) {
        if (!list || list.length == 0) {
            return;
        }

        var companyIds = [];
        for (var item of list) {
            companyIds.push(item.ecompany_id || 0);
        }
        var companyMap = await this.ecompanyDao.findMapByIds(companyIds, " id, name, contractMobile ");
        for (var item of list) {
            item.ecompany = companyMap["id_" + (item.ecompany_id || 0)];
        }
    }

    async setEtemplate(list) {
        if (!list || list.length == 0) {
            return;
        }

        var ids = [];
        for (var item of list) {
            ids.push(item.etemplate_id || 0);
        }
        var templateMap = await this.etemplateDao.findMapByIds(ids, " id, nameA ");
        for (var item of list) {
            item.template = templateMap[item.etemplate_id];
        }
    }


    async findInfo(obj) {
        obj = obj || {};
        let v = [{
            model: this.db.models.ecompany,
            attributes: ["id", "name"]
        },
            {
                model: this.db.models.user,
                attributes: ["id", "userName", "mobile"]
            },
            {
                model: this.db.models.usereaccount,
                attributes: ["id", "userName", "mobile", "personsSign"]
            },
            {
                model: this.db.models.etemplate,
                attributes: ["id", "name"]
            }
        ];
        var result = await this.dao.model.findOne({
            where: obj,
            include: v
        });
        return result;
    }

    async findContracts(obj) {
        obj = obj || {};
        let v = [{
            model: this.db.models.ecompany,
            attributes: ["id", "name"]
        },
            {
                model: this.db.models.user,
                attributes: ["id", "userName", "mobile"]
            },
            {
                model: this.db.models.usereaccount,
                attributes: ["id", "userName", "mobile", "personsSign"]
            },
            {
                model: this.db.models.etemplate,
                attributes: ["id", "name"]
            }
        ];
        var result = await this.dao.model.findAll({
            where: obj,
            include: v
        });
        return result;
    }

    async findUserSinedCompanyIds(usereaccount_id) {
        return this.dao.findUserSinedCompanyIds(usereaccount_id);
    }

    async findUserSinedTemplateIds(usereaccount_id) {
        return this.dao.findUserSinedTemplateIds(usereaccount_id);
    }

    async updateCallbackStatus(obj) {
        obj = obj || {};

        logCtl.info({
            optitle: "e签宝回调修改合同信息info",
            op: "app/base/service/impl/econtractSve/updateCallbackStatus",
            content: "请求参数：" + JSON.stringify(obj),
            clientIp: ""
        });

        let contract;
        try {
            let signTime = obj.signTime;
            let signResult = obj.signResult || "1";
            let thirdOrderNo = Number(obj.thirdOrderNo || 0);

            contract = await super.findById(Number(thirdOrderNo));
            if (!contract) {
                return;
            }

            contract.eflowstatus = signResult.toString();
            contract.completed_at = signTime;
            contract.begin_at = signTime;
            contract.resultDescription = obj.resultDescription || "";
            var end_at = new Date(signTime);
            end_at.setFullYear(end_at.getFullYear() + 1);
            contract.end_at = end_at;

            await contract.save();

            if (contract.isInsure) {
                try {
                    // await this.sendInsure(contract.id);
                } catch (error) {
                    logCtl.error({
                        optitle: "调用团险失败，id = " + contract.id,
                        op: "app/base/service/impl/econtractSve/updateCallbackStatus",
                        content: "错误信息：" + e.stack,
                        clientIp: ""
                    });

                }
            }

            if (signResult == "2") {
                // TODO DOWNLOAD OK
                this.redisClient.rpushBCD({id: contract.id, sve: "e"});

                try {
                    this.updateApply(contract.id);
                } catch (error) {
                }

                try {
                    this.syncContract(contract.id);
                } catch (error) {
                }

                try {
                    // 推送签约信息给客户
                    this.syncSign(contract.id);
                } catch (error) {
                }
            }
        } catch (e) {
            logCtl.error({
                optitle: "e签宝回调修改合同信息error",
                op: "app/base/service/impl/econtractSve/updateCallbackStatus",
                content: "错误信息：" + e.stack,
                clientIp: ""
            });
        }
        return contract;
    }

    async sendInsure(id) {
        var contract = await this.dao.findById(id);
        var account = await this.usereaccountDao.findById(contract.usereaccount_id);
        if (!account || !account.userName || !account.personsSign || !account.mobile) {
            return;
        }

        var url = "https://api.baoxianxia.com.cn/api/yxyy/service/insure";

        var params = {
            "type": "B",
            "name": account.userName,
            "cid": account.personsSign.toUpperCase(),
            "mobile": account.mobile,
            "email": account.mobile + "@yxinsur.com",
            "underwrite": "B",
            "period": "7",
            "channel": "gsb",
            "job": "OE"
        }
        console.log(JSON.stringify(params));
        var rs = await this.restClient.execPost(params, url);
        console.log(rs);

        contract.insurecb = rs.stdout;
        await contract.save();
    }

    async syncSign(contractId) {
        var contract = await this.dao.findById(contractId);
        if (!contract) {
            return null;
        }
        var account = await this.usereaccountDao.findById(contract.usereaccount_id);
        if (!account) {
            return null;
        }
        var user = await this.userDao.findById(account.user_id);

        var busi = await this.ecompanybusiDao.findOne({
            etemplate_id: contract.etemplate_id
        });
        if (!account.isPush && busi && busi.postsignurl) {
            var param = {
                "appId": busi.appId,
                "idNo": account.personsSign,
                "idName": account.userName,
                "bankNo": account.bankno,
                "mobile": account.mobile,
                "appId3rd": user.appId3rd || "",
                "userCode3rd": user.userCode3rd || "",
                "userId3rd": user.userId3rd || "",
                "branchCode3rd": user.branchCode3rd || "",
                "nonceStr": await this.getUidStr(16),
                "beginDate": await this.formateTime(contract.begin_at),
                "endDate": await this.formateTime(contract.end_at),
            }
            if (!user.userCode3rd && !user.userId3rd) {
                param.openId = user.openId;
            }
            if (this.ydCompanyIds.indexOf(contract.ecompany_id) > -1) {
                param.pbType = "eSign";
            }

            var signArr = [];
            signArr.push("appId=" + param.appId);
            signArr.push("appId3rd=" + param.appId3rd);
            signArr.push("bankNo=" + param.bankNo);
            signArr.push("beginDate=" + param.beginDate);
            signArr.push("branchCode3rd=" + param.branchCode3rd);
            signArr.push("endDate=" + param.endDate);
            signArr.push("idName=" + param.idName);
            signArr.push("idNo=" + param.idNo);
            signArr.push("mobile=" + param.mobile);
            signArr.push("nonceStr=" + param.nonceStr);
            if (!user.userCode3rd && !user.userId3rd) {
                signArr.push("openId=" + param.openId);
            }
            // if (contract.ecompany_id == 10173 || contract.ecompany_id == 10174 || contract.ecompany_id == 10175 || contract.ecompany_id == 10207) {
            if (this.ydCompanyIds.indexOf(contract.ecompany_id) > -1) {
                signArr.push("pbType=eSign");
            }
            signArr.push("userCode3rd=" + param.userCode3rd);
            signArr.push("userId3rd=" + param.userId3rd);
            signArr.push("key=" + busi.key);

            param.sign = md5(signArr.join("&")).toUpperCase();
            console.log(JSON.stringify(param));
            var rs = "";
            try {
                var rs = await this.restClient.execPost(param, busi.postsignurl);
                if (rs.stdout) {
                    let rsData = JSON.parse(rs.stdout);
                    if (rsData.code == "0" || rsData.code == "0000") {
                        account.isPush = true;
                        account.save();
                    }
                }
                return rs.stdout;
            } catch (error) {
                console.log(rs, "push sign url " + busi.postsignurl, "rs = " + rs);
                console.log(error);
                return "error";
            }
        }
    }

    async pushArr(company, clist, keyHex, ivHex) {
        //data加密
        var cipherDataStr = JSON.stringify(clist);
        var _d = cryptoJS.TripleDES.encrypt(cipherDataStr, keyHex, {
            iv: ivHex
        }).toString();
        var cipherData = encodeURIComponent(_d);
        let postData = "md5=" + md5(_d) + "&data=" + cipherData
        try {
            // let rs = await this.restClient.execPost({md5:md5(cipherData), data : cipherData}, company.posturl);
            let rs = await this.restClient.execPostForm(postData, company.posturl);
            if (rs.stdout) {
                let rsData = JSON.parse(rs.stdout);
                if (Number(rsData.code || 0) == 0) {
                    // 更新push状态
                    for (let item of clist) {
                        await this.dao.updateByWhere({
                            isPush: true
                        }, {
                            where: {
                                id: item.dataId
                            }
                        });
                    }
                }
            } else {
                logCtl.error({
                    optitle: "curl pos 推送（" + company.name + ", [" + JSON.stringify(errIds) + "]）合同签署人信息, 无返回信息异常error",
                    op: "/app/base/service/impl/econtractSve.js",
                    content: e.stack,
                    clientIp: ""
                });
            }
        } catch (e) {
            console.error(e);
            let errIds = [];
            for (let c of clist) {
                errIds.push(c.dataId);
            }
            logCtl.error({
                optitle: "curl pos 推送（" + company.name + ", [" + JSON.stringify(errIds) + "]）合同签署人信息, 操作异常异常error",
                op: "/app/base/service/impl/econtractSve.js",
                content: e.stack,
                clientIp: ""
            });
        }
    }

    async pushContract() {
        var comsql = "SELECT id, `name`,`encryptkey`, `posturl` FROM `c_ecompany` WHERE posturl <> '' AND posturl IS NOT NULL AND encryptkey IS NOT NULL AND isEnabled = 1";
        var companyList = await this.customQuery(comsql);
        var rs = [];
        for (let company of companyList) {
            let deskey = company.encryptkey || ""
            let posturl = company.posturl;
            if (deskey.length <= 8 || !posturl) {
                continue;
            }
            // company.posturl = "http://192.168.18.102:8080/gongsibao-web/web/common/reviceData";
            var sql = "SELECT " +
                "t1.id, t1.etemplate_id, t1.`name`, t1.`eflowstatus`, t1.`eflowstatusname`, t2.`mobile`, t2.`userName`, t2.`personsSign`, t1.`created_at`, t1.`completed_at`, t1.`end_at` " +
                "FROM c_econtract t1 " +
                "INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id` WHERE t1.isPush = 0 AND t1.`eflowstatus` = '2' AND t1.ecompany_id = " + company.id;

            var list = await this.dao.customQuery(sql);
            if (!list || list.length == 0) {
                continue;
            }

            let keyHex = cryptoJS.enc.Utf8.parse(deskey);
            let ivHex = cryptoJS.enc.Utf8.parse(deskey.substring(0, 8));

            var clist = [];
            for (let item of list) {
                let completeTime = item.completed_at || "";
                if (completeTime) {
                    completeTime = completeTime.Format("yyyy-MM-dd hh:mm:ss")
                }
                let invalidTime = item.end_at || "";
                if (invalidTime) {
                    invalidTime = invalidTime.Format("yyyy-MM-dd hh:mm:ss")
                }
                clist.push({
                    "dataId": item.id,
                    "agreementId": item.etemplate_id,
                    "contractName": item.name,
                    "companyName": company.name,
                    "statusName": item.eflowstatusname,
                    "userName": item.userName,
                    "mobile": item.mobile,
                    "idCard": item.personsSign.toUpperCase(),
                    "beginTime": item.created_at.Format("yyyy-MM-dd hh:mm:ss"),
                    "completeTime": completeTime,
                    "invalidTime": invalidTime
                });
                if (clist.length >= 2) {
                    await this.pushArr(company, clist, keyHex, ivHex);
                    clist = [];
                }
            }

            if (clist.length > 0) {
                await this.pushArr(company, clist, keyHex, ivHex);
            }
        }
        return rs;
    }

    async downloadCompleteUrl(limit) {
        var sql = "SELECT id FROM `c_econtract` WHERE eflowstatus = '2' AND (fileurl IS NULL OR fileurl = '')  ORDER BY id DESC ";
        if (limit) {
            sql = sql + " LIMIT " + limit;
        }
        var list = await this.dao.customQuery(sql);

        if (!list || list.length == 0) {
            return;
        }

        for (var o of list) {
            var id = o.id;
            try {
                var contract = await this.dao.findById(id);
                if (!contract) {
                    continue;
                }

                if (contract.eflowstatus != "2") {
                    continue;
                }

                if (!contract.fileurl) {
                    //  请求文件地址
                    let fileRs = await this.utilesignbaoSve.downloadUserContractFile(contract.eflowid, "econtractSve");
                    if (fileRs.code == 1 && fileRs.data.selfossUrl) {
                        contract.fileurl = fileRs.data.selfossUrl;
                        contract.save();
                    } else {
                        await this.utilesignbaoSve.archiveProcess({flowId: contract.eflowid}, "econtractSve");
                        let fileRs = await this.utilesignbaoSve.downloadUserContractFile(contract.eflowid, "econtractSve");
                        if (fileRs.code == 1 && fileRs.data.selfossUrl) {
                            contract.fileurl = fileRs.data.selfossUrl;
                            contract.save();
                        }
                    }
                }
            } catch (e) {
                console.error(e);
                //日志记录
                logCtl.error({
                    optitle: "定时下载合同任务异常, id=" + id,
                    op: "app/base/service/impl/econtractSve.js",
                    content: e.stack,
                    clientIp: ""
                });
                return {
                    code: -200,
                    message: "error",
                    data: {}
                };
            }
        }
    }

    async fiterSignedCards(ecompanyId, cardList) {
        var sql = "SELECT t2.`personsSign` FROM c_econtract t1 " +
            "INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id` " +
            "WHERE t2.`personsSign` IN (:cardList) AND t1.`ecompany_id` = :ecompanyId AND t1.`eflowstatus` = '2' AND t1.`end_at`>= NOW() " +
            "GROUP BY t2.`personsSign` ";

        var list = await this.dao.customQuery(sql, {
            ecompanyId: ecompanyId,
            cardList: cardList
        });
        var rs = [];
        if (list) {
            for (var item of list) {
                rs.push(item.personsSign);
            }
        }
        return rs;
    }

    async findSignedUsers(ecompanyId, minId, pageSize) {
        var sql = "SELECT t1.id, t2.userName, t2.mobile ,t2.`personsSign` AS idCard, t1.completed_at AS signTime, t1.end_at AS endTime FROM c_econtract t1 " +
            "INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id` " +
            "WHERE t1.id > :minId AND t1.`ecompany_id` = :ecompanyId AND t1.`eflowstatus` = '2' AND t1.`end_at`>= NOW() " +
            "ORDER BY t1.id ASC LIMIT :pageSize ";

        var list = await this.dao.customQuery(sql, {
            ecompanyId: ecompanyId,
            minId: minId,
            pageSize: pageSize
        });
        for (var item of list) {
            item.endTime = await this.formateTime(item.endTime);
            item.signTime = await this.formateTime(item.signTime);
        }
        return list;
    }

    async findSignedUses4Push(params) {
        // var params = {
        //   ecompanyId: busi.ecompany_id,
        //   startId: startId,
        //   idNo: idNo,
        //   pageSize: pageSize,
        //   userId3rd: userId,
        //   userCode3rd: userCode,
        //   branchCode3rd: branchCode,
        // };


        var sql = [];
        sql.push("SELECT t1.id,t1.begin_at as beginDate,t1.end_at as endDate,");
        sql.push("t2.userName AS idName, t2.mobile ,t2.`personsSign` AS idNo, t1.completed_at AS signTime, t2.bankno AS bankNo,");
        sql.push("t3.userId3rd, t3.userCode3rd, t3.branchCode3rd, t1.fileurl AS fileUrl");
        sql.push("FROM c_econtract t1");
        sql.push("INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id`");
        sql.push("INNER JOIN p_user t3 ON t2.`user_id` = t3.`id`");
        sql.push("WHERE t1.id > :startId AND t1.`ecompany_id` = :ecompanyId AND t1.`eflowstatus` = '2' AND t1.`end_at`>= NOW()");
        if (params.idNo) {
            sql.push("AND t2.`personsSign` = :idNo");
        }
        if (params.idNos) {
            sql.push("AND t2.`personsSign` IN (:idNos)");
        }
        if (params.userId3rd) {
            sql.push("AND t3.`userId3rd` = :userId3rd");
        }
        if (params.userCode3rd) {
            sql.push("AND t3.`userCode3rd` = :userCode3rd");
        }
        if (params.branchCode3rd) {
            sql.push("AND t3.`branchCode3rd` = :branchCode3rd");
        }

        sql.push("ORDER BY t1.id ASC LIMIT :pageSize ");
        var list = await this.dao.customQuery(sql.join(" "), params);
        for (var item of list) {
            item.signTime = await this.formateTime(item.signTime);
            item.beginDate = await this.formateTime(item.beginDate);
            item.endDate = await this.formateTime(item.endDate);
        }
        return list;
    }

    async findSingleSignedUser(params) {
        let sql = [];
        sql.push("SELECT t1.id,t1.begin_at as beginDate,t1.end_at as endDate,");
        sql.push("t2.userName AS idName, t2.mobile ,t2.`personsSign` AS idNo, t1.completed_at AS signTime, t2.bankno AS bankNo,");
        sql.push("t3.userId3rd, t3.userCode3rd, t3.branchCode3rd, t1.fileurl AS fileUrl");
        sql.push("FROM c_econtract t1");
        sql.push("INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id`");
        sql.push("INNER JOIN p_user t3 ON t2.`user_id` = t3.`id`");
        sql.push("WHERE t1.`etemplate_id` = :etemplate_id AND t1.`eflowstatus` = '2' AND t1.`end_at`>= NOW()");
        sql.push("AND t2.`personsSign` = :idNo");
        sql.push("ORDER BY t1.id ASC LIMIT 1");
        let list = await this.dao.customQuery(sql.join(" "), params);
        if (!list || list.length == 0) {
            return null;
        }
        for (var item of list) {
            item.signTime = await this.formateTime(item.signTime);
            item.beginDate = await this.formateTime(item.beginDate);
            item.endDate = await this.formateTime(item.endDate);
        }
        return list[0];
    }


    async sinedEcontractStatus(params) {

        var sql = "SELECT * FROM c_econtract WHERE usereaccount_id IN ( SELECT id FROM p_user_eaccount WHERE personsSign = :idNo) AND etemplate_id = :etemplate_id";
        var list = await this.dao.customQuery(sql,params);
        var data  = [];
        for (var item of list) {
            data.push(item.eflowstatus);
        }
        return data;
    }

    async findSignedMerchant4Push(params) {
        var sql = [];
        sql.push("SELECT t1.id,t1.begin_at as beginDate,t1.end_at as endDate,");
        sql.push("t2.userName AS idName, t2.mobile ,t2.`personsSign` AS idNo, t1.completed_at AS signTime, t2.bankno AS bankNo,");
        sql.push("t3.userId3rd, t3.userCode3rd, t3.branchCode3rd, t1.fileurl AS fileUrl");
        sql.push("FROM c_entcontract t1");
        sql.push("INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id`");
        sql.push("INNER JOIN p_user t3 ON t2.`user_id` = t3.`id`");
        sql.push("WHERE t1.id > :startId AND  t1.`eflowstatus` = '2' AND t1.`end_at`>= NOW()");
        if (params.idNo) {
            sql.push("AND t2.`personsSign` = :idNo");
        }
        if (params.userId3rd) {
            sql.push("AND t3.`userId3rd` = :userId3rd");
        }
        if (params.userCode3rd) {
            sql.push("AND t3.`userCode3rd` = :userCode3rd");
        }
        if (params.branchCode3rd) {
            sql.push("AND t3.`branchCode3rd` = :branchCode3rd");
        }

        sql.push("ORDER BY t1.id ASC LIMIT :pageSize ");
        var list = await this.dao.customQuery(sql.join(" "), params);
        for (var item of list) {
            item.signTime = await this.formateTime(item.signTime);
            item.beginDate = await this.formateTime(item.beginDate);
            item.endDate = await this.formateTime(item.endDate);
        }
        return list;
    }

    async setUser(list) {
        if (!list || list.length == 0) {
            return;
        }

        var ownerIds = [];
        for (var row of list) {
            if (row.owner_id) {
                ownerIds.push(row.owner_id);
            }
        }

        if (ownerIds.length == 0) {
            return;
        }

        var ownerMap = await this.userDao.findMapByIds(ownerIds);
        for (var row of rows) {
            if (row.owner_id) {
                row.owner = ownerMap["id_" + row.owner_id] || {};
            }
        }

        console.log(rows);
    }

    async syncAllSigners() {
        var sql = "SELECT t1.id FROM `c_econtract` t1 " +
            " INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id` " +
            " WHERE t1.`eflowstatus` = '2' AND t1.syncCode <> '0' AND t1.syncCode <> '10010000' " +
            " GROUP BY t2.`personsSign` ORDER BY t1.`id` ASC ";
        var ids = await this.dao.customQuery(sql);

        for (var c of ids) {
            try {
                await this.syncContract(c.id);
            } catch (error) {
                console.error(error);
            }
        }
    }

    async updateApply(id) {
        var sql = "UPDATE `c_ejob_apply` SET sign_at = NOW() , `status` = '2' , statusName = '已签约' WHERE econtract_id = " + id;
        await this.dao.customExecAddOrPutSql(sql);
        var apply = await this.ejobapplyDao.findOne({
            econtract_id: id
        });
        if (!apply) {
            return;
        }
        var ecompany = await this.ecompanyDao.findById(apply.ecompany_id);

        var now = moment().format("YYYY年MM月DD日");
        // 发送消息
        var msg = "您于" + now + "与" + ecompany.name + "签约成功, 详情可登录薪必果小程序进行查看。";
        this.emessageDao.create({
            user_id: apply.user_id,
            title: '系统消息',
            type: '0',
            content: msg
        });
        this.ejobapplySve.addMessage(id, "零工签约", "成功签约");
    }

    async syncContract(id) {
        var contract = null;
        var account = null;
        var company = null;
        var signArr = null;
        try {
            contract = await this.dao.findById(id);
            if (!contract) {
                return null;
            }
            account = await this.usereaccountDao.findById(contract.usereaccount_id);
            if (!account) {
                return null;
            }
            company = await this.ecompanyDao.findById(contract.ecompany_id);
            var mainId = await this.maindict.getMainId(company.nameA) || "57731585";

            if (contract.syncCode == '0' || contract.syncCode == '10010000') {
                return null;
            }
            // 39.96.42.199 端口：80  appId:1086941347  mchtId:108694134791293777   mainId:57731585  secret:def87140063233abc
            var item = {
                "accNo": account.bankno || "",
                "appId": "1086941347",
                "beginTime": await this.formateTime2(contract.begin_at),
                "completeTime": await this.formateTime2(contract.completed_at),
                "idName": account.userName,
                "idNo": account.personsSign,
                "idType": "00",
                "invalidTime": await this.formateTime2(contract.end_at),
                "mainId": "57731585",
                "mchtId": "108694134791293777",
                "mobile": account.mobile,
                "nonceStr": await this.getUidStr(16),
                "signType": "MD5",
                "signedName": company.name
            }

            signArr = [];
            signArr.push("appId=" + (item.appId || ""));
            signArr.push("beginTime=" + (item.beginTime || ""));
            signArr.push("completeTime=" + (item.completeTime || ""));
            signArr.push("idName=" + (item.idName || ""));
            signArr.push("idNo=" + (item.idNo || ""));
            signArr.push("idType=" + (item.idType || ""));
            signArr.push("invalidTime=" + (item.invalidTime || ""));
            signArr.push("mainId=" + (item.mainId || ""));
            signArr.push("mchtId=" + (item.mchtId || ""));
            signArr.push("mobile=" + (item.mobile || ""));
            signArr.push("nonceStr=" + (item.nonceStr || ""));
            signArr.push("signType=" + (item.signType || ""));
            signArr.push("signedName=" + (item.signedName || ""));
            signArr.push("key=def87140063233abc");

            item.sign = md5(signArr.join("&")).toUpperCase();
            try {
                let rs = await this.restClient.execPost(item, "https://payadmin.gongsibao.com/merchant/userSigned/asyncNotify");

                if (rs && rs.stdout) {
                    contract.syncCode = JSON.parse(rs.stdout).code;
                } else {
                    contract.syncCode = '-10501';
                }
                await contract.save();
            } catch (error) {
                contract.syncCode = '-10500';
                await contract.save();
            }
        } catch (error) {
            console.error(error);
            if (contract) {
                contract.syncCode = '-500';
                await contract.save();
            }
        }
    }

    async getContractUrl(id) {
        var contract = await this.findById(id);
        if (contract.fileurl) {
            return contract.fileurl;
        }

        let fileRs = await this.utilesignbaoSve.downloadUserContractFile(contract.eflowid, "econtractSve");
        if (fileRs.code == 1 && fileRs.data.selfossUrl) {
            contract.fileurl = fileRs.data.selfossUrl;
            await contract.save();
            return contract.fileurl;
        }
        return "";
    }

    async testtransfer(result) {
        var date = new Date().Format("yyyy-MM-dd hh:mm:ss");
        var v = JSON.stringify(result) + "---" + date;
        var sql = "INSERT INTO `testtransfer` (`v`) VALUES ('" + v + "')  ";
        await this.dao.customExecAddOrPutSql(sql, {});
    }

    async addBankthreeLog(appId, userName, userIdNo, userBankNo, use_esign) {
        var date = new Date().Format("yyyy-MM-dd hh:mm:ss");
        var params = [];
        params.push("'" + appId + "'");
        params.push("'" + userName + "'");
        params.push("'" + userIdNo + "'");
        params.push("'" + userBankNo + "'");
        params.push(use_esign);
        var sql = "INSERT INTO `bankthree` (`appId`, `userName`, `userIdNo`, `userBankNo`, `use_esign`, `created_at`, `updated_at`) VALUES (" + params.join(",") + ")  ";
        await this.dao.customExecAddOrPutSql(sql, {});
    }

    async addPayNotify(result) {
        var sql = [];
        sql.push("INSERT INTO c_pay_notify");
        sql.push("(fromid,username,flag,amount,created_at,orderItemId,income_tax, notifyTime)VALUE(");
        sql.push("'" + result.fromid + "',");
        sql.push("'" + result.username + "',");
        sql.push("'" + result.flag + "',");
        sql.push("'" + result.amount + "',");
        sql.push("NOW(),");
        sql.push("'" + result.orderItemId + "',");
        sql.push("'" + (result.income_tax || 0) + "', ");
        sql.push("'" + result.notifyTime + "')");
        await this.dao.customExecAddOrPutSql(sql.join(""), {});
    }

    async getPayNotify(result) {
        var payNotify = {};
        var sql = "SELECT username,amount,income_tax,notifyTime from c_pay_notify where orderItemId =:orderItemId limit 1";
        var list = await this.dao.customQuery(sql, {
            orderItemId: result
        });

        if (list && list.length > 0) {
            payNotify = list[0] || [];
            payNotify.amount = system.f2y(payNotify.amount);
            payNotify.income_tax = system.f2y(payNotify.income_tax);
            // payNotify.created_at =  await this.formateTime3(payNotify.created_at);
            payNotify.notifyTime = moment(payNotify.notifyTime).add(-8, "hours").format("YYYY年MM月DD日 HH:mm");
        }

        return payNotify;
    }

    async formateTime(inputTime) {
        var date = new Date(inputTime);
        var y = date.getFullYear();
        var m = date.getMonth() + 1;
        m = m < 10 ? ('0' + m) : m;
        var d = date.getDate();
        d = d < 10 ? ('0' + d) : d;
        var h = date.getHours();
        h = h < 10 ? ('0' + h) : h;
        var minute = date.getMinutes();
        var second = date.getSeconds();
        minute = minute < 10 ? ('0' + minute) : minute;
        second = second < 10 ? ('0' + second) : second;
        return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
    }

    async formateTime2(inputTime) {
        if (!inputTime) {
            return '';
        }
        var date = new Date(inputTime);
        var y = date.getFullYear();
        var m = date.getMonth() + 1;
        m = m < 10 ? ('0' + m) : m;
        var d = date.getDate();
        d = d < 10 ? ('0' + d) : d;
        var h = date.getHours();
        h = h < 10 ? ('0' + h) : h;
        var minute = date.getMinutes();
        var second = date.getSeconds();
        minute = minute < 10 ? ('0' + minute) : minute;
        second = second < 10 ? ('0' + second) : second;
        return y + '' + m + '' + d + '' + h + '' + minute + '' + second;
    }

    async formateTime3(inputTime) {
        if (!inputTime) {
            return '';
        }
        var date = new Date(inputTime);
        var y = date.getFullYear();
        var m = date.getMonth() + 1;
        m = m < 10 ? ('0' + m) : m;
        var d = date.getDate();
        d = d < 10 ? ('0' + d) : d;
        var h = date.getHours() - 8;
        h = h < 10 ? ('0' + h) : h;
        var minute = date.getMinutes();
        minute = minute < 10 ? ('0' + minute) : minute;
        return y + '年' + m + '月' + d + '日 ' + h + ':' + minute;
    }

    async getUidStr(len, radix) {
        var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
        var uuid = [],
            i;
        radix = radix || chars.length;
        if (len) {
            for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
        } else {
            var r;
            uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
            uuid[14] = '4';
            for (i = 0; i < 36; i++) {
                if (!uuid[i]) {
                    r = 0 | Math.random() * 16;
                    uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
                }
            }
        }
        return uuid.join('');
    }

    // 银行三要素查询
    async findSinedByThree(userName, personsSign, bankno) {
        if (!userName || !personsSign || !bankno) {
            return [];
        }
        var sql = [];
        sql.push('SELECT t1.* FROM c_econtract t1 ');
        sql.push('INNER JOIN p_user_eaccount t2 ON t1.usereaccount_id = t2.id');
        sql.push('WHERE t2.personsSign = :personsSign AND t2.userName = :userName AND t2.bankno = :bankno');
        sql.push('GROUP BY t1.id ORDER BY t1.id DESC');

        var list = await this.dao.customQuery(sql.join(" "), {
            userName: userName,
            personsSign: personsSign,
            bankno: bankno
        });
        return list || [];
    }

    // 根据身份证Id,获取openId  status-2 签约成功
    async findOpenIdByNo(status, idNo) {
        if (!idNo) {
            return [];
        }
        var sql = [];
        sql.push('SELECT t2.`openId`, t1.`userName`, t1.`mobile` FROM p_user_eaccount t1');
        sql.push('INNER JOIN p_user t2 ON t1.`user_id` = t2.`id`');
        sql.push('INNER JOIN c_econtract t3 ON t1.`id` = t3.`usereaccount_id`');
        sql.push('WHERE t3.eflowstatus = :status AND t1.personsSign = :idNo');

        var list = await this.dao.customQuery(sql.join(" "), {
            status: status,
            idNo: idNo
        });
        return list || [];
    }

    async ydsignnumber() {
        var sql = "SELECT COUNT(1), etemplate_id FROM c_econtract WHERE eflowstatus = '2' AND etemplate_id IN (10066, 10074) GROUP BY etemplate_id";
        return await this.dao.customQuery(sql);
    }

    /**
     * 静默签 带三要素验证
     * @param {ecid, appId, userId, idName, mobile, idNo, bankno, nonceStr, sign} params
     */
    async autoSign(params) {
        let ecid = params.ecid;
        // 验证身份证是否签约过
        let todays = moment().format("YYYY-MM-DD") + " 00:00:00";
        let contractId = await this.dao.findSignedContractId({idno: params.idNo, ecid: ecid, today : todays}) || 0;
        if (contractId) {
            return this.returnjson(0, "用户已经签约", {
                contractId: contractId
            });
        }

        let banklog = await this.bankthreelogDao.findOne({
            userName: params.idName,
            userIdNo: params.idNo,
            userBankNo: params.bankno,
            result: 1,
        });
        if (!banklog) {
            var bankthreeParams = {
                name: params.idName,
                idno: params.idNo,
                cardno: params.bankno
            };
            var threeResult = await this.utilesignbaoSve.bankthree(bankthreeParams, "bankinfoAuth");
            this.bankthreelogDao.create({
                appId :params.appId,
                userName: params.idName,
                userIdNo: params.idNo,
                userBankNo: params.bankno,
                result: threeResult.code,
            });

            // {"code":-110,"message":"手机号格式错误","data":{}}
            //1成功,-110提示验证信息有误，-120亲，提供的信息不正确，请验证后再试！
            console.log("threeResult-----------------------------", threeResult);
            if (!threeResult || threeResult.code == -120) {
                return this.returnjson(-1, "银行三要素（姓名、身份证、银行卡号）验证失败");
            }
            if (threeResult.code == -110) {
                return this.returnjson(-1, "银行三要素验证失败");
            }
        }
        // ecid etemplate
        var etemplate = await this.etemplateSve.findById(ecid);

        // ecompany
        var ecompany = await this.ecompanyDao.findById(etemplate.ecompany_id);

        // p_user
        var unionId = params.appId + "_" + params.userId + params.userCode + params.branchCode;
        var user = await this.userDao.findOne({
            unionId: unionId,
        });
        if (!user) {
            user = await this.userDao.create({
                appkey: params.appId,
                unionId: unionId,
                userId3rd: params.userId,
                userCode3rd: params.userCode,
                branchCode3rd: params.branchCode,
                userName: params.idName,
                mobile: params.mobile,
                utype: 0,
            });
        }

        // p_user_eaccount
        var eaccount = await this.usereaccountDao.findOne({
            user_id: user.id,
            personsSign: params.idNo,
        }) || {};

        var isNeedCreate = !eaccount.eaccountid || eaccount.userName != params.idName || eaccount.mobile != params.mobile || eaccount.bankno != params.bankno;

        eaccount.user_id = user.id;
        eaccount.userName = params.idName;
        eaccount.mobile = params.mobile;
        eaccount.bankno = params.bankno;
        eaccount.personsSign = params.idNo;
        if (eaccount.id) {
            await eaccount.save();
        } else {
            eaccount = await this.usereaccountDao.create(eaccount);
        }

        // e签宝流程
        if (isNeedCreate) {
            var uidStr = await this.getUidStr(8, 36);
            var thirdId = etemplate.id + "_" + eaccount.id + uidStr;

            //2.创建e签宝account 5.2.1 , 创建后save()
            var params = {
                thirdId: thirdId,
                name: eaccount.userName,
                idNo: eaccount.personsSign,
                idType: 19,
                mobile: eaccount.mobile
            };
            var getAccount = await this.utilesignbaoSve.createAccountId(params, "econtractSve");
            if (getAccount && getAccount.code == 1 && getAccount.data) {
                eaccount.eaccountid = getAccount.data.accountId;
                await eaccount.save();
            } else {
                return this.returnjson(-1, "账户创建失败");
            }
        }

        // 3.设置静默签署授权 5.2.5
        if (!eaccount.isGrantAuto) {
            var paramsGrant = {
                grantAccountId: eaccount.eaccountid
            };
            var grantAuto = await this.utilesignbaoSve.grantAuthorization(paramsGrant, "econtractSve");
            if (grantAuto.code != 1) {
                return this.returnjson(-1, "静默签署设置失败");
            }
            eaccount.isGrantAuto = true;
            await eaccount.save();
        }

        // 创建合同   fileurl、esignUrl 怎么赋值????????????
        let econtract = {
            name: ecompany.name,
            eflowstatusname: "签约中",
            eflowstatus: "1",
            // begin_at: now,
            // completed_at: now,
            user_id: eaccount.user_id,
            usereaccount_id: eaccount.id,
            etemplate_id: etemplate.id,
            ecompany_id: ecompany.id,
            // end_at: end,
        };
        econtract = await this.create(econtract);

        // 创建印章id
        var sealId = "";
        var eseal = await this.esealSve.findOne({
            nameA: etemplate.nameA
        });
        // 生产环境需要打开
        if (!eseal) {

            var rs = await this.utilesignbaoSve.creatEntSignet(settings.apiconfig.companyAccountId(), etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            // var rs = await this.utilesignbaoSve.creatEntSignet("740b19e0799a4d7abacfa1a31fb72b1e", etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            if (rs && rs.code == 1) {
                sealId = rs.data.sealId;
                await this.esealSve.create({
                    nameA: etemplate.nameA,
                    sealId: sealId,
                });
            } else {
                return this.returnjson(-1, "生成印章错误");
            }
        } else {
            sealId = eseal.sealId;
        }

        let today = new Date().Format("yyyy-MM-dd");
        var signParams = {
            templateId: etemplate.templateid, //模板id，由创建模板接口调用返回的templateId 必填
            name: ecompany.name, //合同模板名称 必填
            simpleFormFields: {
                nameA: etemplate.nameA, //甲方 必填
                nameB: eaccount.userName, //乙方 必填
                unit: ecompany.name, //合作单位（国美） 必填---------------------------超出长度风险---目前不知多少长度
                signDateA: today, //甲方签约日期 必填
                signDateB: today //乙方签约日期 必填
            }
        };
        var ebaoAccountId = eaccount.eaccountid; //签署人账户id-- 必填
        var thirdOrderNo = econtract.id; //第三方流水号，通知回调使用---选填
        var eBaoRedirectBossUrl = "";

        var tt = await this.utilesignbaoSve.userAutoSignContractNoTemplate(signParams, ebaoAccountId, thirdOrderNo, eBaoRedirectBossUrl, "econtractSve", sealId);
        if (tt && tt.data && tt.code == 1) {
            econtract.eflowid = tt.data.flowId;
            econtract.edocid = tt.data.docId;
            econtract.eflowstatus = '2';
            econtract.eflowstatusname = "已完成";

            var signTime = new Date();
            econtract.completed_at = signTime;
            econtract.begin_at = signTime;
            var end_at = new Date();
            end_at.setFullYear(end_at.getFullYear() + 1);
            econtract.end_at = end_at;

            await econtract.save();
            this.syncSign(econtract.id);
            // TODO DOWNLOAD OK
            this.redisClient.rpushBCD({id: econtract.id, sve: "e"});
            return this.returnjson(0, "success", {
                contractId: econtract.id
            });
        }
        return this.returnjson(-1, tt.message || "签约失败", tt.code);
    }

    /**
     * 静默签 四要素验证
     * @param {ecid, appId, userId, idName, mobile, idNo, bankno, nonceStr, sign} params
     */
    async autoSign4(params) {
        var ecid = params.ecid;

        // 验证身份证是否签约过
        let todays = moment().format("YYYY-MM-DD") + " 00:00:00";
        let contractId = await this.dao.findSignedContractId({idno: params.idNo, ecid: ecid, today : todays}) || 0;
        if (contractId) {
            return this.returnjson(0, "用户已经签约", {
                contractId: contractId
            });
        }

        let banklog = await this.bankthreelogDao.findOne({
            userName: params.idName,
            userIdNo: params.idNo,
            userBankNo: params.bankno,
            userMobile: params.mobile,
            result: 1,
        });
        if (!banklog) {
            var bankthreeParams = {
                name: params.idName,
                idno: params.idNo,
                cardno: params.bankno,
                mobile: params.mobile
            };


            var threeResult = await this.utilesignbaoSve.bankfour(bankthreeParams, "bankinfoAuth");
            this.bankthreelogDao.create({
                appId :params.appId,
                userName: params.idName,
                userIdNo: params.idNo,
                userBankNo: params.bankno,
                userMobile: params.mobile,
                result: threeResult.code,
            });
            // {"code":-110,"message":"手机号格式错误","data":{}}
            //1成功,-110提示验证信息有误，-120亲，提供的信息不正确，请验证后再试！
            console.log("threeResult-----------------------------", threeResult);
            if (!threeResult || threeResult.code == -120) {
                return this.returnjson(-1, "银行四要素（姓名、身份证、银行卡号、手机号）验证失败");
            }
            if (threeResult.code == -110) {
                return this.returnjson(-1, "银行四要素验证失败");
            }
        }

        // ecid etemplate
        var etemplate = await this.etemplateSve.findById(ecid);
        // ecompany
        var ecompany = await this.ecompanyDao.findById(etemplate.ecompany_id);
        // p_user
        var unionId = params.appId + "_" + params.userId + params.userCode + params.branchCode;
        var user = await this.userDao.findOne({
            unionId: unionId,
        });
        if (!user) {
            user = await this.userDao.create({
                appkey: params.appId,
                unionId: unionId,
                userId3rd: params.userId,
                userCode3rd: params.userCode,
                branchCode3rd: params.branchCode,
                userName: params.idName,
                mobile: params.mobile,
                utype: 0,
            });
        }

        // p_user_eaccount
        var eaccount = await this.usereaccountDao.findOne({
            user_id: user.id,
            personsSign: params.idNo,
        }) || {};

        var isNeedCreate = !eaccount.eaccountid || eaccount.userName != params.idName || eaccount.mobile != params.mobile || eaccount.bankno != params.bankno;

        eaccount.user_id = user.id;
        eaccount.userName = params.idName;
        eaccount.mobile = params.mobile;
        eaccount.bankno = params.bankno;
        eaccount.personsSign = params.idNo;
        if (eaccount.id) {
            await eaccount.save();
        } else {
            eaccount = await this.usereaccountDao.create(eaccount);
        }
        // e签宝流程
        if (isNeedCreate) {
            var uidStr = await this.getUidStr(8, 36);
            var thirdId = etemplate.id + "_" + eaccount.id + uidStr;

            //2.创建e签宝account 5.2.1 , 创建后save()
            var params = {
                thirdId: thirdId,
                name: eaccount.userName,
                idNo: eaccount.personsSign,
                idType: 19,
                mobile: eaccount.mobile
            };
            var getAccount = await this.utilesignbaoSve.createAccountId(params, "econtractSve");
            if (getAccount && getAccount.code == 1 && getAccount.data) {
                eaccount.eaccountid = getAccount.data.accountId;
                await eaccount.save();
            } else {
                return this.returnjson(-1, "账户创建失败");
            }
        }

        // 3.设置静默签署授权 5.2.5
        if (!eaccount.isGrantAuto) {
            var paramsGrant = {
                grantAccountId: eaccount.eaccountid
            };
            var grantAuto = await this.utilesignbaoSve.grantAuthorization(paramsGrant, "econtractSve");
            if (grantAuto.code != 1) {
                return this.returnjson(-1, "静默签署设置失败");
            }
            eaccount.isGrantAuto = true;
            await eaccount.save();
        }

        // 创建合同   fileurl、esignUrl 怎么赋值????????????
        let econtract = {
            name: ecompany.name,
            eflowstatusname: "签约中",
            eflowstatus: "1",
            // begin_at: now,
            // completed_at: now,
            user_id: eaccount.user_id,
            usereaccount_id: eaccount.id,
            etemplate_id: etemplate.id,
            ecompany_id: ecompany.id,
            // end_at: end,
        };
        econtract = await this.create(econtract);

        // 创建印章id
        var sealId = "";
        var eseal = await this.esealSve.findOne({
            nameA: etemplate.nameA
        });
        // 生产环境需要打开
        if (!eseal) {
            // var accountId = "";  // 测试

            var rs = await this.utilesignbaoSve.creatEntSignet(settings.apiconfig.companyAccountId(), etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            // var rs = await this.utilesignbaoSve.creatEntSignet("740b19e0799a4d7abacfa1a31fb72b1e", etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            if (rs && rs.code == 1) {
                sealId = rs.data.sealId;
                await this.esealSve.create({
                    nameA: etemplate.nameA,
                    sealId: sealId,
                });
            } else {
                return this.returnjson(-1, "生成印章错误");
            }
        } else {
            sealId = eseal.sealId;
        }

        let today = new Date().Format("yyyy-MM-dd");
        var signParams = {
            templateId: etemplate.templateid, //模板id，由创建模板接口调用返回的templateId 必填
            name: ecompany.name, //合同模板名称 必填
            simpleFormFields: {
                nameA: etemplate.nameA, //甲方 必填
                nameB: eaccount.userName, //乙方 必填
                unit: ecompany.name, //合作单位（国美） 必填---------------------------超出长度风险---目前不知多少长度
                signDateA: today, //甲方签约日期 必填
                signDateB: today //乙方签约日期 必填
            }
        };
        var ebaoAccountId = eaccount.eaccountid; //签署人账户id-- 必填
        var thirdOrderNo = econtract.id; //第三方流水号，通知回调使用---选填
        var eBaoRedirectBossUrl = "";

        var tt = await this.utilesignbaoSve.userAutoSignContractNoTemplate(signParams, ebaoAccountId, thirdOrderNo, eBaoRedirectBossUrl, "econtractSve", sealId);
        if (tt && tt.data && tt.code == 1) {
            econtract.eflowid = tt.data.flowId;
            econtract.edocid = tt.data.docId;
            econtract.eflowstatus = '2';
            econtract.eflowstatusname = "已完成";

            var signTime = new Date();
            econtract.completed_at = signTime;
            econtract.begin_at = signTime;
            var end_at = new Date();
            end_at.setFullYear(end_at.getFullYear() + 1);
            econtract.end_at = end_at;

            await econtract.save();
            this.syncSign(econtract.id);
            // TODO DOWNLOAD OK
            this.redisClient.rpushBCD({id: econtract.id, sve: "e"});
            return this.returnjson(0, "success", {
                contractId: econtract.id
            });
        }
        return this.returnjson(-1, tt.message || "签约失败", tt.code);
    }

    /**
     * 静默签 不带三要素验证
     * @param {ecid, appId, userId, idName, mobile, idNo, bankno, nonceStr, sign} params
     */
    async autoSigns(params) {
        var ecid = params.ecid;

        var unionId = params.appId + "_" + params.userId + params.userCode + params.branchCode;
        // ecid etemplate
        var etemplate = await this.etemplateSve.findById(ecid);

        // ecompany
        var ecompany = await this.ecompanyDao.findById(etemplate.ecompany_id);

        // p_user
        var user = await this.userDao.findOne({
            unionId: unionId,
        });
        if (!user) {
            user = await this.userDao.create({
                appkey: params.appId,
                unionId: unionId,
                userId3rd: params.userId,
                userCode3rd: params.userCode,
                branchCode3rd: params.branchCode,
                userName: params.idName,
                mobile: params.mobile,
                utype: 0,
            });
        }

        // p_user_eaccount
        var eaccount = await this.usereaccountDao.findOne({
            user_id: user.id,
            personsSign: params.idNo,
        }) || {};

        var isNeedCreate = !eaccount.eaccountid || eaccount.userName != params.idName || eaccount.mobile != params.mobile || eaccount.bankno != params.bankno;

        eaccount.user_id = user.id;
        eaccount.userName = params.idName;
        eaccount.mobile = params.mobile;
        eaccount.bankno = params.bankno;
        eaccount.personsSign = params.idNo;
        if (eaccount.id) {
            await eaccount.save();
        } else {
            eaccount = await this.usereaccountDao.create(eaccount);
        }

        // c_econtract
        var econtract = await this.dao.findOne({
            eflowstatus: '2',
            usereaccount_id: eaccount.id,
            etemplate_id: ecid,
        });

        if (econtract) {
            return this.returnjson(0, "用户已经签约", {
                contractId: econtract.id
            });
        }

        // e签宝流程
        if (isNeedCreate) {
            var uidStr = await this.getUidStr(8, 36);
            var thirdId = etemplate.id + "_" + eaccount.id + uidStr;

            //2.创建e签宝account 5.2.1 , 创建后save()
            var params = {
                thirdId: thirdId,
                name: eaccount.userName,
                idNo: eaccount.personsSign,
                idType: 19,
                mobile: eaccount.mobile
            };
            var getAccount = await this.utilesignbaoSve.createAccountId(params, "econtractSve");
            if (getAccount && getAccount.code == 1 && getAccount.data) {
                eaccount.eaccountid = getAccount.data.accountId;
                await eaccount.save();
            } else {
                return this.returnjson(-1, "账户创建失败");
            }
        }

        // 3.设置静默签署授权 5.2.5
        if (!eaccount.isGrantAuto) {
            var paramsGrant = {
                grantAccountId: eaccount.eaccountid
            };
            var grantAuto = await this.utilesignbaoSve.grantAuthorization(paramsGrant, "econtractSve");
            if (grantAuto.code != 1) {
                return this.returnjson(-1, "静默签署设置失败");
            }
            eaccount.isGrantAuto = true;
            await eaccount.save();
        }

        // 创建合同   fileurl、esignUrl 怎么赋值????????????
        econtract = {
            name: ecompany.name,
            eflowstatusname: "签约中",
            eflowstatus: "1",
            // begin_at: now,
            // completed_at: now,
            user_id: eaccount.user_id,
            usereaccount_id: eaccount.id,
            etemplate_id: etemplate.id,
            ecompany_id: ecompany.id,
            // end_at: end,
        };
        econtract = await this.create(econtract);

        // 创建印章id
        var sealId = "";
        var eseal = await this.esealSve.findOne({
            nameA: etemplate.nameA
        });
        // 生产环境需要打开
        if (!eseal) {
            // var accountId = "";  // 测试

            var rs = await this.utilesignbaoSve.creatEntSignet(settings.apiconfig.companyAccountId(), etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            // var rs = await this.utilesignbaoSve.creatEntSignet("740b19e0799a4d7abacfa1a31fb72b1e", etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            if (rs && rs.code == 1) {
                sealId = rs.data.sealId;
                await this.esealSve.create({
                    nameA: etemplate.nameA,
                    sealId: sealId,
                });
            } else {
                return this.returnjson(-1, "生成印章错误");
            }
        } else {
            sealId = eseal.sealId;
        }

        let today = new Date().Format("yyyy-MM-dd");
        var signParams = {
            templateId: etemplate.templateid, //模板id，由创建模板接口调用返回的templateId 必填
            name: ecompany.name, //合同模板名称 必填
            simpleFormFields: {
                nameA: etemplate.nameA, //甲方 必填
                nameB: eaccount.userName, //乙方 必填
                unit: ecompany.name, //合作单位（国美） 必填---------------------------超出长度风险---目前不知多少长度
                signDateA: today, //甲方签约日期 必填
                signDateB: today //乙方签约日期 必填
            }
        };
        var ebaoAccountId = eaccount.eaccountid; //签署人账户id-- 必填
        var thirdOrderNo = econtract.id; //第三方流水号，通知回调使用---选填
        var eBaoRedirectBossUrl = "";

        var tt = await this.utilesignbaoSve.userAutoSignContractNoTemplate(signParams, ebaoAccountId, thirdOrderNo, eBaoRedirectBossUrl, "econtractSve", sealId);
        if (tt && tt.data && tt.code == 1) {
            econtract.eflowid = tt.data.flowId;
            econtract.edocid = tt.data.docId;
            econtract.eflowstatus = '2';
            econtract.eflowstatusname = "已完成";

            var signTime = new Date();
            econtract.completed_at = signTime;
            econtract.begin_at = signTime;
            var end_at = new Date();
            end_at.setFullYear(end_at.getFullYear() + 1);
            econtract.end_at = end_at;

            await econtract.save();
            this.syncSign(econtract.id);
            // TODO DOWNLOAD OK
            this.redisClient.rpushBCD({id: econtract.id, sve: "e"});
            return this.returnjson(0, "success", {
                contractId: econtract.id
            });
        }
        return this.returnjson(-1, tt.message || "签约失败", tt.code);
    }

    /**
     * 静默签
     * @param {ecid, appId, userId, idName, mobile, idNo, bankno, nonceStr, sign} params
     */
    async autoSignTest(params) {
        var ecid = params.ecid;

        var unionId = params.appId + "_" + params.userId;
        // ecid etemplate
        var etemplate = await this.etemplateSve.findById(ecid);

        // ecompany
        var ecompany = await this.ecompanyDao.findById(etemplate.ecompany_id);

        // p_user
        var user = await this.userDao.findOne({
            unionId: unionId,
        });
        if (!user) {
            user = await this.userDao.create({
                appkey: params.appId,
                unionId: unionId,
                userId3rd: params.userId,
                userName: params.idName,
                mobile: params.mobile,
                utype: 0,
            });
        }

        // p_user_eaccount
        var eaccount = await this.usereaccountDao.findOne({
            user_id: user.id,
            personsSign: params.idNo,
        }) || {};

        var isNeedCreate = !eaccount.eaccountid || eaccount.userName != params.idName || eaccount.mobile != params.mobile || eaccount.bankno != params.bankno;

        eaccount.user_id = user.id;
        eaccount.userName = params.idName;
        eaccount.mobile = params.mobile;
        eaccount.bankno = params.bankno;
        eaccount.personsSign = params.idNo;
        if (eaccount.id) {
            await eaccount.save();
        } else {
            eaccount = await this.usereaccountDao.create(eaccount);
        }

        var econtract;

        // e签宝流程
        if (isNeedCreate) {
            var uidStr = await this.getUidStr(8, 36);
            var thirdId = etemplate.id + "_" + eaccount.id + uidStr;

            //2.创建e签宝account 5.2.1 , 创建后save()
            var params = {
                thirdId: thirdId,
                name: eaccount.userName,
                idNo: eaccount.personsSign,
                idType: 19,
                mobile: eaccount.mobile
            };
            var getAccount = await this.utilesignbaoSve.createAccountId(params, "econtractSve");
            if (getAccount && getAccount.code == 1 && getAccount.data) {
                eaccount.eaccountid = getAccount.data.accountId;
                await eaccount.save();
            } else {
                return this.returnjson(-1, "账户创建失败");
            }
        }

        // 3.设置静默签署授权 5.2.5
        if (!eaccount.isGrantAuto) {
            var paramsGrant = {
                grantAccountId: eaccount.eaccountid
            };
            var grantAuto = await this.utilesignbaoSve.grantAuthorization(paramsGrant, "econtractSve");
            if (grantAuto.code != 1) {
                return this.returnjson(-1, "静默签署设置失败");
            }
            eaccount.isGrantAuto = true;
            await eaccount.save();
        }

        // 创建合同   fileurl、esignUrl 怎么赋值????????????
        econtract = {
            name: ecompany.name,
            eflowstatusname: "签约中",
            eflowstatus: "1",
            // begin_at: now,
            // completed_at: now,
            user_id: eaccount.user_id,
            usereaccount_id: eaccount.id,
            etemplate_id: etemplate.id,
            ecompany_id: ecompany.id,
            // end_at: end,
        }
        econtract = await this.create(econtract);

        // 创建印章id
        var sealId = "";
        var eseal = await this.esealSve.findOne({
            nameA: etemplate.nameA
        });
        // 生产环境需要打开
        if (!eseal) {
            // var accountId = "";  // 测试

            var rs = await this.utilesignbaoSve.creatEntSignet(settings.apiconfig.companyAccountId(), etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            // var rs = await this.utilesignbaoSve.creatEntSignet("740b19e0799a4d7abacfa1a31fb72b1e", etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            if (rs && rs.code == 1) {
                sealId = rs.data.sealId;
                await this.esealSve.create({
                    nameA: etemplate.nameA,
                    sealId: sealId,
                });
            } else {
                return this.returnjson(-1, "生成印章错误");
            }
        } else {
            sealId = eseal.sealId;
        }

        let today = new Date().Format("yyyy-MM-dd");
        var signParams = {
            templateId: etemplate.templateid, //模板id，由创建模板接口调用返回的templateId 必填
            name: ecompany.name, //合同模板名称 必填
            simpleFormFields: {
                nameA: etemplate.nameA, //甲方 必填
                nameB: eaccount.userName, //乙方 必填
                unit: ecompany.name, //合作单位（国美） 必填---------------------------超出长度风险---目前不知多少长度
                signDateA: today, //甲方签约日期 必填
                signDateB: today //乙方签约日期 必填
            }
        }
        var ebaoAccountId = eaccount.eaccountid; //签署人账户id-- 必填
        var thirdOrderNo = econtract.id; //第三方流水号，通知回调使用---选填
        var eBaoRedirectBossUrl = "";

        var tt = await this.utilesignbaoSve.userAutoSignContractNoTemplate(signParams, ebaoAccountId, thirdOrderNo, eBaoRedirectBossUrl, "econtractSve", sealId);
        if (tt && tt.data && tt.code == 1) {
            econtract.eflowid = tt.data.flowId;
            econtract.edocid = tt.data.docId;
            econtract.eflowstatus = '2';
            econtract.eflowstatusname = "已完成";

            var signTime = new Date();
            econtract.completed_at = signTime;
            econtract.begin_at = signTime;
            var end_at = new Date();
            end_at.setFullYear(end_at.getFullYear() + 1);
            econtract.end_at = end_at;

            await econtract.save();
            // TODO DOWNLOAD OK
            this.redisClient.rpushBCD({id: econtract.id, sve: "e"});
            return this.returnjson(0, "success", {
                contractId: econtract.id
            });
        }
        return this.returnjson(-1, tt.message || "签约失败", tt.code);
    }

    /**
     * 静默签 暂时提供给有赞使用
     * @param {ecid, appId, userId, idName, mobile, idNo, nonceStr, sign} params
     */
    async autoSignNoBank(params) {
        var ecid = params.ecid;

        var unionId = params.appId + "_" + params.userId;
        // ecid etemplate
        var etemplate = await this.etemplateSve.findById(ecid);

        // ecompany
        var ecompany = await this.ecompanyDao.findById(etemplate.ecompany_id);

        // p_user
        var user = await this.userDao.findOne({
            unionId: unionId,
        });
        if (!user) {
            user = await this.userDao.create({
                appkey: params.appId,
                unionId: unionId,
                userId3rd: params.userId,
                userName: params.idName,
                mobile: params.mobile,
                utype: 0,
            });
        }

        // p_user_eaccount
        var eaccount = await this.usereaccountDao.findOne({
            user_id: user.id,
            personsSign: params.idNo,
        }) || {};

        var isNeedCreate = !eaccount.eaccountid || eaccount.userName != params.idName || eaccount.mobile != params.mobile;

        eaccount.user_id = user.id;
        eaccount.userName = params.idName;
        eaccount.mobile = params.mobile;
        eaccount.personsSign = params.idNo;
        if (eaccount.id) {
            await eaccount.save();
        } else {
            eaccount = await this.usereaccountDao.create(eaccount);
        }

        // c_econtract
        var econtract = await this.dao.findOne({
            eflowstatus: '2',
            usereaccount_id: eaccount.id,
            etemplate_id: ecid,
        });

        if (econtract) {
            return this.returnjson(0, "用户已经签约", {
                contractId: econtract.id
            });
        }

        // e签宝流程
        if (isNeedCreate) {
            var uidStr = await this.getUidStr(8, 36);
            var thirdId = etemplate.id + "_" + eaccount.id + uidStr;

            //2.创建e签宝account 5.2.1 , 创建后save()
            var params = {
                thirdId: thirdId,
                name: eaccount.userName,
                idNo: eaccount.personsSign,
                idType: 19,
                mobile: eaccount.mobile
            };
            var getAccount = await this.utilesignbaoSve.createAccountId(params, "econtractSve");
            if (getAccount && getAccount.code == 1 && getAccount.data) {
                eaccount.eaccountid = getAccount.data.accountId;
                await eaccount.save();
            } else {
                return this.returnjson(-1, "账户创建失败");
            }
        }

        // 3.设置静默签署授权 5.2.5
        if (!eaccount.isGrantAuto) {
            var paramsGrant = {
                grantAccountId: eaccount.eaccountid
            };
            var grantAuto = await this.utilesignbaoSve.grantAuthorization(paramsGrant, "econtractSve");
            if (grantAuto.code != 1) {
                return this.returnjson(-1, "静默签署设置失败");
            }
            eaccount.isGrantAuto = true;
            await eaccount.save();
        }

        // 创建合同   fileurl、esignUrl 怎么赋值????????????
        econtract = {
            name: ecompany.name,
            eflowstatusname: "签约中",
            eflowstatus: "1",
            // begin_at: now,
            // completed_at: now,
            user_id: eaccount.user_id,
            usereaccount_id: eaccount.id,
            etemplate_id: etemplate.id,
            ecompany_id: ecompany.id,
            // end_at: end,
        };
        econtract = await this.create(econtract);

        // 创建印章id
        var sealId = "";
        var eseal = await this.esealSve.findOne({
            nameA: etemplate.nameA
        });
        // 生产环境需要打开
        if (!eseal) {
            // var accountId = "";  // 测试
            var rs = await this.utilesignbaoSve.creatEntSignet(settings.apiconfig.companyAccountId(), etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            // var rs = await this.utilesignbaoSve.creatEntSignet("740b19e0799a4d7abacfa1a31fb72b1e", etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            if (rs && rs.code == 1) {
                sealId = rs.data.sealId;
                await this.esealSve.create({
                    nameA: etemplate.nameA,
                    sealId: sealId,
                });
            } else {
                return this.returnjson(-1, "生成印章错误");
            }
        } else {
            sealId = eseal.sealId;
        }

        let today = new Date().Format("yyyy-MM-dd");
        var signParams = {
            templateId: etemplate.templateid, //模板id，由创建模板接口调用返回的templateId 必填
            name: ecompany.name, //合同模板名称 必填
            simpleFormFields: {
                nameA: etemplate.nameA, //甲方 必填
                nameB: eaccount.userName, //乙方 必填
                unit: ecompany.name, //合作单位（国美） 必填---------------------------超出长度风险---目前不知多少长度
                signDateA: today, //甲方签约日期 必填
                signDateB: today //乙方签约日期 必填
            }
        };
        var ebaoAccountId = eaccount.eaccountid; //签署人账户id-- 必填
        var thirdOrderNo = econtract.id; //第三方流水号，通知回调使用---选填
        var eBaoRedirectBossUrl = "";

        var tt = await this.utilesignbaoSve.userAutoSignContractNoTemplate(signParams, ebaoAccountId, thirdOrderNo, eBaoRedirectBossUrl, "econtractSve", sealId);
        if (tt && tt.data && tt.code == 1) {
            econtract.eflowid = tt.data.flowId;
            econtract.edocid = tt.data.docId;
            econtract.eflowstatus = '2';
            econtract.eflowstatusname = "已完成";

            var signTime = new Date();
            econtract.completed_at = signTime;
            econtract.begin_at = signTime;
            var end_at = new Date();
            end_at.setFullYear(end_at.getFullYear() + 1);
            econtract.end_at = end_at;

            await econtract.save();
            this.syncSign(econtract.id);
            // TODO DOWNLOAD OK
            this.redisClient.rpushBCD({id: econtract.id, sve: "e"});

            return this.returnjson(0, "success", {
                contractId: econtract.id
            });
        }
        return this.returnjson(-1, tt.message || "签约失败", tt.code);
    }


    /**
     * 静默签
     * @param {ecid, appId, userId, idName, idNo, nonceStr, sign} params
     */
    async autoSignPersonalTwo(params) {
        var ecid = params.ecid;

        var unionId = params.appId + "_" + params.userId;
        // ecid etemplate
        var etemplate = await this.etemplateSve.findById(ecid);

        // ecompany
        var ecompany = await this.ecompanyDao.findById(etemplate.ecompany_id);

        // p_user
        var user = await this.userDao.findOne({
            unionId: unionId,
        });
        if (!user) {
            user = await this.userDao.create({
                appkey: params.appId,
                unionId: unionId,
                userName: params.idName,
                userId3rd: params.userId,
                userCode3rd: "",
                branchCode3rd: "",
                mobile: "",
                utype: 0,
            });
        }

        // p_user_eaccount
        var eaccount = await this.usereaccountDao.findOne({
            user_id: user.id,
            personsSign: params.idNo,
        }) || {};

        var isNeedCreate = !eaccount.eaccountid || eaccount.userName != params.idName;

        eaccount.user_id = user.id;
        eaccount.userName = params.idName;
        eaccount.personsSign = params.idNo;
        if (eaccount.id) {
            await eaccount.save();
        } else {
            eaccount = await this.usereaccountDao.create(eaccount);
        }
        let log = await this.bankthreelogDao.findOne({
            userName: eaccount.userName,
            userIdNo: eaccount.personsSign,
            use_esign: 1,
        });
        if (!log) {
            log = await this.bankthreelogDao.create({
                appId: params.appId,
                userName: eaccount.userName,
                userIdNo: eaccount.personsSign,
                use_esign: 1,
            });

            var vparam = {
                name: eaccount.userName,
                idno: eaccount.personsSign,
            };

            var threeResult = await this.utilesignbaoSve.personTwo(vparam, "autoSignPT");
            console.log("threeResult-----------------------------", threeResult);
            if (!threeResult || threeResult.code == -120) {
                return this.returnjson(-1, "银行二要素（姓名、身份证）验证失败");
            }
            if (threeResult.code == -110) {
                return this.returnjson(-1, "银行二要素验证失败");
            }

            log.result = 1;
            log.save();
        }

        // c_econtract
        var econtract = await this.dao.findOne({
            eflowstatus: '2',
            usereaccount_id: eaccount.id,
            etemplate_id: ecid,
        });

        if (econtract) {
            return this.returnjson(0, "用户已经签约", {
                contractId: econtract.id
            });
        }

        // e签宝流程
        if (isNeedCreate) {


            var uidStr = await this.getUidStr(8, 36);
            var thirdId = etemplate.id + "_" + eaccount.id + uidStr;

            //2.创建e签宝account 5.2.1 , 创建后save()
            var params = {
                thirdId: thirdId,
                name: eaccount.userName,
                idNo: eaccount.personsSign,
                idType: 19,
            };
            var getAccount = await this.utilesignbaoSve.createAccountId(params, "econtractSve");
            if (getAccount && getAccount.code == 1 && getAccount.data) {
                eaccount.eaccountid = getAccount.data.accountId;
                await eaccount.save();
            } else {
                return this.returnjson(-1, "账户创建失败");
            }
        }

        // 3.设置静默签署授权 5.2.5
        if (!eaccount.isGrantAuto) {
            var paramsGrant = {
                grantAccountId: eaccount.eaccountid
            };
            var grantAuto = await this.utilesignbaoSve.grantAuthorization(paramsGrant, "econtractSve");
            if (grantAuto.code != 1) {
                return this.returnjson(-1, "静默签署设置失败");
            }
            eaccount.isGrantAuto = true;
            await eaccount.save();
        }

        // 创建合同   fileurl、esignUrl 怎么赋值????????????
        econtract = {
            name: ecompany.name,
            eflowstatusname: "签约中",
            eflowstatus: "1",
            // begin_at: now,
            // completed_at: now,
            user_id: eaccount.user_id,
            usereaccount_id: eaccount.id,
            etemplate_id: etemplate.id,
            ecompany_id: ecompany.id,
            // end_at: end,
        };
        econtract = await this.create(econtract);

        // 创建印章id
        var sealId = "";
        var eseal = await this.esealSve.findOne({
            nameA: etemplate.nameA
        });
        // 生产环境需要打开
        if (!eseal) {
            // var accountId = "";  // 测试

            var rs = await this.utilesignbaoSve.creatEntSignet(settings.apiconfig.companyAccountId(), etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            // var rs = await this.utilesignbaoSve.creatEntSignet("740b19e0799a4d7abacfa1a31fb72b1e", etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            if (rs && rs.code == 1) {
                sealId = rs.data.sealId;
                await this.esealSve.create({
                    nameA: etemplate.nameA,
                    sealId: sealId,
                });
            } else {
                return this.returnjson(-1, "生成印章错误");
            }
        } else {
            sealId = eseal.sealId;
        }

        let today = new Date().Format("yyyy-MM-dd");
        var signParams = {
            templateId: etemplate.templateid, //模板id，由创建模板接口调用返回的templateId 必填
            name: ecompany.name, //合同模板名称 必填
            simpleFormFields: {
                nameA: etemplate.nameA, //甲方 必填
                nameB: eaccount.userName, //乙方 必填
                unit: ecompany.name, //合作单位（国美） 必填---------------------------超出长度风险---目前不知多少长度
                signDateA: today, //甲方签约日期 必填
                signDateB: today //乙方签约日期 必填
            }
        };
        var ebaoAccountId = eaccount.eaccountid; //签署人账户id-- 必填
        var thirdOrderNo = econtract.id; //第三方流水号，通知回调使用---选填
        var eBaoRedirectBossUrl = "";

        var tt = await this.utilesignbaoSve.userAutoSignContractNoTemplate(signParams, ebaoAccountId, thirdOrderNo, eBaoRedirectBossUrl, "econtractSve", sealId);
        if (tt && tt.data && tt.code == 1) {
            econtract.eflowid = tt.data.flowId;
            econtract.edocid = tt.data.docId;
            econtract.eflowstatus = '2';
            econtract.eflowstatusname = "已完成";

            var signTime = new Date();
            econtract.completed_at = signTime;
            econtract.begin_at = signTime;
            var end_at = new Date();
            end_at.setFullYear(end_at.getFullYear() + 1);
            econtract.end_at = end_at;

            await econtract.save();
            this.syncSign(econtract.id);
            // TODO DOWNLOAD
            this.redisClient.rpushBCD({id: econtract.id, sve: "e"});

            return this.returnjson(0, "success", {
                contractId: econtract.id
            });
        }
        return this.returnjson(-1, tt.message || "签约失败", tt.code);
    }

    async autoSignBankTwo(params){
        var ecid = params.ecid;

        var unionId = params.appId + "_" + params.userId;
        // ecid etemplate
        var etemplate = await this.etemplateSve.findById(ecid);

        // ecompany
        var ecompany = await this.ecompanyDao.findById(etemplate.ecompany_id);

        // p_user
        var user = await this.userDao.findOne({
            unionId: unionId,
        });
        if (!user) {
            user = await this.userDao.create({
                appkey: params.appId,
                unionId: unionId,
                userName: params.idName,
                userId3rd: params.userId,
                userCode3rd: "",
                branchCode3rd: "",
                mobile: "",
                utype: 0,
            });
        }

        // p_user_eaccount
        var eaccount = await this.usereaccountDao.findOne({
            user_id: user.id,
            personsSign: params.idNo,
        }) || {};

        var isNeedCreate = !eaccount.eaccountid || eaccount.userName != params.idName;

        eaccount.user_id = user.id;
        eaccount.userName = params.idName;
        eaccount.personsSign = params.idNo;
        if (eaccount.id) {
            await eaccount.save();
        } else {
            eaccount = await this.usereaccountDao.create(eaccount);
        }
        let log = await this.bankthreelogDao.findOne({
            userName: eaccount.userName,
            userIdNo: eaccount.personsSign,
            use_esign: 1,
        });
        if (!log) {
            log = await this.bankthreelogDao.create({
                appId: params.appId,
                userName: eaccount.userName,
                userIdNo: eaccount.personsSign,
                use_esign: 1,
            });

            var vparam = {
                name: eaccount.userName,
                idno: eaccount.personsSign,
            };

            var threeResult = await this.utilesignbaoSve.personTwo(vparam, "autoSignPT");
            console.log("threeResult-----------------------------", threeResult);
            if (!threeResult || threeResult.code == -120) {
                return this.returnjson(-1, "银行二要素（姓名、身份证）验证失败");
            }
            if (threeResult.code == -110) {
                return this.returnjson(-1, "银行二要素验证失败");
            }

            log.result = 1;
            log.save();
        }

        // c_econtract
        var econtract = await this.dao.findOne({
            eflowstatus: '2',
            usereaccount_id: eaccount.id,
            etemplate_id: ecid,
        });

        if (econtract) {
            return this.returnjson(0, "用户已经签约", {
                contractId: econtract.id
            });
        }

        // e签宝流程
        if (isNeedCreate) {


            var uidStr = await this.getUidStr(8, 36);
            var thirdId = etemplate.id + "_" + eaccount.id + uidStr;

            //2.创建e签宝account 5.2.1 , 创建后save()
            var params = {
                thirdId: thirdId,
                name: eaccount.userName,
                idNo: eaccount.personsSign,
                idType: 19,
            };
            var getAccount = await this.utilesignbaoSve.createAccountId(params, "econtractSve");
            if (getAccount && getAccount.code == 1 && getAccount.data) {
                eaccount.eaccountid = getAccount.data.accountId;
                await eaccount.save();
            } else {
                return this.returnjson(-1, "账户创建失败");
            }
        }

        // 3.设置静默签署授权 5.2.5
        if (!eaccount.isGrantAuto) {
            var paramsGrant = {
                grantAccountId: eaccount.eaccountid
            };
            var grantAuto = await this.utilesignbaoSve.grantAuthorization(paramsGrant, "econtractSve");
            if (grantAuto.code != 1) {
                return this.returnjson(-1, "静默签署设置失败");
            }
            eaccount.isGrantAuto = true;
            await eaccount.save();
        }

        // 创建合同   fileurl、esignUrl 怎么赋值????????????
        econtract = {
            name: ecompany.name,
            eflowstatusname: "签约中",
            eflowstatus: "1",
            // begin_at: now,
            // completed_at: now,
            user_id: eaccount.user_id,
            usereaccount_id: eaccount.id,
            etemplate_id: etemplate.id,
            ecompany_id: ecompany.id,
            // end_at: end,
        };
        econtract = await this.create(econtract);

        // 创建印章id
        var sealId = "";
        var eseal = await this.esealSve.findOne({
            nameA: etemplate.nameA
        });
        // 生产环境需要打开
        if (!eseal) {
            // var accountId = "";  // 测试

            var rs = await this.utilesignbaoSve.creatEntSignet(settings.apiconfig.companyAccountId(), etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            // var rs = await this.utilesignbaoSve.creatEntSignet("740b19e0799a4d7abacfa1a31fb72b1e", etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            if (rs && rs.code == 1) {
                sealId = rs.data.sealId;
                await this.esealSve.create({
                    nameA: etemplate.nameA,
                    sealId: sealId,
                });
            } else {
                return this.returnjson(-1, "生成印章错误");
            }
        } else {
            sealId = eseal.sealId;
        }

        let today = new Date().Format("yyyy-MM-dd");
        var signParams = {
            templateId: etemplate.templateid, //模板id，由创建模板接口调用返回的templateId 必填
            name: ecompany.name, //合同模板名称 必填
            simpleFormFields: {
                nameA: etemplate.nameA, //甲方 必填
                nameB: eaccount.userName, //乙方 必填
                unit: ecompany.name, //合作单位（国美） 必填---------------------------超出长度风险---目前不知多少长度
                signDateA: today, //甲方签约日期 必填
                signDateB: today //乙方签约日期 必填
            }
        };
        var ebaoAccountId = eaccount.eaccountid; //签署人账户id-- 必填
        var thirdOrderNo = econtract.id; //第三方流水号，通知回调使用---选填
        var eBaoRedirectBossUrl = "";

        var tt = await this.utilesignbaoSve.userAutoSignContractNoTemplate(signParams, ebaoAccountId, thirdOrderNo, eBaoRedirectBossUrl, "econtractSve", sealId);
        if (tt && tt.data && tt.code == 1) {
            econtract.eflowid = tt.data.flowId;
            econtract.edocid = tt.data.docId;
            econtract.eflowstatus = '2';
            econtract.eflowstatusname = "已完成";

            var signTime = new Date();
            econtract.completed_at = signTime;
            econtract.begin_at = signTime;
            var end_at = new Date();
            end_at.setFullYear(end_at.getFullYear() + 1);
            econtract.end_at = end_at;

            await econtract.save();
            this.syncSign(econtract.id);
            // TODO DOWNLOAD
            this.redisClient.rpushBCD({id: econtract.id, sve: "e"});

            return this.returnjson(0, "success", {
                contractId: econtract.id
            });
        }
        return this.returnjson(-1, tt.message || "签约失败", tt.code);
    }

    async autoSignWX(params){
        let ecid = params.ecid;
        // 验证身份证是否签约过
        let todays = moment().format("YYYY-MM-DD") + " 00:00:00";
        let contractId = await this.dao.findSignedContractId({idno: params.idNo, ecid: ecid, today : todays}) || 0;
        if (contractId) {
            return this.returnjson(0, "用户已经签约", {
                contractId: contractId
            });
        }

        // ecid etemplate
        var etemplate = await this.etemplateSve.findById(ecid);

        // ecompany
        var ecompany = await this.ecompanyDao.findById(etemplate.ecompany_id);

        // p_user
        var unionId = params.appId + "_" + params.idNo;
        var user = await this.userDao.findOne({
            unionId: unionId,
        });
        if (!user) {
            user = await this.userDao.create({
                appkey: params.appId,
                unionId: unionId,
                userId3rd: params.userId,
                userName: params.idName,
                mobile: params.mobile,
                utype: 0,
            });
        }

        // p_user_eaccount
        var eaccount = await this.usereaccountDao.findOne({
            user_id: user.id,
            personsSign: params.idNo,
        }) || {};

        var isNeedCreate = !eaccount.eaccountid || eaccount.userName != params.idName || eaccount.mobile != params.mobile || eaccount.bankno != params.bankno;

        eaccount.user_id = user.id;
        eaccount.userName = params.idName;
        eaccount.mobile = params.mobile;
        eaccount.bankno = params.bankno;
        eaccount.personsSign = params.idNo;
        if (eaccount.id) {
            await eaccount.save();
        } else {
            eaccount = await this.usereaccountDao.create(eaccount);
        }

        // e签宝流程
        if (isNeedCreate) {
            var uidStr = await this.getUidStr(8, 36);
            var thirdId = etemplate.id + "_" + eaccount.id + uidStr;

            //2.创建e签宝account 5.2.1 , 创建后save()
            var params = {
                thirdId: thirdId,
                name: eaccount.userName,
                idNo: eaccount.personsSign,
                idType: 19,
                mobile: eaccount.mobile
            };
            var getAccount = await this.utilesignbaoSve.createAccountId(params, "econtractSve");
            if (getAccount && getAccount.code == 1 && getAccount.data) {
                eaccount.eaccountid = getAccount.data.accountId;
                await eaccount.save();
            } else {
                return this.returnjson(-1, "账户创建失败");
            }
        }

        // 3.设置静默签署授权 5.2.5
        if (!eaccount.isGrantAuto) {
            var paramsGrant = {
                grantAccountId: eaccount.eaccountid
            };
            var grantAuto = await this.utilesignbaoSve.grantAuthorization(paramsGrant, "econtractSve");
            if (grantAuto.code != 1) {
                return this.returnjson(-1, "静默签署设置失败");
            }
            eaccount.isGrantAuto = true;
            await eaccount.save();
        }

        // 创建合同   fileurl、esignUrl 怎么赋值????????????
        let econtract = {
            name: ecompany.name,
            eflowstatusname: "签约中",
            eflowstatus: "1",
            // begin_at: now,
            // completed_at: now,
            user_id: eaccount.user_id,
            usereaccount_id: eaccount.id,
            etemplate_id: etemplate.id,
            ecompany_id: ecompany.id,
            // end_at: end,
        };
        econtract = await this.create(econtract);

        // 创建印章id
        var sealId = "";
        var eseal = await this.esealSve.findOne({
            nameA: etemplate.nameA
        });
        // 生产环境需要打开
        if (!eseal) {

            var rs = await this.utilesignbaoSve.creatEntSignet(settings.apiconfig.companyAccountId(), etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            // var rs = await this.utilesignbaoSve.creatEntSignet("740b19e0799a4d7abacfa1a31fb72b1e", etemplate.nameA + "alias", etemplate.nameA, "", "", "econtractSve");
            if (rs && rs.code == 1) {
                sealId = rs.data.sealId;
                await this.esealSve.create({
                    nameA: etemplate.nameA,
                    sealId: sealId,
                });
            } else {
                return this.returnjson(-1, "生成印章错误");
            }
        } else {
            sealId = eseal.sealId;
        }

        let today = new Date().Format("yyyy-MM-dd");
        var signParams = {
            templateId: etemplate.templateid, //模板id，由创建模板接口调用返回的templateId 必填
            name: ecompany.name, //合同模板名称 必填
            simpleFormFields: {
                nameA: etemplate.nameA, //甲方 必填
                nameB: eaccount.userName, //乙方 必填
                unit: ecompany.name, //合作单位（国美） 必填---------------------------超出长度风险---目前不知多少长度
                signDateA: today, //甲方签约日期 必填
                signDateB: today //乙方签约日期 必填
            }
        };
        var ebaoAccountId = eaccount.eaccountid; //签署人账户id-- 必填
        var thirdOrderNo = econtract.id; //第三方流水号，通知回调使用---选填
        var eBaoRedirectBossUrl = "";

        var tt = await this.utilesignbaoSve.userAutoSignContractNoTemplate(signParams, ebaoAccountId, thirdOrderNo, eBaoRedirectBossUrl, "econtractSve", sealId);
        if (tt && tt.data && tt.code == 1) {
            econtract.eflowid = tt.data.flowId;
            econtract.edocid = tt.data.docId;
            econtract.eflowstatus = '2';
            econtract.eflowstatusname = "已完成";

            var signTime = new Date();
            econtract.completed_at = signTime;
            econtract.begin_at = signTime;
            var end_at = new Date();
            end_at.setFullYear(end_at.getFullYear() + 1);
            econtract.end_at = end_at;

            await econtract.save();
            this.syncSign(econtract.id);
            // TODO DOWNLOAD OK
            this.redisClient.rpushBCD({id: econtract.id, sve: "e"});
            return this.returnjson(0, "success", {
                contractId: econtract.id
            });
        }
        return this.returnjson(-1, tt.message || "签约失败", tt.code);
    }

    returnjson(code, msg, data) {
        return {
            code: code,
            msg: msg,
            data: data || null
        }
    }

    async validLwbSign(idNo, ecid) {
        if(!idNo || !ecid) {
            return false;
        }
        let ids = await this.usereaccountDao.idsByCondition({personsSign: idNo});
        if (!ids || ids.length == 0) {
            return false;
        }

        let list = await this.dao.getFlowIdsAccountIds(ids, ecid);
        return list && list.length > 0;
    }

    async lwbContractUrl(idNo, ecid) {
        try {
            let ids = await this.usereaccountDao.idsByCondition({personsSign: idNo});
            if (!ids || ids.length == 0) {
                return "-1";
            }

            let list = await this.dao.getFlowIdsAccountIds(ids, ecid);
            if(!list || list.length == 0) {
                return "-1";
            }

            for(var item of list) {
                if (item.fileurl) {
                    return item.fileurl;
                }
            }
            let contract = await this.dao.findById(list[0].id);
            let fileRs = await this.utilesignbaoSve.downloadUserContractFile(contract.eflowid, "econtractSve");
            if (fileRs.code == 1 && fileRs.data.selfossUrl) {
                contract.fileurl = fileRs.data.selfossUrl;
                contract.save();
                return contract.fileurl;
            }
            return "";
        }catch (e) {
            console.log(e);
            return system.getErrResult2("接口异常");
        }
    }

    async downloadContract(id) {
        try {
            let contract = await this.dao.findById(id);
            if (!contract || contract.eflowstatus != "2" || contract.fileurl) {
                return ;
            }

            //await this.syncYzSign(2134);
            //  请求文件地址
            let fileRs = await this.utilesignbaoSve.downloadUserContractFile(contract.eflowid, "econtractSve");
            if (fileRs.code == 1 && fileRs.data.selfossUrl) {
                contract.fileurl = fileRs.data.selfossUrl;
                await contract.save();
                this.syncYzSign(contract.id);
            } else {
                await this.utilesignbaoSve.archiveProcess({flowId: contract.eflowid}, "econtractSve");
                let fileRs = await this.utilesignbaoSve.downloadUserContractFile(contract.eflowid, "econtractSve");
                if (fileRs.code == 1 && fileRs.data.selfossUrl) {
                    contract.fileurl = fileRs.data.selfossUrl;
                    await contract.save();
                    this.syncYzSign(contract.id);
                }
            }
        } catch (e) {
            console.error(e);
            return {
                code: -200,
                message: "error",
                data: {}
            };
        }
    }
}

module.exports = EcontractService;
