package asign import ( "bytes" "encoding/json" "errors" "fmt" "io" "mtp2_if/config" "mtp2_if/db" "mtp2_if/logger" "mtp2_if/models" "mtp2_if/utils" "net/http" "strconv" ) // BankCard4 银行卡四要素认证 func BankCard4(req BankCard4Req) (rsp BankCard4Rsp, err error) { // 校验入参 if req.Type == 1 && req.Person == nil { err = errors.New("缺少参数") return } if req.Type == 2 && req.Company == nil { err = errors.New("缺少参数") return } // 判断证件号码是否已经在爱签平台存在 var getUserReq APIGetUserReq getUserReq.Account = strconv.Itoa(req.UserId) apiRsp, err := APIGetUser(getUserReq) if err != nil { return } if apiRsp.Code == CODE_SUCCESS { err = errors.New("电子签平台用户编号已存在") logger.GetLogger().Error("电子签平台用户编号已存在, apiRsp:", apiRsp) return } getUserReq.Account = "" if req.Type == 1 { getUserReq.IdCard = req.Person.IdCardNo } else { getUserReq.CreditCode = req.Company.CreditCode } apiRsp, err = APIGetUser(getUserReq) if err != nil { return } if apiRsp.Code == CODE_SUCCESS && len(apiRsp.Data) > 0 { err = errors.New("电子签平台证件号码已存在") logger.GetLogger().Error("电子签平台证件号码已存在, apiRsp:", apiRsp) return } // 从交易库中获取类型为实名认证的电子签信息 var record models.Useresignrecord has, err := db.GetEngine().Where("TEMPLATETYPE = 1 AND USERID = ?", req.UserId).Get(&record) if err != nil { return } if !has { err = errors.New("无对应实名认证记录信息") logger.GetLogger().Error("无对应实名认证记录信息, userId:", req.UserId) return } if record.RECORDSTATUS == 3 { err = errors.New("账户已实名") logger.GetLogger().Error("账户已实名, userId:", req.UserId) return } // 调用爱签接口 var authinfo []byte var bankCard4Rsp *APIRsp[APIBankCard4Rsp] if req.Type == 1 { // 个人 personBankCard4Req := APIPersonBankCard4Req{ RealName: req.Person.RealName, IdCardNo: req.Person.IdCardNo, BankCard: req.Person.BankCard, Mobile: req.Person.Mobile, } if bankCard4Rsp, err = APIPersonBankCard4(personBankCard4Req); err != nil { return } if authinfo, err = json.Marshal(req.Person); err != nil { return } } else { // 企业 companyBankCard4Req := APICompanyBankCard4Req{ CompanyName: req.Company.CompanyName, CreditCode: req.Company.CreditCode, RealName: req.Company.RealName, IdCardNo: req.Company.IdCardNo, BankCard: req.Company.BankCard, Mobile: req.Company.Mobile, } if bankCard4Rsp, err = APICompanyBankCard4(companyBankCard4Req); err != nil { return } if authinfo, err = json.Marshal(req.Company); err != nil { return } } if bankCard4Rsp.Code != CODE_SUCCESS { err = errors.New(bankCard4Rsp.Msg) return } rsp.SerialNo = bankCard4Rsp.Data.SerialNo // 更新用户电子签记录-记录实名信息 sql := fmt.Sprintf(` UPDATE useresignrecord SET RECORDSTATUS = 2, UPDATETIME = SYSDATE, AUTHINFO = '%v' WHERE USERID = %v AND TEMPLATETYPE = 1 `, string(authinfo), req.UserId) _, err = db.GetEngine().Exec(sql) return } // CaptcaResend 重新发送认证验证码 func CaptcaResend(req CaptchaResendReq) (err error) { apiReq := APICaptchaResendReq{SerialNo: req.SerialNo} apiRsp, err := APICaptchaResend(apiReq) if err != nil { return } if apiRsp.Code != CODE_SUCCESS { err = errors.New(apiRsp.Msg) return } return } // CaptchaVerify 认证验证码校验 func CaptchaVerify(req CaptchaVerifyReq) (err error) { // 从交易库中获取类型为实名认证的电子签信息 var record models.Useresignrecord has, err := db.GetEngine().Where("TEMPLATETYPE = 1 AND RECORDSTATUS = 2 AND USERID = ?", req.UserId).Get(&record) if err != nil { return } if !has { err = errors.New("无对应实名认证记录信息") logger.GetLogger().Error("无对应实名认证记录信息, userId:", req.UserId) return } // 调用爱签接口 - 认证验证码校验 apiReq := APICaptchaVerifyReq{ SerialNo: req.SerialNo, Captcha: req.Captcha, } apiRsp, err := APICaptchaVerify(apiReq) if err != nil { return } if apiRsp.Code != CODE_SUCCESS { err = errors.New(apiRsp.Msg) return } // 调用爱签接口 - 添加用户 var addUserRsp *APIRsp[APIAddUserRsp] if req.Type == 1 { // 个人 addPersonalUserReq := APIAddPersonalUserReq{ Account: strconv.Itoa(req.UserId), SerialNo: req.SerialNo, } if addUserRsp, err = APIAddPersonalUser(addPersonalUserReq); err != nil { return } } else { // 企业 addEnterpriseUserReq := APIAddEnterpriseUserReq{ Account: strconv.Itoa(req.UserId), SerialNo: req.SerialNo, } if addUserRsp, err = APIAddEnterpriseUser(addEnterpriseUserReq); err != nil { return } } if addUserRsp.Code != CODE_SUCCESS { err = errors.New(addUserRsp.Msg) return } // 获取临时存储的用户认证信息 cacheMap := make(map[string]interface{}) if err = json.Unmarshal([]byte(record.AUTHINFO), &cacheMap); err != nil { logger.GetLogger().Error("反序列化临时存储用户信息失败, AUTHINFO:", record.AUTHINFO) return } // 调用JAVA实名认证接口 reqParam := make(map[string]interface{}) if req.Type == 1 { // 个人 reqParam["userid"] = req.UserId reqParam["cardnum"] = cacheMap["idCardNo"] reqParam["username"] = cacheMap["realName"] reqParam["cardtype"] = 0 // 目前写死证件类型为身份证 - 0 reqParam["cardfrontphotourl"] = cacheMap["idCardPhoto"] reqParam["cardbackphotourl"] = cacheMap["idCardPhotoBackURL"] reqParam["userinfotype"] = 1 // 1 - 个人 } else { reqParam["userid"] = req.UserId reqParam["customername"] = cacheMap["companyName"] reqParam["cardtype"] = 21 reqParam["cardfrontphotourl"] = cacheMap["idCardPhoto"] reqParam["legalpersonname"] = cacheMap["realName"] reqParam["cardnum"] = cacheMap["creditCode"] reqParam["mobilephone"] = cacheMap["mobile"] } jsonParam, err := json.Marshal(&reqParam) if err != nil { logger.GetLogger().Error("反序列化JAVA实名认证入参失败, reqParam:", reqParam) return } // 构建请求 javaUrl := config.SerCfg.AsignCfg.OpenApiUrl + "/onlineopen/userInfo/addAuth" javaReq, err := http.NewRequest("POST", javaUrl, bytes.NewReader(jsonParam)) // 设置请求头 javaReq.Header.Set("Content-Type", "application/json; charset=utf-8") client := &http.Client{} rsp, err := client.Do(javaReq) if err != nil { logger.GetLogger().Error("JAVA实名认证请求失败, err:", err) return } defer rsp.Body.Close() body, err := io.ReadAll(rsp.Body) if err != nil { logger.GetLogger().Error("JAVA实名认证请求获取body失败, err:", err) return } // rspData: map[code:0 hasAuth:1 message:认证成功] rspData := make(map[string]interface{}) if err = json.Unmarshal(body, &rspData); err != nil { logger.GetLogger().Error("JAVA实名认证请求反序列化body失败, err:", err) return } logger.GetLogger().Info("调用JAVA实名认证接口返回, rspData:", rspData) code, ok := rspData["code"] if !ok { err = errors.New("实名认证失败,请稍后重试") logger.GetLogger().Error(err.Error()) return } if code != "0" { err = fmt.Errorf("实名认证失败,%v", rspData["message"]) logger.GetLogger().Error(err.Error()) return } // 更新用户电子签记录 - 更新实名认证状态 sql := fmt.Sprintf(` UPDATE useresignrecord SET RECORDSTATUS = 3, UPDATETIME = SYSDATE WHERE USERID = %v AND TEMPLATETYPE = 1 `, req.UserId) _, err = db.GetEngine().Exec(sql) return } // SyncContractStatus 同步合同状态 func SyncContractStatus(req SyncContractStatusReq) (rsp SyncContractStatusRsp, err error) { // 从交易库中获取类型为实名认证的电子签信息 var record models.Useresignrecord has, err := db.GetEngine().Where("RECORDID = ?", req.RecordId).Get(&record) if err != nil { return } if !has { err = errors.New("查无此记录信息") logger.GetLogger().Error("查无此记录信息, RecordId:", req.RecordId) return } if record.CONTRACTNO == "" { err = errors.New("此记录未生成合同编号") logger.GetLogger().Error("此记录未生成合同编号, RecordId:", req.RecordId) return } // 调用爱签接口 - 查询合同状态 apiReq := APIContractStatusReq{ContractNo: record.CONTRACTNO} apiRsp, err := APIContractStatus(apiReq) if err != nil { return } if apiRsp.Code != CODE_SUCCESS { err = errors.New(apiRsp.Msg) return } status := record.RECORDSTATUS // 记录状态: 1:未签署 2:签署中 3:已签署 4:签署拒绝 switch apiRsp.Data.Status { // 合同状态:0:等待签约 1:签约中 2:已签约 3:过期 4:拒签 6:作废 -2:状态异常 case 0: status = 1 case 1: status = 2 case 2: status = 3 case 4: status = 4 } // 更新用户电子签记录 - 更新合同签署状态 sql := fmt.Sprintf(` UPDATE useresignrecord SET RECORDSTATUS = %v, UPDATETIME = SYSDATE WHERE RECORDID = %v `, status, req.RecordId) _, err = db.GetEngine().Exec(sql) if err != nil { return } rsp = SyncContractStatusRsp{ ContractNo: apiRsp.Data.ContractNo, ContractName: apiRsp.Data.ContractName, Status: apiRsp.Data.Status, } return } // PARTYA_SIGNATURE // PARTYA_DATE // // P_PARTYB_SIGNATURE // P_PARTYB_ID // P_PARTYB_MOBILE // P_PARTYB_DATE // // E_PARTYB_SIGNATURE // E_PARTYB_LEGAL // E_PARTYB_DATE // CreateContract 创建合同 func CreateContract(req CreateContractReq) (rsp CreateContractRsp, err error) { // 获取电子签信息 var record models.Useresignrecord has, err := db.GetEngine().Where("RECORDID = ?", req.RecordId).Get(&record) if err != nil { logger.GetLogger().Error("获取电子签信息失败, err", err) err = errors.New("获取电子签信息失败") return } if !has { err = errors.New("查无此记录信息") logger.GetLogger().Error("查无此记录信息, RecordId:", req.RecordId) return } if record.RECORDSTATUS != 1 { err = errors.New("记录信息状态异常") logger.GetLogger().Error("记录信息状态异常, RecordId:", req.RecordId, record.RECORDSTATUS) return } // // 获取电子签模板字段配置信息 // fields := make([]models.Esigntemplatefield, 0) // if err = db.GetEngine().Where("TEMPLATECONFIGID = ?", record.TEMPLATECONFIGID).Find(&fields); err != nil { // logger.GetLogger().Error("获取电子签模板字段配置信息失败, err", err) // err = errors.New("获取电子签模板字段配置信息失败") // return // } // if len(fields) == 0 { // err = errors.New("获取电子签模板字段配置信息异常") // logger.GetLogger().Error("获取电子签模板字段配置信息异常, templateconfigid:", record.TEMPLATECONFIGID) // return // } // 调用爱签接口 - 查询模板列表 apiReq := APITemplateListReq{Page: 1, Rows: 10} apiRsp, err := APITemplateList(apiReq) if err != nil { return } if apiRsp.Code != CODE_SUCCESS { err = errors.New(apiRsp.Msg) return } if len(apiRsp.Data.List) == 0 { err = errors.New("获取查询模板列表失败") logger.GetLogger().Error("获取查询模板列表失败") return } // 获取用户信息 userInfo, err := models.GetUserInfo(int(record.USERID)) if err != nil { logger.GetLogger().Error("获取用户信息失败, err:", err) err = errors.New("获取用户信息失败") return } templateName := record.TEMPLATENAME if userInfo.Userinfotype == 1 { // 个人 templateName += "-个人" } else { // 企业 templateName += "-企业" } // 获取模板信息 templateIdent := "" for _, item := range apiRsp.Data.List { if item.TemplateName == templateName { templateIdent = item.TemplateIdent break } } if templateIdent == "" { err = errors.New("获取模板信息失败") logger.GetLogger().Error("获取模板信息失败") return } // 获取用户实名信息 var recordAuth models.Useresignrecord has, err = db.GetEngine().Where("TEMPLATETYPE = 1 AND USERID = ?", userInfo.Userid).Get(&recordAuth) if err != nil { return } if !has { err = errors.New("无对应实名认证记录信息") logger.GetLogger().Error("无对应实名认证记录信息, userId:", userInfo.Userid) return } // 调用爱签接口 - 上传待签署文件 contractNo := strconv.Itoa(int(utils.GenID())) apiCreateContractReq := APICreateContractReq{ ContractNo: contractNo, ContractName: templateName, SignOrder: 1, ValidityTime: 30, NotifyUrl: config.SerCfg.AsignCfg.NotifyUrl, } apiCreateContractReq.Templates = []APITemplate{ { TemplateNo: templateIdent, }, } apiCreateContractRsp, err := APICreateContract(apiCreateContractReq) if err != nil { return } if apiCreateContractRsp.Code != CODE_SUCCESS { err = errors.New(apiCreateContractRsp.Msg) return } // 将合同编号写入数据库 sql := fmt.Sprintf(` UPDATE useresignrecord SET contractNo = '%v', UPDATETIME = SYSDATE WHERE RECORDID = %v `, contractNo, record.RECORDID) if _, err = db.GetEngine().Exec(sql); err != nil { logger.GetLogger().Error("更新合同编号失败, err:", err) err = errors.New("更新合同编号失败") return } // 添加签署方 - 甲方 - 交易所 appAddSignerReq1 := APIAddSignerReq{ ContractNo: contractNo, Account: "ZR_LEGAL", SignType: 2, // 无感知签约(需要开通权限) SignStrategyList: []APISignStrategy{ {AttachNo: 1, LocationMode: 4, SignKey: "PARTYA_SIGNATURE", SignType: 1}, // 甲方签章 {AttachNo: 1, LocationMode: 4, SignKey: "PARTYA_DATE", SignType: 2}, // 甲方签署时间 }, } // 获取临时存储的用户认证信息 cacheMap := make(map[string]interface{}) if err = json.Unmarshal([]byte(recordAuth.AUTHINFO), &cacheMap); err != nil { logger.GetLogger().Error("反序列化临时存储用户信息失败, AUTHINFO:", recordAuth.AUTHINFO) return } if recordAuth.AUTHINFO == "" { err = errors.New("获取实名信息失败") logger.GetLogger().Error("获取实名信息失败") return } // 添加签署方 - 乙方 - 投资者 appAddSignerReq2 := APIAddSignerReq{ ContractNo: contractNo, Account: strconv.Itoa(int(record.USERID)), SignType: 3, ValidateType: 3, } // 签章策略 signStrategyList := make([]APISignStrategy, 0) // 接收方模板填充策略 receiverFillStrategyList := make([]APIReceiverFillStrategy, 0) if userInfo.Userinfotype == 1 { // 个人 // 乙方签章 signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "P_PARTYB_SIGNATURE", SignType: 1}) // 乙方签署时间 signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "P_PARTYB_DATE", SignType: 2}) // 身份证号 receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "P_PARTYB_ID", Value: cacheMap["idCardNo"].(string)}) // 联系方式 receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "P_PARTYB_MOBILE", Value: cacheMap["mobile"].(string)}) } else { // 企业 // 乙方签章 signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "E_PARTYB_SIGNATURE", SignType: 1}) // 乙方签署时间 signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "E_PARTYB_DATE", SignType: 2}) // 法定代表人名称 receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "E_PARTYB_LEGAL", Value: cacheMap["realName"].(string)}) } appAddSignerReq2.SignStrategyList = signStrategyList appAddSignerReq2.ReceiverFillStrategyList = receiverFillStrategyList apiAddSignerRsp, err := APIAddSigner([]APIAddSignerReq{appAddSignerReq1, appAddSignerReq2}) if err != nil { return } if apiAddSignerRsp.Code != CODE_SUCCESS { err = errors.New(apiAddSignerRsp.Msg) return } if len(apiAddSignerRsp.Data.SignUser) == 0 { err = errors.New("获取合同签署地址失败") logger.GetLogger().Error("获取合同签署地址失败") return } // 将返回的合同签署地址写入数据库 sql = fmt.Sprintf(` UPDATE useresignrecord SET RECORDSTATUS = 2, SIGNURL = '%v', UPDATETIME = SYSDATE WHERE RECORDID = %v `, apiAddSignerRsp.Data.SignUser[0].SignUrl, record.RECORDID) if _, err = db.GetEngine().Exec(sql); err != nil { logger.GetLogger().Error("合同签署地址失败, err:", err) err = errors.New("合同签署地址失败") return } rsp = CreateContractRsp{SignUrl: apiAddSignerRsp.Data.SignUser[0].SignUrl} return } func ASignCompleted(contractNo, status string) (err error) { /* // 合同签署完成后回调通知示例 String publickey = "MFwwDQcccccxxxxmEz/nw27Ln6AP90ZCMPi+iNF1m9mhNECAwEAAQ=="; String remark = ""; // 若被拒签则会返回拒签原因,拒签原因不参与签名 Map map = new HashMap<>(); map.put("action", "signCompleted"); map.put("contractNo", "20221114142140345"); map.put("status", "2"); map.put("signTime", "2022-11-14 14:22:00"); map.put("timestamp", "1668406920005"); map.put("validityTime", "2022-11-24 23:59:59"); String json = JSONObject.toJSONString(map, SerializerFeature.MapSortField); System.out.println("数据:" + json); // 计算签名 try { String sign = "feFfcprGjdmDDqRmxK5qlWlMncX0mc6LJ5agebOGIx2QiAern+6ZRg/SBHOgvHp/+1ywVRdyKNUKxPneETwKPw=="; System.out.println(RSAUtils.rsaSignCheck(sign, json, publickey)); } catch (Exception e) { e.printStackTrace(); } */ // 获取合同编号 if contractNo == "" { logger.GetLogger().Error("获取合同编号失败") err = errors.New("获取合同编号失败") return } // 获取合同状态 if status == "" { logger.GetLogger().Error("获取获取合同状态失败") err = errors.New("获取获取合同状态失败") return } // 更新数据库记录 sql := fmt.Sprintf(` UPDATE useresignrecord SET RECORDSTATUS = 3, UPDATETIME = SYSDATE WHERE CONTRACTNO = '%v' `, contractNo) _, err = db.GetEngine().Exec(sql) return }