servcies.go 33 KB

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