package logic import ( "bytes" "errors" "fmt" "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(customerName string, contract string, signImgPath string) (outputUrl string, err error) { filePath := customerName + "_" + time.Now().String() + ".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 := customerName + "signed" + "_" + time.Now().String() + ".pdf" signErr := InsertSignature(filePath, signFile, signImgPath) 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 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 }