zhou.xiaoning 2 jaren geleden
bovenliggende
commit
28921e0da6
5 gewijzigde bestanden met toevoegingen van 200 en 54 verwijderingen
  1. 13 1
      api/v1/account/certification.go
  2. 25 1
      model/account/certification.go
  3. 5 3
      py/Api.py
  4. 73 11
      service/asign/asign.go
  5. 84 38
      service/sign/sign.go

+ 13 - 1
api/v1/account/certification.go

@@ -67,7 +67,7 @@ func AddUser(c *gin.Context) {
 	}
 }
 
-// AddUser 上传待签署文件和添加签署方
+// CreateContractAndAddSigner 上传待签署文件和添加签署方
 // @Summary  上传待签署文件和添加签署方
 // @Security ApiKeyAuth
 // @accept   application/json
@@ -97,3 +97,15 @@ func CreateContractAndAddSigner(c *gin.Context) {
 		response.FailWithMessage(err.Error(), c)
 	}
 }
+
+// POST
+// func HandleASignCompleted(c *gin.Context) {
+// 	g := utils.GinUtils{C: c}
+
+// 	if rsp, err := signService.HandleASignCompleted(); err == nil {
+// 		response.OkWithDetailed(rsp, "操作成功", g.C)
+// 	} else {
+// 		global.M2A_LOG.Error(err.Error(), zap.Error(err))
+// 		response.FailWithMessage(err.Error(), c)
+// 	}
+// }

+ 25 - 1
model/account/certification.go

@@ -1,6 +1,9 @@
 package account
 
