From 3da5e13db4b9f93df325f4f491a7c9823278ea8f Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Fri, 1 May 2026 14:09:45 +0800 Subject: [PATCH] f --- .../api/internal/service/apirequestService.go | 35 ++++- .../internal/service/authorizationService.go | 148 ++++++++++++++++++ app/main/api/internal/svc/servicecontext.go | 4 +- .../api/static/authorization_ivyz4y27.tmpl | 85 ++++++++++ 4 files changed, 269 insertions(+), 3 deletions(-) create mode 100644 app/main/api/static/authorization_ivyz4y27.tmpl diff --git a/app/main/api/internal/service/apirequestService.go b/app/main/api/internal/service/apirequestService.go index 37b1702..6d06c51 100644 --- a/app/main/api/internal/service/apirequestService.go +++ b/app/main/api/internal/service/apirequestService.go @@ -37,15 +37,17 @@ type ApiRequestService struct { featureModel model.FeatureModel productFeatureModel model.ProductFeatureModel tianyuanapi *tianyuanapi.Client + authService *AuthorizationService } // NewApiRequestService 是一个构造函数,用于初始化 ApiRequestService -func NewApiRequestService(c config.Config, featureModel model.FeatureModel, productFeatureModel model.ProductFeatureModel, tianyuanapi *tianyuanapi.Client) *ApiRequestService { +func NewApiRequestService(c config.Config, featureModel model.FeatureModel, productFeatureModel model.ProductFeatureModel, tianyuanapi *tianyuanapi.Client, authService *AuthorizationService) *ApiRequestService { return &ApiRequestService{ config: c, featureModel: featureModel, productFeatureModel: productFeatureModel, tianyuanapi: tianyuanapi, + authService: authService, } } @@ -196,6 +198,7 @@ var requestProcessors = map[string]func(*ApiRequestService, []byte) ([]byte, err "IVYZ7F3A": (*ApiRequestService).ProcessIVYZ7F3ARequest, "IVYZ3P9M": (*ApiRequestService).ProcessIVYZ3P9MRequest, "FLXG7E8F": (*ApiRequestService).ProcessFLXG7E8FRequest, + "IVYZ4Y27": (*ApiRequestService).ProcessIVYZ4Y27Request, } // PreprocessRequestApi 调用指定的请求处理函数 @@ -1456,3 +1459,33 @@ func (a *ApiRequestService) ProcessFLXG7E8FRequest(params []byte) ([]byte, error return convertTianyuanResponse(resp) } + +// ProcessIVYZ4Y27Request 学历信息查询(需生成专用授权书PDF并Base64编码传入) +func (a *ApiRequestService) ProcessIVYZ4Y27Request(params []byte) ([]byte, error) { + name := gjson.GetBytes(params, "name") + idCard := gjson.GetBytes(params, "id_card") + if !name.Exists() || !idCard.Exists() { + return nil, errors.New("api请求, IVYZ4Y27, 获取相关参数失败") + } + + // 生成专用授权书PDF并Base64编码 + userInfo := map[string]interface{}{ + "name": name.String(), + "id_card": idCard.String(), + } + authFileBase64, err := a.authService.GenerateIVYZ4Y27AuthorizationBase64(userInfo) + if err != nil { + return nil, fmt.Errorf("生成IVYZ4Y27授权书失败: %v", err) + } + + resp, err := a.tianyuanapi.CallInterface("IVYZ4Y27", map[string]interface{}{ + "name": name.String(), + "id_card": idCard.String(), + "auth_authorize_file_base64": authFileBase64, + }) + if err != nil { + return nil, err + } + + return convertTianyuanResponse(resp) +} diff --git a/app/main/api/internal/service/authorizationService.go b/app/main/api/internal/service/authorizationService.go index 2c52518..28ece23 100644 --- a/app/main/api/internal/service/authorizationService.go +++ b/app/main/api/internal/service/authorizationService.go @@ -4,11 +4,13 @@ import ( "bytes" "context" "database/sql" + "encoding/base64" "fmt" "net/url" "os" "path/filepath" "strings" + "text/template" "time" "tydata-server/app/main/api/internal/config" "tydata-server/app/main/model" @@ -329,3 +331,149 @@ func getUserInfoString(userInfo map[string]interface{}, key string) string { } return "" } + +// generatePDFFromTemplate 从模板文件生成PDF内容 +func (s *AuthorizationService) generatePDFFromTemplate(templatePath string, data map[string]string) ([]byte, error) { + // 查找模板文件 + tmplPaths := []string{ + templatePath, + "/app/" + templatePath, + "app/main/api/" + templatePath, + "../../" + templatePath, + "../../../" + templatePath, + "../../../../" + templatePath, + "../../../../../" + templatePath, + "../../static/" + filepath.Base(templatePath), + "../../../static/" + filepath.Base(templatePath), + "../../../../static/" + filepath.Base(templatePath), + } + + var tmplFile string + for _, p := range tmplPaths { + if _, err := os.Stat(p); err == nil { + tmplFile = p + break + } + } + + if tmplFile == "" { + return nil, fmt.Errorf("未找到模板文件: %s", templatePath) + } + + // 解析模板文件 + tmpl, err := template.ParseFiles(tmplFile) + if err != nil { + return nil, errors.Wrapf(err, "解析模板文件失败: %s", tmplFile) + } + + // 渲染模板 + var contentBuf bytes.Buffer + if err := tmpl.Execute(&contentBuf, data); err != nil { + return nil, errors.Wrapf(err, "渲染模板失败") + } + renderedContent := contentBuf.String() + + // 创建PDF文档 + pdf := gofpdf.New("P", "mm", "A4", "") + + // 加载中文字体 + fontPaths := []string{ + "static/SIMHEI.TTF", + "/app/static/SIMHEI.TTF", + "app/main/api/static/SIMHEI.TTF", + "../../static/SIMHEI.TTF", + "../../../static/SIMHEI.TTF", + "../../../../static/SIMHEI.TTF", + } + + fontAdded := false + for _, fontPath := range fontPaths { + if _, err := os.Stat(fontPath); err == nil { + pdf.AddUTF8Font("ChineseFont", "", fontPath) + fontAdded = true + logx.Infof("成功加载字体: %s", fontPath) + break + } else { + logx.Debugf("字体文件不存在: %s, 错误: %v", fontPath, err) + } + } + + if !fontAdded { + pdf.SetFont("Arial", "", 11) + logx.Errorf("未找到中文字体文件,使用默认Arial字体,可能无法正确显示中文") + } else { + pdf.SetFont("ChineseFont", "", 11) + } + + // 设置每页Footer回调,用于在每页添加水印 + companyName := data["CompanyName"] + if companyName == "" { + companyName = "海南海宇大数据科技有限公司" + } + capturedFontAdded := fontAdded + capturedCompanyName := companyName + pdf.SetFooterFunc(func() { + addWatermarkToPage(pdf, capturedFontAdded, capturedCompanyName) + }) + + pdf.AddPage() + + // 写入渲染后的内容 + pdf.MultiCell(0, 6, renderedContent, "", "", false) + + // 输出PDF字节 + var pdfBuf bytes.Buffer + if err := pdf.Output(&pdfBuf); err != nil { + return nil, errors.Wrapf(err, "生成PDF字节数组失败") + } + + return pdfBuf.Bytes(), nil +} + +// addWatermarkToPage 给当前页面添加水印(红色公司名,居中单个水印) +func addWatermarkToPage(pdf *gofpdf.Fpdf, fontAdded bool, companyName string) { + if fontAdded { + pdf.SetFont("ChineseFont", "", 40) + } else { + pdf.SetFont("Arial", "", 40) + } + pdf.SetTextColor(255, 200, 200) // 浅红色 + + // A4页面尺寸 210x297mm,水印放在页面正中央 + pageWidth, pageHeight := pdf.GetPageSize() + x := pageWidth / 2 + y := pageHeight / 2 + + pdf.TransformBegin() + pdf.TransformRotate(45, x, y) + pdf.Text(x, y, companyName) + pdf.TransformEnd() + pdf.SetTextColor(0, 0, 0) +} + +// GenerateIVYZ4Y27AuthorizationBase64 生成IVYZ4Y27专用授权书PDF并返回Base64编码字符串 +func (s *AuthorizationService) GenerateIVYZ4Y27AuthorizationBase64(userInfo map[string]interface{}) (string, error) { + name := getUserInfoString(userInfo, "name") + idCard := getUserInfoString(userInfo, "id_card") + if name == "" || idCard == "" { + return "", fmt.Errorf("缺少必要的用户信息(name或id_card)") + } + + // 构建模板变量 + data := map[string]string{ + "CompanyName": "海南海宇大数据科技有限公司", + "Name": name, + "IdCard": idCard, + "Mobile": getUserInfoString(userInfo, "mobile"), + "Date": time.Now().Format("2006年1月2日"), + } + + // 从模板生成PDF + pdfBytes, err := s.generatePDFFromTemplate("static/authorization_ivyz4y27.tmpl", data) + if err != nil { + return "", errors.Wrapf(err, "生成IVYZ4Y27授权书PDF失败") + } + + // Base64编码 + return base64.StdEncoding.EncodeToString(pdfBytes), nil +} diff --git a/app/main/api/internal/svc/servicecontext.go b/app/main/api/internal/svc/servicecontext.go index 8dd3fba..52c9701 100644 --- a/app/main/api/internal/svc/servicecontext.go +++ b/app/main/api/internal/svc/servicecontext.go @@ -191,7 +191,8 @@ func NewServiceContext(c config.Config) *ServiceContext { alipayService := service.NewAliPayService(c) wechatPayService := service.NewWechatPayService(c, userAuthModel, service.InitTypeWxPayPubKey) applePayService := service.NewApplePayService(c) - apiRequestService := service.NewApiRequestService(c, featureModel, productFeatureModel, tianyuanapi) + authorizationService := service.NewAuthorizationService(c, authorizationDocumentModel) + apiRequestService := service.NewApiRequestService(c, featureModel, productFeatureModel, tianyuanapi, authorizationService) verificationService := service.NewVerificationService(c, tianyuanapi, apiRequestService) asynqService := service.NewAsynqService(c) agentService := service.NewAgentService(c, orderModel, agentModel, agentAuditModel, agentClosureModel, @@ -204,7 +205,6 @@ func NewServiceContext(c config.Config) *ServiceContext { adminPromotionLinkStatsService := service.NewAdminPromotionLinkStatsService(adminPromotionLinkModel, adminPromotionLinkStatsTotalModel, adminPromotionLinkStatsHistoryModel) imageService := service.NewImageService() - authorizationService := service.NewAuthorizationService(c, authorizationDocumentModel) // ============================== 异步任务服务 ============================== asynqServer := asynq.NewServer( diff --git a/app/main/api/static/authorization_ivyz4y27.tmpl b/app/main/api/static/authorization_ivyz4y27.tmpl new file mode 100644 index 0000000..3c871d7 --- /dev/null +++ b/app/main/api/static/authorization_ivyz4y27.tmpl @@ -0,0 +1,85 @@ +【重要提示】为了保障您的合法权益,您在签署本授权书前,应当确保您为具有完全民事权利能力和民事行为能力的自然人,并审慎阅读、充分理解本授权书所有条款(特别是加粗字体的条款)。您在操作页面上的确认、勾选等行为或以其他方式接受即表示您已阅读并同意本授权书,本授权书随即在法律上生效并在您和{{.CompanyName}}之间产生法律约束力。 + +个人信息处理授权书 + +致:{{.CompanyName}} + +本人("授权人")在此确认、同意并授权{{.CompanyName}}("贵司")及贵司授权的第三方,为本文件所列之目的,处理(指收集、整理、存储、使用、加工、分析和比对、核验、传输、提供等)本人的个人信息。 + +一、 授权处理的个人信息范围 + +1.本人同意并授权贵司处理以下类型的个人信息(无论以电子或非电子形式存在): + +身份信息:包括但不限于姓名、身份证号码。 + +教育背景信息:包括但不限于各教育阶段的入学与毕业时间、毕业院校、专业、学位类型、学历学位证书信息、学信网验证信息等。 + +婚姻家庭信息:包括但不限于婚姻状况(未婚、已婚、离异等)。 + +工作履历信息:包括但不限于过往及当前工作单位、任职时间、职位、职责、证明人及其联系方式等。 + +其他与背景调查相关的信息:贵司为完成背景调查认为必要的其他信息。 + +2.本人知悉且同意,贵司拟处理的数据信息可能包含身份证件信息、生物识别信息等敏感信息,本人明确知悉对本人权益的影响且同意贵司处理该等信息。 + +二、 信息来源与查询方式 + +本人知晓并同意,贵司为完成背景调查,将通过以下方式查询并核实本授权书第一条所列的个人信息: + +1. 通过本人或委托贵司开展背景调查的拟入职机构提供的联系方式和证明材料进行直接核实。 + +2. 通过贵司链接的权威数据源进行查询或验证、核实,包括但不限于政府部门或事业单位、社会团体、公用事业服务单位、第三方数据库或数据平台(如从中国高等教育学生信息网-学信网)等。本人授权贵司通过地方信用服务平台向前述数据源单位收集、处理、加工和分析本人的婚姻家庭信息、教育背景信息。 + +3. 通过向本人前任及现任雇主、同事、证明人等进行访谈核实。 + +4. 在法律允许的范围内,通过其他公开、合法的渠道进行核实。 + +三、 信息处理的目的与使用 + +本人同意贵司将本授权书项下收集的个人信息用于以下目的: + +1. 为{{.CompanyName}}("委托方")对本人进行的员工招聘/录用前背景调查/持续的尽职调查提供信息核实与报告服务。 + +2. 基于核实的信息,生成关于本人的《背景调查报告》或《尽职调查报告》("报告"),并提供给委托方,以供其评估本人的任职资格与工作能力。 + +3. 贵司为内部质量控制和合规目的而对相关信息进行留存、处理与管理。 + +四、 信息存储与保护 + +贵司承诺将采取必要的技术和管理措施,保护本人个人信息的安全性与机密性,防止信息丢失、泄露、篡改或毁损。 + +除非法律法规另有规定或为履行本授权书目的之必要,贵司处理及存储本人个人信息的时间将在完成本次背景调查目的后12个月内,或直至委托方与本人的劳动关系确立或明确终止之时。具体留存期限届满后,贵司将依法对相关信息进行删除或匿名化处理。删除个人信息从技术上难以实现的,贵司将停止除存储和采取必要的安全保护措施之外的处理。 + +五、 授权转移与共享 + +(一)本人知晓并同意,为实现本授权书之目的,贵司可能将本人的个人信息提供给以下接收方: + +1. 委托方(即本次背景调查的发起企业/拟入职机构)。 + +2. 为完成特定核实工作而必需的第三方合作伙伴,如数据源提供方(包括但不限于地方融资信用服务平台、政府部门或事业单位)等,但贵司应确保该等第三方受到与本授权书同等严格的保密义务约束。 + +六、 权利告知与行使 + +1.本人知悉并理解,根据相关法律法规,本人有权: + +(1)查阅、复制及要求更正本人的个人信息; + +(2)在满足法定条件时,要求删除个人信息或撤回本授权同意。 + +本人确认,撤回本授权同意将不影响撤回前基于本授权已进行的个人信息处理活动的效力。但若撤回授权,可能导致委托方无法完整评估本人的任职资格,从而可能影响本次招聘/录用结果,本人将自行承担相应后果。 + +2. 本人知悉:如本人对贵司或数据源单位个人信息处理活动有任何疑问、意见建议或需要依法行使权利,可通过以下联系方式进行咨询、反映或行使法定权利: + +贵司:【联系方式:{{.Mobile}}】 + +七、 全部协议与授权效力 + +本授权书自本人同意之日起生效,并在上述业务办理及存续期间持续有效,至本授权书所述的所有业务终结之日止。 + +本人已仔细阅读并完全理解本授权书的全部内容,特别是加粗字体部分。本人的签署是基于本人的真实意愿,本人知悉且理解由此产生的法律效力及相应信息披露产生的不利后果(包括不限于第三方通过非法手段或方式获取、使用该信息,可能会给本人造成人身财产的损害,或是造成本人预期利益减少、损失扩大,或是其他不良或不利影响等),自愿作出上述授权。 + + +授权人签署:{{.Name}} +身份证号码:{{.IdCard}} + +签署日期:{{.Date}}