servcies.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  1. package asign
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "mtp2_if/config"
  9. "mtp2_if/db"
  10. "mtp2_if/logger"
  11. "mtp2_if/models"
  12. "mtp2_if/utils"
  13. "net/http"
  14. "strconv"
  15. )
  16. // CreateSeal 创建印章
  17. func CreateSeal(req CreateSealReq) (err error) {
  18. apiReq := APIReq[APICreateSealReq]{
  19. Data: APICreateSealReq{
  20. Account: req.Account,
  21. IsDefault: req.IsDefault,
  22. Base64ImageStr: req.Base64ImageStr,
  23. SealName: req.SealName,
  24. SealNo: strconv.Itoa(int(utils.GenID())),
  25. },
  26. }
  27. apiRsp, err := APIPost[APICreateSealReq, interface{}](apiReq, APIURL_CreateSeal)
  28. if err != nil {
  29. return
  30. }
  31. if apiRsp.Code != CODE_SUCCESS {
  32. err = errors.New(apiRsp.Msg)
  33. return
  34. }
  35. return
  36. }
  37. // ModifySeal 修改印章
  38. func ModifySeal(req ModifySealReq) (err error) {
  39. apiReq := APIReq[APIModifySealReq]{
  40. Data: APIModifySealReq{
  41. Account: req.Account,
  42. IsDefault: req.IsDefault,
  43. Base64ImageStr: req.Base64ImageStr,
  44. SealName: req.SealName,
  45. SealNo: req.SealNo,
  46. },
  47. }
  48. apiRsp, err := APIPost[APIModifySealReq, interface{}](apiReq, APIURL_ModifySeal)
  49. if err != nil {
  50. return
  51. }
  52. if apiRsp.Code != CODE_SUCCESS {
  53. err = errors.New(apiRsp.Msg)
  54. return
  55. }
  56. return
  57. }
  58. // BankCard4 银行卡四要素认证
  59. func BankCard4(req BankCard4Req) (rsp BankCard4Rsp, err error) {
  60. // 校验入参
  61. if req.Type == 1 && req.Person == nil {
  62. err = errors.New("缺少参数")
  63. return
  64. }
  65. if req.Type == 2 && req.Company == nil {
  66. err = errors.New("缺少参数")
  67. return
  68. }
  69. if req.Type == 1 {
  70. // 判断此身份证号已经已经被别的账户占用
  71. if idCardNo, e := models.EncryptField(req.Person.IdCardNo); e == nil {
  72. if us, e := models.GetUserInfoByIdCardNo(idCardNo); e == nil {
  73. if len(us) > 0 {
  74. u := us[0]
  75. if u.Userid != int64(req.UserId) {
  76. err = errors.New("身份证号已被占用")
  77. return
  78. }
  79. }
  80. }
  81. }
  82. // 判断此手机号码已经已经被别的账户占用
  83. if mobile, e := models.EncryptField(req.Person.Mobile); e == nil {
  84. if us, e := models.GetUserInfoByMobile(mobile); e == nil {
  85. if len(us) > 0 {
  86. u := us[0]
  87. if u.Userid != int64(req.UserId) {
  88. err = errors.New("手机号码已被占用")
  89. return
  90. }
  91. }
  92. }
  93. }
  94. }
  95. // 判断目标用户在爱签平台是否已经存在
  96. getUserReq := APIReq[APIGetUserReq]{}
  97. if req.Type == 1 {
  98. getUserReq.Data.IdCard = req.Person.IdCardNo
  99. } else {
  100. getUserReq.Data.CreditCode = req.Company.CreditCode
  101. }
  102. apiRsp, err := APIPost[APIGetUserReq, []APIGetUserRsp](getUserReq, APIURL_GetUser)
  103. if err != nil {
  104. return
  105. }
  106. if apiRsp.Code == CODE_SUCCESS && len(apiRsp.Data) > 0 {
  107. var has = false
  108. var record models.Useresignrecord
  109. has, err = db.GetEngine().Where("TEMPLATETYPE = 1 AND RECORDSTATUS = 1 AND USERID = ?", req.UserId).Get(&record)
  110. if err != nil {
  111. return
  112. }
  113. if !has {
  114. err = errors.New("无对应实名认证记录信息")
  115. logger.GetLogger().Error("无对应实名认证记录信息, userId:", req.UserId)
  116. return
  117. }
  118. // 判断四要素是否一致,如果一致则直接调用JAVA实名接口
  119. // 注意:爱签接口返回的BankCard为空
  120. apiGetUserRsp := apiRsp.Data[0]
  121. if req.Type == 1 {
  122. // 个人
  123. // if strconv.Itoa(req.UserId) == apiGetUserRsp.Account &&
  124. // req.Person.RealName == apiGetUserRsp.Name &&
  125. // req.Person.Mobile == apiGetUserRsp.Mobile {
  126. if req.Person.RealName == apiGetUserRsp.Name &&
  127. req.Person.Mobile == apiGetUserRsp.Mobile {
  128. // 更新用户电子签记录-记录实名信息
  129. var authinfo []byte
  130. if authinfo, err = json.Marshal(req.Person); err != nil {
  131. return
  132. }
  133. // 2024-05-13 由于存在用户注销后重新注册后USERID变化的问题,这里使用type=1中的contractno存储爱签中的key
  134. sql := fmt.Sprintf(`
  135. UPDATE useresignrecord
  136. SET RECORDSTATUS = 2,
  137. CONTRACTNO = '%v',
  138. UPDATETIME = SYSDATE,
  139. AUTHINFO = '%v'
  140. WHERE USERID = %v AND TEMPLATETYPE = 1
  141. `, apiGetUserRsp.Account, string(authinfo), req.UserId)
  142. if _, err = db.GetEngine().Exec(sql); err != nil {
  143. return
  144. }
  145. // 调用JAVA实名认证接口
  146. err = callJavaAuthFunc(&record, req.Type)
  147. return
  148. } else {
  149. // 证件号码已在爱签平台的另外的用户占用
  150. // err = errors.New("电子签平台证件号码已存在")
  151. // logger.GetLogger().Error("电子签平台证件号码已存在, apiRsp:", apiRsp)
  152. // return
  153. // 手机号码不一致,则走正常实名认证
  154. }
  155. } else {
  156. // 企业
  157. // if strconv.Itoa(req.UserId) == apiGetUserRsp.Account &&
  158. // req.Company.RealName == apiGetUserRsp.Name &&
  159. // req.Company.Mobile == apiGetUserRsp.Mobile &&
  160. // req.Company.CompanyName == apiGetUserRsp.CompanyName &&
  161. // req.Company.CreditCode == apiGetUserRsp.CreditCode {
  162. if req.Company.RealName == apiGetUserRsp.Name &&
  163. req.Company.Mobile == apiGetUserRsp.Mobile &&
  164. req.Company.CompanyName == apiGetUserRsp.CompanyName &&
  165. req.Company.CreditCode == apiGetUserRsp.CreditCode {
  166. // 更新用户电子签记录-记录实名信息
  167. var authinfo []byte
  168. if authinfo, err = json.Marshal(req.Company); err != nil {
  169. return
  170. }
  171. sql := fmt.Sprintf(`
  172. UPDATE useresignrecord
  173. SET RECORDSTATUS = 2,
  174. UPDATETIME = SYSDATE,
  175. AUTHINFO = '%v'
  176. WHERE USERID = %v AND TEMPLATETYPE = 1
  177. `, string(authinfo), req.UserId)
  178. if _, err = db.GetEngine().Exec(sql); err != nil {
  179. return
  180. }
  181. // 调用JAVA实名认证接口
  182. err = callJavaAuthFunc(&record, req.Type)
  183. return
  184. } else {
  185. // 社会统一信用代码已在爱签平台的另外的用户占用
  186. // err = errors.New("电子签平台社会统一信用代码已存在")
  187. // logger.GetLogger().Error("电子签平台社会统一信用代码已存在, apiRsp:", apiRsp)
  188. // return
  189. }
  190. }
  191. }
  192. // 从交易库中获取类型为实名认证的电子签信息
  193. var record models.Useresignrecord
  194. has, err := db.GetEngine().Where("TEMPLATETYPE = 1 AND USERID = ?", req.UserId).Get(&record)
  195. if err != nil {
  196. return
  197. }
  198. if !has {
  199. err = errors.New("无对应实名认证记录信息")
  200. logger.GetLogger().Error("无对应实名认证记录信息, userId:", req.UserId)
  201. return
  202. }
  203. if record.RECORDSTATUS == 3 {
  204. err = errors.New("账户已实名")
  205. logger.GetLogger().Error("账户已实名, userId:", req.UserId)
  206. return
  207. }
  208. // 调用爱签接口
  209. var authinfo []byte
  210. var bankCard4Rsp *APIRsp[APIBankCard4Rsp]
  211. if req.Type == 1 { // 个人
  212. personBankCard4Req := APIReq[APIPersonBankCard4Req]{
  213. Data: APIPersonBankCard4Req{
  214. RealName: req.Person.RealName,
  215. IdCardNo: req.Person.IdCardNo,
  216. BankCard: req.Person.BankCard,
  217. Mobile: req.Person.Mobile,
  218. },
  219. }
  220. if bankCard4Rsp, err = APIPost[APIPersonBankCard4Req, APIBankCard4Rsp](personBankCard4Req, APIURL_Person_BankCard4); err != nil {
  221. return
  222. }
  223. if authinfo, err = json.Marshal(req.Person); err != nil {
  224. return
  225. }
  226. } else { // 企业
  227. companyBankCard4Req := APIReq[APICompanyBankCard4Req]{
  228. Data: APICompanyBankCard4Req{
  229. CompanyName: req.Company.CompanyName,
  230. CreditCode: req.Company.CreditCode,
  231. RealName: req.Company.RealName,
  232. IdCardNo: req.Company.IdCardNo,
  233. BankCard: req.Company.BankCard,
  234. Mobile: req.Company.Mobile,
  235. },
  236. }
  237. if bankCard4Rsp, err = APIPost[APICompanyBankCard4Req, APIBankCard4Rsp](companyBankCard4Req, APIURL_Person_BankCard4); err != nil {
  238. return
  239. }
  240. if authinfo, err = json.Marshal(req.Company); err != nil {
  241. return
  242. }
  243. }
  244. if bankCard4Rsp.Code != CODE_SUCCESS {
  245. err = errors.New(bankCard4Rsp.Msg)
  246. return
  247. }
  248. rsp.SerialNo = bankCard4Rsp.Data.SerialNo
  249. // 更新用户电子签记录-记录实名信息
  250. sql := fmt.Sprintf(`
  251. UPDATE useresignrecord
  252. SET RECORDSTATUS = 2,
  253. UPDATETIME = SYSDATE,
  254. AUTHINFO = '%v'
  255. WHERE USERID = %v AND TEMPLATETYPE = 1
  256. `, string(authinfo), req.UserId)
  257. _, err = db.GetEngine().Exec(sql)
  258. return
  259. }
  260. // CaptcaResend 重新发送认证验证码
  261. func CaptcaResend(req CaptchaResendReq) (err error) {
  262. apiReq := APIReq[APICaptchaResendReq]{Data: APICaptchaResendReq{SerialNo: req.SerialNo}}
  263. apiRsp, err := APIPost[APICaptchaResendReq, interface{}](apiReq, APIURL_Captcha_Resend)
  264. if err != nil {
  265. return
  266. }
  267. if apiRsp.Code != CODE_SUCCESS {
  268. err = errors.New(apiRsp.Msg)
  269. return
  270. }
  271. return
  272. }
  273. // CaptchaVerify 认证验证码校验
  274. func CaptchaVerify(req CaptchaVerifyReq) (err error) {
  275. // 从交易库中获取类型为实名认证的电子签信息
  276. var record models.Useresignrecord
  277. has, err := db.GetEngine().Where("TEMPLATETYPE = 1 AND RECORDSTATUS = 2 AND USERID = ?", req.UserId).Get(&record)
  278. if err != nil {
  279. return
  280. }
  281. if !has {
  282. err = errors.New("无对应实名认证记录信息")
  283. logger.GetLogger().Error("无对应实名认证记录信息, userId:", req.UserId)
  284. return
  285. }
  286. // 调用爱签接口 - 认证验证码校验
  287. apiReq := APIReq[APICaptchaVerifyReq]{
  288. Data: APICaptchaVerifyReq{
  289. SerialNo: req.SerialNo,
  290. Captcha: req.Captcha,
  291. },
  292. }
  293. apiRsp, err := APIPost[APICaptchaVerifyReq, interface{}](apiReq, APIURL_Captcha_Verify)
  294. if err != nil {
  295. return
  296. }
  297. if apiRsp.Code != CODE_SUCCESS {
  298. err = errors.New(apiRsp.Msg)
  299. return
  300. }
  301. // 调用爱签接口 - 添加用户
  302. var addUserRsp *APIRsp[APIAddUserRsp]
  303. if req.Type == 1 { // 个人
  304. addPersonalUserReq := APIReq[APIAddPersonalUserReq]{
  305. Data: APIAddPersonalUserReq{
  306. Account: strconv.Itoa(req.UserId),
  307. SerialNo: req.SerialNo,
  308. },
  309. }
  310. if addUserRsp, err = APIPost[APIAddPersonalUserReq, APIAddUserRsp](addPersonalUserReq, APIURL_V2_User_AddPersonalUser); err != nil {
  311. return
  312. }
  313. } else { // 企业
  314. addEnterpriseUserReq := APIReq[APIAddEnterpriseUserReq]{
  315. Data: APIAddEnterpriseUserReq{
  316. Account: strconv.Itoa(req.UserId),
  317. SerialNo: req.SerialNo,
  318. },
  319. }
  320. if addUserRsp, err = APIPost[APIAddEnterpriseUserReq, APIAddUserRsp](addEnterpriseUserReq, APIURL_V2_User_AddEnterpriseUser); err != nil {
  321. return
  322. }
  323. }
  324. if addUserRsp.Code != CODE_SUCCESS {
  325. err = errors.New(addUserRsp.Msg)
  326. return
  327. }
  328. // 调用JAVA实名认证接口
  329. err = callJavaAuthFunc(&record, req.Type)
  330. return
  331. }
  332. // callJavaAuthFunc 调用JAVA实名认证接口
  333. func callJavaAuthFunc(record *models.Useresignrecord, userType int) (err error) {
  334. // 获取临时存储的用户认证信息
  335. cacheMap := make(map[string]interface{})
  336. if err = json.Unmarshal([]byte(record.AUTHINFO), &cacheMap); err != nil {
  337. logger.GetLogger().Errorf("反序列化临时存储用户信息失败, AUTHINFO: %s", record.AUTHINFO)
  338. return
  339. }
  340. // 调用JAVA实名认证接口
  341. reqParam := make(map[string]interface{})
  342. if userType == 1 { // 个人
  343. reqParam["userid"] = strconv.Itoa(int(record.USERID))
  344. reqParam["cardnum"] = cacheMap["idCardNo"]
  345. reqParam["username"] = cacheMap["realName"]
  346. reqParam["cardtype"] = 0 // 目前写死证件类型为身份证 - 0
  347. reqParam["cardfrontphotourl"] = cacheMap["idCardPhoto"]
  348. reqParam["cardbackphotourl"] = cacheMap["idCardPhotoBackURL"]
  349. reqParam["bankaccount"] = cacheMap["bankCard"]
  350. reqParam["bankid"] = cacheMap["bankId"]
  351. reqParam["userinfotype"] = 1 // 1 - 个人
  352. } else {
  353. reqParam["userid"] = strconv.Itoa(int(record.USERID))
  354. reqParam["customername"] = cacheMap["companyName"]
  355. reqParam["cardtype"] = 4 // 企业统一信用
  356. reqParam["cardfrontphotourl"] = cacheMap["idCardPhoto"]
  357. reqParam["legalpersonname"] = cacheMap["realName"]
  358. reqParam["cardnum"] = cacheMap["creditCode"]
  359. reqParam["mobilephone"] = cacheMap["mobile"]
  360. reqParam["userinfotype"] = 2 // 2 - 企业
  361. }
  362. jsonParam, err := json.Marshal(&reqParam)
  363. if err != nil {
  364. logger.GetLogger().Error("反序列化JAVA实名认证入参失败, reqParam:", reqParam)
  365. return
  366. }
  367. // 构建请求
  368. javaUrl := config.SerCfg.AsignCfg.OpenApiUrl + "/onlineopen/userInfo/addAuth"
  369. javaReq, err := http.NewRequest("POST", javaUrl, bytes.NewReader(jsonParam))
  370. // 设置请求头
  371. javaReq.Header.Set("Content-Type", "application/json; charset=utf-8")
  372. client := &http.Client{}
  373. rsp, err := client.Do(javaReq)
  374. if err != nil {
  375. logger.GetLogger().Error("JAVA实名认证请求失败, err:", err)
  376. return
  377. }
  378. defer rsp.Body.Close()
  379. body, err := io.ReadAll(rsp.Body)
  380. if err != nil {
  381. logger.GetLogger().Error("JAVA实名认证请求获取body失败, err:", err)
  382. return
  383. }
  384. // rspData: map[code:0 hasAuth:1 message:认证成功]
  385. rspData := make(map[string]interface{})
  386. if err = json.Unmarshal(body, &rspData); err != nil {
  387. logger.GetLogger().Error("JAVA实名认证请求反序列化body失败, err:", err)
  388. return
  389. }
  390. logger.GetLogger().Info("调用JAVA实名认证接口返回, rspData:", rspData)
  391. code, ok := rspData["code"]
  392. if !ok {
  393. err = errors.New("实名认证失败,请稍后重试")
  394. logger.GetLogger().Error(err.Error())
  395. return
  396. }
  397. if code != "0" {
  398. err = fmt.Errorf("实名认证失败,%v", rspData["message"])
  399. logger.GetLogger().Error(err.Error())
  400. return
  401. }
  402. // 更新用户电子签记录 - 更新实名认证状态
  403. sql := fmt.Sprintf(`
  404. UPDATE useresignrecord
  405. SET RECORDSTATUS = 3,
  406. UPDATETIME = SYSDATE
  407. WHERE USERID = %v AND TEMPLATETYPE = 1
  408. `, record.USERID)
  409. _, err = db.GetEngine().Exec(sql)
  410. return
  411. }
  412. // SyncContractStatus 同步合同状态
  413. func SyncContractStatus(req SyncContractStatusReq) (rsp SyncContractStatusRsp, err error) {
  414. // 从交易库中获取类型为实名认证的电子签信息
  415. var record models.Useresignrecord
  416. has, err := db.GetEngine().Where("RECORDID = ?", req.RecordId).Get(&record)
  417. if err != nil {
  418. return
  419. }
  420. if !has {
  421. err = errors.New("查无此记录信息")
  422. logger.GetLogger().Error("查无此记录信息, RecordId:", req.RecordId)
  423. return
  424. }
  425. if record.CONTRACTNO == "" {
  426. err = errors.New("此记录未生成合同编号")
  427. logger.GetLogger().Error("此记录未生成合同编号, RecordId:", req.RecordId)
  428. return
  429. }
  430. // 调用爱签接口 - 查询合同状态
  431. apiReq := APIReq[APIContractStatusReq]{Data: APIContractStatusReq{ContractNo: record.CONTRACTNO}}
  432. apiRsp, err := APIPost[APIContractStatusReq, APIContractStatusRsp](apiReq, APIURL_Contract_Status)
  433. if err != nil {
  434. return
  435. }
  436. if apiRsp.Code != CODE_SUCCESS {
  437. err = errors.New(apiRsp.Msg)
  438. return
  439. }
  440. status := record.RECORDSTATUS // 记录状态: 1:未签署 2:签署中 3:已签署 4:签署拒绝
  441. switch apiRsp.Data.Status { // 合同状态:0:等待签约 1:签约中 2:已签约 3:过期 4:拒签 6:作废 -2:状态异常
  442. case 0:
  443. status = 1
  444. case 1:
  445. status = 2
  446. case 2:
  447. status = 3
  448. case 4:
  449. status = 4
  450. }
  451. // 更新用户电子签记录 - 更新合同签署状态
  452. sql := fmt.Sprintf(`
  453. UPDATE useresignrecord
  454. SET RECORDSTATUS = %v,
  455. UPDATETIME = SYSDATE
  456. WHERE RECORDID = %v
  457. `, status, req.RecordId)
  458. _, err = db.GetEngine().Exec(sql)
  459. if err != nil {
  460. return
  461. }
  462. rsp = SyncContractStatusRsp{
  463. ContractNo: apiRsp.Data.ContractNo,
  464. ContractName: apiRsp.Data.ContractName,
  465. Status: apiRsp.Data.Status,
  466. }
  467. return
  468. }
  469. // PARTYA_SIGNATURE
  470. // PARTYA_DATE
  471. //
  472. // P_PARTYB_SIGNATURE
  473. // P_PARTYB_ID
  474. // P_PARTYB_MOBILE
  475. // P_PARTYB_DATE
  476. //
  477. // E_PARTYB_SIGNATURE
  478. // E_PARTYB_LEGAL
  479. // E_PARTYB_DATE
  480. // CreateContract 创建合同
  481. func CreateContract(req CreateContractReq) (rsp CreateContractRsp, err error) {
  482. // 获取电子签信息
  483. var record models.Useresignrecord
  484. has, err := db.GetEngine().Where("RECORDID = ?", req.RecordId).Get(&record)
  485. if err != nil {
  486. logger.GetLogger().Error("获取电子签信息失败, err", err)
  487. err = errors.New("获取电子签信息失败")
  488. return
  489. }
  490. if !has {
  491. err = errors.New("查无此记录信息")
  492. logger.GetLogger().Error("查无此记录信息, RecordId:", req.RecordId)
  493. return
  494. }
  495. if record.RECORDSTATUS != 1 {
  496. err = errors.New("记录信息状态异常")
  497. logger.GetLogger().Error("记录信息状态异常, RecordId:", req.RecordId, record.RECORDSTATUS)
  498. return
  499. }
  500. // 调用爱签接口 - 查询模板列表
  501. apiReq := APIReq[APITemplateListReq]{Data: APITemplateListReq{Page: 1, Rows: 10}}
  502. apiRsp, err := APIPost[APITemplateListReq, APITemplateListRsp](apiReq, APIURL_Template_List)
  503. if err != nil {
  504. return
  505. }
  506. if apiRsp.Code != CODE_SUCCESS {
  507. err = errors.New(apiRsp.Msg)
  508. return
  509. }
  510. if len(apiRsp.Data.List) == 0 {
  511. err = errors.New("获取查询模板列表失败")
  512. logger.GetLogger().Error("获取查询模板列表失败")
  513. return
  514. }
  515. // 获取用户信息
  516. userInfo, err := models.GetUserInfo(int(record.USERID))
  517. if err != nil {
  518. logger.GetLogger().Error("获取用户信息失败, err:", err)
  519. err = errors.New("获取用户信息失败")
  520. return
  521. }
  522. templateName := record.TEMPLATENAME
  523. if userInfo.Userinfotype == 1 { // 个人
  524. templateName += "-个人"
  525. } else { // 企业
  526. templateName += "-企业"
  527. }
  528. // 获取模板信息
  529. templateIdent := ""
  530. for _, item := range apiRsp.Data.List {
  531. if item.TemplateName == templateName {
  532. templateIdent = item.TemplateIdent
  533. break
  534. }
  535. }
  536. if templateIdent == "" {
  537. err = errors.New("获取模板信息失败")
  538. logger.GetLogger().Error("获取模板信息失败")
  539. return
  540. }
  541. // 获取用户实名信息
  542. var recordAuth models.Useresignrecord
  543. has, err = db.GetEngine().Where("TEMPLATETYPE = 1 AND USERID = ?", userInfo.Userid).Get(&recordAuth)
  544. if err != nil {
  545. return
  546. }
  547. if !has {
  548. err = errors.New("无对应实名认证记录信息")
  549. logger.GetLogger().Error("无对应实名认证记录信息, userId:", userInfo.Userid)
  550. return
  551. }
  552. // 调用爱签接口 - 上传待签署文件
  553. contractNo := strconv.Itoa(int(utils.GenID()))
  554. apiCreateContractReq := APIReq[APICreateContractReq]{
  555. Data: APICreateContractReq{
  556. ContractNo: contractNo,
  557. ContractName: templateName,
  558. SignOrder: 1,
  559. ValidityTime: 30,
  560. NotifyUrl: config.SerCfg.AsignCfg.NotifyUrl,
  561. },
  562. }
  563. apiCreateContractReq.Data.Templates = []APITemplate{
  564. {
  565. TemplateNo: templateIdent,
  566. },
  567. }
  568. apiCreateContractRsp, err := APIPost[APICreateContractReq, APICreateContractRsp](apiCreateContractReq, APIURL_CreateContract)
  569. if err != nil {
  570. return
  571. }
  572. if apiCreateContractRsp.Code != CODE_SUCCESS {
  573. err = errors.New(apiCreateContractRsp.Msg)
  574. return
  575. }
  576. // 将合同编号写入数据库
  577. sql := fmt.Sprintf(`
  578. UPDATE useresignrecord
  579. SET contractNo = '%v',
  580. UPDATETIME = SYSDATE
  581. WHERE RECORDID = %v
  582. `, contractNo, record.RECORDID)
  583. if _, err = db.GetEngine().Exec(sql); err != nil {
  584. logger.GetLogger().Error("更新合同编号失败, err:", err)
  585. err = errors.New("更新合同编号失败")
  586. return
  587. }
  588. // 添加签署方 - 甲方 - 交易所
  589. // appAddSignerReq1 := APIAddSignerReq{
  590. // ContractNo: contractNo,
  591. // Account: "ZR_LEGAL",
  592. // SignType: 2, // 无感知签约(需要开通权限)
  593. // SignStrategyList: []APISignStrategy{
  594. // {AttachNo: 1, LocationMode: 4, SignKey: "PARTYA_SIGNATURE", SignType: 1}, // 甲方签章
  595. // {AttachNo: 1, LocationMode: 4, SignKey: "PARTYA_DATE", SignType: 2}, // 甲方签署时间
  596. // },
  597. // }
  598. appAddSignerReq1 := APIAddSignerReq{
  599. ContractNo: contractNo,
  600. Account: "EX_LEGAL",
  601. SignType: 2, // 无感知签约(需要开通权限)
  602. }
  603. signStrategyListPartyA, err := buildStrategyByPartyA(int(record.TEMPLATECONFIGID))
  604. if err != nil {
  605. return
  606. }
  607. if len(signStrategyListPartyA) > 0 {
  608. appAddSignerReq1.SignStrategyList = signStrategyListPartyA
  609. }
  610. // 获取临时存储的用户认证信息
  611. cacheMap := make(map[string]interface{})
  612. if err = json.Unmarshal([]byte(recordAuth.AUTHINFO), &cacheMap); err != nil {
  613. logger.GetLogger().Errorf("反序列化临时存储用户信息失败, AUTHINFO: %s", recordAuth.AUTHINFO)
  614. return
  615. }
  616. if recordAuth.AUTHINFO == "" {
  617. err = errors.New("获取实名信息失败")
  618. logger.GetLogger().Error("获取实名信息失败")
  619. return
  620. }
  621. // 添加签署方 - 乙方 - 投资者
  622. asignAccount := recordAuth.CONTRACTNO // 2024-05-13 由于存在用户注销后重新注册后USERID变化的问题,这里使用type=1中的contractno存储爱签中的key
  623. if asignAccount == "" {
  624. asignAccount = strconv.Itoa(int(record.USERID))
  625. }
  626. appAddSignerReq2 := APIAddSignerReq{
  627. ContractNo: contractNo,
  628. Account: asignAccount,
  629. SignType: 3,
  630. ValidateType: 3,
  631. }
  632. // // 签章策略
  633. // signStrategyList := make([]APISignStrategy, 0)
  634. // // 接收方模板填充策略
  635. // receiverFillStrategyList := make([]APIReceiverFillStrategy, 0)
  636. // if userInfo.Userinfotype == 1 { // 个人
  637. // // 乙方签章
  638. // signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "P_PARTYB_SIGNATURE", SignType: 1})
  639. // // 乙方签署时间
  640. // signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "P_PARTYB_DATE", SignType: 2})
  641. // // 身份证号
  642. // receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "P_PARTYB_ID", Value: cacheMap["idCardNo"].(string)})
  643. // // 联系方式
  644. // receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "P_PARTYB_MOBILE", Value: cacheMap["mobile"].(string)})
  645. // } else { // 企业
  646. // // 乙方签章
  647. // signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "E_PARTYB_SIGNATURE", SignType: 1})
  648. // // 乙方签署时间
  649. // signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "E_PARTYB_DATE", SignType: 2})
  650. // // 法定代表人名称
  651. // receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "E_PARTYB_LEGAL", Value: cacheMap["realName"].(string)})
  652. // }
  653. // appAddSignerReq2.SignStrategyList = signStrategyList
  654. // appAddSignerReq2.ReceiverFillStrategyList = receiverFillStrategyList
  655. signStrategyList, receiverFillStrategyList, err := buildStrategyByPartyB(int(record.TEMPLATECONFIGID), int(userInfo.Userinfotype), cacheMap)
  656. if err != nil {
  657. return
  658. }
  659. if len(signStrategyList) > 0 {
  660. appAddSignerReq2.SignStrategyList = signStrategyList
  661. }
  662. if len(receiverFillStrategyList) > 0 {
  663. appAddSignerReq2.ReceiverFillStrategyList = receiverFillStrategyList
  664. }
  665. apiAddSignerReq := APIReq[APIAddSignerReq]{Datas: []APIAddSignerReq{appAddSignerReq1, appAddSignerReq2}}
  666. apiAddSignerRsp, err := APIPost[APIAddSignerReq, APIAddSignerRsp](apiAddSignerReq, APIURL_AddSigner)
  667. if err != nil {
  668. return
  669. }
  670. if apiAddSignerRsp.Code != CODE_SUCCESS {
  671. err = errors.New(apiAddSignerRsp.Msg)
  672. return
  673. }
  674. if len(apiAddSignerRsp.Data.SignUser) == 0 {
  675. err = errors.New("获取合同签署地址失败")
  676. logger.GetLogger().Error("获取合同签署地址失败")
  677. return
  678. }
  679. // 将返回的合同签署地址写入数据库
  680. sql = fmt.Sprintf(`
  681. UPDATE useresignrecord
  682. SET RECORDSTATUS = 2,
  683. SIGNURL = '%v',
  684. UPDATETIME = SYSDATE
  685. WHERE RECORDID = %v
  686. `, apiAddSignerRsp.Data.SignUser[0].SignUrl, record.RECORDID)
  687. if _, err = db.GetEngine().Exec(sql); err != nil {
  688. logger.GetLogger().Error("合同签署地址失败, err:", err)
  689. err = errors.New("合同签署地址失败")
  690. return
  691. }
  692. rsp = CreateContractRsp{SignUrl: apiAddSignerRsp.Data.SignUser[0].SignUrl}
  693. return
  694. }
  695. // WillFace 个人意愿核身认证
  696. func WillFace(req WillFaceReq) (rsp WillFaceRsp, err error) {
  697. // 从交易库中获取类型为实名认证的电子签信息
  698. var record models.Useresignrecord
  699. has, err := db.GetEngine().Where("TEMPLATETYPE = 3 AND USERID = ?", req.UserId).Get(&record)
  700. if !has {
  701. if err == nil {
  702. err = errors.New("获取用户电子签记录失败")
  703. }
  704. logger.GetLogger().Error("个人意愿核身认证异常,错误:", err.Error())
  705. return
  706. }
  707. // 调用爱签接口
  708. apiWillFaceReq := APIWillFaceReq{
  709. RealName: req.RealName,
  710. IdCardNo: req.IdCardNo,
  711. Question: record.TEMPLATENO,
  712. Answer: record.TEMPLATENAME,
  713. RedirectUrl: config.SerCfg.AsignCfg.NotifyUrl + "?recordId=" + strconv.Itoa(int(record.RECORDID)),
  714. }
  715. apiReq := APIReq[APIWillFaceReq]{Data: apiWillFaceReq}
  716. apiRsp, err := APIPost[APIWillFaceReq, APIWillFaceRsp](apiReq, APIURL_Person_WillFace)
  717. if err != nil {
  718. return
  719. }
  720. if apiRsp.Code != CODE_SUCCESS {
  721. err = errors.New(apiRsp.Msg)
  722. return
  723. }
  724. rsp.FaceUrl = apiRsp.Data.FaceUrl
  725. // 更新用户电子签记录
  726. sql := fmt.Sprintf(`
  727. UPDATE useresignrecord
  728. SET RECORDSTATUS = 2,
  729. UPDATETIME = SYSDATE,
  730. SIGNURL = '%v'
  731. WHERE RECORDID = %v
  732. `, rsp.FaceUrl, record.RECORDID)
  733. _, err = db.GetEngine().Exec(sql)
  734. return
  735. }
  736. // 构建甲方签章策略
  737. func buildStrategyByPartyA(templateConfigId int) (signStrategyList []APISignStrategy, err error) {
  738. signStrategyList = make([]APISignStrategy, 0)
  739. // 获取电子签模板字段配置
  740. fields := make([]models.Esigntemplatefield, 0)
  741. if err = db.GetEngine().Where("TEMPLATECONFIGID = ?", templateConfigId).Find(&fields); err != nil {
  742. logger.GetLogger().Error("获取电子签模板字段配置失败, err", err)
  743. err = errors.New("获取电子签模板字段配置失败")
  744. return
  745. }
  746. if len(fields) == 0 {
  747. err = errors.New("获取电子签模板字段配置信息异常")
  748. logger.GetLogger().Error("获取电子签模板字段配置异常, templateconfigid:", templateConfigId)
  749. return
  750. }
  751. for _, item := range fields {
  752. switch item.FIELDKEY {
  753. case "PARTYA_SIGNATURE": // 甲方签章(企业印章)
  754. signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "PARTYA_SIGNATURE", SignType: 1})
  755. case "PARTYA_DATE": // 甲方签署时间
  756. signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "PARTYA_DATE", SignType: 2})
  757. }
  758. }
  759. return
  760. }
  761. // cacheMap {"realName":"邓志明","idCardNo":"430426198507087670","bankCard":"6221885840097492396","mobile":"18033442829","idCardPhoto":"./uploadFile/20231227/202312271427518530.jpg","idCardPhotoBackURL":"./uploadFile/20231227/202312271427544764.jpg","bankId":"403100000004"}
  762. // 构建乙方签章策略和模板填充策略
  763. func buildStrategyByPartyB(templateConfigId int, fieldUserType int, cacheMap map[string]interface{}) (signStrategyList []APISignStrategy, receiverFillStrategyList []APIReceiverFillStrategy, err error) {
  764. signStrategyList = make([]APISignStrategy, 0)
  765. receiverFillStrategyList = make([]APIReceiverFillStrategy, 0)
  766. // 获取电子签模板字段配置
  767. fields := make([]models.Esigntemplatefield, 0)
  768. if err = db.GetEngine().Where("TEMPLATECONFIGID = ? AND FIELDUSERTYPE = ?", templateConfigId, fieldUserType).Find(&fields); err != nil {
  769. logger.GetLogger().Error("获取电子签模板字段配置失败, err", err)
  770. err = errors.New("获取电子签模板字段配置失败")
  771. return
  772. }
  773. if len(fields) == 0 {
  774. err = errors.New("获取电子签模板字段配置信息异常")
  775. logger.GetLogger().Error("获取电子签模板字段配置异常, templateconfigid:", templateConfigId)
  776. return
  777. }
  778. for _, item := range fields {
  779. switch item.FIELDKEY {
  780. case "P_PARTYB_NAME": // 乙方名称
  781. receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "P_PARTYB_NAME", Value: cacheMap["realName"].(string)})
  782. case "P_PARTYB_ID": // 乙方证件号码
  783. receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "P_PARTYB_ID", Value: cacheMap["idCardNo"].(string)})
  784. case "P_PARTYB_MOBILE": // 乙方电话号码
  785. receiverFillStrategyList = append(receiverFillStrategyList, APIReceiverFillStrategy{AttachNo: 1, Key: "P_PARTYB_MOBILE", Value: cacheMap["mobile"].(string)})
  786. case "P_PARTYB_SIGNATURE": // 乙方签章(个人)
  787. signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "P_PARTYB_SIGNATURE", SignType: 1})
  788. case "P_PARTYB_DATE": // 乙方签署时间
  789. signStrategyList = append(signStrategyList, APISignStrategy{AttachNo: 1, LocationMode: 4, SignKey: "P_PARTYB_DATE", SignType: 2})
  790. }
  791. }
  792. return
  793. }
  794. func ASignCompleted(contractNo, status string) (err error) {
  795. /*
  796. // 合同签署完成后回调通知示例
  797. String publickey = "MFwwDQcccccxxxxmEz/nw27Ln6AP90ZCMPi+iNF1m9mhNECAwEAAQ==";
  798. String remark = ""; // 若被拒签则会返回拒签原因,拒签原因不参与签名
  799. Map <String, String> map = new HashMap<>();
  800. map.put("action", "signCompleted");
  801. map.put("contractNo", "20221114142140345");
  802. map.put("status", "2");
  803. map.put("signTime", "2022-11-14 14:22:00");
  804. map.put("timestamp", "1668406920005");
  805. map.put("validityTime", "2022-11-24 23:59:59");
  806. String json = JSONObject.toJSONString(map, SerializerFeature.MapSortField);
  807. System.out.println("数据:" + json);
  808. // 计算签名
  809. try {
  810. String sign = "feFfcprGjdmDDqRmxK5qlWlMncX0mc6LJ5agebOGIx2QiAern+6ZRg/SBHOgvHp/+1ywVRdyKNUKxPneETwKPw==";
  811. System.out.println(RSAUtils.rsaSignCheck(sign, json, publickey));
  812. } catch (Exception e) {
  813. e.printStackTrace();
  814. }
  815. */
  816. // 获取合同编号
  817. if contractNo == "" {
  818. logger.GetLogger().Error("获取合同编号失败")
  819. err = errors.New("获取合同编号失败")
  820. return
  821. }
  822. // 获取合同状态
  823. if status == "" {
  824. logger.GetLogger().Error("获取获取合同状态失败")
  825. err = errors.New("获取获取合同状态失败")
  826. return
  827. }
  828. // 更新数据库记录
  829. sql := fmt.Sprintf(`
  830. UPDATE useresignrecord
  831. SET RECORDSTATUS = 3,
  832. UPDATETIME = SYSDATE
  833. WHERE CONTRACTNO = '%v'
  834. `, contractNo)
  835. _, err = db.GetEngine().Exec(sql)
  836. return
  837. }
  838. // 个人意愿核身认证爱签回调通知处理
  839. func HandleWillFace(sign, result, msg, recordId string) (err error) {
  840. // 获取用户电子签记录
  841. useresignrecord := new(models.Useresignrecord)
  842. has, err := db.GetEngine().Where("RECORDID = ?", recordId).Get(useresignrecord)
  843. if err != nil || !has {
  844. if err == nil {
  845. err = errors.New("无对应电子签记录")
  846. }
  847. logger.GetLogger().Error("获取用户电子签记录失败, 错误:", err)
  848. return
  849. }
  850. // 人脸认证结果
  851. // 1:认证成功
  852. // 2:认证失败
  853. if result == "1" {
  854. // FIXME: - 这里应该校验签名(姓名和身份证号码)
  855. // 更新数据库记录
  856. sql := fmt.Sprintf(`
  857. UPDATE useresignrecord
  858. SET RECORDSTATUS = 3,
  859. UPDATETIME = SYSDATE
  860. WHERE RECORDID = %v
  861. `, recordId)
  862. if _, err = db.GetEngine().Exec(sql); err != nil {
  863. logger.GetLogger().Error("更新用户电子签记录失败, 错误:", err)
  864. return
  865. }
  866. }
  867. return
  868. }