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, FileName: s.config.Contract.Name, }, }, 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{ PositionPage: "8", PositionX: 200, PositionY: 430, }, }, }, }, } } // 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{ PositionPage: "8", PositionX: 450, PositionY: 430, }, OrgSealBizTypes: "PUBLIC", }, }, }, } } // buildSignFlowConfig 构建签署流程配置 func (s *SignFlowService) buildSignFlowConfig() SignFlowConfig { return SignFlowConfig{ SignFlowTitle: s.config.Contract.Name, SignFlowExpireTime: calculateExpireTime(s.config.Contract.ExpireDays), AutoFinish: s.config.Sign.AutoFinish, AuthConfig: &AuthConfig{ PsnAvailableAuthModes: []string{AuthModeMobile3}, WillingnessAuthModes: []string{WillingnessAuthSMS}, }, ContractConfig: &ContractConfig{ AllowToRescind: false, }, RedirectConfig: &RedirectConfig{ RedirectUrl: s.config.Sign.RedirectUrl, }, } }