Browse Source

腾讯电子签业务功能上线

zhou.xiaoning 2 năm trước cách đây
mục cha
commit
2a1b35901e

+ 92 - 0
config/config.go

@@ -59,6 +59,19 @@ type MySQLConfig struct {
 	Password string
 }
 
+type TencentConfig struct {
+	Enabled                 int
+	SecretId                string
+	SecretKey               string
+	EndPoint                string
+	AppId                   string
+	ProxyOrganizationName   string
+	ProxyOrganizationOpenId string
+	ProxyOperatorOpenId     string
+	SignToken               string
+	SignKey                 string
+}
+
 type ServiceConfig struct {
 	WebCfg     WebConfig
 	LogCfg     LogConfig
@@ -67,6 +80,7 @@ type ServiceConfig struct {
 	MqCfg      MqConfig
 	MongoDBCfg MongoDBConfig
 	MySQLCfg   MySQLConfig
+	TencentCfg TencentConfig
 }
 
 func (c *ServiceConfig) Init(path string) error {
@@ -339,6 +353,84 @@ func (c *ServiceConfig) Init(path string) error {
 		SerCfg.MySQLCfg.Password = password.SelectAttrValue("value", "")
 	}
 
+	// Tencent配置
+	tencentsettings := root.SelectElements("Tencent")
+	for _, setting := range tencentsettings {
+		// 启用标志
+		enabled := setting.SelectElement("Enabled")
+		if enabled == nil {
+			return errors.New("read tencent enabled failed")
+		}
+		ret, err := strconv.ParseUint(enabled.SelectAttrValue("value", "0"), 10, 32)
+		if err != nil {
+			return errors.New("read tencent enabled failed")
+		}
+		SerCfg.TencentCfg.Enabled = int(ret)
+
+		// 密钥ID
+		secretId := setting.SelectElement("SecretId")
+		if secretId == nil {
+			return errors.New("read tencent SecretId failed")
+		}
+		SerCfg.TencentCfg.SecretId = secretId.SelectAttrValue("value", "")
+
+		// 密钥key
+		secretKey := setting.SelectElement("SecretKey")
+		if secretKey == nil {
+			return errors.New("read tencent SecretKey failed")
+		}
+		SerCfg.TencentCfg.SecretKey = secretKey.SelectAttrValue("value", "")
+
+		// EndPoint API域名,现网使用 essbasic.tencentcloudapi.com 测试使用 essbasic.test.ess.tencent.cn
+		endPoint := setting.SelectElement("EndPoint")
+		if endPoint == nil {
+			return errors.New("read tencent EndPoint failed")
+		}
+		SerCfg.TencentCfg.EndPoint = endPoint.SelectAttrValue("value", "")
+
+		// 应用的唯一标识
+		appId := setting.SelectElement("AppId")
+		if appId == nil {
+			return errors.New("read tencent AppId failed")
+		}
+		SerCfg.TencentCfg.AppId = appId.SelectAttrValue("value", "")
+
+		// 子客企业真实名称
+		proxyOrganizationName := setting.SelectElement("ProxyOrganizationName")
+		if proxyOrganizationName == nil {
+			return errors.New("read tencent ProxyOrganizationName failedd")
+		}
+		SerCfg.TencentCfg.ProxyOrganizationName = proxyOrganizationName.SelectAttrValue("value", "")
+
+		// 道子客企业OpenId(OrganizationOpenId):简称OrgOpenId,对应通用参数ProxyOrganizationOpenId。
+		proxyOrganizationOpenId := setting.SelectElement("ProxyOrganizationOpenId")
+		if proxyOrganizationOpenId == nil {
+			return errors.New("read tencent proxyOrganizationOpenId failedd")
+		}
+		SerCfg.TencentCfg.ProxyOrganizationOpenId = proxyOrganizationOpenId.SelectAttrValue("value", "")
+
+		// 子客企业员工/经办人OpenId(OperatorOpenId):简称员工/经办人OpenId。对应通用ProxyOperator中的参数OpenId。
+		proxyOperatorOpenId := setting.SelectElement("ProxyOperatorOpenId")
+		if proxyOperatorOpenId == nil {
+			return errors.New("read tencent proxyOperatorOpenId failedd")
+		}
+		SerCfg.TencentCfg.ProxyOperatorOpenId = proxyOperatorOpenId.SelectAttrValue("value", "")
+
+		// 电子签推送的回调内容基于此 token
+		signToken := setting.SelectElement("SignToken")
+		if signToken == nil {
+			return errors.New("read tencent signToken failedd")
+		}
+		SerCfg.TencentCfg.SignToken = signToken.SelectAttrValue("value", "")
+
+		// 电子签推送的回调内容基于此加密Key
+		signKey := setting.SelectElement("SignKey")
+		if signKey == nil {
+			return errors.New("read tencent signKey failedd")
+		}
+		SerCfg.TencentCfg.SignKey = signKey.SelectAttrValue("value", "")
+	}
+
 	return nil
 }
 

+ 12 - 0
config/config.j2

@@ -42,4 +42,16 @@
     <Username value="{{mysql_db_user}}"/>
     <Password value="{{mysql_db_pwd}}"/>
   </MySQLSetting>
+  <Tencent>
+    <Enabled value="{{Enabled}}"/>
+    <SecretId value="{{SecretId}}"/>
+    <SecretKey value="{{SecretKey}}"/>
+    <EndPoint value="{{EndPoint}}"/>
+    <AppId value="{{AppId}}"/>
+    <ProxyOrganizationName value="{{ProxyOrganizationName}}"/>
+    <ProxyOrganizationOpenId value="{{ProxyOrganizationOpenId}}"/>
+    <ProxyOperatorOpenId value="{{ProxyOperatorOpenId}}"/>
+    <SignToken value="{{SignToken}}"/>
+    <SignKey value="{{SignKey}}"/>
+  </Tencent>
 </Configuration>

+ 13 - 1
config/config.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Configuration xmlns:http="http://www.w3.org/2001/XMLSchema-instance">
   <WebSetting>
-    <ListenAddress value="0.0.0.0:8081"/>
+    <ListenAddress value="0.0.0.0:8082"/>
     <DebugMode value="1"/>
   </WebSetting>
   <LogSetting>
@@ -42,4 +42,16 @@
     <Username value="quote_test204"/>
     <Password value="123456"/>
   </MySQLSetting>
+  <Tencent>
+    <Enabled value="1"/>
+    <SecretId value="AKyDwiyUUckpkct4igUy8lsS7SEqR6c7yR"/>
+    <SecretKey value="SKwvG74cbV3OrAiJdjU5k4507vZwNYDbwT"/>
+    <EndPoint value="essbasic.test.ess.tencent.cn"/>
+    <AppId value="yDwiuUUckpogfoa4UxhigrYChFMdSJQV"/>
+    <ProxyOrganizationName value="天津麦顿"/>
+    <ProxyOrganizationOpenId value="TJMD"/>
+    <ProxyOperatorOpenId value="TJMD01"/>
+    <SignToken value="D586D270A51448179277A11729F37D3E"/>
+    <SignKey value="8774F484EA294C1E829EA6E2D7F99123"/>
+  </Tencent>
 </Configuration>

+ 284 - 0
controllers/tencent/qian.go

@@ -0,0 +1,284 @@
+package tencent
+
+import (
+	"fmt"
+	"io"
+	"mtp2_if/global/app"
+	"mtp2_if/global/e"
+	"mtp2_if/logger"
+	"mtp2_if/models"
+	"mtp2_if/services/tencent"
+	"mtp2_if/utils"
+	"net/http"
+	"strconv"
+
+	"github.com/gin-gonic/gin"
+)
+
+// 腾讯电子签
+
+type QueryUsereSignRecordsReq struct {
+	UserId           int  `form:"userId" binding:"required"`       // 用户ID
+	MemberUserId     int  `form:"memberUserId" binding:"required"` // 所属会员ID
+	RecordId         *int `form:"recordId"`                        // 记录ID
+	TemplateConfigId *int `form:"templateConfigId"`                // 模板配置ID
+	Templatetype     *int `form:"templatetype"`                    // 模板类型 - 1:实名认证 2:开户协议 3:日结算单 4:交易协议
+}
+
+// QueryUsereSignRecords 查询用户电子签记录表
+// @Summary 查询用户电子签记录表
+// @Produce json
+// @accept  application/json
+// @Param   userId           query    int true  "用户ID"
+// @Param   memberUserId     query    int true  "所属会员ID"
+// @Param   recordId         query    int false "记录ID"
+// @Param   templateConfigId query    int false "模板配置ID"
+// @Param   templatetype     query    int false "模板类型 - 1:实名认证 2:开户协议 3:日结算单 4:交易协议"
+// @Success 200              {array}  models.Useresignrecord
+// @Failure 500        {object} app.Response
+// @Router  /Tencent/QueryUsereSignRecords [get]
+// @Tags    腾讯电子签
+func QueryUsereSignRecords(c *gin.Context) {
+	appG := app.Gin{C: c}
+
+	// 获取请求参数
+	var req QueryUsereSignRecordsReq
+	if err := appG.C.ShouldBindQuery(&req); err != nil {
+		logger.GetLogger().Errorf("QueryUsereSignRecords failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
+		return
+	}
+
+	if rsp, err := models.QueryUsereSignRecords(req.UserId, req.MemberUserId, req.RecordId, req.TemplateConfigId, req.Templatetype); err == nil {
+		appG.Response(http.StatusOK, e.SUCCESS, rsp)
+	} else {
+		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
+	}
+}
+
+// QianNotice 腾讯电子签回调接口
+// @Summary 腾讯电子签回调接口
+// @Produce json
+// @accept  application/json
+// @Success 200 {object} app.Response
+// @Failure 500  {object} app.Response
+// @Router  /Tencent/QianNotice [post]
+// @Tags    腾讯电子签
+func QianNotice(c *gin.Context) {
+	appG := app.Gin{C: c}
+
+	// 获取推送内容
+	b, err := io.ReadAll(appG.C.Request.Body)
+	if err != nil {
+		return
+	}
+	payload := string(b)
+
+	// 验签
+	if payload != "" {
+		signFromHeader := appG.C.Request.Header.Get("Content-Signature")
+		if signFromHeader != "" {
+			if tencent.VerifySign(payload, signFromHeader) {
+				// 验签成功
+				// 内容解密
+				content, err := tencent.DecryptContent(payload)
+				if err == nil {
+					// 解密成功
+					tencent.ProcessNotice(content)
+				}
+			}
+		}
+	}
+
+	appG.Response(http.StatusOK, e.SUCCESS, "ok")
+}
+
+// CreateConsoleLoginUrl 创建电子签控制台登录链接
+// @Summary 创建电子签控制台登录链接
+// @Produce json
+// @accept  application/json
+// @Success 200 {object} app.Response
+// @Failure 500  {object} app.Response
+// @Router  /Tencent/CreateConsoleLoginUrl [post]
+// @Tags    腾讯电子签
+func CreateConsoleLoginUrl(c *gin.Context) {
+	appG := app.Gin{C: c}
+
+	agent := utils.SetAgent()
+	proxyOrganizationName := "天津麦顿"
+	response, _ := tencent.CreateConsoleLoginUrl(agent, proxyOrganizationName)
+
+	appG.Response(http.StatusOK, e.SUCCESS, response.ToJsonString())
+}
+
+type InitTencentESSReq struct {
+	UserId       int `json:"userId" binding:"required"`       // 用户ID
+	MemberUserId int `json:"memberUserId" binding:"required"` // 所属会员ID
+}
+
+// InitTencentESS 按用户ID和机构ID创建腾讯电子签业务信息
+// @Summary 按用户ID和机构ID创建腾讯电子签业务信息
+// @Produce json
+// @accept  application/json
+// @Param   data body     InitTencentESSReq true "入参"
+// @Failure 500 {object} app.Response
+// @Router  /Tencent/InitTencentESS [post]
+// @Tags    腾讯电子签
+func InitTencentESS(c *gin.Context) {
+	appG := app.Gin{C: c}
+
+	// 获取请求参数
+	var req InitTencentESSReq
+	if err := appG.C.ShouldBindJSON(&req); err != nil {
+		logger.GetLogger().Errorf("InitTencentESS failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
+		return
+	}
+
+	if err := tencent.InitTencentESS(req.UserId, req.MemberUserId); err == nil {
+		appG.Response(http.StatusOK, e.SUCCESS, "ok")
+	} else {
+		appG.Response(http.StatusBadRequest, e.ERROR, nil)
+	}
+}
+
+// PersonInfo  签署人信息
+type PersonInfo struct {
+	Name         string `json:"name"`         // 姓名
+	Mobile       string `json:"mobile"`       // 手机号码
+	IdCardNumber string `json:"idCardNumber"` // 身份证号码,目前只支持身份证
+}
+
+// OrganizationInfo 签署企业信息
+type OrganizationInfo struct {
+	Name string `json:"name"` // 企业签署方工商营业执照上的企业名称
+}
+
+// CreateFlowByTemplateDirectlyReq 通过合同模板名称直接发起签署流程请求
+type CreateFlowByTemplateDirectlyReq struct {
+	UserESignRecordID uint64            `json:"userESignRecordID" binding:"required"` // 用户电子签记录表ID 只有当前状态是1和4的电子签记录才能发起合同签署
+	UserType          int               `json:"userType" binding:"required"`          // 用户类型 1-个人 2-企业
+	PersonInfo        *PersonInfo       `json:"personInfo"`                           // 签署人信息,用户类型为个人时必填
+	OrganizationInfo  *OrganizationInfo `json:"organizationInfo"`                     // 签署企业信息,用户类型为企业时必填
+}
+
+// CreateFlowByTemplateDirectlyRsp 通过合同模板名称直接发起签署流程回复
+type CreateFlowByTemplateDirectlyRsp struct {
+	FlowId  string `json:"flowId"`  // 流程编号
+	SignUrl string `json:"signUrl"` // 合同签署小程序URL
+}
+
+// CreateFlowByTemplateDirectly 通过合同模板名称直接发起签署流程
+// @Summary 通过合同模板名称直接发起签署流程
+// @accept  application/json
+// @Produce application/json
+// @Param   data body     CreateFlowByTemplateDirectlyReq                    true "入参"
+// @Success 200  {object} app.Response{Data=CreateFlowByTemplateDirectlyRsp} "出参"
+// @Failure 500 {object} app.Response
+// @Router  /Tencent/CreateFlowByTemplateDirectly [post]
+// @Tags    腾讯电子签
+func CreateFlowByTemplateDirectly(c *gin.Context) {
+	appG := app.Gin{C: c}
+
+	// 获取请求参数
+	var req CreateFlowByTemplateDirectlyReq
+	if err := appG.C.ShouldBindJSON(&req); err != nil {
+		logger.GetLogger().Errorf("CreateFlowByTemplateDirectly failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
+		return
+	}
+	// 进阶判断请求参数
+	if req.UserType == 1 {
+		if req.PersonInfo == nil {
+			appG.ResponseByMsg(http.StatusBadRequest, e.INVALID_PARAMS, "缺少PersonInfo", nil)
+			return
+		}
+	}
+	if req.UserType == 2 {
+		if req.OrganizationInfo == nil {
+			appG.ResponseByMsg(http.StatusBadRequest, e.INVALID_PARAMS, "缺少OrganizationInfo", nil)
+			return
+		}
+	}
+
+	// 获取电子签信息表记录
+	record, err := models.GetUseresignRecord(req.UserESignRecordID)
+	if err != nil {
+		appG.ResponseByMsg(http.StatusBadRequest, e.ERROR, "获取电子签信息失败", nil)
+		return
+	}
+	// 确认电子签信息状态
+	// 记录状态 - 1:未签署 2:签署中 3:已签署 4:签署拒绝
+	if record.RECORDSTATUS != 1 && record.RECORDSTATUS != 4 {
+		appG.ResponseByMsg(http.StatusBadRequest, e.ERROR, "电子签信息状态异常", nil)
+		return
+	}
+
+	// 获取用户信息
+	// userAccount, err := models.GetUserAccount(int(record.USERID))
+	// if err != nil {
+	// 	appG.ResponseByMsg(http.StatusBadRequest, e.ERROR, "获取获取用户信息失败", nil)
+	// 	return
+	// }
+
+	// 构建电子签平台合同模板名称
+	// 格式:所属会员ID_类型标志_合同模板名称;例如 "1000_P_风险提示书",个人为P企业为A
+	flag := "P"
+	if req.UserType == 2 {
+		flag = "A"
+	}
+	tmplateName := fmt.Sprintf("%s_%s_%s", strconv.Itoa(int(record.AREAUSERID)), flag, record.TEMPLATENAME)
+
+	personName := ""
+	personMobile := ""
+	idCardNumber := ""
+	if req.PersonInfo != nil {
+		personName = req.PersonInfo.Name
+		personMobile = req.PersonInfo.Mobile
+		idCardNumber = req.PersonInfo.IdCardNumber
+	}
+	organizationName := ""
+	if req.OrganizationInfo != nil {
+		organizationName = req.OrganizationInfo.Name
+	}
+	flowId, signUrl, err := tencent.CreateFlowByTemplateDirectly(tmplateName, req.UserType, personName, personMobile, idCardNumber, organizationName, record)
+	if err == nil {
+		appG.Response(http.StatusOK, e.SUCCESS, CreateFlowByTemplateDirectlyRsp{
+			FlowId:  flowId,
+			SignUrl: signUrl,
+		})
+	} else {
+		appG.ResponseByMsg(http.StatusBadRequest, e.ERROR, err.Error(), nil)
+	}
+}
+
+type GetFlowStatusReq struct {
+	ContractNo string `form:"contractno" binding:"required"` // 合同编号
+}
+
+// GetFlowStatus 获取合同状态
+// @Summary 获取合同状态
+// @Produce json
+// @accept  application/json
+// @Param   contractno query    string true "合同编号"
+// @Success 200        {object} int    "记录状态 - 1:未签署 2:签署中 3:已签署 4:签署拒绝"
+// @Failure 500              {object} app.Response
+// @Router  /Tencent/GetFlowStatus [get]
+// @Tags    腾讯电子签
+func GetFlowStatus(c *gin.Context) {
+	appG := app.Gin{C: c}
+
+	// 获取请求参数
+	var req GetFlowStatusReq
+	if err := appG.C.ShouldBindQuery(&req); err != nil {
+		logger.GetLogger().Errorf("GetFlowStatus failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
+		return
+	}
+
+	if recordStatus, err := tencent.GetFlowStatus(req.ContractNo); err == nil {
+		appG.Response(http.StatusOK, e.SUCCESS, recordStatus)
+	} else {
+		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
+	}
+}

+ 36 - 0
controllers/user/user.go

@@ -647,3 +647,39 @@ func UpdateUserHeadUrl(c *gin.Context) {
 	logger.GetLogger().Debugln("UpdateUserHeadUrl successed: %v", "ok")
 	appG.Response(http.StatusOK, e.SUCCESS, "ok")
 }
+
+type QueryMdUserSwapProtocolReq struct {
+	UserId int `form:"userId" binding:"required"` // 用户ID
+}
+
+// QueryMdUserSwapProtocol 获取用户掉期协议签署表
+// @Summary  获取用户掉期协议签署表
+// @Produce  json
+// @Security ApiKeyAuth
+// @Param    userId query    int true "用户ID"
+// @Success  200    {array}  models.Mduserswapprotocol
+// @Failure  500    {object} app.Response
+// @Router   /User/QueryMdUserSwapProtocol [get]
+// @Tags     用户信息
+func QueryMdUserSwapProtocol(c *gin.Context) {
+	appG := app.Gin{C: c}
+
+	// 获取请求参数
+	var req QueryMdUserSwapProtocolReq
+	if err := appG.C.ShouldBindQuery(&req); err != nil {
+		logger.GetLogger().Errorf("QueryMdUserSwapProtocol failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
+		return
+	}
+
+	datas, err := models.QueryMdUserSwapProtocol(req.UserId, nil)
+	if err != nil {
+		// 查询失败
+		logger.GetLogger().Errorf("QueryMdUserSwapProtocol failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
+		return
+	}
+
+	// 查询成功
+	appG.Response(http.StatusOK, e.SUCCESS, datas)
+}

+ 479 - 0
docs/docs.go

@@ -17989,6 +17989,248 @@ const docTemplate = `{
                 }
             }
         },
+        "/Tencent/CreateConsoleLoginUrl": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "创建电子签控制台登录链接",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/Tencent/CreateFlowByTemplateDirectly": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "通过合同模板名称直接发起签署流程",
+                "parameters": [
+                    {
+                        "description": "入参",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/tencent.CreateFlowByTemplateDirectlyReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "出参",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/app.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "Data": {
+                                            "$ref": "#/definitions/tencent.CreateFlowByTemplateDirectlyRsp"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/Tencent/GetFlowStatus": {
+            "get": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "获取合同状态",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "合同编号",
+                        "name": "contractno",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "记录状态 - 1:未签署 2:签署中 3:已签署 4:签署拒绝",
+                        "schema": {
+                            "type": "integer"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/Tencent/InitTencentESS": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "按用户ID和机构ID创建腾讯电子签业务信息",
+                "parameters": [
+                    {
+                        "description": "入参",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/tencent.InitTencentESSReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/Tencent/QianNotice": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "腾讯电子签回调接口",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/Tencent/QueryUsereSignRecords": {
+            "get": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "查询用户电子签记录表",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "用户ID",
+                        "name": "userId",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "所属会员ID",
+                        "name": "memberUserId",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "记录ID",
+                        "name": "recordId",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "模板配置ID",
+                        "name": "templateConfigId",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "模板类型 - 1:实名认证 2:开户协议 3:日结算单 4:交易协议",
+                        "name": "templatetype",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "array",
+                            "items": {
+                                "$ref": "#/definitions/models.Useresignrecord"
+                            }
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
         "/Tjmd/QueryQuoteGoodsList": {
             "get": {
                 "security": [
@@ -18648,6 +18890,48 @@ const docTemplate = `{
                 }
             }
         },
+        "/User/QueryMdUserSwapProtocol": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "用户信息"
+                ],
+                "summary": "获取用户掉期协议签署表",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "用户ID",
+                        "name": "userId",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "array",
+                            "items": {
+                                "$ref": "#/definitions/models.Mduserswapprotocol"
+                            }
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
         "/User/QueryMessageBoard": {
             "get": {
                 "security": [
@@ -40536,6 +40820,35 @@ const docTemplate = `{
                 }
             }
         },
+        "models.Mduserswapprotocol": {
+            "type": "object",
+            "properties": {
+                "areauserid": {
+                    "description": "掉期服务商ID",
+                    "type": "integer"
+                },
+                "auditid": {
+                    "description": "审核人",
+                    "type": "integer"
+                },
+                "audittime": {
+                    "description": "审核时间",
+                    "type": "string"
+                },
+                "protocolstatus": {
+                    "description": "协议状态 - 1:未签署 2:签署中 3:已签署 4:已审核",
+                    "type": "integer"
+                },
+                "updatetime": {
+                    "description": "更新时间",
+                    "type": "string"
+                },
+                "userid": {
+                    "description": "用户ID",
+                    "type": "integer"
+                }
+            }
+        },
         "models.Membergoodslimitconfig": {
             "type": "object",
             "required": [
@@ -54250,6 +54563,91 @@ const docTemplate = `{
                 }
             }
         },
+        "models.Useresignrecord": {
+            "type": "object",
+            "properties": {
+                "areauserid": {
+                    "description": "服务商ID - 麦顿",
+                    "type": "integer"
+                },
+                "authinfo": {
+                    "description": "认证信息",
+                    "type": "string"
+                },
+                "contractfileaddr": {
+                    "description": "合同签署文件地址",
+                    "type": "string"
+                },
+                "contractno": {
+                    "description": "合同编号",
+                    "type": "string"
+                },
+                "createtime": {
+                    "description": "创建时间",
+                    "type": "string"
+                },
+                "creatorid": {
+                    "description": "创建人",
+                    "type": "integer"
+                },
+                "orderindex": {
+                    "description": "显示顺序",
+                    "type": "integer"
+                },
+                "partakey": {
+                    "description": "甲方Key(逗号分隔)",
+                    "type": "string"
+                },
+                "partbkey": {
+                    "description": "乙方Key(逗号分隔)",
+                    "type": "string"
+                },
+                "recordid": {
+                    "description": "记录ID(SEQ_USERESIGNRECORD)",
+                    "type": "integer"
+                },
+                "recordstatus": {
+                    "description": "记录状态 - 1:未签署 2:签署中 3:已签署 4:签署拒绝",
+                    "type": "integer"
+                },
+                "signremark": {
+                    "description": "签署备注",
+                    "type": "string"
+                },
+                "signurl": {
+                    "description": "合同签署URL(三方URL)",
+                    "type": "string"
+                },
+                "templateconfigid": {
+                    "description": "模板配置ID",
+                    "type": "integer"
+                },
+                "templatename": {
+                    "description": "模板名称",
+                    "type": "string"
+                },
+                "templateno": {
+                    "description": "模板编号(电子签类型对应的模板编号)",
+                    "type": "string"
+                },
+                "templatetype": {
+                    "description": "模板类型 - 1:实名认证 2:开户协议 3:日结算单",
+                    "type": "integer"
+                },
+                "tradedate": {
+                    "description": "交易日",
+                    "type": "string"
+                },
+                "updatetime": {
+                    "description": "更新时间",
+                    "type": "string"
+                },
+                "userid": {
+                    "description": "用户ID",
+                    "type": "integer"
+                }
+            }
+        },
         "models.Userfavoritegoods": {
             "type": "object",
             "required": [
@@ -62072,6 +62470,87 @@ const docTemplate = `{
                 }
             }
         },
+        "tencent.CreateFlowByTemplateDirectlyReq": {
+            "type": "object",
+            "required": [
+                "userESignRecordID",
+                "userType"
+            ],
+            "properties": {
+                "organizationInfo": {
+                    "description": "签署企业信息,用户类型为企业时必填",
+                    "$ref": "#/definitions/tencent.OrganizationInfo"
+                },
+                "personInfo": {
+                    "description": "签署人信息,用户类型为个人时必填",
+                    "$ref": "#/definitions/tencent.PersonInfo"
+                },
+                "userESignRecordID": {
+                    "description": "用户电子签记录表ID 只有当前状态是1和4的电子签记录才能发起合同签署",
+                    "type": "integer"
+                },
+                "userType": {
+                    "description": "用户类型 1-个人 2-企业",
+                    "type": "integer"
+                }
+            }
+        },
+        "tencent.CreateFlowByTemplateDirectlyRsp": {
+            "type": "object",
+            "properties": {
+                "flowId": {
+                    "description": "流程编号",
+                    "type": "string"
+                },
+                "signUrl": {
+                    "description": "合同签署小程序URL",
+                    "type": "string"
+                }
+            }
+        },
+        "tencent.InitTencentESSReq": {
+            "type": "object",
+            "required": [
+                "memberUserId",
+                "userId"
+            ],
+            "properties": {
+                "memberUserId": {
+                    "description": "所属会员ID",
+                    "type": "integer"
+                },
+                "userId": {
+                    "description": "用户ID",
+                    "type": "integer"
+                }
+            }
+        },
+        "tencent.OrganizationInfo": {
+            "type": "object",
+            "properties": {
+                "name": {
+                    "description": "企业签署方工商营业执照上的企业名称",
+                    "type": "string"
+                }
+            }
+        },
+        "tencent.PersonInfo": {
+            "type": "object",
+            "properties": {
+                "idCardNumber": {
+                    "description": "身份证号码,目前只支持身份证",
+                    "type": "string"
+                },
+                "mobile": {
+                    "description": "手机号码",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "姓名",
+                    "type": "string"
+                }
+            }
+        },
         "trade.QueryRecieptOrderRsp": {
             "type": "object",
             "required": [

+ 479 - 0
docs/swagger.json

@@ -17980,6 +17980,248 @@
                 }
             }
         },
+        "/Tencent/CreateConsoleLoginUrl": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "创建电子签控制台登录链接",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/Tencent/CreateFlowByTemplateDirectly": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "通过合同模板名称直接发起签署流程",
+                "parameters": [
+                    {
+                        "description": "入参",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/tencent.CreateFlowByTemplateDirectlyReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "出参",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/app.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "Data": {
+                                            "$ref": "#/definitions/tencent.CreateFlowByTemplateDirectlyRsp"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/Tencent/GetFlowStatus": {
+            "get": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "获取合同状态",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "合同编号",
+                        "name": "contractno",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "记录状态 - 1:未签署 2:签署中 3:已签署 4:签署拒绝",
+                        "schema": {
+                            "type": "integer"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/Tencent/InitTencentESS": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "按用户ID和机构ID创建腾讯电子签业务信息",
+                "parameters": [
+                    {
+                        "description": "入参",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/tencent.InitTencentESSReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/Tencent/QianNotice": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "腾讯电子签回调接口",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/Tencent/QueryUsereSignRecords": {
+            "get": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "腾讯电子签"
+                ],
+                "summary": "查询用户电子签记录表",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "用户ID",
+                        "name": "userId",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "所属会员ID",
+                        "name": "memberUserId",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "记录ID",
+                        "name": "recordId",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "模板配置ID",
+                        "name": "templateConfigId",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "模板类型 - 1:实名认证 2:开户协议 3:日结算单 4:交易协议",
+                        "name": "templatetype",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "array",
+                            "items": {
+                                "$ref": "#/definitions/models.Useresignrecord"
+                            }
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
         "/Tjmd/QueryQuoteGoodsList": {
             "get": {
                 "security": [
@@ -18639,6 +18881,48 @@
                 }
             }
         },
+        "/User/QueryMdUserSwapProtocol": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "用户信息"
+                ],
+                "summary": "获取用户掉期协议签署表",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "用户ID",
+                        "name": "userId",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "array",
+                            "items": {
+                                "$ref": "#/definitions/models.Mduserswapprotocol"
+                            }
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
         "/User/QueryMessageBoard": {
             "get": {
                 "security": [
@@ -40527,6 +40811,35 @@
                 }
             }
         },
+        "models.Mduserswapprotocol": {
+            "type": "object",
+            "properties": {
+                "areauserid": {
+                    "description": "掉期服务商ID",
+                    "type": "integer"
+                },
+                "auditid": {
+                    "description": "审核人",
+                    "type": "integer"
+                },
+                "audittime": {
+                    "description": "审核时间",
+                    "type": "string"
+                },
+                "protocolstatus": {
+                    "description": "协议状态 - 1:未签署 2:签署中 3:已签署 4:已审核",
+                    "type": "integer"
+                },
+                "updatetime": {
+                    "description": "更新时间",
+                    "type": "string"
+                },
+                "userid": {
+                    "description": "用户ID",
+                    "type": "integer"
+                }
+            }
+        },
         "models.Membergoodslimitconfig": {
             "type": "object",
             "required": [
@@ -54241,6 +54554,91 @@
                 }
             }
         },
+        "models.Useresignrecord": {
+            "type": "object",
+            "properties": {
+                "areauserid": {
+                    "description": "服务商ID - 麦顿",
+                    "type": "integer"
+                },
+                "authinfo": {
+                    "description": "认证信息",
+                    "type": "string"
+                },
+                "contractfileaddr": {
+                    "description": "合同签署文件地址",
+                    "type": "string"
+                },
+                "contractno": {
+                    "description": "合同编号",
+                    "type": "string"
+                },
+                "createtime": {
+                    "description": "创建时间",
+                    "type": "string"
+                },
+                "creatorid": {
+                    "description": "创建人",
+                    "type": "integer"
+                },
+                "orderindex": {
+                    "description": "显示顺序",
+                    "type": "integer"
+                },
+                "partakey": {
+                    "description": "甲方Key(逗号分隔)",
+                    "type": "string"
+                },
+                "partbkey": {
+                    "description": "乙方Key(逗号分隔)",
+                    "type": "string"
+                },
+                "recordid": {
+                    "description": "记录ID(SEQ_USERESIGNRECORD)",
+                    "type": "integer"
+                },
+                "recordstatus": {
+                    "description": "记录状态 - 1:未签署 2:签署中 3:已签署 4:签署拒绝",
+                    "type": "integer"
+                },
+                "signremark": {
+                    "description": "签署备注",
+                    "type": "string"
+                },
+                "signurl": {
+                    "description": "合同签署URL(三方URL)",
+                    "type": "string"
+                },
+                "templateconfigid": {
+                    "description": "模板配置ID",
+                    "type": "integer"
+                },
+                "templatename": {
+                    "description": "模板名称",
+                    "type": "string"
+                },
+                "templateno": {
+                    "description": "模板编号(电子签类型对应的模板编号)",
+                    "type": "string"
+                },
+                "templatetype": {
+                    "description": "模板类型 - 1:实名认证 2:开户协议 3:日结算单",
+                    "type": "integer"
+                },
+                "tradedate": {
+                    "description": "交易日",
+                    "type": "string"
+                },
+                "updatetime": {
+                    "description": "更新时间",
+                    "type": "string"
+                },
+                "userid": {
+                    "description": "用户ID",
+                    "type": "integer"
+                }
+            }
+        },
         "models.Userfavoritegoods": {
             "type": "object",
             "required": [
@@ -62063,6 +62461,87 @@
                 }
             }
         },
+        "tencent.CreateFlowByTemplateDirectlyReq": {
+            "type": "object",
+            "required": [
+                "userESignRecordID",
+                "userType"
+            ],
+            "properties": {
+                "organizationInfo": {
+                    "description": "签署企业信息,用户类型为企业时必填",
+                    "$ref": "#/definitions/tencent.OrganizationInfo"
+                },
+                "personInfo": {
+                    "description": "签署人信息,用户类型为个人时必填",
+                    "$ref": "#/definitions/tencent.PersonInfo"
+                },
+                "userESignRecordID": {
+                    "description": "用户电子签记录表ID 只有当前状态是1和4的电子签记录才能发起合同签署",
+                    "type": "integer"
+                },
+                "userType": {
+                    "description": "用户类型 1-个人 2-企业",
+                    "type": "integer"
+                }
+            }
+        },
+        "tencent.CreateFlowByTemplateDirectlyRsp": {
+            "type": "object",
+            "properties": {
+                "flowId": {
+                    "description": "流程编号",
+                    "type": "string"
+                },
+                "signUrl": {
+                    "description": "合同签署小程序URL",
+                    "type": "string"
+                }
+            }
+        },
+        "tencent.InitTencentESSReq": {
+            "type": "object",
+            "required": [
+                "memberUserId",
+                "userId"
+            ],
+            "properties": {
+                "memberUserId": {
+                    "description": "所属会员ID",
+                    "type": "integer"
+                },
+                "userId": {
+                    "description": "用户ID",
+                    "type": "integer"
+                }
+            }
+        },
+        "tencent.OrganizationInfo": {
+            "type": "object",
+            "properties": {
+                "name": {
+                    "description": "企业签署方工商营业执照上的企业名称",
+                    "type": "string"
+                }
+            }
+        },
+        "tencent.PersonInfo": {
+            "type": "object",
+            "properties": {
+                "idCardNumber": {
+                    "description": "身份证号码,目前只支持身份证",
+                    "type": "string"
+                },
+                "mobile": {
+                    "description": "手机号码",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "姓名",
+                    "type": "string"
+                }
+            }
+        },
         "trade.QueryRecieptOrderRsp": {
             "type": "object",
             "required": [

+ 321 - 0
docs/swagger.yaml

@@ -13816,6 +13816,27 @@ definitions:
     - tradedate
     - tradedate2
     type: object
+  models.Mduserswapprotocol:
+    properties:
+      areauserid:
+        description: 掉期服务商ID
+        type: integer
+      auditid:
+        description: 审核人
+        type: integer
+      audittime:
+        description: 审核时间
+        type: string
+      protocolstatus:
+        description: 协议状态 - 1:未签署 2:签署中 3:已签署 4:已审核
+        type: integer
+      updatetime:
+        description: 更新时间
+        type: string
+      userid:
+        description: 用户ID
+        type: integer
+    type: object
   models.Membergoodslimitconfig:
     properties:
       autoid:
@@ -23970,6 +23991,69 @@ definitions:
     required:
     - userid
     type: object
+  models.Useresignrecord:
+    properties:
+      areauserid:
+        description: 服务商ID - 麦顿
+        type: integer
+      authinfo:
+        description: 认证信息
+        type: string
+      contractfileaddr:
+        description: 合同签署文件地址
+        type: string
+      contractno:
+        description: 合同编号
+        type: string
+      createtime:
+        description: 创建时间
+        type: string
+      creatorid:
+        description: 创建人
+        type: integer
+      orderindex:
+        description: 显示顺序
+        type: integer
+      partakey:
+        description: 甲方Key(逗号分隔)
+        type: string
+      partbkey:
+        description: 乙方Key(逗号分隔)
+        type: string
+      recordid:
+        description: 记录ID(SEQ_USERESIGNRECORD)
+        type: integer
+      recordstatus:
+        description: 记录状态 - 1:未签署 2:签署中 3:已签署 4:签署拒绝
+        type: integer
+      signremark:
+        description: 签署备注
+        type: string
+      signurl:
+        description: 合同签署URL(三方URL)
+        type: string
+      templateconfigid:
+        description: 模板配置ID
+        type: integer
+      templatename:
+        description: 模板名称
+        type: string
+      templateno:
+        description: 模板编号(电子签类型对应的模板编号)
+        type: string
+      templatetype:
+        description: 模板类型 - 1:实名认证 2:开户协议 3:日结算单
+        type: integer
+      tradedate:
+        description: 交易日
+        type: string
+      updatetime:
+        description: 更新时间
+        type: string
+      userid:
+        description: 用户ID
+        type: integer
+    type: object
   models.Userfavoritegoods:
     properties:
       goodsid:
@@ -29843,6 +29927,63 @@ definitions:
     - histradedate
     - operatetype
     type: object
+  tencent.CreateFlowByTemplateDirectlyReq:
+    properties:
+      organizationInfo:
+        $ref: '#/definitions/tencent.OrganizationInfo'
+        description: 签署企业信息,用户类型为企业时必填
+      personInfo:
+        $ref: '#/definitions/tencent.PersonInfo'
+        description: 签署人信息,用户类型为个人时必填
+      userESignRecordID:
+        description: 用户电子签记录表ID 只有当前状态是1和4的电子签记录才能发起合同签署
+        type: integer
+      userType:
+        description: 用户类型 1-个人 2-企业
+        type: integer
+    required:
+    - userESignRecordID
+    - userType
+    type: object
+  tencent.CreateFlowByTemplateDirectlyRsp:
+    properties:
+      flowId:
+        description: 流程编号
+        type: string
+      signUrl:
+        description: 合同签署小程序URL
+        type: string
+    type: object
+  tencent.InitTencentESSReq:
+    properties:
+      memberUserId:
+        description: 所属会员ID
+        type: integer
+      userId:
+        description: 用户ID
+        type: integer
+    required:
+    - memberUserId
+    - userId
+    type: object
+  tencent.OrganizationInfo:
+    properties:
+      name:
+        description: 企业签署方工商营业执照上的企业名称
+        type: string
+    type: object
+  tencent.PersonInfo:
+    properties:
+      idCardNumber:
+        description: 身份证号码,目前只支持身份证
+        type: string
+      mobile:
+        description: 手机号码
+        type: string
+      name:
+        description: 姓名
+        type: string
+    type: object
   trade.QueryRecieptOrderRsp:
     properties:
       accountName:
@@ -41279,6 +41420,160 @@ paths:
       summary: 查询关联资金账户信息
       tags:
       - 资金账户
+  /Tencent/CreateConsoleLoginUrl:
+    post:
+      consumes:
+      - application/json
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/app.Response'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/app.Response'
+      summary: 创建电子签控制台登录链接
+      tags:
+      - 腾讯电子签
+  /Tencent/CreateFlowByTemplateDirectly:
+    post:
+      consumes:
+      - application/json
+      parameters:
+      - description: 入参
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/tencent.CreateFlowByTemplateDirectlyReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 出参
+          schema:
+            allOf:
+            - $ref: '#/definitions/app.Response'
+            - properties:
+                Data:
+                  $ref: '#/definitions/tencent.CreateFlowByTemplateDirectlyRsp'
+              type: object
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/app.Response'
+      summary: 通过合同模板名称直接发起签署流程
+      tags:
+      - 腾讯电子签
+  /Tencent/GetFlowStatus:
+    get:
+      consumes:
+      - application/json
+      parameters:
+      - description: 合同编号
+        in: query
+        name: contractno
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 记录状态 - 1:未签署 2:签署中 3:已签署 4:签署拒绝
+          schema:
+            type: integer
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/app.Response'
+      summary: 获取合同状态
+      tags:
+      - 腾讯电子签
+  /Tencent/InitTencentESS:
+    post:
+      consumes:
+      - application/json
+      parameters:
+      - description: 入参
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/tencent.InitTencentESSReq'
+      produces:
+      - application/json
+      responses:
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/app.Response'
+      summary: 按用户ID和机构ID创建腾讯电子签业务信息
+      tags:
+      - 腾讯电子签
+  /Tencent/QianNotice:
+    post:
+      consumes:
+      - application/json
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/app.Response'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/app.Response'
+      summary: 腾讯电子签回调接口
+      tags:
+      - 腾讯电子签
+  /Tencent/QueryUsereSignRecords:
+    get:
+      consumes:
+      - application/json
+      parameters:
+      - description: 用户ID
+        in: query
+        name: userId
+        required: true
+        type: integer
+      - description: 所属会员ID
+        in: query
+        name: memberUserId
+        required: true
+        type: integer
+      - description: 记录ID
+        in: query
+        name: recordId
+        type: integer
+      - description: 模板配置ID
+        in: query
+        name: templateConfigId
+        type: integer
+      - description: 模板类型 - 1:实名认证 2:开户协议 3:日结算单 4:交易协议
+        in: query
+        name: templatetype
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            items:
+              $ref: '#/definitions/models.Useresignrecord'
+            type: array
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/app.Response'
+      summary: 查询用户电子签记录表
+      tags:
+      - 腾讯电子签
   /Tjmd/QueryQuoteGoodsList:
     get:
       description: 用户类型必传, 查掉期报价列表 marketids=掉期市场id
@@ -41697,6 +41992,32 @@ paths:
       summary: 账户登录后信息查询
       tags:
       - 用户信息
+  /User/QueryMdUserSwapProtocol:
+    get:
+      parameters:
+      - description: 用户ID
+        in: query
+        name: userId
+        required: true
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            items:
+              $ref: '#/definitions/models.Mduserswapprotocol'
+            type: array
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/app.Response'
+      security:
+      - ApiKeyAuth: []
+      summary: 获取用户掉期协议签署表
+      tags:
+      - 用户信息
   /User/QueryMessageBoard:
     get:
       parameters:

+ 8 - 2
global/app/response.go

@@ -26,7 +26,14 @@ func (g *Gin) Response(httpCode, errCode int, data interface{}) {
 		Msg:  e.GetMsg(errCode),
 		Data: data,
 	})
-	return
+}
+
+func (g *Gin) ResponseByMsg(httpCode, errCode int, msg string, data interface{}) {
+	g.C.JSON(httpCode, Response{
+		Code: errCode,
+		Msg:  msg,
+		Data: data,
+	})
 }
 
 // ResponseByPage 带分页信息返回方法
@@ -37,7 +44,6 @@ func (g *Gin) ResponseByPage(httpCode, errCode int, data interface{}, page PageI
 		PageInfo: page,
 		Data:     data,
 	})
-	return
 }
 
 // GetPageData 获取指定分页的数据

+ 2 - 0
go.mod

@@ -59,6 +59,8 @@ require (
 	github.com/swaggo/files v1.0.1
 	github.com/swaggo/gin-swagger v1.6.0
 	github.com/swaggo/swag v1.16.2
+	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.772
+	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic v1.0.772
 )
 
 require (

+ 4 - 0
go.sum

@@ -172,6 +172,10 @@ github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
 github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
 github.com/tebeka/strftime v0.1.3 h1:5HQXOqWKYRFfNyBMNVc9z5+QzuBtIXy03psIhtdJYto=
 github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.772 h1:zwJinPIIMaBUJB9Sr5eeMcNaEQBcMzsjev4S14RhA10=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.772/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic v1.0.772 h1:iD060QlYTUVdEJ3stHhLZzuTYtKFuTbsMCygrcSisaM=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic v1.0.772/go.mod h1:4zkfwdL6iHCeCd+WTi9ngH2//I5dkM+n0J5b18t1MQQ=
 github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=

+ 10 - 0
main.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"mtp2_if/controllers/other"
 	"mtp2_if/models"
+	"mtp2_if/utils"
 	"net/http"
 	"os"
 	"os/signal"
@@ -113,6 +114,15 @@ func main() {
 		gin.SetMode(gin.ReleaseMode)
 	}
 
+	// 判断是否启动腾讯电子签
+	if config.SerCfg.TencentCfg.Enabled == 1 {
+		err = utils.InitTencentESSClient()
+		if err != nil {
+			logger.GetLogger().Errorf("init tencent ess failed:%v", err.Error())
+			return
+		}
+	}
+
 	// 启动定时同步盘面Timer
 	models.StartSyncRedisQuoteDay()
 

+ 103 - 0
models/esign.go

@@ -0,0 +1,103 @@
+package models
+
+import (
+	"fmt"
+	"mtp2_if/db"
+
+	"github.com/xormplus/xorm"
+)
+
+// GetUseresignRecord 通过ID获取记录
+func GetUseresignRecord(id uint64) (useresignrecord *Useresignrecord, err error) {
+	datas := make([]Useresignrecord, 0)
+	err = db.GetEngine().Where("RECORDID = ?", id).Find(&datas)
+	if err == nil {
+		if len(datas) == 0 {
+			err = xorm.ErrNotExist
+			return
+		}
+		useresignrecord = &datas[0]
+	}
+
+	return
+}
+
+// GetUseresignRecordByFlowID 通过合同编号获取记录
+func GetUseresignRecordByFlowID(flowId string) (useresignrecord *Useresignrecord, err error) {
+	datas := make([]Useresignrecord, 0)
+	err = db.GetEngine().Where("CONTRACTNO = ?", flowId).Find(&datas)
+	if err == nil {
+		if len(datas) == 0 {
+			err = xorm.ErrNotExist
+			return
+		}
+		useresignrecord = &datas[0]
+	}
+
+	return
+}
+
+func (t *Useresignrecord) Update(cols string) (err error) {
+	_, err = db.GetEngine().Cols(cols).Where("RECORDID = ?", t.RECORDID).Update(t)
+	return
+}
+
+func QueryUsereSignRecords(userId, memberUserId int, recordId, templateConfigId, templatetype *int) (records []Useresignrecord, err error) {
+	session := db.GetEngine().Table("USERESIGNRECORD").Where("USERID = ? AND AREAUSERID = ?", userId, memberUserId)
+	if recordId != nil {
+		session = session.And("RECORDID = ?", recordId)
+	}
+	if templateConfigId != nil {
+		session = session.And("TEMPLATECONFIGID = ?", templateConfigId)
+	}
+	if templatetype != nil {
+		session = session.And("TEMPLATETYPE = ?", templatetype)
+	}
+	err = session.Find(&records)
+
+	return
+}
+
+func QueryMdUserSwapProtocol(userId int, areaUserId *int64) (datas []Mduserswapprotocol, err error) {
+	session := db.GetEngine().Table("MD_USERSWAPPROTOCOL").Where("USERID = ?", userId)
+	if areaUserId != nil {
+		session = session.And("AREAUSERID = ?", areaUserId)
+	}
+	err = session.Find(&datas)
+
+	return
+}
+
+func (t *Mduserswapprotocol) Update(cols string) (err error) {
+	_, err = db.GetEngine().Cols(cols).Where("USERID = ? AND AREAUSERID = ?", t.USERID, t.AREAUSERID).Update(t)
+	return
+}
+
+func QueryEsignTemplateConfigs(esignType, templateType int) (datas []Esigntemplateconfig, err error) {
+	err = db.GetEngine().Table("ESIGNTEMPLATECONFIG").Where("ESIGNTYPE = ? AND TEMPLATETYPE = ?", esignType, templateType).Find(&datas)
+	return
+}
+
+func InsertMdUserSwapProtocol(userId, areaUserId int, session *xorm.Session) (err error) {
+	sql := fmt.Sprintf(`
+	INSERT INTO MD_USERSWAPPROTOCOL 
+	(USERID,AREAUSERID,PROTOCOLSTATUS,AUDITTIME,UPDATETIME) 
+	VALUES
+	(%v,%v,1,sysdate,sysdate)
+	`, userId, areaUserId)
+	_, err = session.Exec(sql)
+
+	return
+}
+
+func InsertUserEsignRecord(userId, areaUserId int, econfig Esigntemplateconfig, session *xorm.Session) (err error) {
+	sql := fmt.Sprintf(`
+	INSERT INTO USERESIGNRECORD 
+	(RECORDID,USERID,TEMPLATECONFIGID,TEMPLATETYPE,TEMPLATENAME,ORDERINDEX,RECORDSTATUS,CREATETIME,UPDATETIME,AREAUSERID) 
+	VALUES
+	(SEQ_USERESIGNRECORD.nextval,%v,%v,%v,'%v',%v,1,sysdate,sysdate,%v)
+	`, userId, econfig.TEMPLATECONFIGID, econfig.TEMPLATETYPE, econfig.TEMPLATENAME, econfig.ORDERINDEX, areaUserId)
+	_, err = session.Exec(sql)
+
+	return
+}

+ 64 - 0
models/ori.go

@@ -695,3 +695,67 @@ type Deliveryofflineoperatelog struct {
 func (r *Deliveryofflineoperatelog) TableName() string {
 	return "DELIVERYOFFLINEOPERATELOG"
 }
+
+// Useresignrecord 用户电子签记录表
+type Useresignrecord struct {
+	RECORDID         int64     `json:"recordid" xorm:"RECORDID"`                 // 记录ID(SEQ_USERESIGNRECORD)
+	USERID           int64     `json:"userid" xorm:"USERID"`                     // 用户ID
+	TEMPLATECONFIGID int64     `json:"templateconfigid" xorm:"TEMPLATECONFIGID"` // 模板配置ID
+	TEMPLATENO       string    `json:"templateno" xorm:"TEMPLATENO"`             // 模板编号(电子签类型对应的模板编号)
+	TEMPLATETYPE     int32     `json:"templatetype" xorm:"TEMPLATETYPE"`         // 模板类型 - 1:实名认证 2:开户协议 3:日结算单
+	TEMPLATENAME     string    `json:"templatename" xorm:"TEMPLATENAME"`         // 模板名称
+	ORDERINDEX       int32     `json:"orderindex" xorm:"ORDERINDEX"`             // 显示顺序
+	RECORDSTATUS     int32     `json:"recordstatus" xorm:"RECORDSTATUS"`         // 记录状态 - 1:未签署 2:签署中 3:已签署 4:签署拒绝
+	CONTRACTNO       string    `json:"contractno" xorm:"CONTRACTNO"`             // 合同编号
+	CONTRACTFILEADDR string    `json:"contractfileaddr" xorm:"CONTRACTFILEADDR"` // 合同签署文件地址
+	SIGNREMARK       string    `json:"signremark" xorm:"SIGNREMARK"`             // 签署备注
+	CREATORID        int64     `json:"creatorid" xorm:"CREATORID"`               // 创建人
+	CREATETIME       time.Time `json:"createtime" xorm:"CREATETIME"`             // 创建时间
+	UPDATETIME       time.Time `json:"updatetime" xorm:"UPDATETIME"`             // 更新时间
+	AUTHINFO         string    `json:"authinfo" xorm:"AUTHINFO"`                 // 认证信息
+	SIGNURL          string    `json:"signurl" xorm:"SIGNURL"`                   // 合同签署URL(三方URL)
+	PARTAKEY         string    `json:"partakey" xorm:"PARTAKEY"`                 // 甲方Key(逗号分隔)
+	PARTBKEY         string    `json:"partbkey" xorm:"PARTBKEY"`                 // 乙方Key(逗号分隔)
+	TRADEDATE        string    `json:"tradedate" xorm:"TRADEDATE"`               // 交易日
+	AREAUSERID       int64     `json:"areauserid" xorm:"AREAUSERID"`             // 服务商ID - 麦顿
+}
+
+// TableName is USERESIGNRECORD
+func (r *Useresignrecord) TableName() string {
+	return "USERESIGNRECORD"
+}
+
+// Mduserswapprotocol 用户掉期协议签署表(麦顿)
+type Mduserswapprotocol struct {
+	USERID         int64     `json:"userid" xorm:"USERID"`                 // 用户ID
+	AREAUSERID     int64     `json:"areauserid" xorm:"AREAUSERID"`         // 掉期服务商ID
+	PROTOCOLSTATUS int32     `json:"protocolstatus" xorm:"PROTOCOLSTATUS"` // 协议状态 - 1:未签署 2:签署中 3:已签署 4:已审核
+	AUDITID        int64     `json:"auditid" xorm:"AUDITID"`               // 审核人
+	AUDITTIME      time.Time `json:"audittime" xorm:"AUDITTIME"`           // 审核时间
+	UPDATETIME     time.Time `json:"updatetime" xorm:"UPDATETIME"`         // 更新时间
+}
+
+// TableName is MD_USERSWAPPROTOCOL
+func (r *Mduserswapprotocol) TableName() string {
+	return "MD_USERSWAPPROTOCOL"
+}
+
+// Esigntemplateconfig 电子签模板配置表
+type Esigntemplateconfig struct {
+	TEMPLATECONFIGID int64     `json:"templateconfigid" xorm:"TEMPLATECONFIGID"` // 模板配置ID(SEQ_ESIGNTEMPLATECONFIG)
+	ESIGNTYPE        int32     `json:"esigntype" xorm:"ESIGNTYPE"`               // 电子签类型 - 1:爱签 2:腾讯电子签
+	TEMPLATENO       string    `json:"templateno" xorm:"TEMPLATENO"`             // 模板编号(电子签类型对应的模板编号)
+	TEMPLATETYPE     int32     `json:"templatetype" xorm:"TEMPLATETYPE"`         // 模板类型 - 1:实名认证(爱签-贵州云上) 2:开户协议(爱签-贵州云上) 3:日结算单(暂未使用) 4:交易协议(麦顿)
+	TEMPLATENAME     string    `json:"templatename" xorm:"TEMPLATENAME"`         // 模板名称
+	ORDERINDEX       int32     `json:"orderindex" xorm:"ORDERINDEX"`             // 显示顺序
+	CREATORID        int64     `json:"creatorid" xorm:"CREATORID"`               // 创建人
+	CREATETIME       time.Time `json:"createtime" xorm:"CREATETIME"`             // 创建时间
+	UPDATETIME       time.Time `json:"updatetime" xorm:"UPDATETIME"`             // 更新时间
+	PARTAKEY         string    `json:"partakey" xorm:"PARTAKEY"`                 // 甲方Key(逗号分隔)
+	PARTBKEY         string    `json:"partbkey" xorm:"PARTBKEY"`                 // 乙方Key(逗号分隔)
+}
+
+// TableName is ESIGNTEMPLATECONFIG
+func (r *Esigntemplateconfig) TableName() string {
+	return "ESIGNTEMPLATECONFIG"
+}

+ 42 - 0
res/doc/腾讯电子签/readme.txt

@@ -0,0 +1,42 @@
+SaaS控制台入口:
+https://beta.qian.tencent.cn/ 
+加入企业后,扫码登录即可
+
+文档在这
+https://qian.tencent.com/developers/company/overview
+
+腾讯电子签注册认证-入口:
+https://qian.tencent.com/console/company-register
+
+密钥(测试)
+Secret Id:AKyDwiyUUckpkct4igUy8lsS7SEqR6c7yR
+Secret Key:SKwvG74cbV3OrAiJdjU5k4507vZwNYDbwT
+
+子客(测试)
+贵州云上 
+ProxyOrganizationOpenId:GZYS
+Agent. ProxyOperator.OpenId:GZYS01
+
+APPID: yDwiuUUckpogftgaUxhigrYuO5OwMFwf
+
+指定回调
+地址:http://218.17.158.45:15154/api/Tencent/QianNotice
+加密 key:0DEE80AF2ECA488F97CAB8560BA42217
+签名验证 token:258B729A6F3947F492C2CA6F4C31E6BD
+
+天津麦顿 
+ProxyOrganizationOpenId:TJMD
+Agent. ProxyOperator.OpenId:TJMD01
+
+APPID: yDwiuUUckpogfoa4UxhigrYChFMdSJQV
+
+指定回调
+地址:http://218.17.158.45:15160/api/Tencent/QianNotice
+加密 key:8774F484EA294C1E829EA6E2D7F99123
+签名验证 token:D586D270A51448179277A11729F37D3E
+
+子客登录信息:
+https://embed.beta.qian.tencent.cn/console/?channel=PROXYCHANNEL&expiredTime=0&code=&menuStatus=ENABLE&token=yDwi0UUckpohy6yaUEdhBFERTLeuj39p
+{"Response":{"ConsoleUrl":"https://embed.beta.qian.tencent.cn/console/?channel=PROXYCHANNEL\\u0026expiredTime=0\\u0026code=\\u0026menuStatus=ENABLE\\u0026token=yDwi0UUckpohy6ybUEdhBFE896SjooDs","IsActivated":false,"ProxyOperatorIsVerified":false,"RequestId":"ba01db87-a97f-4f1f-8319-b5632df336d7"}}
+
+

+ 15 - 0
routers/router.go

@@ -28,6 +28,7 @@ import (
 	"mtp2_if/controllers/search"
 	"mtp2_if/controllers/szdz"
 	"mtp2_if/controllers/taaccount"
+	"mtp2_if/controllers/tencent"
 	"mtp2_if/controllers/tjmd"
 	"mtp2_if/controllers/trade"
 	"mtp2_if/controllers/tradexx"
@@ -105,6 +106,8 @@ func InitRouter() *gin.Engine {
 		userR.Use(token.Auth()).GET("/LoginQuery", user.LoginQuery)
 
 		userR.Use(token.Auth()).POST("/UpdateUserHeadUrl", user.UpdateUserHeadUrl)
+
+		userR.Use(token.Auth()).GET("/QueryMdUserSwapProtocol", user.QueryMdUserSwapProtocol)
 	}
 	// ************************ 资金账户 ************************
 	taAccountR := apiR.Group("TaAccount")
@@ -811,6 +814,18 @@ func InitRouter() *gin.Engine {
 		reportR.GET("QueryReportMonthTaaccount", report.QueryReportMonthTaaccount)
 	}
 
+	// ************************* 腾讯 *************************
+	tencentR := apiR.Group("Tencent")
+	tencentR.Use(token.Auth())
+	{
+		tencentR.GET("QueryUsereSignRecords", tencent.QueryUsereSignRecords)
+		tencentR.POST("QianNotice", tencent.QianNotice)
+		tencentR.POST("CreateConsoleLoginUrl", tencent.CreateConsoleLoginUrl)
+		tencentR.POST("CreateFlowByTemplateDirectly", tencent.CreateFlowByTemplateDirectly)
+		tencentR.GET("GetFlowStatus", tencent.GetFlowStatus)
+		tencentR.POST("InitTencentESS", tencent.InitTencentESS)
+	}
+
 	return r
 }
 

+ 369 - 0
services/tencent/ess.go

@@ -0,0 +1,369 @@
+package tencent
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/hmac"
+	"crypto/sha256"
+	"encoding/base64"
+	"encoding/hex"
+	"encoding/json"
+	"fmt"
+	"mtp2_if/config"
+	"mtp2_if/db"
+	"mtp2_if/logger"
+	"mtp2_if/models"
+	"mtp2_if/services/tencent/essapi"
+	"mtp2_if/utils"
+
+	essbasic "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic/v20210526"
+)
+
+func CreateConsoleLoginUrl(agent *essbasic.Agent, proxyOrganizationName string) (response *essbasic.CreateConsoleLoginUrlResponse, err error) {
+	response, err = essapi.CreateConsoleLoginUrl(agent, proxyOrganizationName)
+	// 输出json格式的字符串回包
+	fmt.Printf("%s", response.ToJsonString())
+
+	return
+}
+
+// InitTencentESS 按用户ID和机构ID创建腾讯电子签业务信息
+func InitTencentESS(userId, areaUserId int) (err error) {
+	esignTemplateConfigs, err := models.QueryEsignTemplateConfigs(2, 4)
+	if err != nil {
+		return
+	}
+
+	session := db.GetEngine().NewSession()
+	defer session.Close()
+	// 开启事务
+	session.Begin()
+
+	// 新增 MdUserSwapProtocol
+	err = models.InsertMdUserSwapProtocol(userId, areaUserId, session)
+	if err != nil {
+		session.Rollback()
+		return
+	}
+
+	// 新增 UserEsignRecord
+	for _, item := range esignTemplateConfigs {
+		err = models.InsertUserEsignRecord(userId, areaUserId, item, session)
+		if err != nil {
+			session.Rollback()
+			return
+		}
+	}
+
+	return session.Commit()
+}
+
+// CreateFlowByTemplateDirectly 通过合同模板创建合同签署流程
+func CreateFlowByTemplateDirectly(tmplateName string, userType int,
+	personName, personMobile, personIdCardNumber string,
+	organizationName string,
+	record *models.Useresignrecord) (flowId, signUrl string, err error) {
+
+	// 获取模板信息
+	templateInfo, err := getTemplateInfo(&tmplateName)
+	if err != nil {
+		return
+	}
+	if templateInfo == nil {
+		err = fmt.Errorf("获取模板信息失败, tmplateName:%v", tmplateName)
+		logger.GetLogger().Errorf("CreateFlowByTemplateDirectly, %v", err.Error())
+		return
+	}
+
+	// 获取模板里面的参与方RecipientId
+	recipients := templateInfo.Recipients
+	if recipients == nil {
+		err = fmt.Errorf("获取模板参与方信息失败, tmplateName:%v", tmplateName)
+		logger.GetLogger().Errorf("CreateFlowByTemplateDirectly, %v", err.Error())
+		return
+	}
+
+	// 此处为快速发起的签署方;如果是正式接入,构造签署方,请参考函数内说明,构造需要的场景参数
+	var flowApproverInfos []*essbasic.FlowApproverInfo
+	if userType == 1 {
+		flowApproverInfos = buildPersonApprovers(personName, personMobile, personIdCardNumber, recipients)
+	} else {
+		flowApproverInfos = buildOrganizationApprovers(organizationName, recipients)
+	}
+
+	// 发起合同
+	resp, err := essapi.CreateFlowByTemplateDirectly(*templateInfo.TemplateName, *templateInfo.TemplateId, flowApproverInfos)
+	if err != nil {
+		return
+	}
+	if resp == nil || len(resp["flowIds"]) == 0 || len(resp["urls"]) == 0 {
+		err = fmt.Errorf("发起合同签署流程失败, tmplateName:%v", tmplateName)
+		logger.GetLogger().Errorf("CreateFlowByTemplateDirectly, %v", err.Error())
+		return
+	}
+	flowId = *resp["flowIds"][0]
+	signUrl = *resp["urls"][0]
+
+	// 更新电子签记录表信息状态
+	record.CONTRACTNO = flowId
+	record.SIGNURL = signUrl
+	record.RECORDSTATUS = 2
+	if err = record.Update("CONTRACTNO,SIGNURL,RECORDSTATUS"); err != nil {
+		logger.GetLogger().Errorf("CreateFlowByTemplateDirectly, %v", err.Error())
+	}
+
+	return
+}
+
+// GetFlowStatus 获取合同状态
+func GetFlowStatus(flowId string) (recordStatus int, err error) {
+	agent := utils.SetAgent()
+	response, err := essapi.DescribeFlowDetailInfo(agent, []*string{&flowId})
+	if err == nil {
+		if len(response.Response.FlowInfo) == 0 {
+			err = fmt.Errorf("获取合同明细失败")
+			return
+		}
+		flowDetailInfo := response.Response.FlowInfo[0]
+
+		// 获取对应电子签信息
+		var record *models.Useresignrecord
+		record, err = models.GetUseresignRecordByFlowID(flowId)
+		if err != nil {
+			err = fmt.Errorf("获取电子签信息失败")
+			return
+		}
+
+		// 更新电子签信息状态
+		if *flowDetailInfo.FlowStatus == "ALL" {
+			recordStatus = 3
+		}
+		if *flowDetailInfo.FlowStatus == "REJECT" {
+			recordStatus = 4
+		}
+		if recordStatus == 0 {
+			err = fmt.Errorf("合同状态异常")
+			return
+		}
+		record.RECORDSTATUS = int32(recordStatus)
+		if err = record.Update("RECORDSTATUS"); err != nil {
+			logger.GetLogger().Errorf("GetFlowStatus, %v", err.Error())
+		}
+
+		if recordStatus == 3 {
+			// 更新用户掉期协议签署表
+			UpdateMdUserSwapProtocol(flowId)
+		}
+	}
+
+	return
+}
+
+func UpdateMdUserSwapProtocol(flowId string) (err error) {
+	// 获取对应的电子签记录
+	var record *models.Useresignrecord
+	record, err = models.GetUseresignRecordByFlowID(flowId)
+	if err != nil {
+		logger.GetLogger().Errorf("UpdateMdUserSwapProtocol, 获取对应的电子签记录失败:%v", err.Error())
+		return
+	}
+
+	// 获取此用户对应机构的电子签记录列表
+	records, err := models.QueryUsereSignRecords(int(record.USERID), int(record.AREAUSERID), nil, nil, nil)
+	if err == nil {
+		// 所有合同签署完成后,更新用户掉期协议签署表
+		flag := true
+		for _, item := range records {
+			if item.RECORDSTATUS != 3 {
+				flag = false
+				break
+			}
+		}
+		if flag {
+			// 获取对应用户掉期协议签署记录
+			datas, err := models.QueryMdUserSwapProtocol(int(record.USERID), &record.AREAUSERID)
+			if err == nil {
+				if len(datas) > 0 {
+					data := datas[0]
+
+					// 获取用户信息,如果是用户所属机构则改状态为 4:已审核,否则改为 3:已签署
+					var userAccount *models.Useraccount
+					if userAccount, err = models.GetUserAccount(int(record.USERID)); err == nil {
+						status := 4
+						if userAccount.Memberuserid != record.AREAUSERID {
+							status = 3
+						}
+						data.PROTOCOLSTATUS = int32(status)
+						err = data.Update("PROTOCOLSTATUS")
+					}
+				}
+			} else {
+				logger.GetLogger().Errorf("UpdateMdUserSwapProtocol, 获取对应用户掉期协议签署记录失败:%v", err.Error())
+			}
+		}
+	} else {
+		logger.GetLogger().Errorf("UpdateMdUserSwapProtocol, 获取对应的机构电子签记录失败:%v", err.Error())
+	}
+
+	return
+}
+
+// getTemplateInfo 获取模板信息
+func getTemplateInfo(contractName *string) (templateInfo *essbasic.TemplateInfo, err error) {
+	agent := utils.SetAgent()
+	templatesResp, err := essapi.DescribeTemplates(agent, contractName)
+	if err == nil {
+		if len(templatesResp.Response.Templates) > 0 {
+			templateInfo = templatesResp.Response.Templates[0]
+		} else {
+			err = fmt.Errorf("获取模板信息失败")
+		}
+
+	}
+
+	return
+}
+
+// buildPersonApprovers 构造个人签署人 - 以BtoC为例, 实际请根据自己的场景构造签署方、控件
+func buildPersonApprovers(personName, personMobile, personIdCardNumber string, recipients []*essbasic.Recipient) []*essbasic.FlowApproverInfo {
+	var flowApproverInfos []*essbasic.FlowApproverInfo
+
+	// 传入个人签署方
+	flowApproverInfo := &essbasic.FlowApproverInfo{}
+	approverType := "PERSON"
+	flowApproverInfo.ApproverType = &approverType
+	flowApproverInfo.Name = &personName
+	flowApproverInfo.Mobile = &personMobile
+	flowApproverInfo.IdCardType = utils.SetPointValue("ID_CARD")
+	flowApproverInfo.IdCardNumber = &personIdCardNumber
+	// 模板中对应签署方的参与方id
+	flowApproverInfo.RecipientId = recipients[0].RecipientId
+
+	flowApproverInfos = append(flowApproverInfos, flowApproverInfo)
+
+	// 传入企业静默签署,此处需要在config.php中设置一个持有的印章值serverSignSealId
+	// flowApproverInfos = append(flowApproverInfos, BuildServerSignApprover())
+
+	// 内容控件填充结构,详细说明参考
+	// https://cloud.tencent.com/document/api/1420/61525#FormField
+
+	return flowApproverInfos
+}
+
+// buildOrganizationApprovers 构造企业签署人
+func buildOrganizationApprovers(organizationName string, recipients []*essbasic.Recipient) []*essbasic.FlowApproverInfo {
+	var flowApproverInfos []*essbasic.FlowApproverInfo
+
+	// 传入企业签署方
+	flowApproverInfo := &essbasic.FlowApproverInfo{}
+	approverType := "ORGANIZATION"
+	flowApproverInfo.ApproverType = &approverType
+	flowApproverInfo.OrganizationName = &organizationName
+	// 模板中对应签署方的参与方id
+	flowApproverInfo.RecipientId = recipients[0].RecipientId
+
+	flowApproverInfos = append(flowApproverInfos, flowApproverInfo)
+
+	return flowApproverInfos
+}
+
+func ProcessNotice(content string) {
+	// "{\"MsgId\":\"yDSLWUUckposmdf8UBxiJvuDbgiYRYbj\",\"MsgType\":\"FlowStatusChange\",\"MsgVersion\":\"ThirdPartyApp\",\"MsgData\":{\"ApplicationId\":\"yDwiuUUckpogfoa4UxhigrYChFMdSJQV\",\"ProxyOrganizationOpenId\":\"TJMD\",\"CustomerData\":\"\",\"FlowId\":\"yDSLWUUckposcsthUwvcaGSuV5EKZAzu\",\"FlowName\":\"1000_P_风险揭示书\",\"FlowType\":\"合同\",\"FlowStatus\":\"INIT\",\"FlowMessage\":\"\",\"CreateOn\":1699077064,\"Deadline\":1730613064,\"FlowApproverInfo\":[{\"ProxyOrganizationOpenId\":\"\",\"ProxyOperatorOpenId\":\"\",\"recipientId\":\"yDSLNUUckpos1i71UuGNih5yMGbZij46\",\"RecipientId\":\"yDSLNUUckpos1i71UuGNih5yMGbZij46\",\"PhoneNumber\":\"15914012152\",\"ProxyOrganizationName\":\"\",\"SignOrder\":0,\"ApproveName\":\"曹晓亮\",\"ApproveStatus\":\"PENDING\",\"ApproveMessage\":\"\",\"ApproveTime\":0,\"CaSign\":\"\"}],\"OccurTime\":1699077064,\"CcInfo\":[]}}"
+	m := make(map[string]interface{})
+	if err := json.Unmarshal([]byte(content), &m); err == nil {
+		// 判断通知类型
+		msgType, _ := m["MsgType"].(string)
+		if msgType == "FlowStatusChange" {
+			// 合同相关回调
+			// https://qian.tencent.com/developers/partner/callback_types_contracts_sign
+			msgData, _ := m["MsgData"].(map[string]interface{})
+			flowId, _ := msgData["FlowId"].(string)
+			flowStatus, _ := msgData["FlowStatus"].(string)
+			if flowStatus == "ALL" || flowStatus == "REJECT" {
+				// 更新电子签合同状态
+				if record, err := models.GetUseresignRecordByFlowID(flowId); err == nil {
+					if flowStatus == "ALL" {
+						record.RECORDSTATUS = 3
+					} else {
+						record.RECORDSTATUS = 4
+					}
+					if err = record.Update("RECORDSTATUS"); err != nil {
+						logger.GetLogger().Errorf("ProcessNotice, %v", err.Error())
+					}
+
+					if record.RECORDSTATUS == 3 {
+						// 更新用户掉期协议签署表
+						UpdateMdUserSwapProtocol(flowId)
+					}
+				}
+			}
+		}
+	}
+}
+
+// VerifySign 电子签通知推送验签
+func VerifySign(payload, signFromHeader string) bool {
+	// 验证签名
+	hash := "sha256=" + hmacsha256hex(payload, config.SerCfg.TencentCfg.SignToken)
+	return hash == signFromHeader
+}
+
+// DecryptContent 电子签通知推送内容解密
+func DecryptContent(payload string) (content string, err error) {
+	// string -> json
+	m := make(map[string]string)
+	err = json.Unmarshal([]byte(payload), &m)
+	if err != nil {
+		return
+	}
+	encrypt, ok := m["encrypt"]
+	if !ok {
+		err = fmt.Errorf("电子签通知推送内容解密失败")
+		logger.GetLogger().Errorf("DecryptContent, %v", err.Error())
+		return
+	}
+
+	// base64解密
+	crypted, err := base64.StdEncoding.DecodeString(encrypt)
+	if err != nil {
+		logger.GetLogger().Errorf("base64 DecodeString returned: %s", err)
+		return
+	}
+
+	b, err := aesDecrypt(crypted, []byte(config.SerCfg.TencentCfg.SignKey))
+	if err != nil {
+		logger.GetLogger().Errorf("AesDecrypt returned: %s", err)
+		return
+	}
+	content = string(b)
+
+	return
+}
+
+// Hmacsha256hex hmac sha256
+func hmacsha256hex(s, key string) string {
+	hashed := hmac.New(sha256.New, []byte(key))
+	hashed.Write([]byte(s))
+	return hex.EncodeToString(hashed.Sum(nil))
+}
+
+// 使用callbackKey解密
+func aesDecrypt(crypted, key []byte) ([]byte, error) {
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+	blockSize := block.BlockSize()
+	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
+	origData := make([]byte, len(crypted))
+	blockMode.CryptBlocks(origData, crypted)
+	origData = pkcs7UnPadding(origData)
+	return origData, nil
+}
+
+// PKCS7UnPadding 去除填充
+func pkcs7UnPadding(origData []byte) []byte {
+	length := len(origData)
+	unPadding := int(origData[length-1])
+	return origData[:(length - unPadding)]
+}

+ 32 - 0
services/tencent/essapi/CreateConsoleLoginUrl.go

@@ -0,0 +1,32 @@
+package essapi
+
+import (
+	"fmt"
+	"mtp2_if/logger"
+	"mtp2_if/utils"
+
+	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
+	essbasic "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic/v20210526"
+)
+
+func CreateConsoleLoginUrl(agent *essbasic.Agent, proxyOrganizationName string) (response *essbasic.CreateConsoleLoginUrlResponse, err error) {
+	if utils.TencentESSClient == nil {
+		err = fmt.Errorf("腾讯电子签客户端未初始化")
+		logger.GetLogger().Errorf("CreateConsoleLoginUrl failed: %s", err.Error())
+		return
+	}
+
+	// 实例化一个请求对象,每个接口都会对应一个request对象
+	request := essbasic.NewCreateConsoleLoginUrlRequest()
+	request.Agent = agent
+	request.ProxyOrganizationName = &proxyOrganizationName
+
+	response, err = utils.TencentESSClient.CreateConsoleLoginUrl(request)
+	if _, ok := err.(*errors.TencentCloudSDKError); ok {
+		logger.GetLogger().Errorf("CreateConsoleLoginUrl failed: %s", err.Error())
+		return
+	}
+
+	return
+
+}

+ 42 - 0
services/tencent/essapi/CreateFlowByTemplateDirectly.go

@@ -0,0 +1,42 @@
+package essapi
+
+import (
+	"mtp2_if/utils"
+
+	essbasic "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic/v20210526"
+)
+
+// CreateFlowByTemplateDirectly 通过合同名和模板Id直接发起签署流程
+// 本接口是对于发起合同几个接口的封装,详细参数需要根据自身业务进行调整
+// CreateFlowsByTemplates--CreateSignUrls
+func CreateFlowByTemplateDirectly(flowName, templateId string, flowApproverInfos []*essbasic.FlowApproverInfo) (resp map[string][]*string, err error) {
+	agent := utils.SetAgent()
+	resp = make(map[string][]*string)
+
+	// 创建签署流程
+	var flowInfos []*essbasic.FlowInfo
+	flowInfos = append(flowInfos, utils.FillFlowInfo(templateId, flowName, flowApproverInfos))
+	// 构建内容控件填充结构(根据自己需求使用)
+	// flowInfos[i].FormFields = []*v20210526.FormField{utils.BuildFormField("姓名", "张三")}
+
+	// 发起签署
+	flowResponse, err := CreateFlowsByTemplates(agent, flowInfos)
+	if err != nil {
+		return
+	}
+	flowIds := flowResponse.Response.FlowIds
+	resp["flowIds"] = flowIds
+
+	// 获取签署链接
+	createSignUrlsResp, err := CreateSignUrls(flowIds, agent)
+	if err != nil {
+		return
+	}
+	if len(createSignUrlsResp.Response.SignUrlInfos) != 0 {
+		var urls []*string
+		urls = append(urls, createSignUrlsResp.Response.SignUrlInfos[0].SignUrl)
+		resp["urls"] = urls
+	}
+
+	return
+}

+ 38 - 0
services/tencent/essapi/CreateFlowsByTemplates.go

@@ -0,0 +1,38 @@
+package essapi
+
+import (
+	"fmt"
+	"mtp2_if/logger"
+	"mtp2_if/utils"
+
+	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
+	essbasic "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic/v20210526"
+)
+
+func CreateFlowsByTemplates(agent *essbasic.Agent, flowInfos []*essbasic.FlowInfo) (response *essbasic.CreateFlowsByTemplatesResponse, err error) {
+	if utils.TencentESSClient == nil {
+		err = fmt.Errorf("腾讯电子签客户端未初始化")
+		logger.GetLogger().Errorf("CreateFlowsByTemplates failed: %s", err.Error())
+		return
+	}
+
+	// 实例化一个请求对象,每个接口都会对应一个request对象
+	request := essbasic.NewCreateFlowsByTemplatesRequest()
+
+	request.Agent = agent
+
+	request.FlowInfos = flowInfos
+
+	// 返回的resp是一个CreateFlowsByTemplatesResponse的实例,与请求对象对应
+	response, err = utils.TencentESSClient.CreateFlowsByTemplates(request)
+	if _, ok := err.(*errors.TencentCloudSDKError); ok {
+		logger.GetLogger().Errorf("CreateFlowsByTemplates failed: %s", err.Error())
+		return
+	}
+	if *response.Response.ErrorMessages[0] != "" {
+		err = fmt.Errorf("%v", *response.Response.ErrorMessages[0])
+		logger.GetLogger().Errorf("CreateFlowsByTemplates failed: %s", err)
+	}
+
+	return
+}

+ 38 - 0
services/tencent/essapi/CreateSignUrls.go

@@ -0,0 +1,38 @@
+package essapi
+
+import (
+	"fmt"
+	"mtp2_if/logger"
+	"mtp2_if/utils"
+
+	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
+	essbasic "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic/v20210526"
+)
+
+func CreateSignUrls(flowIds []*string, agent *essbasic.Agent) (response *essbasic.CreateSignUrlsResponse, err error) {
+	if utils.TencentESSClient == nil {
+		err = fmt.Errorf("腾讯电子签客户端未初始化")
+		logger.GetLogger().Errorf("CreateSignUrls failed: %s", err.Error())
+		return
+	}
+
+	// 实例化一个请求对象,每个接口都会对应一个request对象
+	request := essbasic.NewCreateSignUrlsRequest()
+
+	request.Agent = agent
+
+	request.FlowIds = flowIds
+
+	// 返回的resp是一个CreateSignUrlsResponse的实例,与请求对象对应
+	response, err = utils.TencentESSClient.CreateSignUrls(request)
+	if _, ok := err.(*errors.TencentCloudSDKError); ok {
+		logger.GetLogger().Errorf("CreateSignUrls failed: %s", err.Error())
+		return
+	}
+	if *response.Response.ErrorMessages[0] != "" {
+		err = fmt.Errorf("%v", *response.Response.ErrorMessages[0])
+		logger.GetLogger().Errorf("CreateSignUrls failed: %s", err)
+	}
+
+	return
+}

+ 27 - 0
services/tencent/essapi/DescribeFlowDetailInfo.go

@@ -0,0 +1,27 @@
+package essapi
+
+import (
+	"mtp2_if/logger"
+	"mtp2_if/utils"
+
+	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
+	essbasic "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic/v20210526"
+)
+
+func DescribeFlowDetailInfo(agent *essbasic.Agent, flowIds []*string) (response *essbasic.DescribeFlowDetailInfoResponse, err error) {
+	// 实例化一个请求对象,每个接口都会对应一个request对象
+	request := essbasic.NewDescribeFlowDetailInfoRequest()
+
+	request.Agent = agent
+
+	request.FlowIds = flowIds
+
+	// 返回的resp是一个DescribeFlowDetailInfoResponse的实例,与请求对象对应
+	response, err = utils.TencentESSClient.DescribeFlowDetailInfo(request)
+	if _, ok := err.(*errors.TencentCloudSDKError); ok {
+		logger.GetLogger().Errorf("An API error has returned: %s", err)
+		return
+	}
+
+	return
+}

+ 36 - 0
services/tencent/essapi/DescribeTemplates.go

@@ -0,0 +1,36 @@
+package essapi
+
+import (
+	"fmt"
+	"mtp2_if/logger"
+	"mtp2_if/utils"
+
+	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
+	essbasic "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic/v20210526"
+)
+
+func DescribeTemplates(agent *essbasic.Agent, templateName *string) (response *essbasic.DescribeTemplatesResponse, err error) {
+	if utils.TencentESSClient == nil {
+		err = fmt.Errorf("腾讯电子签客户端未初始化")
+		logger.GetLogger().Errorf("DescribeTemplates failed: %s", err.Error())
+		return
+	}
+
+	// 实例化一个请求对象,每个接口都会对应一个request对象
+	request := essbasic.NewDescribeTemplatesRequest()
+
+	request.Agent = agent
+
+	if templateName != nil {
+		request.TemplateName = templateName
+	}
+
+	// 返回的resp是一个DescribeTemplatesResponse的实例,与请求对象对应
+	response, err = utils.TencentESSClient.DescribeTemplates(request)
+	if _, ok := err.(*errors.TencentCloudSDKError); ok {
+		logger.GetLogger().Errorf("DescribeTemplates failed: %s", err.Error())
+		return
+	}
+
+	return
+}

+ 76 - 0
utils/CreateFlowUtils.go

@@ -0,0 +1,76 @@
+package utils
+
+import (
+	"encoding/base64"
+	SysConfig "mtp2_if/config"
+	"os"
+
+	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
+	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
+	essbasic "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/essbasic/v20210526"
+)
+
+var TencentESSClient *essbasic.Client
+
+// InitTencentESSClient 初始化Client
+func InitTencentESSClient() (err error) {
+	secretId := SysConfig.SerCfg.TencentCfg.SecretId
+	secretKey := SysConfig.SerCfg.TencentCfg.SecretKey
+
+	// 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密
+	// 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
+	credential := common.NewCredential(
+		secretId,
+		secretKey,
+	)
+	// 实例化一个client选项,可选的,没有特殊需求可以跳过
+	cpf := profile.NewClientProfile()
+	cpf.HttpProfile.Endpoint = SysConfig.SerCfg.TencentCfg.EndPoint
+	// 实例化要请求产品的client对象,clientProfile是可选的
+	TencentESSClient, err = essbasic.NewClient(credential, "", cpf)
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// SetAgent 设置Agent
+func SetAgent() *essbasic.Agent {
+	appId := SysConfig.SerCfg.TencentCfg.AppId
+	proxyAppId := ""
+	proxyOrganizationOpenId := SysConfig.SerCfg.TencentCfg.ProxyOrganizationOpenId
+	proxyOperatorOpenId := SysConfig.SerCfg.TencentCfg.ProxyOperatorOpenId
+	userInfo := &essbasic.UserInfo{}
+	userInfo.OpenId = &proxyOperatorOpenId
+	var agent = &essbasic.Agent{
+		AppId:                   &appId,
+		ProxyAppId:              &proxyAppId,
+		ProxyOrganizationOpenId: &proxyOrganizationOpenId,
+		ProxyOperator:           userInfo,
+	}
+	return agent
+}
+
+// FillFlowInfo 设置FlowInfo
+func FillFlowInfo(templateId, flowName string,
+	flowApproverInfos []*essbasic.FlowApproverInfo) *essbasic.FlowInfo {
+	FlowType := "合同"
+	var flowInfo = &essbasic.FlowInfo{
+		TemplateId:    &templateId,
+		FlowName:      &flowName,
+		FlowApprovers: flowApproverInfos,
+		FlowType:      &FlowType,
+	}
+	return flowInfo
+}
+
+// ConvertImageFileToBase64 将图片文件转化为字符串,并对其进行Base64编码处理
+func ConvertImageFileToBase64(filePath string) string {
+	fileBytes, err := os.ReadFile(filePath)
+	if err != nil {
+		return ""
+	}
+	bs64 := base64.StdEncoding.EncodeToString(fileBytes)
+	return bs64
+}

+ 13 - 0
utils/var.go

@@ -0,0 +1,13 @@
+package utils
+
+type PointValue interface {
+	int | bool | float64 | uint | uint32 | uint64 | string
+}
+
+// SetPointValue 给Struct的指针类型成员赋值
+func SetPointValue[T PointValue](value T) (field *T) {
+	field = new(T)
+	*field = value
+
+	return
+}