|
|
@@ -0,0 +1,229 @@
|
|
|
+package qiyuesuosdk
|
|
|
+
|
|
|
+import (
|
|
|
+ "net/url"
|
|
|
+ "strconv"
|
|
|
+
|
|
|
+ contract_request "git.sxidc.com/student-physical-examination/contract_lock_sdk/model/contract/request"
|
|
|
+ "git.sxidc.com/student-physical-examination/contract_lock_sdk/model/common"
|
|
|
+ v2contract_request "git.sxidc.com/student-physical-examination/contract_lock_sdk/model/v2contract/request"
|
|
|
+ v2document_response "git.sxidc.com/student-physical-examination/contract_lock_sdk/model/v2document/response"
|
|
|
+)
|
|
|
+
|
|
|
+// SignDocument 上传 PDF → 创建合同 → 企业静默签 → [个人静默签] → 下载。
|
|
|
+func (c *Client) SignDocument(req SignDocumentRequest) ([]byte, error) {
|
|
|
+ processID := c.resolveProcessID(req.ProcessID)
|
|
|
+ launcher := c.resolveLauncher(req.Launcher)
|
|
|
+ if processID == "" || launcher == "" {
|
|
|
+ return nil, ErrInvalidParams
|
|
|
+ }
|
|
|
+
|
|
|
+ docID, err := c.uploadDocument(req.Subject, req.PDF)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ openUserIDs := make([]string, 0, len(req.PersonalSeals))
|
|
|
+ for _, p := range req.PersonalSeals {
|
|
|
+ openUserIDs = append(openUserIDs, p.OpenUserID)
|
|
|
+ }
|
|
|
+ contractID, err := c.createContract(processID, req.Subject, launcher, docID, req.CompanySeal.CompanyName, openUserIDs)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ if err = c.companySilentSign(contractID, req.CompanySeal); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ for _, p := range req.PersonalSeals {
|
|
|
+ if err = c.personalSilentSign(contractID, p); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return c.downloadDocument(docID)
|
|
|
+}
|
|
|
+
|
|
|
+// SignDualCompany 双企业公章签署(无个人签)。
|
|
|
+func (c *Client) SignDualCompany(req SignDualCompanyRequest) ([]byte, error) {
|
|
|
+ processID := c.resolveProcessID(req.ProcessID)
|
|
|
+ launcher := c.resolveLauncher(req.Launcher)
|
|
|
+ if processID == "" || launcher == "" || len(req.CompanySeals) == 0 {
|
|
|
+ return nil, ErrInvalidParams
|
|
|
+ }
|
|
|
+
|
|
|
+ docID, err := c.uploadDocument(req.Subject, req.PDF)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ names := make([]string, len(req.CompanySeals))
|
|
|
+ for i, s := range req.CompanySeals {
|
|
|
+ names[i] = s.CompanyName
|
|
|
+ }
|
|
|
+ contractID, err := c.createDualCompanyContract(processID, req.Subject, launcher, docID, names)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ for _, seal := range req.CompanySeals {
|
|
|
+ if err = c.companySilentSign(contractID, seal); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return c.downloadDocument(docID)
|
|
|
+}
|
|
|
+
|
|
|
+func (c *Client) uploadDocument(title string, pdf []byte) (string, error) {
|
|
|
+ fields := map[string]string{
|
|
|
+ "title": title,
|
|
|
+ "fileType": "pdf",
|
|
|
+ }
|
|
|
+ var resp struct {
|
|
|
+ apiResponse
|
|
|
+ Result v2document_response.V2DocumentCreatebyfileResponse `json:"result"`
|
|
|
+ }
|
|
|
+ if err := c.postMultipart("/v2/document/createbyfile", fields, "file", pdf, &resp); err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ if err := resp.err(); err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ return resp.Result.DocumentId, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (c *Client) createContract(processID, subject, launcher, documentID, companyName string, openUserIDs []string) (string, error) {
|
|
|
+ docInt, err := strconv.ParseInt(documentID, 10, 64)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ send := true
|
|
|
+ remind := false
|
|
|
+ var serialNo int64 = 1
|
|
|
+ signatories := []*common.Signatory{{
|
|
|
+ TenantName: companyName,
|
|
|
+ TenantType: "COMPANY",
|
|
|
+ SerialNo: &serialNo,
|
|
|
+ Remind: &remind,
|
|
|
+ }}
|
|
|
+ for _, uid := range openUserIDs {
|
|
|
+ serialNo++
|
|
|
+ sNo := serialNo
|
|
|
+ signatories = append(signatories, &common.Signatory{
|
|
|
+ TenantType: "PERSONAL",
|
|
|
+ SerialNo: &sNo,
|
|
|
+ Remind: &remind,
|
|
|
+ OpenUserId: uid,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ req := contract_request.ContractCreatebycategoryRequest{
|
|
|
+ CategoryId: processID,
|
|
|
+ Subject: subject,
|
|
|
+ Send: &send,
|
|
|
+ TenantName: launcher,
|
|
|
+ Documents: []int64{docInt},
|
|
|
+ Signatories: signatories,
|
|
|
+ }
|
|
|
+ var contractID string
|
|
|
+ resp := c.sdk.ServiceAsModel(req, contractID)
|
|
|
+ id, err := c.serviceString(resp)
|
|
|
+ return id, err
|
|
|
+}
|
|
|
+
|
|
|
+func (c *Client) createDualCompanyContract(processID, subject, launcher, documentID string, companyNames []string) (string, error) {
|
|
|
+ docInt, err := strconv.ParseInt(documentID, 10, 64)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ send := true
|
|
|
+ remind := false
|
|
|
+ var serialNo int64 = 1
|
|
|
+ var actionSerial int64 = 1
|
|
|
+ signatories := make([]*common.Signatory, 0, len(companyNames))
|
|
|
+ for _, name := range companyNames {
|
|
|
+ sNo := serialNo
|
|
|
+ serialNo++
|
|
|
+ aNo := actionSerial
|
|
|
+ signatories = append(signatories, &common.Signatory{
|
|
|
+ TenantName: name,
|
|
|
+ TenantType: "COMPANY",
|
|
|
+ SerialNo: &sNo,
|
|
|
+ Remind: &remind,
|
|
|
+ Actions: []*common.Action{{
|
|
|
+ Type_: "CORPORATE",
|
|
|
+ SerialNo: &aNo,
|
|
|
+ }},
|
|
|
+ })
|
|
|
+ }
|
|
|
+ req := contract_request.ContractCreatebycategoryRequest{
|
|
|
+ CategoryId: processID,
|
|
|
+ Subject: subject,
|
|
|
+ Send: &send,
|
|
|
+ TenantName: launcher,
|
|
|
+ Documents: []int64{docInt},
|
|
|
+ Signatories: signatories,
|
|
|
+ }
|
|
|
+ var contractID string
|
|
|
+ resp := c.sdk.ServiceAsModel(req, contractID)
|
|
|
+ id, err := c.serviceString(resp)
|
|
|
+ return id, err
|
|
|
+}
|
|
|
+
|
|
|
+func (c *Client) companySilentSign(contractID string, spec CompanySealSpec) error {
|
|
|
+ cInt, err := strconv.ParseInt(contractID, 10, 64)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ stamper := &common.CompanyStamperBean{
|
|
|
+ Type_: "SEAL_CORPORATE",
|
|
|
+ Keyword: spec.Keyword,
|
|
|
+ OffsetX: spec.OffsetX,
|
|
|
+ OffsetY: spec.OffsetY,
|
|
|
+ }
|
|
|
+ if spec.RotateDegree != 0 {
|
|
|
+ stamper.RotateDegree = &spec.RotateDegree
|
|
|
+ }
|
|
|
+ if spec.Page != "" {
|
|
|
+ stamper.Page = spec.Page
|
|
|
+ }
|
|
|
+ req := v2contract_request.V2ContractSignbycompanyRequest{
|
|
|
+ Contract: &common.SignSilentContract{Id: &cInt},
|
|
|
+ Company: &common.CompanyRequest{Name: spec.CompanyName},
|
|
|
+ SealRequest: &common.SealMultipleRequest{
|
|
|
+ Company: &common.CompanyRequest{Name: spec.CompanyName},
|
|
|
+ },
|
|
|
+ Stampers: []*common.CompanyStamperBean{stamper},
|
|
|
+ }
|
|
|
+ return c.serviceOK(c.sdk.Service(req))
|
|
|
+}
|
|
|
+
|
|
|
+func (c *Client) personalSilentSign(contractID string, spec PersonalSealSpec) error {
|
|
|
+ cInt, err := strconv.ParseInt(contractID, 10, 64)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ width, height := 12.0, 5.0
|
|
|
+ offsetX, offsetY := -30.0, 16.0
|
|
|
+ useDefault := true
|
|
|
+ req := v2contract_request.V2ContractSignbypersonRequest{
|
|
|
+ Contract: &common.SignSilentContract{Id: &cInt},
|
|
|
+ User: &common.User{OpenUserId: spec.OpenUserID},
|
|
|
+ SealInfoRequest: &common.PersonSealInfoRequest{
|
|
|
+ User: &common.UserInfoRequest{OpenUserId: spec.OpenUserID},
|
|
|
+ DefaultPersonSignFlag: &useDefault,
|
|
|
+ PersonSealCarrier: "PERSON_SIGN",
|
|
|
+ },
|
|
|
+ Stampers: []*common.StamperBean{{
|
|
|
+ Type_: "SEAL_PERSONAL",
|
|
|
+ Keyword: spec.Keyword,
|
|
|
+ KeywordIndex: "0",
|
|
|
+ Width: &width,
|
|
|
+ Height: &height,
|
|
|
+ OffsetX: &offsetX,
|
|
|
+ OffsetY: &offsetY,
|
|
|
+ OffsetUnit: "POINT",
|
|
|
+ }},
|
|
|
+ }
|
|
|
+ return c.serviceOK(c.sdk.Service(req))
|
|
|
+}
|
|
|
+
|
|
|
+func (c *Client) downloadDocument(documentID string) ([]byte, error) {
|
|
|
+ q := url.Values{"documentId": {documentID}}
|
|
|
+ return c.download("/document/download", q)
|
|
|
+}
|