Pārlūkot izejas kodu

feat: 空白 PDF 静默签章预览机构公章

Co-authored-by: Cursor <cursoragent@cursor.com>
郭铭泽 5 dienas atpakaļ
vecāks
revīzija
36bfdb3b60
2 mainītis faili ar 91 papildinājumiem un 6 dzēšanām
  1. 74 0
      preview.go
  2. 17 6
      sign.go

+ 74 - 0
preview.go

@@ -0,0 +1,74 @@
+package qiyuesuosdk
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// SealPreviewKeyword 预览 PDF 内用于关键字定位公章的占位文本。
+const SealPreviewKeyword = "__SEAL_PREVIEW__"
+
+func buildSealPreviewPDF() []byte {
+	text := fmt.Sprintf("BT /F1 20 Tf 72 400 Td (%s) Tj ET", SealPreviewKeyword)
+	streamObj := fmt.Sprintf("4 0 obj\n<< /Length %d >>\nstream\n%s\nendstream\n", len(text), text)
+	objects := []string{
+		"1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n",
+		"2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n",
+		"3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >>\nendobj\n",
+		streamObj,
+		"5 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\nendobj\n",
+	}
+
+	var buf bytes.Buffer
+	buf.WriteString("%PDF-1.4\n")
+	offsets := make([]int, len(objects)+1)
+	for i, obj := range objects {
+		offsets[i+1] = buf.Len()
+		buf.WriteString(obj)
+	}
+	xrefPos := buf.Len()
+	buf.WriteString(fmt.Sprintf("xref\n0 %d\n0000000000 65535 f \n", len(objects)+1))
+	for i := 1; i <= len(objects); i++ {
+		buf.WriteString(fmt.Sprintf("%010d 00000 n \n", offsets[i]))
+	}
+	buf.WriteString(fmt.Sprintf("trailer\n<< /Size %d /Root 1 0 R >>\nstartxref\n%d\n%%EOF\n", len(objects)+1, xrefPos))
+	return buf.Bytes()
+}
+
+// PreviewCompanySealPDF 生成空白 PDF 并静默盖机构公章,用于预览(不依赖印章图片查看权限)。
+func (c *Client) PreviewCompanySealPDF(company CompanyLocateParams, companyDisplayName string) ([]byte, error) {
+	processID := c.resolveProcessID("")
+	launcher := c.resolveLauncher("")
+	if processID == "" || launcher == "" {
+		return nil, ErrInvalidParams
+	}
+	displayName := companyDisplayName
+	if displayName == "" {
+		displayName = company.Name
+	}
+	if displayName == "" {
+		return nil, ErrInvalidParams
+	}
+
+	pdf := buildSealPreviewPDF()
+	subject := "机构公章预览"
+	docID, err := c.uploadDocument(subject, pdf)
+	if err != nil {
+		return nil, err
+	}
+	contractID, err := c.createContract(processID, subject, launcher, docID, displayName, nil)
+	if err != nil {
+		return nil, err
+	}
+	spec := CompanySealSpec{
+		CompanyName: displayName,
+		Keyword:     SealPreviewKeyword,
+		OffsetX:     "0",
+		OffsetY:     "0",
+		Page:        "1",
+	}
+	if err = c.companySilentSignFor(contractID, company, spec); err != nil {
+		return nil, err
+	}
+	return c.downloadDocument(docID)
+}

+ 17 - 6
sign.go

@@ -166,15 +166,26 @@ func (c *Client) createDualCompanyContract(processID, subject, launcher, documen
 }
 
 func (c *Client) companySilentSign(contractID string, spec CompanySealSpec) error {
+	return c.companySilentSignFor(contractID, CompanyLocateParams{Name: spec.CompanyName}, spec)
+}
+
+func (c *Client) companySilentSignFor(contractID string, company CompanyLocateParams, spec CompanySealSpec) error {
 	cInt, err := strconv.ParseInt(contractID, 10, 64)
 	if err != nil {
 		return err
 	}
+	companyReq, err := company.toCompanyRequest()
+	if err != nil {
+		return err
+	}
+	if companyReq.Name == "" && spec.CompanyName != "" {
+		companyReq.Name = spec.CompanyName
+	}
 	stamper := &common.CompanyStamperBean{
-		Type_:        "SEAL_CORPORATE",
-		Keyword:      spec.Keyword,
-		OffsetX:      spec.OffsetX,
-		OffsetY:      spec.OffsetY,
+		Type_:   "SEAL_CORPORATE",
+		Keyword: spec.Keyword,
+		OffsetX: spec.OffsetX,
+		OffsetY: spec.OffsetY,
 	}
 	if spec.RotateDegree != 0 {
 		stamper.RotateDegree = &spec.RotateDegree
@@ -184,9 +195,9 @@ func (c *Client) companySilentSign(contractID string, spec CompanySealSpec) erro
 	}
 	req := v2contract_request.V2ContractSignbycompanyRequest{
 		Contract: &common.SignSilentContract{Id: &cInt},
-		Company:  &common.CompanyRequest{Name: spec.CompanyName},
+		Company:  companyReq,
 		SealRequest: &common.SealMultipleRequest{
-			Company: &common.CompanyRequest{Name: spec.CompanyName},
+			Company: companyReq,
 		},
 		Stampers: []*common.CompanyStamperBean{stamper},
 	}