package tencent import ( "fmt" "io" "mtp2_if/global/app" "mtp2_if/global/e" "mtp2_if/logger" "mtp2_if/models" "mtp2_if/services/tencent" "net/http" "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 // @Security ApiKeyAuth // @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 != "" { logger.GetLogger().Infof("QianNotice payload:%s", 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) } else { logger.GetLogger().Errorf("QianNotice failed: 解密失败 %v", err) appG.Response(http.StatusOK, e.ERROR, "fail") return } } else { logger.GetLogger().Errorf("QianNotice failed: 验签失败") appG.Response(http.StatusOK, e.ERROR, "fail") return } appG.Response(http.StatusOK, e.SUCCESS, "ok") } } else { logger.GetLogger().Errorf("QianNotice failed: 获取推送内容为空") appG.Response(http.StatusOK, e.ERROR, "fail") } } 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 // @Security ApiKeyAuth // @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) } } // InitMdUserSwapProtocol 按用户ID和机构ID创建机构交易协议申请信息 // @Summary 按用户ID和机构ID创建机构交易协议申请信息 // @Produce json // @Security ApiKeyAuth // @accept application/json // @Param data body InitTencentESSReq true "入参" // @Failure 500 {object} app.Response // @Router /Tencent/InitMdUserSwapProtocol [post] // @Tags 腾讯电子签 func InitMdUserSwapProtocol(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.InitMdUserSwapProtocol(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"` // 证件号码 IdCardType *int `json:"idCardType"` // 证件类型 0-身份证 1-港澳通行证 } // 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 通过合同模板名称直接发起签署流程 // @Security ApiKeyAuth // @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 } // 构建电子签平台合同模板名称 // 格式:类型标志_合同模板名称;例如 "P_风险提示书",个人为P企业为E flag := "P" if req.UserType == 2 { flag = "E" } tmplateName := fmt.Sprintf("%s_%s", flag, record.TEMPLATENAME) personName := "" personMobile := "" idCardNumber := "" idCardType := 0 if req.PersonInfo != nil { personName = req.PersonInfo.Name personMobile = req.PersonInfo.Mobile idCardNumber = req.PersonInfo.IdCardNumber if req.PersonInfo.IdCardType != nil { if *req.PersonInfo.IdCardType != 0 && *req.PersonInfo.IdCardType != 1 { appG.ResponseByMsg(http.StatusBadRequest, e.ERROR, "证件类型不支持", nil) return } idCardType = *req.PersonInfo.IdCardType } } organizationName := "" if req.OrganizationInfo != nil { organizationName = req.OrganizationInfo.Name } flowId, signUrl, err := tencent.CreateFlowByTemplateDirectly(tmplateName, req.UserType, personName, personMobile, idCardNumber, organizationName, record, idCardType) 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 // @Security ApiKeyAuth // @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) } }