package service import ( "encoding/json" "fmt" "github.com/jung-kurt/gofpdf" "io" "log" "net/http" "os" "qnc-server/utils" "strings" "time" ) const API_KEY = "aMsrBNGUJxgcgqdm3SEdcumm" const SECRET_KEY = "sWlv2h2AWA3aAt5bjXCkE6WeA5AzpAAD" type Feature struct { } // Service 函数:接受 base64 编码的图像,返回 OCR 识别结果 func (f *Feature) OCRService(imageBase64 string) (string, error) { // 获取 Access Token accessToken := f.GetAccessToken() if accessToken == "" { return "", fmt.Errorf("获取 Access Token 失败") } // 设置请求 URL url := "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token=" + accessToken // 设置请求体,包含图片的 base64 编码 payload := strings.NewReader(fmt.Sprintf("image=%s&detect_direction=false¶graph=false&probability=false&multidirectional_recognize=false", imageBase64)) // 创建 HTTP 客户端和请求 client := &http.Client{} req, err := http.NewRequest("POST", url, payload) if err != nil { return "", err } // 设置请求头 req.Header.Add("Content-Type", "application/x-www-form-urlencoded") req.Header.Add("Accept", "application/json") // 发送请求并获取响应 res, err := client.Do(req) if err != nil { return "", err } defer res.Body.Close() // 读取响应体 body, err := io.ReadAll(res.Body) if err != nil { return "", err } return string(body), nil } /** * 使用 AK,SK 生成鉴权签名(Access Token) * @return string 鉴权签名信息(Access Token) */ func (f *Feature) GetAccessToken() string { url := "https://aip.baidubce.com/oauth/2.0/token" postData := fmt.Sprintf("grant_type=client_credentials&client_id=%s&client_secret=%s", API_KEY, SECRET_KEY) resp, err := http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(postData)) if err != nil { fmt.Println(err) return "" } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { fmt.Println(err) return "" } accessTokenObj := map[string]interface{}{} _ = json.Unmarshal(body, &accessTokenObj) return accessTokenObj["access_token"].(string) } func (f *Feature) GenerateSignPDF(name string, id uint, signatureBase64 string) (fileName string, err error) { // 创建 PDF 实例,A4 纸张大小 pdf := gofpdf.New("P", "mm", "A4", "") fontPath := "simhei.ttf" // 添加中文字体支持 pdf.AddUTF8Font("SimHei", "", fontPath) // 使用 simhei.ttf 字体 pdf.SetFont("SimHei", "", 12) // 添加一页 pdf.AddPage() // 插入标题,居中对齐 pdf.SetFont("SimHei", "", 20) pdf.CellFormat(0, 10, "声明", "", 1, "C", false, 0, "") // C 表示居中对齐 pdf.Ln(12) // 插入副标题 pdf.SetFont("SimHei", "", 14) pdf.Cell(40, 10, "全能查声明:") pdf.Ln(10) // 插入正文内容,添加两字符的缩进(全角空格) pdf.SetFont("SimHei", "", 12) indent := "  " // 两字符的缩进,使用全角空格 pdf.MultiCell(0, 10, indent+"1、本产品所有数据均来自第三方。可能部分数据未公开,数据更新延迟或信息受到限制,不一定全部返回,因此我们不做准确性、真实性、完整性承诺。不同数据格式及记录详细程度会存在差异,此为行业正常现象。本报告仅供参考,不能作为诉讼证据、决策性依据等材料,请结合实际情况,做出更准确的决策。", "", "", false) pdf.Ln(3) pdf.MultiCell(0, 10, indent+"2、本产品仅供用户本人查询或被授权查询。除非用户取得合法授权,用户不得利用本产品查询他人信息。用户因未获得合法授权而擅自查询他人信息所产生的任何后果,由用户自行承担责任。", "", "", false) pdf.Ln(3) // 插入承诺声明 pdf.SetFont("SimHei", "", 14) pdf.Cell(40, 10, "本人承诺:") pdf.Ln(10) text := fmt.Sprintf("本人%s在此声明,我即将通过此小程序查询的婚姻状态信息仅涉及本人。本人确认不将所得信息用作任何诉讼证据,不会将所获取的信息用于任何非法用途,包括但不限于欺诈、胁迫、侵犯隐私或其他违法行为,不将所得信息转卖、传播给他人。本人承诺对查询结果所引发的任何后果承担全部责任。", name) // 插入承诺内容,添加两字符的缩进 pdf.SetFont("SimHei", "", 12) pdf.MultiCell(0, 10, indent+text, "", "", false) pdf.Ln(10) // 定位签名和日期到右下角 pageWidth, pageHeight := pdf.GetPageSize() rightMargin := 20.0 bottomMargin := 20.0 // 设置签名部分的 XY 坐标,靠右下角 pdf.SetXY(pageWidth-rightMargin-40, pageHeight-bottomMargin-40) // 签名部分坐标 pdf.SetFont("SimHei", "", 12) pdf.Cell(40, 10, "签名:") // 解码 Base64 签名图片并保存为临时文件 var tempFileName = fmt.Sprintf("signature-%d.png", id) signaturePath, err := utils.DecodeBase64ToPNG(signatureBase64, tempFileName) if err != nil { log.Printf("【签名图片生成】解码 Base64 签名图片并保存为临时文件失败:%v", err) return "", err } // 在 PDF 中嵌入签名图片 pdf.ImageOptions(signaturePath, pageWidth-rightMargin-28, pageHeight-bottomMargin-40, 40, 10, false, gofpdf.ImageOptions{ImageType: "PNG"}, 0, "") // 插入当前日期,显示在签名下方 currentDate := time.Now().Format("2006-01-02") currentDateCN := time.Now().Format("2006年01月02日") pdf.SetXY(pageWidth-rightMargin-40, pageHeight-bottomMargin-20) pdf.Cell(40, 10, "日期:"+currentDateCN) // 根据日期和 ID 动态生成文件名 outputDir := "signature" os.MkdirAll(outputDir, os.ModePerm) // 如果不存在则创建目录 fileName = fmt.Sprintf("%s/%s_%d.pdf", outputDir, currentDate, id) // 保存 PDF 文件 err = pdf.OutputFileAndClose(fileName) if err != nil { log.Printf("【签名图片生成】保存 PDF 文件失败:%v", err) return "", err } // 删除临时签名图片文件 err = os.Remove(signaturePath) if err != nil { log.Printf("【签名图片生成】删除临时文件失败:%v", err) } return fileName, nil }