# -*- coding: UTF-8 -*- import esigntool import requests from esigntool import esign_run_print_outer from esigntool.esign_file import fileHelp # 签署场景:平台方自动签署(签署方1)+个人用户手动签署流程(签署方2) # 平台方(签署方1):appId所属企业为平台方,默认平台方已完成实名认证,通过获取企业签署帐号来实现平台方自动签署。 # 个人用户手动签署(签署方2):通过传入个人信息,来实现个人用户手动签署。 config = esigntool.Config() # 初始化配置类 @esign_run_print_outer def findOrgIdentityInfo(orgName): """ 查询机构认证信息 :return: """ api_path = "/v3/organizations/identity-info?orgName={}".format(orgName) method = esigntool.httpMethodEnum.GET if orgName == "": print("请设置实名企业名称") exit() # 签名并构造签名鉴权json请求头 json_headers = esigntool.buildSignJsonHeader(config.appId, config.scert, method, esigntool.apiPathSort(api_path)) # 发起请求 resp = requests.request(method, config.host + api_path, json=None, headers=json_headers) print(resp.text) orgId = resp.json()['data']['orgId'] return orgId @esign_run_print_outer def getFileUploadUrl(file): """ 获取文件上传地址 :return: """ contentType = "application/pdf" # 声明请求变量 body = { "contentMd5": file.contentMd5, "contentType": contentType, "convert2Pdf": False, "fileName": file.fileName, "fileSize": file.fileSize } # 构建请求参数body体 api_path = "/v3/files/file-upload-url" method = esigntool.httpMethodEnum.POST json_headers = esigntool.buildSignJsonHeader(config.appId, config.scert, method, api_path, body) # 签名并构造签名鉴权json请求头 resp = requests.request(method, config.host + api_path, json=body, headers=json_headers) # 发送请求 fileUploadUrl = resp.json()['data']['fileUploadUrl'] # 获取文件上传路径 fileId = resp.json()['data']['fileId'] print(resp.text) return fileUploadUrl, fileId @esign_run_print_outer def fileStreamUpload(binfile, fileUploadUrl): """ 文件流上传服务器 :return: """ contentMd5 = file.contentMd5 # 声明请求变量 contentType = "application/pdf" # 声明请求变量 method = esigntool.httpMethodEnum.PUT # 声明请求方法 json_headers = esigntool.buildFileUploadHeader(contentType, contentMd5) # 构建请求头 resp = requests.request(method, fileUploadUrl, data=binfile, headers=json_headers) # 发送请求 print(resp.text) return resp @esign_run_print_outer def signFlowCreateByFile(fileId, orgId, psnAccount): """ 基于文件发起签署 :return: """ body = { "docs": [{ "fileId": fileId, "fileName": "xx企业劳动合同.pdf" }], "attachments": [{ "fileId": fileId, "fileName": "入职材料.pdf" }], "signers": [{ "psnSignerInfo": { "psnAccount": psnAccount }, "signConfig": { "forcedReadingTime": "10", "signOrder": 2 }, "signFields": [{ "customBizNum": "自定义编码", "fileId": fileId, "normalSignFieldConfig": { "freeMode": False, "movableSignField": False, "psnSealStyles": "0,1", "signFieldPosition": { "positionPage": "1", "positionX": 100, "positionY": 100 }, "signFieldStyle": 1 } }], "signerType": 0 }, { "orgSignerInfo": { "orgId": orgId }, "signConfig": { "signOrder": 1 }, "signFields": [{ "customBizNum": "自定义编码", "fileId": fileId, "normalSignFieldConfig": { "autoSign": True, "signFieldPosition": { "positionPage": "1", "positionX": 100, "positionY": 200 }, "signFieldStyle": 1 } }], "signerType": 1 }], "signFlowConfig": { "autoFinish": False, "autoStart": True, "noticeConfig": { "noticeTypes": "1" }, "notifyUrl": "http://xx.xx.86.172:8081/asyn/notify", "redirectConfig": { "redirectDelayTime": "3", "redirectUrl": "http://www.esign.cn" }, "signConfig": { "availableSignClientTypes": "1", "showBatchDropSealButton": True }, "signFlowTitle": "企业员工劳动合同签署" } } # 构建请求body体 api_path = "/v3/sign-flow/create-by-file" # 拼接请求路径 method = esigntool.httpMethodEnum.POST # 声明请求方法 json_headers = esigntool.buildSignJsonHeader(config.appId, config.scert, method, api_path, body) # 签名并构造签名鉴权json请求头 resp = requests.request(method, config.host + api_path, json=body, headers=json_headers) # 发送请求 print(resp.text) sign_flowId = resp.json()['data']['signFlowId'] return sign_flowId @esign_run_print_outer def signUrl(sign_flowId, psnAccount): """ 获取合同文件签署链接 :return: """ body = { "clientType": "ALL", "needLogin": True, "operator": { "psnAccount": psnAccount }, "urlType": 2 } # 构建请求body体 api_path = "/v3/sign-flow/{}/sign-url".format(sign_flowId) # 拼接请求路径 method = esigntool.httpMethodEnum.POST # 请求方法 json_headers = esigntool.buildSignJsonHeader(config.appId, config.scert, method, api_path, body) # 签名并构造签名鉴权json请求头 resp = requests.request(method, config.host + api_path, json=body, headers=json_headers) # 发送http请求 print(resp.text) return resp @esign_run_print_outer def fileDownloadUrl(sign_flowId): """ 下载已签署文件及附属材料 :return: """ api_path = "/v3/sign-flow/{}/file-download-url".format(sign_flowId) # 拼接请求路径 method = esigntool.httpMethodEnum.GET # 声明请求方法 json_headers = esigntool.buildSignJsonHeader(config.appId, config.scert, method, api_path) # 签名并构造签名鉴权json请求头 resp = requests.request(method, config.host + api_path, json=None, headers=json_headers) # 发送请求 print(resp.text) return resp if __name__ == '__main__': if config.appId == "" or config.scert == "": print("请设置应用Appid和应用Secret") exit() fileUrl = "D:\\**文件\\1.pdf" # 本地文件路径 orgName = "***企业" # 平台自身企业名称,即appid所属的企业名称 psnAccount = "1*****" # 个人用户手机号 orgId = findOrgIdentityInfo(orgName) # 查询平台自身实名帐号ID file = fileHelp(fileUrl) # 初始化文件辅助类 fileUploadUrl, fileId = getFileUploadUrl(file) # 获取文件ID&文件上传路径 fileStreamUpload(file.getBinFile(), fileUploadUrl) # 上传文件流 sign_flowId = signFlowCreateByFile(fileId, orgId, psnAccount) # 发起一步签署:主动发送签署短信给签署用户 signUrl(sign_flowId, psnAccount) # 手动获取当前签署任务中,个人的签署链接 fileDownloadUrl(sign_flowId) # 合同结束后(个人用户签署完成后),下载签署后合同