EsignHttpUtil.java 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. package com.kingdee.eas.custom.esign.util;
  2. import cn.hutool.core.net.url.UrlBuilder;
  3. import com.alibaba.fastjson.JSON;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.google.common.collect.Maps;
  6. import com.kingdee.bos.BOSException;
  7. import com.kingdee.bos.Context;
  8. import com.kingdee.bos.ContextUtils;
  9. import com.kingdee.bos.dao.IObjectPK;
  10. import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
  11. import com.kingdee.bos.util.BOSUuid;
  12. import com.kingdee.eas.basedata.person.PersonInfo;
  13. import com.kingdee.eas.common.EASBizException;
  14. import com.kingdee.eas.custom.esign.*;
  15. import com.kingdee.eas.custom.esign.bizEnum.EsignConfigEnum;
  16. import com.kingdee.eas.custom.esign.bizEnum.EsignStatusEnum;
  17. import com.kingdee.eas.custom.esign.bizEnum.SendStatusEnum;
  18. import com.kingdee.eas.custom.esign.tsign.hz.comm.EsignHttpHelper;
  19. import com.kingdee.eas.custom.esign.tsign.hz.comm.EsignHttpResponse;
  20. import com.kingdee.eas.custom.esign.tsign.hz.enums.EsignRequestType;
  21. import com.kingdee.eas.custom.esign.tsign.hz.exception.EsignException;
  22. import com.kingdee.eas.mobileaccess.hr.sHR.config.EASConfig;
  23. import com.kingdee.eas.util.app.DbUtil;
  24. import com.kingdee.jdbc.rowset.IRowSet;
  25. import org.apache.commons.lang3.StringUtils;
  26. import org.apache.http.client.utils.URIBuilder;
  27. import org.springframework.web.util.UriBuilder;
  28. import org.springframework.web.util.UriComponentsBuilder;
  29. import java.net.URI;
  30. import java.net.URISyntaxException;
  31. import java.nio.charset.Charset;
  32. import java.nio.charset.StandardCharsets;
  33. import java.sql.SQLException;
  34. import java.text.MessageFormat;
  35. import java.util.List;
  36. import java.util.Locale;
  37. import java.util.Map;
  38. /**
  39. * description: EsignHttpUtil <br>
  40. * date: 17/11/2025 下午 4:26 <br>
  41. * author: lhbj <br>
  42. * version: 1.0 <br>
  43. */
  44. public class EsignHttpUtil {
  45. /**
  46. * 基础请求接口
  47. *
  48. * @param url 请求地址
  49. * @param jsonParm JSON字符串参数
  50. * @param requestType 请求类型 POST/GET
  51. * @param debug 输出日志
  52. * @param sourceId 来源id
  53. * @return
  54. * @throws EsignException
  55. */
  56. public static EsignHttpResponse doCommHttp(Context ctx, String url, String jsonParm, EsignRequestType requestType, Boolean debug, String sourceId, EsignConfigEnum configEnum) throws EsignException {
  57. //
  58. //生成签名鉴权方式的的header
  59. Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(EsignConfig.getInstance().getEsignAppId(),
  60. EsignConfig.getInstance().getEsignAppSecret(), jsonParm, requestType.name(), url, debug);
  61. EsignHttpResponse response = EsignHttpHelper.doCommHttp(EsignConfig.getInstance().getEsignHost(), url, requestType, jsonParm, header, debug);
  62. try {
  63. if (null == ctx) {
  64. return response;
  65. }
  66. if (null == ctx) {
  67. String currentSolutionName = EASConfig.getInstance().getSlnName();
  68. String currentDatabaseCenter = EASConfig.getInstance().getDcCode();
  69. ctx = new Context(new ObjectUuidPK(), currentSolutionName, currentDatabaseCenter, new Locale("l2"));
  70. }
  71. EsignLogInfo esignLogInfo = new EsignLogInfo();
  72. IEsignLog log = EsignLogFactory.getLocalInstance(ctx);
  73. esignLogInfo.setEsiginName(configEnum);
  74. esignLogInfo.setRequestState(String.valueOf(response.getStatus()));
  75. esignLogInfo.setUrl(url);
  76. esignLogInfo.setRequestData(jsonParm);
  77. esignLogInfo.setResponseData(response.getBody());
  78. esignLogInfo.setSource(sourceId);
  79. IObjectPK pk = log.addnew(esignLogInfo);
  80. response.setLogId(pk.toString());
  81. } catch (Exception e) {
  82. e.printStackTrace();
  83. } finally {
  84. }
  85. //发起接口请求
  86. return response;
  87. }
  88. /**
  89. * POST请求接口
  90. *
  91. * @param url 请求地址
  92. * @param jsonParm JSON字符串参数
  93. * @param debug 输出日志
  94. * @param sourceId 来源id
  95. * @return
  96. * @throws EsignException
  97. */
  98. public static EsignHttpResponse POST(Context ctx, String url, String jsonParm, Boolean debug, String sourceId, EsignConfigEnum configEnum) throws EsignException {
  99. //请求方法
  100. EsignRequestType requestType = EsignRequestType.POST;
  101. return doCommHttp(ctx, url, jsonParm, requestType, debug, sourceId, configEnum);
  102. }
  103. public static EsignHttpResponse POST(Context ctx, String url, String jsonParm, String sourceId, EsignConfigEnum configEnum) throws EsignException {
  104. return POST(ctx, url, jsonParm, false, sourceId, configEnum);
  105. }
  106. /**
  107. * GET请求接口
  108. *
  109. * @param url 请求地址
  110. * @param jsonParm JSON字符串参数
  111. * @param debug 输出日志
  112. * @param sourceId 来源id
  113. * @return
  114. * @throws EsignException
  115. */
  116. public static EsignHttpResponse GET(Context ctx, String url, String jsonParm, Boolean debug, String sourceId, EsignConfigEnum configEnum) throws EsignException {
  117. //请求方法
  118. EsignRequestType requestType = EsignRequestType.GET;
  119. return doCommHttp(ctx, url, jsonParm, requestType, debug, sourceId, configEnum);
  120. }
  121. public static EsignHttpResponse GET(Context ctx, String url, String jsonParm, String sourceId, EsignConfigEnum configEnum) throws EsignException {
  122. return GET(ctx, url, jsonParm, false, sourceId, configEnum);
  123. }
  124. public static EsignHttpResponse DELETE(Context ctx, String url, String jsonParm, String sourceId, EsignConfigEnum configEnum) throws EsignException {
  125. return DELETE(ctx, url, jsonParm, false, sourceId, configEnum);
  126. }
  127. public static EsignHttpResponse DELETE(Context ctx, String url, String jsonParm, Boolean debug, String sourceId, EsignConfigEnum configEnum) throws EsignException {
  128. //请求方法
  129. EsignRequestType requestType = EsignRequestType.DELETE;
  130. return doCommHttp(ctx, url, jsonParm, requestType, debug, sourceId, configEnum);
  131. }
  132. public static EsignHttpResponse getDocTemplatesDetailById(Context ctx, String id) throws EsignException {
  133. return getDocTemplatesDetailById(ctx, id, null);
  134. }
  135. /**
  136. * 查询合同模板中控件详情
  137. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/aoq509
  138. * 接口地址:https://{host}/v3/doc-templates/{docTemplateId}
  139. * 请求方法:GET
  140. *
  141. * @param id 模板id
  142. * @param sourceId 来源id
  143. * @return
  144. * @throws EsignException
  145. */
  146. public static EsignHttpResponse getDocTemplatesDetailById(Context ctx, String id, String sourceId) throws EsignException {
  147. EsignConfigEnum configEnum = EsignConfigEnum.docTemplatesDetailById;
  148. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  149. apiaddr = MessageFormat.format(apiaddr, id);
  150. String jsonParm = null;
  151. return GET(ctx, apiaddr, jsonParm, sourceId, configEnum);
  152. }
  153. /**
  154. * 填写模板生成文件
  155. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/mv8a3i
  156. * 接口地址:https://{host}/v3/files/create-by-doc-template
  157. * 请求方法:POST
  158. * 注意事项:componentId与componentKey两个字段不能同时传值,只能一个有值
  159. *
  160. * @param json
  161. * @param sourceId 来源id
  162. * @return
  163. * @throws EsignException
  164. */
  165. public static EsignHttpResponse createByDocTemplate(Context ctx, String json, String sourceId) throws EsignException {
  166. EsignConfigEnum configEnum = EsignConfigEnum.createByDocTemplate;
  167. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  168. return POST(ctx, apiaddr, json, sourceId, configEnum);
  169. }
  170. /**
  171. * 查询机构认证信息
  172. * 参考文档:https://open.esign.cn/doc/opendoc/auth3/xxz4tc
  173. * 接口地址:https://{host}/v3/organizations/identity-info
  174. * 请求方法:GET
  175. * 注意事项:
  176. * 入参中orgId、orgName和orgIDCardNum三个参数只选择一个传入即可查询机构认证信息。
  177. * 查询优先级为 orgId > orgName > orgIDCardNum。
  178. *
  179. * @param orgId
  180. * @param orgName
  181. * @param orgIDCardNum
  182. * @param orgIDCardType 组织机构证件类型(传orgIDCardNum时,该参数为必传)
  183. * CRED_ORG_USCC - 统一社会信用代码 * CRED_ORG_REGCODE - 工商注册号
  184. * @param sourceId 来源id
  185. * @return
  186. * @throws EsignException
  187. */
  188. public static EsignHttpResponse getOrgIdentity_info(Context ctx, String orgId, String orgName, String orgIDCardNum, String orgIDCardType, String sourceId) throws EsignException, URISyntaxException {
  189. EsignConfigEnum configEnum = EsignConfigEnum.organizations_identity_info;
  190. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  191. if (StringUtils.isBlank(orgId) && StringUtils.isBlank(orgName)) {
  192. if (StringUtils.isNotBlank(orgIDCardNum) && StringUtils.isBlank(orgIDCardType)) {
  193. throw new EsignException("传orgIDCardNum时,orgIDCardType参数为必传");
  194. } else {
  195. throw new EsignException("orgId与orgName与orgIDCardNum不能都为空");
  196. }
  197. }
  198. URIBuilder uriBuilder = new URIBuilder(apiaddr);
  199. if (StringUtils.isNotBlank(orgId)) {
  200. //uriBuilder.queryParam("orgId", orgId);
  201. uriBuilder.addParameter("orgId", orgId);
  202. }
  203. if (StringUtils.isNotBlank(orgIDCardNum) && StringUtils.isNotBlank(orgIDCardType)) {
  204. uriBuilder.addParameter("orgIDCardNum", orgIDCardNum);
  205. uriBuilder.addParameter("orgIDCardType", orgIDCardType);
  206. }
  207. URI uri =uriBuilder.build();
  208. apiaddr = uri.toString();
  209. if (StringUtils.isNotBlank(orgName)) {
  210. if (apiaddr.indexOf("?")>0){
  211. apiaddr+="&orgName="+orgName;
  212. }else {
  213. apiaddr+="?orgName="+orgName;
  214. }
  215. }
  216. return GET(ctx, apiaddr, null, sourceId, configEnum);
  217. }
  218. public static EsignHttpResponse getOrgIdentity_infoByOrgId(Context ctx, String orgId) throws EsignException, URISyntaxException {
  219. return getOrgIdentity_info(ctx, orgId, null, null, null, null);
  220. }
  221. public static EsignHttpResponse getOrgIdentity_infoByOrgName(Context ctx, String orgName) throws EsignException, URISyntaxException {
  222. return getOrgIdentity_info(ctx, null, orgName, null, null, null);
  223. }
  224. public static EsignHttpResponse getOrgIdentity_infoByOrgIDCardNum(Context ctx, String orgIDCardNum, String orgIDCardType) throws EsignException, URISyntaxException {
  225. return getOrgIdentity_info(ctx, null, null, orgIDCardNum, orgIDCardType, null);
  226. }
  227. /**
  228. * 查询个人认证信息
  229. * 参考文档:https://open.esign.cn/doc/opendoc/auth3/xxz4tc
  230. * 接口地址:https://{host}/v3/persons/identity-info
  231. * 请求方法:GET
  232. * 注意事项:
  233. * 入参中psnId、psnAccount和psnIDCardNum三个参数只选择一个传入即可查询个人的认证信息。
  234. * 查询优先级为 psnId > psnAccount > psnIDCardNum
  235. *
  236. * @param psnId
  237. * @param psnAccount
  238. * @param psnIDCardNum
  239. * @param psnIDCardType 个人证件号类型 (传psnIDCardNum时,证件类型为必传项)
  240. * CRED_PSN_CH_IDCARD - 中国大陆居民身份证
  241. * CRED_PSN_CH_HONGKONG - 香港来往大陆通行证
  242. * CRED_PSN_CH_MACAO - 澳门来往大陆通行证
  243. * CRED_PSN_CH_TWCARD - 台湾来往大陆通行证
  244. * CRED_PSN_PASSPORT - 护照
  245. * @param sourceId 来源id
  246. * @return
  247. * @throws EsignException
  248. */
  249. public static EsignHttpResponse getPersonIdentity_info(Context ctx, String psnId, String psnAccount, String psnIDCardNum, String psnIDCardType, String sourceId) throws EsignException, URISyntaxException {
  250. EsignConfigEnum configEnum = EsignConfigEnum.persons_identity_info;
  251. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  252. if (StringUtils.isBlank(psnId) && StringUtils.isBlank(psnAccount)) {
  253. if (StringUtils.isNotBlank(psnIDCardNum) && StringUtils.isBlank(psnIDCardType)) {
  254. throw new EsignException("传orgIDCardNum时,psnIDCardType参数为必传");
  255. } else {
  256. throw new EsignException("orgId与orgName与orgIDCardNum不能都为空");
  257. }
  258. }
  259. URIBuilder uriBuilder = new URIBuilder(apiaddr);
  260. if (StringUtils.isNotBlank(psnId)) {
  261. uriBuilder.addParameter("psnId", psnId);
  262. }
  263. if (StringUtils.isNotBlank(psnAccount)) {
  264. uriBuilder.addParameter("psnAccount", psnAccount);
  265. }
  266. if (StringUtils.isNotBlank(psnIDCardNum) && StringUtils.isNotBlank(psnIDCardType)) {
  267. uriBuilder.addParameter("psnIDCardNum", psnIDCardNum);
  268. uriBuilder.addParameter("psnIDCardType", psnIDCardType);
  269. }
  270. URI uri = uriBuilder.build(); // 自动编码
  271. apiaddr = uri.toString();
  272. return GET(ctx, apiaddr, null, sourceId, configEnum);
  273. }
  274. public static EsignHttpResponse getPersonIdentity_infoByPsnId(Context ctx, String psnId) throws EsignException, URISyntaxException {
  275. return getPersonIdentity_info(ctx, psnId, null, null, null, null);
  276. }
  277. public static EsignHttpResponse getPersonIdentity_infoByPsnAccount(Context ctx, String psnAccount) throws EsignException, URISyntaxException {
  278. return getPersonIdentity_info(ctx, null, psnAccount, null, null, null);
  279. }
  280. public static EsignHttpResponse getPersonIdentity_infoByOrgIDCardNum(Context ctx, String psnIDCardNum, String psnIDCardType) throws EsignException, URISyntaxException {
  281. return getPersonIdentity_info(ctx, null, null, psnIDCardNum, psnIDCardType, null);
  282. }
  283. /**
  284. * 查询签署流程详情
  285. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/xxk4q6
  286. * 接口地址:https://{host}/v3/sign-flow/{signFlowId}/detail
  287. * 请求方法:GET
  288. * 注意事项:
  289. *
  290. * @param signFlowId 签署流程ID
  291. * @param sourceId 来源id
  292. * @return
  293. */
  294. public static EsignHttpResponse getSign_fields(Context ctx, String signFlowId, String sourceId) throws EsignException {
  295. EsignConfigEnum configEnum = EsignConfigEnum.detail_sign_fields;
  296. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  297. apiaddr = MessageFormat.format(apiaddr, signFlowId);
  298. return GET(ctx, apiaddr, null, sourceId, configEnum);
  299. }
  300. public static EsignHttpResponse getSign_fields(Context ctx, String signFlowId) throws EsignException {
  301. return getSign_fields(ctx, signFlowId, null);
  302. }
  303. /**
  304. * 追加签署区
  305. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/ohzup7
  306. * 接口地址:https://{host}/v3/sign-flow/{signFlowId}/signers/sign-fields
  307. * 请求方法:POST
  308. * 注意事项:在追加一个签署区时,请确保流程在开启之前已添加了该签署区所在的待签署文件,参考【追加待签文件】;
  309. * 流程在“草稿”和“签署中”状态时,允许向流程中再追加签署区;
  310. * 【基于文件发起签署】时设置了自动完结(autoFinish为 true)的流程不支持再添加签署区。
  311. *
  312. * @param signFlowId 签署流程ID
  313. * @param json 添加签署方信息
  314. * @param sourceId 来源id
  315. * @return
  316. */
  317. public static EsignHttpResponse addSign_fields(Context ctx, String signFlowId, String json, String sourceId) throws EsignException {
  318. EsignConfigEnum configEnum = EsignConfigEnum.add_sign_fields;
  319. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  320. apiaddr = MessageFormat.format(apiaddr, signFlowId);
  321. return POST(ctx, apiaddr, json, sourceId, configEnum);
  322. }
  323. /**
  324. * 删除签署区
  325. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/ohzup7
  326. * 接口地址:https://{host}/v3/sign-flow/{signFlowId}/signers/sign-fields
  327. * 请求方法:POST
  328. * 注意事项:在追加一个签署区时,请确保流程在开启之前已添加了该签署区所在的待签署文件,参考【追加待签文件】;
  329. * 流程在“草稿”和“签署中”状态时,允许向流程中再追加签署区;
  330. * 【基于文件发起签署】时设置了自动完结(autoFinish为 true)的流程不支持再添加签署区。
  331. *
  332. * @param signFlowId 签署流程ID
  333. * @param signFieldIds 添加签署方信息
  334. * @param sourceId 来源id
  335. * @return
  336. */
  337. public static EsignHttpResponse delSign_fields(Context ctx, String signFlowId, String signFieldIds, String sourceId) throws EsignException, URISyntaxException {
  338. EsignConfigEnum configEnum = EsignConfigEnum.del_sign_fields;
  339. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  340. apiaddr = MessageFormat.format(apiaddr, signFlowId);
  341. URIBuilder uriBuilder = new URIBuilder(apiaddr);
  342. if (StringUtils.isNotBlank(signFieldIds)) {
  343. uriBuilder.addParameter("signFieldIds", signFieldIds);
  344. }
  345. URI uri = uriBuilder.build(); // 自动编码
  346. apiaddr = uri.toString();
  347. return DELETE(ctx, apiaddr, null, sourceId, configEnum);
  348. }
  349. /**
  350. * 添加抄送方信息
  351. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/ohzup7
  352. * 接口地址:https://{host}/v3/sign-flow/{signFlowId}/signers/sign-fields
  353. * 请求方法:POST
  354. * 注意事项:
  355. * “抄送方”的概念:
  356. * 指不参与签署文件的机构或个人,可以进行查看签署流程中的签署文件以及附属材料等信息,当流程中的签署方全部完成签署,抄送方也会收到签署完成的通知。
  357. * 接口注意事项:
  358. * 自动完结的流程(autoFinish设置为true)不支持添加抄送方,否则将会报错:“自动归档流程开启后,不允许添加签署区”。
  359. * 添加的抄送方不可与流程中已有的抄送方重复。。
  360. *
  361. * @param signFlowId 签署流程ID
  362. * @param json 添加抄送方信息
  363. * @param sourceId 来源id
  364. * @return
  365. */
  366. public static EsignHttpResponse addCopiers(Context ctx, String signFlowId, String json, String sourceId) throws EsignException {
  367. EsignConfigEnum configEnum = EsignConfigEnum.add_copiers;
  368. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  369. apiaddr = MessageFormat.format(apiaddr, signFlowId);
  370. return POST(ctx, apiaddr, json, sourceId, configEnum);
  371. }
  372. /**
  373. * 删除抄送方信息
  374. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/bdn9yt
  375. * 接口地址:https://{host}/v3/sign-flow/{signFlowId}/copiers/delete
  376. * <p>
  377. * 请求方法:POST
  378. * 注意事项:流程若已开启,将不支持再删除抄送方信息。
  379. *
  380. * @param signFlowId 签署流程ID
  381. * @param json 删除抄送方信息
  382. * @param sourceId 来源id
  383. * @return
  384. */
  385. public static EsignHttpResponse delCopiers(Context ctx, String signFlowId, String json, String sourceId) throws EsignException {
  386. EsignConfigEnum configEnum = EsignConfigEnum.del_copiers;
  387. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  388. apiaddr = MessageFormat.format(apiaddr, signFlowId);
  389. return POST(ctx, apiaddr, json, sourceId, configEnum);
  390. }
  391. /**
  392. * 基于文件发起签署
  393. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/su5g42
  394. * 接口地址:https://{host}/v3/sign-flow/create-by-file
  395. * 请求方法:POST
  396. * 注意事项:
  397. * 1. 单个签署流程中对签署文件(docs)要求如下:
  398. * 单个签署流程中所添加的文件个数不可超过50个。
  399. * 单个文件大小不可超过50MB。
  400. * 单个文件内单页大小不可超过20MB(文件内含图片时,需特别关注单页大小)。
  401. * 单个签署流程中所添加的文件大小总和不可超过500MB。
  402. * 2. 单个签署流程中一次性添加的签署方(signers)不要超过10个,如果超过10个后续可以用《追加签署区》接口追加,整个流程不能超过50个签署方。
  403. * 3. 单个签署流程中所添加的签署区(signFields)总和不要超过300个。
  404. * 4. 单个签署流程中对附属材料(attachments)要求如下:
  405. * 单个签署流程中所添加的附件个数不可超过50个。
  406. * 单个附件大小不可超过10MB。
  407. * 5. autoStart自动开启签署流程,默认值 true
  408. * true - 自动开启(发起签署流程,将直接进入“签署中”状态)
  409. * false - 非自动开启(发起“草稿”状态的签署流程,需调用【开启签署流程】接口后流程进入“签署中”状态)
  410. * 补充说明: 自动开启的流程不允许再追加待签署文件,点击这里了解更多流程状态说明。
  411. *
  412. * @param ctx 上下文
  413. * @param personId 签署员工id
  414. * @param fileName 签署文件名称
  415. * @param operatorId 操作人
  416. * @param efileId 发起单据id
  417. * @param json 签署信息
  418. * @return
  419. */
  420. public static EsignHttpResponse create_by_file(Context ctx, String personId, String fileName, String operatorId, String efileId,
  421. String json) throws BOSException {
  422. EsignHttpResponse resp = create_by_file(ctx, personId, fileName, operatorId, efileId, EsignStatusEnum.SIGNING, json);
  423. return resp;
  424. }
  425. public static EsignHttpResponse create_by_file(Context ctx, String personId, String fileName, String operatorId, String efileId,
  426. EsignStatusEnum esignStatus,
  427. String json) throws BOSException {
  428. EsignConfigEnum configEnum = EsignConfigEnum.create_by_file;
  429. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  430. EsignHttpResponse resp = new EsignHttpResponse();
  431. resp.setStatus(500);
  432. /**
  433. * 发起签署前需要新增电子签全域状态总览表
  434. */
  435. IESignGlobalStatusOverview globalStatusOverview = ESignGlobalStatusOverviewFactory.getLocalInstance(ctx);
  436. ESignGlobalStatusOverviewInfo info = new ESignGlobalStatusOverviewInfo();
  437. // try {
  438. // String str = "select fid from CT_ESI_ESGSO where cfefileId=?";
  439. // IRowSet rs = DbUtil.executeQuery(ctx, str, new Object[]{efileId});
  440. // if (rs.next()) {
  441. // String fid = rs.getString("fid");
  442. // info = globalStatusOverview.getESignGlobalStatusOverviewInfo(new ObjectUuidPK(fid));
  443. // }
  444. // } catch (SQLException | EASBizException e) {
  445. // e.printStackTrace();
  446. // }
  447. info.setEsignStatus(EsignStatusEnum.DRAFT);
  448. info.setSendStatus(SendStatusEnum.FAILURE);
  449. if (StringUtils.isNotBlank(personId)) {
  450. PersonInfo personInfo = new PersonInfo();
  451. personInfo.setId(BOSUuid.read(personId));
  452. info.setPerson(personInfo);
  453. }
  454. if (StringUtils.isNotBlank(operatorId)) {
  455. PersonInfo operator = new PersonInfo();
  456. operator.setId(BOSUuid.read(operatorId));
  457. info.setOperator(operator);
  458. }
  459. info.setFileName(fileName);
  460. info.setEfileId(efileId);
  461. info.setRequestParams(json);
  462. info.setEsignName(configEnum);
  463. try {
  464. resp = POST(ctx, apiaddr, json, efileId, configEnum);
  465. if (resp.getStatus() >= 200 && resp.getStatus() < 300) {
  466. JSONObject object = JSON.parseObject(resp.getBody());
  467. if ("0".equals(String.valueOf(object.get("code")))) {
  468. JSONObject data = object.getJSONObject("data");
  469. info.setSignFlowId(data.getString("signFlowId"));
  470. info.setSendStatus(SendStatusEnum.SUCCESS);
  471. info.setEsignStatus(esignStatus);
  472. }
  473. }
  474. info.setSourceBillId(resp.getLogId());
  475. } catch (Exception e) {
  476. e.printStackTrace();
  477. info.setSendStatus(SendStatusEnum.FAILURE);
  478. } finally {
  479. try {
  480. globalStatusOverview.save(info);
  481. } catch (Exception e) {
  482. e.printStackTrace();
  483. }
  484. }
  485. return resp;
  486. }
  487. /**
  488. * 开启签署流程
  489. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/bdn9yt
  490. * 接口地址:https://{host}/v3/sign-flow/{signFlowId}/start
  491. * <p>
  492. * 请求方法:POST
  493. * 注意事项:流程若已开启,将不支持再删除抄送方信息。
  494. *
  495. * @param signFlowId 签署流程ID
  496. * @param sourceId 来源id
  497. * @return
  498. */
  499. public static EsignHttpResponse start_by_file(Context ctx, String signFlowId, String sourceId) throws EsignException {
  500. EsignConfigEnum configEnum = EsignConfigEnum.start_by_file;
  501. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  502. apiaddr = MessageFormat.format(apiaddr, signFlowId);
  503. return POST(ctx, apiaddr, null, sourceId, configEnum);
  504. }
  505. /**
  506. * 撤销签署流程
  507. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/klbicu
  508. * 接口地址:https://{host}/v3/sign-flow/{signFlowId}/revoke
  509. * <p>
  510. * 请求方法:POST
  511. * 注意事项:撤销签署中的流程,撤销后签署流程将终止,变为已撤销状态。
  512. *
  513. * @param signFlowId 签署流程ID
  514. * @param revokeReason 撤销原因 撤销原因最多50字
  515. * @param sourceId 来源id
  516. * @return
  517. */
  518. public static EsignHttpResponse revoke_by_file(Context ctx, String signFlowId, String revokeReason, String sourceId) throws EsignException {
  519. EsignConfigEnum configEnum = EsignConfigEnum.revoke_by_file;
  520. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  521. apiaddr = MessageFormat.format(apiaddr, signFlowId);
  522. Map<String, String> jsonMap = Maps.newHashMap();
  523. jsonMap.put("revokeReason", (StringUtils.isNotBlank(revokeReason) ? revokeReason : ""));
  524. String json = JSON.toJSONString(jsonMap);
  525. return POST(ctx, apiaddr, json, sourceId, configEnum);
  526. }
  527. /**
  528. * 催签流程中签署人
  529. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/yws940
  530. * 接口地址:https://{host}/v3/sign-flow/{signFlowId}/urge
  531. * 请求方法:POST
  532. * 【注意事项】
  533. * 发起签署之后的前半小时不可进行催签;
  534. * 与上一次催签,请至少间隔十分钟再发起下一次催签提醒。
  535. *
  536. * @param signFlowId 签署流程ID
  537. * @param json 催签的签署人信息
  538. * @param sourceId 来源id
  539. * @return
  540. */
  541. public static EsignHttpResponse urge_by_file(Context ctx, String signFlowId, String json, String sourceId) throws EsignException {
  542. EsignConfigEnum configEnum = EsignConfigEnum.urge_by_file;
  543. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  544. apiaddr = MessageFormat.format(apiaddr, signFlowId);
  545. return POST(ctx, apiaddr, json, sourceId, configEnum);
  546. }
  547. /**
  548. * 下载已签署文件及附属材料
  549. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/kczf8g
  550. * 接口地址:https://{host}/v3/sign-flow/{signFlowId}/file-download-url
  551. * 请求方法:GET
  552. * 【注意事项】
  553. * 未签署完成的流程,无法下载相关文件,否则会报错:"流程非签署完成状态,不允许下载文档"。
  554. *
  555. * @param signFlowId 签署流程ID
  556. * @param urlAvailableDate 下载链接有效期,单位:秒。默认:3600秒(60分钟)
  557. * 可传入:1-3600
  558. * 补充说明:
  559. * 为链接设置有效期是一项安全措施,旨在降低因无关人员访问而导致的信息泄露风险。
  560. * @param sourceId 来源id
  561. * @return
  562. */
  563. public static EsignHttpResponse getFile_download_url(Context ctx, String signFlowId, Integer urlAvailableDate, String sourceId) throws EsignException, URISyntaxException {
  564. EsignConfigEnum configEnum = EsignConfigEnum.file_download_url;
  565. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  566. apiaddr = MessageFormat.format(apiaddr, signFlowId);
  567. if (null != urlAvailableDate && urlAvailableDate > 0 && urlAvailableDate <= 3600) {
  568. URIBuilder uriBuilder = new URIBuilder(apiaddr);
  569. uriBuilder.addParameter("urlAvailableDate", String.valueOf(urlAvailableDate));
  570. URI uri = uriBuilder.build(); // 自动编码
  571. apiaddr = uri.toString();
  572. }
  573. return GET(ctx, apiaddr, null, sourceId, configEnum);
  574. }
  575. /**
  576. * 下载签署中文件
  577. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/gkgc4729sa67upfn
  578. * 接口地址:https://{host}/v3/sign-flow/{signFlowId}/preview-file-download-url
  579. * 请求方法:GET
  580. * 【注意事项】
  581. * 通过该接口可以下载流程正在签署中的文件进行预览查看,用于开发者内部系统展示合同内容。本接口下载的文件因为是过程中文件所以不支持验签和出证,并且文件中会带有“本文档仅供预览查看”的水印字样。
  582. *
  583. * @param signFlowId 签署流程ID
  584. * @param docFileId 本次签署流程中的文件ID【注】仅支持签署文件,不支持附件
  585. * 可传入:1-3600
  586. * 补充说明:
  587. * 为链接设置有效期是一项安全措施,旨在降低因无关人员访问而导致的信息泄露风险。
  588. * @param sourceId 来源id
  589. * @return
  590. */
  591. public static EsignHttpResponse getPreview_file_download_url(Context ctx, String signFlowId, String docFileId, String sourceId) throws EsignException, URISyntaxException {
  592. EsignConfigEnum configEnum = EsignConfigEnum.preview_file_download_url;
  593. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  594. apiaddr = MessageFormat.format(apiaddr, signFlowId);
  595. URIBuilder uriBuilder = new URIBuilder(apiaddr);
  596. uriBuilder.addParameter("docFileId", docFileId);
  597. URI uri = uriBuilder.build(); // 自动编码
  598. apiaddr = uri.toString();
  599. return GET(ctx, apiaddr, null, sourceId, configEnum);
  600. }
  601. /**
  602. * 查询企业内部印章
  603. * 参考文档:https://open.esign.cn/doc/opendoc/seal3/ups6h1
  604. * 接口地址:https://{host}/v3/seals/org-own-seal-list?orgId=xx&pageNum=1&pageSize=20
  605. * 请求方法:GET
  606. * 【注意事项】
  607. * 查询 orgId (机构企业)名下自身创建的内部自有企业印章,包括印章的编号、名称、状态、印章业务类型、印章图片下载地址等信息。
  608. *
  609. * @param orgId 机构账号ID 【注】用户在e签宝注册实名后才有账号ID,账号ID获取方式请使用【查询机构认证信息】接口通过组织机构名称/组织机构证件号进行查询
  610. * @param pageNum 查询页码
  611. * @param pageSize 每页显示的数量,最大值:20
  612. * @param sealBizTypes 印章业务类型(多项可使用英文逗号分隔)
  613. * PUBLIC - 公章
  614. * CONTRACT - 合同专用章
  615. * FINANCE - 财务专用章
  616. * PERSONNEL - 人事专用章
  617. * LEGAL_PERSON - 法定代表人章
  618. * OMMON - 其他
  619. * @param revocationSeal 是否需要查询已吊销印章,默认不查询 【注】曾经有用印记录的印章删除后即为已吊销状态
  620. * false - 不查询已吊销印章
  621. * ture - 查询已吊销印章
  622. * @param sourceId 来源id
  623. * @return
  624. */
  625. public static EsignHttpResponse getOrg_own_seal_list(Context ctx, String orgId,
  626. Integer pageNum, Integer pageSize,
  627. String sealBizTypes, Boolean revocationSeal,
  628. String sourceId
  629. ) throws EsignException, URISyntaxException {
  630. EsignConfigEnum configEnum = EsignConfigEnum.org_own_seal_list;
  631. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  632. URIBuilder uriBuilder = new URIBuilder(apiaddr);
  633. uriBuilder.addParameter("orgId", orgId);
  634. if(pageNum<0) {
  635. uriBuilder.addParameter("pageNum", String.valueOf(1));
  636. }else {
  637. uriBuilder.addParameter("pageNum", String.valueOf(pageNum));
  638. }
  639. if(pageSize<=0) {
  640. uriBuilder.addParameter("pageSize", String.valueOf(1));
  641. }else if(pageSize>20){
  642. uriBuilder.addParameter("pageSize", String.valueOf(20));
  643. }else {
  644. uriBuilder.addParameter("pageSize", String.valueOf(pageSize));
  645. }
  646. if(StringUtils.isNotBlank(sealBizTypes)){
  647. uriBuilder.addParameter("sealBizTypes", sealBizTypes);
  648. }
  649. if(null!=revocationSeal){
  650. uriBuilder.addParameter("revocationSeal", revocationSeal.toString());
  651. }
  652. URI uri = uriBuilder.build(); // 自动编码
  653. apiaddr = uri.toString();
  654. return GET(ctx, apiaddr, null, sourceId, configEnum);
  655. }
  656. /**
  657. * 查询文件上传状态
  658. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/qz4aip
  659. * 接口地址:https://{host}/v3/files/{fileId}
  660. * @param ctx
  661. * @param fileId
  662. * @param sourceId
  663. * 请求方法:GET
  664. */
  665. public static EsignHttpResponse getFileStatus(Context ctx,String fileId, String sourceId) throws EsignException {
  666. EsignConfigEnum configEnum = EsignConfigEnum.getFilesState;
  667. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  668. apiaddr = MessageFormat.format(apiaddr, fileId);
  669. //发起接口请求
  670. return GET(ctx, apiaddr, null, sourceId, configEnum);
  671. }
  672. /**
  673. * 检索文件关键字坐标
  674. * 参考文档:https://open.esign.cn/doc/opendoc/pdf-sign3/ze0ahv
  675. * 接口地址:https://{host}/v3/files/{fileId}/keyword-positions
  676. * @param ctx
  677. * @param fileId
  678. * @param keywords
  679. * @param sourceId
  680. * 请求方法:GET
  681. */
  682. public static EsignHttpResponse keyword_positions(Context ctx,String fileId, List<String> keywords, String sourceId) throws EsignException {
  683. EsignConfigEnum configEnum = EsignConfigEnum.keyword_positions;
  684. String apiaddr = EsignConfig.getInstance().get(configEnum.getValue());
  685. apiaddr = MessageFormat.format(apiaddr, fileId);
  686. Map<String,List<String>> jsonMap = Maps.newHashMap();
  687. jsonMap.put("keywords",keywords);
  688. String json = JSON.toJSONString(jsonMap);
  689. //发起接口请求
  690. return POST(ctx, apiaddr, json, sourceId, configEnum);
  691. }
  692. }