-import "time"
+import (
+	"mtp20access/global"
+	"time"
+)
 
 // Useresignrecord 用户电子签记录表
 type Useresignrecord struct {
@@ -26,3 +29,24 @@ type Useresignrecord struct {
 func (r *Useresignrecord) TableName() string {
 	return "USERESIGNRECORD"
 }
+
+// Wskhopenaccountconfig 网上开户配置表
+type Wskhopenaccountconfig struct {
+	CONFIGID     int32     `json:"configid" xorm:"CONFIGID"`         // 配置ID
+	CONFIGTYPE   int32     `json:"configtype" xorm:"CONFIGTYPE"`     // 配置类型
+	CONFIGVALUE  string    `json:"configvalue" xorm:"CONFIGVALUE"`   // 配置值
+	REMARK       string    `json:"remark" xorm:"REMARK"`             // 备注
+	CREATETIME   time.Time `json:"createtime" xorm:"CREATETIME"`     // 创建时间
+	MODIFIEDTIME time.Time `json:"modifiedtime" xorm:"MODIFIEDTIME"` // 修改时间
+	MODIFIEDBY   int64     `json:"modifiedby" xorm:"MODIFIEDBY"`     // 修改人帐号
+}
+
+// TableName is WSKH_OPENACCOUNTCONFIG
+func (r *Wskhopenaccountconfig) TableName() string {
+	return "WSKH_OPENACCOUNTCONFIG"
+}
+
+// Get 获取CONFIGID获取信息
+func (t *Wskhopenaccountconfig) Get() (has bool, err error) {
+	return global.M2A_DB.Where("CONFIGID = ?", t.CONFIGID).Get(t)
+}

+ 5 - 3
py/Api.py

@@ -64,6 +64,7 @@ def addSigner(inputData):
     # 从输入数据中获取调用接口
     contractNo = inputData["contractNo"]
     account = inputData["account"]
+    signType = inputData["signType"]
     signStrategyList = inputData["signStrategyList"]
     
     appId = inputData["appId"]
@@ -74,6 +75,7 @@ def addSigner(inputData):
     reqBodyData = [{
         "contractNo": contractNo, 
         "account": account, 
+        "signType": signType,
         "signStrategyList": signStrategyList
     }]
     #请求地址
@@ -85,7 +87,7 @@ def addSigner(inputData):
 def downloadContract(inputData):
     # 从输入数据中获取调用接口
     contractNo = inputData["contractNo"]
-    downloadFileType = inputData["downloadFileType"]
+    # downloadFileType = inputData["downloadFileType"]
     
     appId = inputData["appId"]
     appKey = inputData["appKey"]
@@ -93,8 +95,8 @@ def downloadContract(inputData):
 
     # 组装参数
     reqBodyData = {
-        "contractNo": contractNo, 
-        "downloadFileType": downloadFileType
+        "contractNo": contractNo
+        # "downloadFileType": downloadFileType
     }
     #请求地址
     Result = HttpUtils.HttpUtils.doPOST(apiUrl, reqBodyData, appId, appKey)

+ 73 - 11
service/asign/asign.go

@@ -112,7 +112,7 @@ import (
 // }
 
 type AsignData interface {
-	AddPersonalUserData | CreateContractData | AddSignerData
+	AddPersonalUserData | CreateContractData | AddSignerData | DownloadContractData
 }
 
 // AsignRsp 爱签响应参数
@@ -256,8 +256,8 @@ func AddPersonalUserBy(account, name, idCard, mobile string, idCardType *int) (r
 	// 执行命令
 	err = cmd.Run()
 	// 输出标准输出和标准错误
-	fmt.Println("标准输出:", stdoutBuf.String())
-	fmt.Println("标准错误:", stderrBuf.String())
+	fmt.Println("AddPersonalUserBy 标准输出:", stdoutBuf.String())
+	fmt.Println("AddPersonalUserBy 标准错误:", stderrBuf.String())
 	if err != nil {
 		global.M2A_LOG.Error("[AddPersonalUserBy] 请求失败", zap.Error(err))
 		return
@@ -307,7 +307,7 @@ func CreateContract(contractNo, contractName, templateNo string) (rspData AsignR
 	// 将请求数据转换为JSON字符串
 	reqJSON, err := json.Marshal(reqData)
 	if err != nil {
-		global.M2A_LOG.Error("[AddPersonalUserBy] 构建请求参数失败", zap.Error(err))
+		global.M2A_LOG.Error("[CreateContract] 构建请求参数失败", zap.Error(err))
 		return
 	}
 	// 要执行的Python脚本命令
@@ -323,9 +323,9 @@ func CreateContract(contractNo, contractName, templateNo string) (rspData AsignR
 	// 执行命令
 	err = cmd.Run()
 	// 输出标准输出和标准错误
-	fmt.Println("标准输入:", string(reqJSON))
-	fmt.Println("标准输出:", stdoutBuf.String())
-	fmt.Println("标准错误:", stderrBuf.String())
+	// fmt.Println("标准输入:", string(reqJSON))
+	fmt.Println("CreateContract 标准输出:", stdoutBuf.String())
+	fmt.Println("CreateContract 标准错误:", stderrBuf.String())
 	if err != nil {
 		global.M2A_LOG.Error("[CreateContract] 请求失败", zap.Error(err))
 		return
@@ -374,8 +374,9 @@ func AddSigner(contractNo, account string) (rspData AsignRsp[AddSignerData], err
 	reqData := make(map[string]interface{})
 	reqData["contractNo"] = contractNo
 	reqData["account"] = account
-	reqData["signStrategyList"] = []map[string]int{
-		{"attachNo": 1, "locationMode": 4}}
+	reqData["signType"] = 3
+	reqData["signStrategyList"] = []map[string]interface{}{
+		{"attachNo": 1, "locationMode": 4, "signKey": "key1"}}
 
 	reqData["api"] = "addSigner"
 	reqData["appId"] = global.M2A_CONFIG.Asign.AppId
@@ -401,8 +402,8 @@ func AddSigner(contractNo, account string) (rspData AsignRsp[AddSignerData], err
 	// 执行命令
 	err = cmd.Run()
 	// 输出标准输出和标准错误
-	fmt.Println("标准输出:", stdoutBuf.String())
-	fmt.Println("标准错误:", stderrBuf.String())
+	fmt.Println("AddSigner 标准输出:", stdoutBuf.String())
+	fmt.Println("AddSigner 标准错误:", stderrBuf.String())
 	if err != nil {
 		global.M2A_LOG.Error("[AddSigner] 请求失败", zap.Error(err))
 		return
@@ -416,3 +417,64 @@ func AddSigner(contractNo, account string) (rspData AsignRsp[AddSignerData], err
 
 	return
 }
+
+// 添加签署方响应数据
+type DownloadContractData struct {
+	FileName string `json:"fileName"` // 文件名
+	MD5      string `json:"md5"`      // 文件md5值
+	FileType int    `json:"fileType"` // 文件类型 0:PDF 1:ZIP
+	Size     int    `json:"size"`     // 文件大小
+	Data     string `json:"data"`     // Base64字符串
+}
+
+/*
+DownloadContract 下载合同
+
+contractNo 合同ID,合同唯一编号
+*/
+func DownloadContract(contractNo string) (rspData AsignRsp[DownloadContractData], err error) {
+	apiUrl := global.M2A_CONFIG.Asign.URL + "contract/downloadContract"
+
+	// 构建请求数据结构
+	reqData := make(map[string]interface{})
+	reqData["contractNo"] = contractNo
+
+	reqData["api"] = "downloadContract"
+	reqData["appId"] = global.M2A_CONFIG.Asign.AppId
+	reqData["appKey"] = global.M2A_CONFIG.Asign.PrivateKey
+	reqData["apiUrl"] = apiUrl
+
+	// 将请求数据转换为JSON字符串
+	reqJSON, err := json.Marshal(reqData)
+	if err != nil {
+		global.M2A_LOG.Error("[DownloadContract] 构建请求参数失败", zap.Error(err))
+		return
+	}
+	// 要执行的Python脚本命令
+	pythonScriptPath := "./py/Enter.py"
+	// 创建一个命令对象
+	cmd := exec.Command("py", pythonScriptPath)
+	// 设置标准输入为JSON字符串
+	cmd.Stdin = strings.NewReader(string(reqJSON))
+	// 创建一个字节缓冲区来捕获命令的输出
+	var stdoutBuf, stderrBuf bytes.Buffer
+	cmd.Stdout = &stdoutBuf
+	cmd.Stderr = &stderrBuf
+	// 执行命令
+	err = cmd.Run()
+	// 输出标准输出和标准错误
+	fmt.Println("DownloadContract 标准输出:", stdoutBuf.String())
+	fmt.Println("DownloadContract 标准错误:", stderrBuf.String())
+	if err != nil {
+		global.M2A_LOG.Error("[DownloadContract] 请求失败", zap.Error(err))
+		return
+	}
+	// 结果
+	rspBody := stdoutBuf.String()
+	if err = json.Unmarshal([]byte(rspBody), &rspData); err != nil {
+		global.M2A_LOG.Error("[DownloadContract] 反序列化body失败", zap.Error(err))
+		return
+	}
+
+	return
+}

+ 84 - 38
service/sign/sign.go

@@ -9,9 +9,11 @@ import (
 	"mtp20access/model/account/request"
 	"mtp20access/model/account/response"
 	"mtp20access/service/asign"
+	"os"
 	"strconv"
 	"time"
 
+	"github.com/gofrs/uuid"
 	"go.uber.org/zap"
 )
 
@@ -85,7 +87,7 @@ func CreateContractAndAddSigner(req request.CreateContractAndAddSignerReq, userI
 	if useresignrecord.CONTRACTNO == "" {
 		// 生成合同编号
 		// #{userid} || '_' || to_char(sysdate, 'yyyyMMddhh24miss') || '_' ||              seq_useresignrecord.currval,
-		contractNo := fmt.Sprintf("%d_%s_%v", userId, time.Now().Format("2006-01-02 15:04:05"), useresignrecord.RECORDID)
+		contractNo := fmt.Sprintf("%d_%s_%v", userId, time.Now().Format("20060102150405"), useresignrecord.RECORDID)
 		// 调用爱签API-上传待签署文件(https://{host}/contract/createContract)
 		r, e := asign.CreateContract(
 			contractNo,
@@ -105,7 +107,7 @@ func CreateContractAndAddSigner(req request.CreateContractAndAddSignerReq, userI
 		useresignrecord.CONTRACTNO = contractNo
 		sql := fmt.Sprintf(`
 			UPDATE useresignrecord 
-			SET SIGNURL = '%v' 
+			SET contractNo = '%v',
 				UPDATETIME = SYSDATE
 			WHERE RECORDID = %v
 		`, useresignrecord.CONTRACTNO, useresignrecord.RECORDID)
@@ -138,7 +140,7 @@ func CreateContractAndAddSigner(req request.CreateContractAndAddSignerReq, userI
 			// 将返回的合同编号写入数据库
 			sql := fmt.Sprintf(`
 				UPDATE useresignrecord 
-				SET SIGNURL = '%v' 
+				SET SIGNURL = '%v', 
 					UPDATETIME = SYSDATE
 				WHERE RECORDID = %v
 			`, useresignrecord.SIGNURL, useresignrecord.RECORDID)
@@ -160,43 +162,87 @@ handleASignCompleted 处理爱签合同签署完成后回调通知
 req 异步推送参数
 */
 func HandleASignCompleted(req map[string]string) (err error) {
-	// 合同签署完成后回调通知示例
-	// String publickey = "MFwwDQcccccxxxxmEz/nw27Ln6AP90ZCMPi+iNF1m9mhNECAwEAAQ==";
-	// String remark = ""; // 若被拒签则会返回拒签原因,拒签原因不参与签名
-	// Map <String, String> 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();
-	// }
+	/*
+		// 合同签署完成后回调通知示例
+		String publickey = "MFwwDQcccccxxxxmEz/nw27Ln6AP90ZCMPi+iNF1m9mhNECAwEAAQ==";
+		String remark = ""; // 若被拒签则会返回拒签原因,拒签原因不参与签名
+		Map <String, String> 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();
+		}
+	*/
 
 	// 获取合同编号
-	// contractNo, ok := req["contractNo"]
-	// if !ok {
-	// 	global.M2A_LOG.Error("【HandleASignCompleted】 获取合同编号失败", zap.Any("req", req))
-	// 	return
-	// }
-	// // 获取合同状态
-	// status, ok := req["status"]
-	// if !ok {
-	// 	global.M2A_LOG.Error("【HandleASignCompleted】 获取获取合同状态失败", zap.Any("req", req))
-	// 	return
-	// }
-	// if status == "2" {
-	// 	// 已签约
-	// 	// 下载合同
-
-	// }
+	contractNo, ok := req["contractNo"]
+	if !ok {
+		global.M2A_LOG.Error("【HandleASignCompleted】 获取合同编号失败", zap.Any("req", req))
+		return
+	}
+	// 获取合同状态
+	status, ok := req["status"]
+	if !ok {
+		global.M2A_LOG.Error("【HandleASignCompleted】 获取获取合同状态失败", zap.Any("req", req))
+		return
+	}
+	if status == "2" {
+		// 已签约
+		// 下载合同
+		r, e := asign.DownloadContract(contractNo)
+		if e != nil {
+			err = e
+			return
+		}
+		if r.Code != 100000 {
+			err = errors.New(strconv.Itoa(r.Code))
+			global.M2A_LOG.Error("【HandleASignCompleted】 下载合同接口调用失败", zap.Error(err))
+			return
+		}
+		if r.Data.Data != "" {
+			// 获取网上开户地址(用于客户端下载文件)
+			openconfig := account.Wskhopenaccountconfig{CONFIGID: 6}
+			has, e := openconfig.Get()
+			if e != nil || !has {
+				err = e
+				global.M2A_LOG.Error("【HandleASignCompleted】 获取网上开户地址失败", zap.Error(err))
+				return
+			}
+			// 将Base64写入目标文件
+			uid, _ := uuid.NewV4()
+			fileName := fmt.Sprintf("%v_%v.pdf", r.Data.FileName, uid.String())
+			openconfig.CONFIGVALUE = "./" // FIXME: - 测试代码
+			folderPath := "sign/" + time.Now().Format("20060102")
+			savePath := openconfig.CONFIGVALUE + "/uploadFile/" + folderPath
+			fmt.Println(savePath + "/" + fileName)
+			f, e := os.OpenFile(savePath+"/"+fileName, os.O_RDWR|os.O_CREATE, os.ModePerm)
+			if e != nil {
+				err = e
+				global.M2A_LOG.Error("【HandleASignCompleted】 获取网上开户地址失败", zap.Error(err))
+				return
+			}
+			defer f.Close()
+			// 更新数据库记录
+			// 获取用户电子签记录
+			useresignrecord := new(account.Useresignrecord)
+			has, e = global.M2A_DB.Where("CONTRACTNO = ?", contractNo).Get(useresignrecord)
+			if e != nil || !has {
+				err = e
+				global.M2A_LOG.Error("【HandleASignCompleted】 获取用户电子签记录失败", zap.Error(err))
+				return
+			}
+		}
+	}
 
 	return
 }