sign.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package qiyuesuosdk
  2. import (
  3. "net/url"
  4. "strconv"
  5. contract_request "git.sxidc.com/student-physical-examination/contract_lock_sdk/model/contract/request"
  6. "git.sxidc.com/student-physical-examination/contract_lock_sdk/model/common"
  7. v2contract_request "git.sxidc.com/student-physical-examination/contract_lock_sdk/model/v2contract/request"
  8. v2document_response "git.sxidc.com/student-physical-examination/contract_lock_sdk/model/v2document/response"
  9. )
  10. // SignDocument 上传 PDF → 创建合同 → 企业静默签 → [个人静默签] → 下载。
  11. func (c *Client) SignDocument(req SignDocumentRequest) ([]byte, error) {
  12. processID := c.resolveProcessID(req.ProcessID)
  13. launcher := c.resolveLauncher(req.Launcher)
  14. if processID == "" || launcher == "" {
  15. return nil, ErrInvalidParams
  16. }
  17. docID, err := c.uploadDocument(req.Subject, req.PDF)
  18. if err != nil {
  19. return nil, err
  20. }
  21. openUserIDs := make([]string, 0, len(req.PersonalSeals))
  22. for _, p := range req.PersonalSeals {
  23. openUserIDs = append(openUserIDs, p.OpenUserID)
  24. }
  25. contractID, err := c.createContract(processID, req.Subject, launcher, docID, req.CompanySeal.CompanyName, openUserIDs)
  26. if err != nil {
  27. return nil, err
  28. }
  29. if err = c.companySilentSign(contractID, req.CompanySeal); err != nil {
  30. return nil, err
  31. }
  32. for _, p := range req.PersonalSeals {
  33. if err = c.personalSilentSign(contractID, p); err != nil {
  34. return nil, err
  35. }
  36. }
  37. return c.downloadDocument(docID)
  38. }
  39. // SignDualCompany 双企业公章签署(无个人签)。
  40. func (c *Client) SignDualCompany(req SignDualCompanyRequest) ([]byte, error) {
  41. processID := c.resolveProcessID(req.ProcessID)
  42. launcher := c.resolveLauncher(req.Launcher)
  43. if processID == "" || launcher == "" || len(req.CompanySeals) == 0 {
  44. return nil, ErrInvalidParams
  45. }
  46. docID, err := c.uploadDocument(req.Subject, req.PDF)
  47. if err != nil {
  48. return nil, err
  49. }
  50. names := make([]string, len(req.CompanySeals))
  51. for i, s := range req.CompanySeals {
  52. names[i] = s.CompanyName
  53. }
  54. contractID, err := c.createDualCompanyContract(processID, req.Subject, launcher, docID, names)
  55. if err != nil {
  56. return nil, err
  57. }
  58. for _, seal := range req.CompanySeals {
  59. if err = c.companySilentSign(contractID, seal); err != nil {
  60. return nil, err
  61. }
  62. }
  63. return c.downloadDocument(docID)
  64. }
  65. func (c *Client) uploadDocument(title string, pdf []byte) (string, error) {
  66. fields := map[string]string{
  67. "title": title,
  68. "fileType": "pdf",
  69. }
  70. var resp struct {
  71. apiResponse
  72. Result v2document_response.V2DocumentCreatebyfileResponse `json:"result"`
  73. }
  74. if err := c.postMultipart("/v2/document/createbyfile", fields, "file", pdf, &resp); err != nil {
  75. return "", err
  76. }
  77. if err := resp.err(); err != nil {
  78. return "", err
  79. }
  80. return resp.Result.DocumentId, nil
  81. }
  82. func (c *Client) createContract(processID, subject, launcher, documentID, companyName string, openUserIDs []string) (string, error) {
  83. docInt, err := strconv.ParseInt(documentID, 10, 64)
  84. if err != nil {
  85. return "", err
  86. }
  87. send := true
  88. remind := false
  89. var serialNo int64 = 1
  90. signatories := []*common.Signatory{{
  91. TenantName: companyName,
  92. TenantType: "COMPANY",
  93. SerialNo: &serialNo,
  94. Remind: &remind,
  95. }}
  96. for _, uid := range openUserIDs {
  97. serialNo++
  98. sNo := serialNo
  99. signatories = append(signatories, &common.Signatory{
  100. TenantType: "PERSONAL",
  101. SerialNo: &sNo,
  102. Remind: &remind,
  103. OpenUserId: uid,
  104. })
  105. }
  106. req := contract_request.ContractCreatebycategoryRequest{
  107. CategoryId: processID,
  108. Subject: subject,
  109. Send: &send,
  110. TenantName: launcher,
  111. Documents: []int64{docInt},
  112. Signatories: signatories,
  113. }
  114. var contractID string
  115. resp := c.sdk.ServiceAsModel(req, contractID)
  116. id, err := c.serviceString(resp)
  117. return id, err
  118. }
  119. func (c *Client) createDualCompanyContract(processID, subject, launcher, documentID string, companyNames []string) (string, error) {
  120. docInt, err := strconv.ParseInt(documentID, 10, 64)
  121. if err != nil {
  122. return "", err
  123. }
  124. send := true
  125. remind := false
  126. var serialNo int64 = 1
  127. var actionSerial int64 = 1
  128. signatories := make([]*common.Signatory, 0, len(companyNames))
  129. for _, name := range companyNames {
  130. sNo := serialNo
  131. serialNo++
  132. aNo := actionSerial
  133. signatories = append(signatories, &common.Signatory{
  134. TenantName: name,
  135. TenantType: "COMPANY",
  136. SerialNo: &sNo,
  137. Remind: &remind,
  138. Actions: []*common.Action{{
  139. Type_: "CORPORATE",
  140. SerialNo: &aNo,
  141. }},
  142. })
  143. }
  144. req := contract_request.ContractCreatebycategoryRequest{
  145. CategoryId: processID,
  146. Subject: subject,
  147. Send: &send,
  148. TenantName: launcher,
  149. Documents: []int64{docInt},
  150. Signatories: signatories,
  151. }
  152. var contractID string
  153. resp := c.sdk.ServiceAsModel(req, contractID)
  154. id, err := c.serviceString(resp)
  155. return id, err
  156. }
  157. func (c *Client) companySilentSign(contractID string, spec CompanySealSpec) error {
  158. return c.companySilentSignFor(contractID, CompanyLocateParams{Name: spec.CompanyName}, spec)
  159. }
  160. func (c *Client) companySilentSignFor(contractID string, company CompanyLocateParams, spec CompanySealSpec) error {
  161. cInt, err := strconv.ParseInt(contractID, 10, 64)
  162. if err != nil {
  163. return err
  164. }
  165. companyReq, err := company.toCompanyRequest()
  166. if err != nil {
  167. return err
  168. }
  169. if companyReq.Name == "" && spec.CompanyName != "" {
  170. companyReq.Name = spec.CompanyName
  171. }
  172. stamper := &common.CompanyStamperBean{
  173. Type_: "SEAL_CORPORATE",
  174. Keyword: spec.Keyword,
  175. OffsetX: spec.OffsetX,
  176. OffsetY: spec.OffsetY,
  177. }
  178. if spec.RotateDegree != 0 {
  179. stamper.RotateDegree = &spec.RotateDegree
  180. }
  181. if spec.Page != "" {
  182. stamper.Page = spec.Page
  183. }
  184. req := v2contract_request.V2ContractSignbycompanyRequest{
  185. Contract: &common.SignSilentContract{Id: &cInt},
  186. Company: companyReq,
  187. SealRequest: &common.SealMultipleRequest{
  188. Company: companyReq,
  189. },
  190. Stampers: []*common.CompanyStamperBean{stamper},
  191. }
  192. return c.serviceOK(c.sdk.Service(req))
  193. }
  194. func (c *Client) personalSilentSign(contractID string, spec PersonalSealSpec) error {
  195. cInt, err := strconv.ParseInt(contractID, 10, 64)
  196. if err != nil {
  197. return err
  198. }
  199. width, height := 12.0, 5.0
  200. offsetX, offsetY := -30.0, 16.0
  201. useDefault := true
  202. req := v2contract_request.V2ContractSignbypersonRequest{
  203. Contract: &common.SignSilentContract{Id: &cInt},
  204. User: &common.User{OpenUserId: spec.OpenUserID},
  205. SealInfoRequest: &common.PersonSealInfoRequest{
  206. User: &common.UserInfoRequest{OpenUserId: spec.OpenUserID},
  207. DefaultPersonSignFlag: &useDefault,
  208. PersonSealCarrier: "PERSON_SIGN",
  209. },
  210. Stampers: []*common.StamperBean{{
  211. Type_: "SEAL_PERSONAL",
  212. Keyword: spec.Keyword,
  213. KeywordIndex: "0",
  214. Width: &width,
  215. Height: &height,
  216. OffsetX: &offsetX,
  217. OffsetY: &offsetY,
  218. OffsetUnit: "POINT",
  219. }},
  220. }
  221. return c.serviceOK(c.sdk.Service(req))
  222. }
  223. func (c *Client) downloadDocument(documentID string) ([]byte, error) {
  224. q := url.Values{"documentId": {documentID}}
  225. return c.download("/document/download", q)
  226. }