package logic import ( "bytes" "errors" "fmt" "fonchain-fiee/pkg/model" "fonchain-fiee/pkg/service/bundle/common" "fonchain-fiee/pkg/service/upload" "github.com/signintech/gopdf" "go.uber.org/zap" "image" "io" "log" "net/http" "os" "time" ) func SignContract(customerNum, contract, signImgPath, companyImgPath, contractNo, buyerName, idNo, telNum, address string, price float32, contractDuration int64) (outputUrl string, err error) { filePath := model.MediaPath + customerNum + time.Now().Format("20060102150405") + ".pdf" downloadFileErr := DownloadFile(filePath, contract) if downloadFileErr != nil { zap.L().Error("download file error: ", zap.Error(downloadFileErr)) //service.Error(c, errors.New(common.ErrorDownloadFile)) return outputUrl, errors.New(common.ErrorDownloadFile) } signFile := model.MediaPath + customerNum + "signed" + time.Now().Format("20060102150405") + ".pdf" /*signErr := InsertSignature(filePath, signFile, signImgPath, contractNo, idNo, telNum, address, price) if signErr != nil { zap.L().Error("insert signature error: ", zap.Error(signErr)) return outputUrl, errors.New(common.ErrorInsertSignature) }*/ signErr := InsertSignatureV1(filePath, signFile, signImgPath, companyImgPath, contractNo, buyerName, idNo, telNum, address, price, contractDuration) if signErr != nil { zap.L().Error("insert signature error: ", zap.Error(signErr)) return outputUrl, errors.New(common.ErrorInsertSignature) } os.Remove(filePath) outputUrl, ossErr := upload.PutBos(signFile, upload.PdfType, true) if ossErr != nil { return "", errors.New(common.ErrorUploadFile) } return outputUrl, nil } // InsertSignature 把用户签字内容 填充到 合同模版里面 func InsertSignature(templatePath string, outputPath string, signImgPath string) error { pdf := gopdf.GoPdf{} pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4}) resp, imageErr := http.Get(signImgPath) if imageErr != nil { return errors.New("error downloading signature image") } defer resp.Body.Close() b, _err := io.ReadAll(resp.Body) if _err != nil { return errors.New("error reading signature image") } // Create a new reader from the bytes imgReader := bytes.NewReader(b) img, _, err := image.DecodeConfig(imgReader) if err != nil { return errors.New("error decoding signature image") } w := img.Width h := img.Height // 导入模板文件中的页面 err = pdf.ImportPagesFromSource(templatePath, "/MediaBox") if err != nil { log.Fatalf("无法导入页面: %v", err) } // 获取模板文件的总页数 totalPages := pdf.GetNumberOfPages() fmt.Printf("模板文件的总页数: %d\n", totalPages) targetPage := totalPages // 遍历所有页 for i := 1; i <= totalPages; i++ { tpl := pdf.ImportPage(templatePath, i, "/MediaBox") pdf.AddPage() pdf.UseImportedTemplate(tpl, 0, 0, gopdf.PageSizeA4.W, gopdf.PageSizeA4.H) // 只在目标页插入签名 if i == targetPage { imgH1, _err := gopdf.ImageHolderByBytes(b) if _err != nil { //zap.L().Error("SignContract err", zap.Error(err)) return errors.New("error processing signature image") } newWidth := 80.0 newHeight := (newWidth / float64(w)) * float64(h) err = pdf.ImageByHolder(imgH1, 380, 540, &gopdf.Rect{W: newWidth, H: newHeight}) if err != nil { //zap.L().Error("SignContract err", zap.Error(err)) return errors.New("error inserting signature") } } } // 生成新的 PDF if err = pdf.WritePdf(outputPath); err != nil { //zap.L().Error("WritePdf err", zap.Error(err)) return errors.New("error writing final PDF") } return nil } func InsertSignatureV1(templatePath, outputPath, signImgPath, companyImgPath, contractNo, buyerName, idNo, telNum, address string, price float32, contractDuration int) error { pdf := gopdf.GoPdf{} pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4}) // 导入模板文件中的页面 err := pdf.ImportPagesFromSource(templatePath, "/MediaBox") if err != nil { log.Fatalf("无法导入页面: %v", err) } // 获取模板文件的总页数 totalPages := pdf.GetNumberOfPages() fmt.Printf("模板文件的总页数: %d\n", totalPages) buyerPage := 1 pricePage := 2 limitTimePage := 3 signPage := totalPages tffErr := pdf.AddTTFFont("simfang", "./simfang.ttf") if tffErr != nil { log.Fatalf("加载中文字体失败: %v", tffErr) } // 设置字体和字号 err = pdf.SetFont("simfang", "", 14) if err != nil { log.Fatalf("设置字体失败: %v", err) } // 写 buyer info pdf.SetPage(buyerPage) pdf.SetX(145) pdf.SetY(134) pdf.Cell(nil, contractNo) pdf.SetX(145) pdf.SetY(159) pdf.Cell(nil, time.Now().Format("2006-01-02")) pdf.SetX(180) pdf.SetY(208) pdf.Cell(nil, buyerName) pdf.SetX(210) pdf.SetY(233) pdf.Cell(nil, idNo) pdf.SetX(200) pdf.SetY(259) pdf.Cell(nil, telNum) pdf.SetX(200) pdf.SetY(284) pdf.Cell(nil, address) // 填 金额 pdf.SetPage(pricePage) pdf.SetX(379) pdf.SetY(639) pdf.Cell(nil, price) // 写 有效期 t := time.Now().AddDate(contractDuration, 0, 0) pdf.SetPage(limitTimePage) pdf.SetX(327) pdf.SetY(358) pdf.Cell(nil, t.Format("2006")) pdf.SetX(420) pdf.SetY(358) pdf.Cell(nil, t.Format("01")) pdf.SetX(486) pdf.SetY(358) pdf.Cell(nil, t.Format("02")) // 只在目标页插入签名 pdf.SetPage(signPage) signImgResp, imageErr := http.Get(signImgPath) if imageErr != nil { return errors.New("error downloading signature image") } defer signImgResp.Body.Close() signImgB, _err := io.ReadAll(signImgResp.Body) if _err != nil { return errors.New("error reading signature image") } // Create a new reader from the bytes signImgReader := bytes.NewReader(signImgB) signImg, _, err := image.DecodeConfig(signImgReader) if err != nil { return errors.New("error decoding signature image") } signImgw := signImg.Width signImgh := signImg.Height imgH1, _err := gopdf.ImageHolderByBytes(signImgB) if _err != nil { //zap.L().Error("SignContract err", zap.Error(err)) return errors.New("error processing signature image") } newSignWidth := 80.0 newSignHeight := (newSignWidth / float64(signImgw)) * float64(signImgh) // buyer sign err = pdf.ImageByHolder(imgH1, 180, 560, &gopdf.Rect{W: newSignWidth, H: newSignHeight}) if err != nil { //zap.L().Error("SignContract err", zap.Error(err)) return errors.New("error inserting signature") } pdf.SetX(320) pdf.SetY(585) pdf.Cell(nil, time.Now().Format("2006-01-02")) companyImgResp, companyImageErr := http.Get(companyImgPath) if companyImageErr != nil { return errors.New("error downloading signature image") } defer companyImgResp.Body.Close() companyImgB, _err := io.ReadAll(companyImgResp.Body) if _err != nil { return errors.New("error reading signature image") } // Create a new reader from the bytes companyImgReader := bytes.NewReader(companyImgB) companyImg, _, err := image.DecodeConfig(companyImgReader) if err != nil { return errors.New("error decoding signature image") } companyImgw := companyImg.Width companyImgh := companyImg.Height companyImgH1, _err := gopdf.ImageHolderByBytes(companyImgB) if _err != nil { //zap.L().Error("SignContract err", zap.Error(err)) return errors.New("error processing signature image") } newCompanyWidth := 80.0 newCompanyHeight := (newCompanyWidth / float64(companyImgw)) * float64(companyImgh) // seller sign err = pdf.ImageByHolder(companyImgH1, 180, 610, &gopdf.Rect{W: newCompanyWidth, H: newCompanyHeight}) if err != nil { //zap.L().Error("SignContract err", zap.Error(err)) return errors.New("error inserting signature") } pdf.SetX(320) pdf.SetY(635) pdf.Cell(nil, time.Now().Format("2006-01-02")) // 生成新的 PDF if err = pdf.WritePdf(outputPath); err != nil { //zap.L().Error("WritePdf err", zap.Error(err)) return errors.New("error writing final PDF") } return nil } func DownloadFile(filepath string, url string) error { resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() out, err := os.Create(filepath) if err != nil { return err } defer out.Close() _, err = io.Copy(out, resp.Body) return err }