| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | package esign | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // SignFlowService 签署流程服务 | 
					
						
							|  |  |  |  | // 处理签署流程创建、链接获取等操作 | 
					
						
							|  |  |  |  | type SignFlowService struct { | 
					
						
							|  |  |  |  | 	httpClient *HTTPClient | 
					
						
							|  |  |  |  | 	config     *Config | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // NewSignFlowService 创建签署流程服务 | 
					
						
							|  |  |  |  | func NewSignFlowService(httpClient *HTTPClient, config *Config) *SignFlowService { | 
					
						
							|  |  |  |  | 	return &SignFlowService{ | 
					
						
							|  |  |  |  | 		httpClient: httpClient, | 
					
						
							|  |  |  |  | 		config:     config, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // UpdateConfig 更新配置 | 
					
						
							|  |  |  |  | func (s *SignFlowService) UpdateConfig(config *Config) { | 
					
						
							|  |  |  |  | 	s.config = config | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Create 创建签署流程 | 
					
						
							|  |  |  |  | // 创建包含多个签署人的签署流程,支持自动盖章和手动签署 | 
					
						
							|  |  |  |  | func (s *SignFlowService) Create(req *CreateSignFlowRequest) (string, error) { | 
					
						
							|  |  |  |  | 	fmt.Println("开始创建签署流程...") | 
					
						
							|  |  |  |  | 	fmt.Println("(将创建包含甲方自动盖章和乙方手动签署的流程)") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 构建甲方签署人信息(自动盖章) | 
					
						
							|  |  |  |  | 	partyASigner := s.buildPartyASigner(req.FileID) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 构建乙方签署人信息(手动签署) | 
					
						
							|  |  |  |  | 	partyBSigner := s.buildPartyBSigner(req.FileID, req.SignerAccount, req.SignerName, req.TransactorPhone, req.TransactorName, req.TransactorIDCardNum) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	signers := []SignerInfo{partyASigner, partyBSigner} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 构建请求数据 | 
					
						
							|  |  |  |  | 	requestData := CreateSignFlowByFileRequest{ | 
					
						
							|  |  |  |  | 		Docs: []DocInfo{ | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				FileId:   req.FileID, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 				FileName: s.config.Contract.Name, | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 			}, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		SignFlowConfig: s.buildSignFlowConfig(), | 
					
						
							|  |  |  |  | 		Signers:        signers, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 序列化请求数据 | 
					
						
							|  |  |  |  | 	jsonData, err := MarshalRequest(requestData) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return "", err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	fmt.Printf("发起签署请求数据: %s\n", string(jsonData)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 发送API请求 | 
					
						
							|  |  |  |  | 	responseBody, err := s.httpClient.Request("POST", "/v3/sign-flow/create-by-file", jsonData) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return "", fmt.Errorf("发起签署失败: %v", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 解析响应 | 
					
						
							|  |  |  |  | 	var response CreateSignFlowByFileResponse | 
					
						
							|  |  |  |  | 	if err := UnmarshalResponse(responseBody, &response); err != nil { | 
					
						
							|  |  |  |  | 		return "", err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err := CheckResponseCode(response.Code, response.Message); err != nil { | 
					
						
							|  |  |  |  | 		return "", err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	fmt.Printf("签署流程创建成功,流程ID: %s\n", response.Data.SignFlowId) | 
					
						
							|  |  |  |  | 	return response.Data.SignFlowId, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetSignURL 获取签署页面链接 | 
					
						
							|  |  |  |  | // 为指定的签署人获取签署页面链接 | 
					
						
							|  |  |  |  | func (s *SignFlowService) GetSignURL(signFlowID, psnAccount, orgName string) (string, string, error) { | 
					
						
							|  |  |  |  | 	fmt.Println("开始获取签署页面链接...") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 构建请求数据 | 
					
						
							|  |  |  |  | 	requestData := GetSignUrlRequest{ | 
					
						
							|  |  |  |  | 		NeedLogin: false, | 
					
						
							|  |  |  |  | 		UrlType:   UrlTypeSign, | 
					
						
							|  |  |  |  | 		Operator: &Operator{ | 
					
						
							|  |  |  |  | 			PsnAccount: psnAccount, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		Organization: &Organization{ | 
					
						
							|  |  |  |  | 			OrgName: orgName, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		ClientType: ClientTypeAll, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 序列化请求数据 | 
					
						
							|  |  |  |  | 	jsonData, err := MarshalRequest(requestData) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return "", "", err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	fmt.Printf("获取签署页面链接请求数据: %s\n", string(jsonData)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 发送API请求 | 
					
						
							|  |  |  |  | 	urlPath := fmt.Sprintf("/v3/sign-flow/%s/sign-url", signFlowID) | 
					
						
							|  |  |  |  | 	responseBody, err := s.httpClient.Request("POST", urlPath, jsonData) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return "", "", fmt.Errorf("获取签署页面链接失败: %v", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 解析响应 | 
					
						
							|  |  |  |  | 	var response GetSignUrlResponse | 
					
						
							|  |  |  |  | 	if err := UnmarshalResponse(responseBody, &response); err != nil { | 
					
						
							|  |  |  |  | 		return "", "", err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err := CheckResponseCode(response.Code, response.Message); err != nil { | 
					
						
							|  |  |  |  | 		return "", "", err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	fmt.Printf("签署页面链接获取成功!\n") | 
					
						
							|  |  |  |  | 	fmt.Printf("完整链接: %s\n", response.Data.Url) | 
					
						
							|  |  |  |  | 	fmt.Printf("短链接: %s\n", response.Data.ShortUrl) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return response.Data.Url, response.Data.ShortUrl, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // buildPartyASigner 构建甲方签署人信息(自动盖章) | 
					
						
							|  |  |  |  | func (s *SignFlowService) buildPartyASigner(fileID string) SignerInfo { | 
					
						
							|  |  |  |  | 	return SignerInfo{ | 
					
						
							|  |  |  |  | 		SignConfig: &SignConfig{SignOrder: 1}, | 
					
						
							|  |  |  |  | 		SignerType: SignerTypeOrg, | 
					
						
							|  |  |  |  | 		SignFields: []SignField{ | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				CustomBizNum: "甲方签章", | 
					
						
							|  |  |  |  | 				FileId:       fileID, | 
					
						
							|  |  |  |  | 				NormalSignFieldConfig: &NormalSignFieldConfig{ | 
					
						
							|  |  |  |  | 					AutoSign:       true, | 
					
						
							|  |  |  |  | 					SignFieldStyle: SignFieldStyleNormal, | 
					
						
							|  |  |  |  | 					SignFieldPosition: &SignFieldPosition{ | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 						PositionPage: "8", | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 						PositionX:    200, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 						PositionY:    430, | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 					}, | 
					
						
							|  |  |  |  | 				}, | 
					
						
							|  |  |  |  | 			}, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // buildPartyBSigner 构建乙方签署人信息(手动签署) | 
					
						
							|  |  |  |  | func (s *SignFlowService) buildPartyBSigner(fileID, signerAccount, signerName, transactorPhone, transactorName, transactorIDCardNum string) SignerInfo { | 
					
						
							|  |  |  |  | 	return SignerInfo{ | 
					
						
							|  |  |  |  | 		SignConfig: &SignConfig{ | 
					
						
							|  |  |  |  | 			SignOrder: 2, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		AuthConfig: &AuthConfig{ | 
					
						
							|  |  |  |  | 			PsnAvailableAuthModes: []string{AuthModeMobile3}, | 
					
						
							|  |  |  |  | 			WillingnessAuthModes:  []string{WillingnessAuthSMS}, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		SignerType: SignerTypeOrg, | 
					
						
							|  |  |  |  | 		OrgSignerInfo: &OrgSignerInfo{ | 
					
						
							|  |  |  |  | 			OrgName: signerName, | 
					
						
							|  |  |  |  | 			OrgInfo: &OrgInfo{ | 
					
						
							|  |  |  |  | 				LegalRepName:       transactorName, | 
					
						
							|  |  |  |  | 				LegalRepIDCardNum:  transactorIDCardNum, | 
					
						
							|  |  |  |  | 				LegalRepIDCardType: IDCardTypeChina, | 
					
						
							|  |  |  |  | 				OrgIDCardNum:       signerAccount, | 
					
						
							|  |  |  |  | 				OrgIDCardType:      OrgCardTypeUSCC, | 
					
						
							|  |  |  |  | 			}, | 
					
						
							|  |  |  |  | 			TransactorInfo: &TransactorInfo{ | 
					
						
							|  |  |  |  | 				PsnAccount: transactorPhone, | 
					
						
							|  |  |  |  | 				PsnInfo: &PsnInfo{ | 
					
						
							|  |  |  |  | 					PsnName:       transactorName, | 
					
						
							|  |  |  |  | 					PsnIDCardNum:  transactorIDCardNum, | 
					
						
							|  |  |  |  | 					PsnIDCardType: IDCardTypeChina, | 
					
						
							|  |  |  |  | 				}, | 
					
						
							|  |  |  |  | 			}, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		SignFields: []SignField{ | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				CustomBizNum: "乙方签章", | 
					
						
							|  |  |  |  | 				FileId:       fileID, | 
					
						
							|  |  |  |  | 				NormalSignFieldConfig: &NormalSignFieldConfig{ | 
					
						
							|  |  |  |  | 					AutoSign:       false, | 
					
						
							|  |  |  |  | 					SignFieldStyle: SignFieldStyleNormal, | 
					
						
							|  |  |  |  | 					SignFieldPosition: &SignFieldPosition{ | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 						PositionPage: "8", | 
					
						
							|  |  |  |  | 						PositionX:    450, | 
					
						
							|  |  |  |  | 						PositionY:    430, | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 					}, | 
					
						
							| 
									
										
										
										
											2025-07-28 22:35:13 +08:00
										 |  |  |  | 					OrgSealBizTypes: "PUBLIC", | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 				}, | 
					
						
							|  |  |  |  | 			}, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // buildSignFlowConfig 构建签署流程配置 | 
					
						
							|  |  |  |  | func (s *SignFlowService) buildSignFlowConfig() SignFlowConfig { | 
					
						
							|  |  |  |  | 	return SignFlowConfig{ | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		SignFlowTitle:      s.config.Contract.Name, | 
					
						
							|  |  |  |  | 		SignFlowExpireTime: calculateExpireTime(s.config.Contract.ExpireDays), | 
					
						
							|  |  |  |  | 		AutoFinish:         s.config.Sign.AutoFinish, | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 		AuthConfig: &AuthConfig{ | 
					
						
							|  |  |  |  | 			PsnAvailableAuthModes: []string{AuthModeMobile3}, | 
					
						
							|  |  |  |  | 			WillingnessAuthModes:  []string{WillingnessAuthSMS}, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		ContractConfig: &ContractConfig{ | 
					
						
							|  |  |  |  | 			AllowToRescind: false, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		RedirectConfig: &RedirectConfig{ | 
					
						
							|  |  |  |  | 			RedirectUrl: s.config.Sign.RedirectUrl, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | }  |