实现用印签名功能
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
package com.ruoyi.wisdomarbitrate.domain;
|
||||
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
||||
public class SealSignRecord extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** ID */
|
||||
private Long id;
|
||||
/** 文件id */
|
||||
private String fileid;
|
||||
/** 文件名称 */
|
||||
private String filename;
|
||||
/** 流程id */
|
||||
private String signFlowid;
|
||||
/** 签名人账户 */
|
||||
private String pensonAccount;
|
||||
/** 签名人姓名 */
|
||||
private String pensonName;
|
||||
/** 机构名称 */
|
||||
private String orgnizeName;
|
||||
/** 机构经办人 */
|
||||
private String orgnizeNamePsnAccount;
|
||||
/** 机构经办人名称 */
|
||||
private String orgnizeNamepsnName;
|
||||
|
||||
public String getFileid() {
|
||||
return fileid;
|
||||
}
|
||||
|
||||
public void setFileid(String fileid) {
|
||||
this.fileid = fileid;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public String getSignFlowid() {
|
||||
return signFlowid;
|
||||
}
|
||||
|
||||
public void setSignFlowid(String signFlowid) {
|
||||
this.signFlowid = signFlowid;
|
||||
}
|
||||
|
||||
public String getPensonAccount() {
|
||||
return pensonAccount;
|
||||
}
|
||||
|
||||
public void setPensonAccount(String pensonAccount) {
|
||||
this.pensonAccount = pensonAccount;
|
||||
}
|
||||
|
||||
public String getPensonName() {
|
||||
return pensonName;
|
||||
}
|
||||
|
||||
public void setPensonName(String pensonName) {
|
||||
this.pensonName = pensonName;
|
||||
}
|
||||
|
||||
public String getOrgnizeName() {
|
||||
return orgnizeName;
|
||||
}
|
||||
|
||||
public void setOrgnizeName(String orgnizeName) {
|
||||
this.orgnizeName = orgnizeName;
|
||||
}
|
||||
|
||||
public String getOrgnizeNamePsnAccount() {
|
||||
return orgnizeNamePsnAccount;
|
||||
}
|
||||
|
||||
public void setOrgnizeNamePsnAccount(String orgnizeNamePsnAccount) {
|
||||
this.orgnizeNamePsnAccount = orgnizeNamePsnAccount;
|
||||
}
|
||||
|
||||
public String getOrgnizeNamepsnName() {
|
||||
return orgnizeNamepsnName;
|
||||
}
|
||||
|
||||
public void setOrgnizeNamepsnName(String orgnizeNamepsnName) {
|
||||
this.orgnizeNamepsnName = orgnizeNamepsnName;
|
||||
}
|
||||
|
||||
public String getPositionPagepsn() {
|
||||
return positionPagepsn;
|
||||
}
|
||||
|
||||
public void setPositionPagepsn(String positionPagepsn) {
|
||||
this.positionPagepsn = positionPagepsn;
|
||||
}
|
||||
|
||||
public double getPositionXpsn() {
|
||||
return positionXpsn;
|
||||
}
|
||||
|
||||
public void setPositionXpsn(double positionXpsn) {
|
||||
this.positionXpsn = positionXpsn;
|
||||
}
|
||||
|
||||
public double getPositionYpsn() {
|
||||
return positionYpsn;
|
||||
}
|
||||
|
||||
public void setPositionYpsn(double positionYpsn) {
|
||||
this.positionYpsn = positionYpsn;
|
||||
}
|
||||
|
||||
public String getPositionPageorg() {
|
||||
return positionPageorg;
|
||||
}
|
||||
|
||||
public void setPositionPageorg(String positionPageorg) {
|
||||
this.positionPageorg = positionPageorg;
|
||||
}
|
||||
|
||||
public double getPositionXorg() {
|
||||
return positionXorg;
|
||||
}
|
||||
|
||||
public void setPositionXorg(double positionXorg) {
|
||||
this.positionXorg = positionXorg;
|
||||
}
|
||||
|
||||
public double getPositionYorg() {
|
||||
return positionYorg;
|
||||
}
|
||||
|
||||
public void setPositionYorg(double positionYorg) {
|
||||
this.positionYorg = positionYorg;
|
||||
}
|
||||
|
||||
/** 签名位置页数 */
|
||||
private String positionPagepsn;
|
||||
/** 签名位置x坐标 */
|
||||
private double positionXpsn;
|
||||
/** 签名位置y坐标 */
|
||||
private double positionYpsn;
|
||||
/** 印章位置页数 */
|
||||
private String positionPageorg;
|
||||
/** 印章位置x坐标 */
|
||||
private double positionXorg;
|
||||
/** 印章位置y坐标 */
|
||||
private double positionYorg;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
|
||||
public class EsignApplicaConfig {
|
||||
|
||||
// 应用ID
|
||||
public static final String EsignAppId = "7438987614";
|
||||
// 应用密钥
|
||||
public static final String EsignAppSecret = "9d7844f13830931037772b9d20cf1529";
|
||||
// e签宝接口调用域名(模拟环境)
|
||||
public static final String EsignHost = "https://smlopenapi.esign.cn";
|
||||
// e签宝接口调用域名(正式环境)
|
||||
// public static final String EsignHost = "https://openapi.esign.cn";
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
/**
|
||||
* esignSDK-core信息类
|
||||
* @author 澄泓
|
||||
* @date 2022/2/22 13:59
|
||||
* @version
|
||||
*/
|
||||
public class EsignCoreSdkInfo {
|
||||
private static final String SdkVersion="Esign-Sdk-Core1.0";
|
||||
private static final String SupportedVersion="JDK1.7 MORE THAN";
|
||||
|
||||
private static final String Info="sdk-esign-api核心工具包,主要处理e签宝公有云产品接口调用时的签名计算以及网络请求,通过EsignHttpHelper.signAndBuildSignAndJsonHeader构造签名鉴权+json数据格式的请求头,通过HttpHelper.doCommHttp方法入参发起网络请求。让开发者无需关注具体的请求签名算法,专注于接口业务的json参数构造";
|
||||
public static String getSdkVersion() {
|
||||
return SdkVersion;
|
||||
}
|
||||
|
||||
public static String getInfo() {
|
||||
return Info;
|
||||
}
|
||||
|
||||
public static String getSupportedVersion() {
|
||||
return SupportedVersion;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.Collator;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @description 请求数据通用处理类
|
||||
*/
|
||||
public class EsignEncryption {
|
||||
|
||||
/**
|
||||
* 不允许外部创建实例
|
||||
*/
|
||||
private EsignEncryption(){}
|
||||
|
||||
/**
|
||||
* 拼接待签名字符串
|
||||
* @param httpMethod
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static String appendSignDataString(String httpMethod, String contentMd5,String accept,String contentType,String headers,String date, String url) throws EsignInterfacException {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(httpMethod).append("\n").append(accept).append("\n").append(contentMd5).append("\n")
|
||||
.append(contentType).append("\n");
|
||||
|
||||
if ("".equals(date) || date == null) {
|
||||
sb.append("\n");
|
||||
} else {
|
||||
sb.append(date).append("\n");
|
||||
}
|
||||
if ("".equals(headers) || headers == null) {
|
||||
sb.append(url);
|
||||
} else {
|
||||
sb.append(headers).append("\n").append(url);
|
||||
}
|
||||
return new String(sb);
|
||||
}
|
||||
|
||||
/***
|
||||
* Content-MD5的计算方法
|
||||
* @param str 待计算的消息
|
||||
* @return MD5计算后摘要值的Base64编码(ContentMD5)
|
||||
* @throws EsignInterfacException 加密过程中的异常信息
|
||||
*/
|
||||
public static String doContentMD5(String str) throws EsignInterfacException {
|
||||
byte[] md5Bytes = null;
|
||||
MessageDigest md5 = null;
|
||||
String contentMD5 = null;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
// 计算md5函数
|
||||
md5.update(str.getBytes("UTF-8"));
|
||||
// 获取文件MD5的二进制数组(128位)
|
||||
md5Bytes = md5.digest();
|
||||
// 把MD5摘要后的二进制数组md5Bytes使用Base64进行编码(而不是对32位的16进制字符串进行编码)
|
||||
contentMD5 = Base64.encodeBase64String(md5Bytes);
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("不支持此算法",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return contentMD5;
|
||||
}
|
||||
|
||||
/***
|
||||
* 计算请求签名值-HmacSHA256摘要
|
||||
* @param message 待签名字符串
|
||||
* @param secret 密钥APP KEY
|
||||
* @return reqSignature HmacSHA256计算后摘要值的Base64编码
|
||||
* @throws EsignInterfacException 加密过程中的异常信息
|
||||
*/
|
||||
public static String doSignatureBase64(String message, String secret) throws EsignInterfacException {
|
||||
String algorithm = "HmacSHA256";
|
||||
Mac hmacSha256;
|
||||
String digestBase64 = null;
|
||||
try {
|
||||
hmacSha256 = Mac.getInstance(algorithm);
|
||||
byte[] keyBytes = secret.getBytes("UTF-8");
|
||||
byte[] messageBytes = message.getBytes("UTF-8");
|
||||
hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm));
|
||||
// 使用HmacSHA256对二进制数据消息Bytes计算摘要
|
||||
byte[] digestBytes = hmacSha256.doFinal(messageBytes);
|
||||
// 把摘要后的结果digestBytes使用Base64进行编码
|
||||
digestBase64 = Base64.encodeBase64String(digestBytes);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("不支持此算法",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch (InvalidKeyException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("无效的密钥规范",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return digestBase64;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取时间戳
|
||||
* @return
|
||||
*/
|
||||
public static String timeStamp() {
|
||||
long timeStamp = System.currentTimeMillis();
|
||||
return String.valueOf(timeStamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* byte字节数组转换成字符串
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
public static String byteArrayToHexString(byte[] b) {
|
||||
StringBuilder hs = new StringBuilder();
|
||||
String stmp;
|
||||
for (int n = 0; b != null && n < b.length; n++) {
|
||||
stmp = Integer.toHexString(b[n] & 0XFF);
|
||||
if (stmp.length() == 1)
|
||||
hs.append('0');
|
||||
hs.append(stmp);
|
||||
}
|
||||
return hs.toString().toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* hash散列加密算法
|
||||
* @return
|
||||
*/
|
||||
public static String Hmac_SHA256(String message,String key) throws EsignInterfacException {
|
||||
byte[] rawHmac=null;
|
||||
try {
|
||||
SecretKeySpec sk = new SecretKeySpec(key.getBytes(), "HmacSHA256");
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(sk);
|
||||
rawHmac = mac.doFinal(message.getBytes());
|
||||
}catch (InvalidKeyException e){
|
||||
EsignInterfacException ex = new EsignInterfacException("无效的密钥规范",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("不支持此算法",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
}catch (Exception e){
|
||||
EsignInterfacException ex = new EsignInterfacException("hash散列加密算法报错",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
}finally {
|
||||
return byteArrayToHexString(rawHmac);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* MD5加密32位
|
||||
*/
|
||||
public static String MD5Digest(String text) throws EsignInterfacException {
|
||||
byte[] digest=null;
|
||||
try {
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
md5.update(text.getBytes());
|
||||
digest = md5.digest();
|
||||
}catch (NoSuchAlgorithmException e){
|
||||
EsignInterfacException ex = new EsignInterfacException("不支持此算法",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
}finally {
|
||||
return byteArrayToHexString(digest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void formDataSort(List<BasicNameValuePair> param) {
|
||||
Collections.sort(param, new Comparator<BasicNameValuePair>() {
|
||||
@Override
|
||||
public int compare(BasicNameValuePair o1, BasicNameValuePair o2) {
|
||||
Comparator<Object> com = Collator.getInstance(Locale.CHINA);
|
||||
return com.compare(o1.getName(), o2.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/***
|
||||
* 字符串是否为空(含空格校验)
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static boolean isBlank(String str) {
|
||||
if (null == str || 0 == str.length()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int strLen = str.length();
|
||||
|
||||
for (int i = 0; i < strLen; i++) {
|
||||
if (!Character.isWhitespace(str.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* 对请求URL中的Query参数按照字段名的 ASCII 码从小到大排序(字典排序)
|
||||
*
|
||||
* @param apiUrl
|
||||
* @return 排序后的API接口地址
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String sortApiUrl(String apiUrl) throws EsignInterfacException {
|
||||
|
||||
if (!apiUrl.contains("?")) {
|
||||
return apiUrl;
|
||||
}
|
||||
|
||||
int queryIndex = apiUrl.indexOf("?");
|
||||
String apiUrlPath =apiUrl.substring(0,queryIndex+1);
|
||||
String apiUrlQuery = apiUrl.substring(queryIndex+1);
|
||||
//apiUrlQuery为空时返回
|
||||
if(isBlank(apiUrlQuery)){
|
||||
return apiUrl.substring(0,apiUrl.length()-1);
|
||||
}
|
||||
// 请求URL中Query参数转成Map
|
||||
Map<Object, Object> queryParamsMap = new HashMap<Object, Object>();
|
||||
String[] params = apiUrlQuery.split("&");
|
||||
for (String str : params) {
|
||||
int index = str.indexOf("=");
|
||||
String key = str.substring(0, index);
|
||||
String value = str.substring(index + 1);
|
||||
if (queryParamsMap.containsKey(key)) {
|
||||
String msg = MessageFormat.format("请求URL中的Query参数的{0}重复", key);
|
||||
throw new EsignInterfacException(msg);
|
||||
}
|
||||
queryParamsMap.put(key, value);
|
||||
}
|
||||
|
||||
ArrayList<String> queryMapKeys = new ArrayList<String>();
|
||||
for (Map.Entry<Object, Object> entry : queryParamsMap.entrySet()) {
|
||||
queryMapKeys.add((String) entry.getKey());
|
||||
}
|
||||
// 按照字段名的 ASCII 码从小到大排序(字典排序)
|
||||
Collections.sort(queryMapKeys, new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
return (o1.compareToIgnoreCase(o2) == 0 ? -o1.compareTo(o2) : o1.compareToIgnoreCase(o2));
|
||||
}
|
||||
});
|
||||
|
||||
StringBuffer queryString = new StringBuffer();
|
||||
// 构造Query参数键值对值对的格式
|
||||
for (int i = 0; i < queryMapKeys.size(); i++) {
|
||||
String key = queryMapKeys.get(i);
|
||||
String value = (String) queryParamsMap.get(key);
|
||||
queryString.append(key);
|
||||
queryString.append("=");
|
||||
queryString.append(value);
|
||||
queryString.append("&");
|
||||
}
|
||||
if (queryString.length() > 0) {
|
||||
queryString = queryString.deleteCharAt(queryString.length() - 1);
|
||||
}
|
||||
|
||||
// Query参数排序后的接口请求地址
|
||||
StringBuffer sortApiUrl = new StringBuffer();
|
||||
sortApiUrl.append(apiUrlPath);
|
||||
sortApiUrl.append(queryString.toString());
|
||||
return sortApiUrl.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*获取query
|
||||
* @param apiUrl
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
*/
|
||||
public static ArrayList<BasicNameValuePair> getQuery(String apiUrl) throws EsignInterfacException {
|
||||
ArrayList<BasicNameValuePair> BasicNameValuePairList = new ArrayList<>();
|
||||
|
||||
if (!apiUrl.contains("?")) {
|
||||
return BasicNameValuePairList;
|
||||
}
|
||||
|
||||
int queryIndex = apiUrl.indexOf("\\?");
|
||||
String apiUrlQuery = apiUrl.substring(queryIndex,apiUrl.length());
|
||||
|
||||
// 请求URL中Query参数转成Map
|
||||
Map<Object, Object> queryParamsMap = new HashMap<Object, Object>();
|
||||
String[] params = apiUrlQuery.split("&");
|
||||
for (String str : params) {
|
||||
int index = str.indexOf("=");
|
||||
String key = str.substring(0, index);
|
||||
String value = str.substring(index + 1);
|
||||
if (queryParamsMap.containsKey(key)) {
|
||||
String msg = MessageFormat.format("请求URL中的Query参数的{0}重复", key);
|
||||
throw new EsignInterfacException(msg);
|
||||
}
|
||||
BasicNameValuePairList.add(new BasicNameValuePair(key,value));
|
||||
queryParamsMap.put(key, value);
|
||||
}
|
||||
return BasicNameValuePairList;
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static boolean callBackCheck(String timestamp,String requestQuery,String body,String key,String signature){
|
||||
String algorithm="HmacSHA256";
|
||||
String encoding="UTF-8";
|
||||
Mac mac = null;
|
||||
try {
|
||||
String data = timestamp + requestQuery + body;
|
||||
mac = Mac.getInstance(algorithm);
|
||||
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(encoding), algorithm);
|
||||
mac.init(secretKey);
|
||||
mac.update(data.getBytes(encoding));
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("获取Signature签名信息异常:" + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
return byte2hex(mac.doFinal()).equalsIgnoreCase(signature);
|
||||
}
|
||||
|
||||
/***
|
||||
* 将byte[]转成16进制字符串
|
||||
*
|
||||
* @param data
|
||||
*
|
||||
* @return 16进制字符串
|
||||
*/
|
||||
public static String byte2hex(byte[] data) {
|
||||
StringBuilder hash = new StringBuilder();
|
||||
String stmp;
|
||||
for (int n = 0; data != null && n < data.length; n++) {
|
||||
stmp = Integer.toHexString(data[n] & 0XFF);
|
||||
if (stmp.length() == 1)
|
||||
hash.append('0');
|
||||
hash.append(stmp);
|
||||
}
|
||||
return hash.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @description 文件基础信息封装类
|
||||
* @author 澄泓
|
||||
* @date 2020/10/26 14:54
|
||||
* @version JDK1.7
|
||||
*/
|
||||
public class EsignFileBean {
|
||||
//文件名称
|
||||
private String fileName;
|
||||
//文件大小
|
||||
private int fileSize;
|
||||
//文件内容MD5
|
||||
private String fileContentMD5;
|
||||
//文件地址
|
||||
private String filePath;
|
||||
|
||||
|
||||
public EsignFileBean(String filePath) throws EsignInterfacException {
|
||||
this.filePath=filePath;
|
||||
this.fileContentMD5 = FileTransformation.getFileContentMD5(filePath);
|
||||
File file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
throw new EsignInterfacException("文件不存在");
|
||||
}
|
||||
this.fileName = file.getName();
|
||||
this.fileSize = (int) file.length();
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public int getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public String getFileContentMD5() {
|
||||
return fileContentMD5;
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入本地文件地址获取二进制数据
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
*/
|
||||
public byte[] getFileBytes() throws EsignInterfacException {
|
||||
return FileTransformation.fileToBytes(filePath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
/**
|
||||
* @description 头部信息常量
|
||||
* @author 澄泓
|
||||
* @date 2020/10/22 15:05
|
||||
* @version JDK1.7
|
||||
*/
|
||||
public enum EsignHeaderConstant {
|
||||
ACCEPT("*/*"),
|
||||
DATE(""),
|
||||
HEADERS( ""),
|
||||
CONTENTTYPE_FORMDATA("application/x-www-form-urlencoded"),
|
||||
CONTENTTYPE_JSON("application/json; charset=UTF-8"),
|
||||
CONTENTTYPE_PDF("application/pdf"),
|
||||
CONTENTTYPE_STREAM("application/octet-stream"),
|
||||
AUTHMODE("Signature");
|
||||
|
||||
private String value;
|
||||
private EsignHeaderConstant(String value) {
|
||||
this.value=value;
|
||||
}
|
||||
|
||||
public String VALUE(){
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
|
||||
import org.apache.http.*;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.CredentialsProvider;
|
||||
import org.apache.http.client.HttpRequestRetryHandler;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.config.Registry;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.ConnectTimeoutException;
|
||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
|
||||
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @description Http请求 辅助类
|
||||
*/
|
||||
public class EsignHttpCfgHelper {
|
||||
|
||||
private static Logger LOGGER = LoggerFactory.getLogger(EsignHttpCfgHelper.class);
|
||||
/**
|
||||
* 超时时间,默认15000毫秒
|
||||
*/
|
||||
private static int MAX_TIMEOUT = 15000;
|
||||
/**
|
||||
* 请求池最大连接数,默认100个
|
||||
*/
|
||||
private static int MAX_TOTAL=100;
|
||||
/**
|
||||
* 单域名最大的连接数,默认50个
|
||||
*/
|
||||
private static int ROUTE_MAX_TOTAL=50;
|
||||
/**
|
||||
* 请求失败重试次数,默认3次
|
||||
*/
|
||||
private static int MAX_RETRY = 3;
|
||||
/**
|
||||
* 是否需要域名校验,默认不需要校验
|
||||
*/
|
||||
private static boolean SSL_VERIFY=false;
|
||||
|
||||
/**
|
||||
* 正向代理IP
|
||||
*/
|
||||
private static String PROXY_IP;
|
||||
/**
|
||||
* 正向代理端口,默认8888
|
||||
*/
|
||||
private static int PROXY_PORT=8888;
|
||||
/**
|
||||
* 代理协议,默认http
|
||||
*/
|
||||
private static String PROXY_AGREEMENT="http";
|
||||
|
||||
/**
|
||||
* 是否开启代理,默认false
|
||||
*/
|
||||
private static boolean OPEN_PROXY=false;
|
||||
|
||||
/**
|
||||
* 代理服务器用户名
|
||||
*/
|
||||
private static String PROXY_USERNAME="";
|
||||
|
||||
/**
|
||||
* 代理服务器密码
|
||||
*/
|
||||
private static String PROXY_PASSWORD="";
|
||||
|
||||
|
||||
private static PoolingHttpClientConnectionManager connMgr; //连接池
|
||||
private static HttpRequestRetryHandler retryHandler; //重试机制
|
||||
|
||||
private static CloseableHttpClient httpClient=null;
|
||||
|
||||
public static int getMaxTimeout() {
|
||||
return MAX_TIMEOUT;
|
||||
}
|
||||
|
||||
public static void setMaxTimeout(int maxTimeout) {
|
||||
MAX_TIMEOUT = maxTimeout;
|
||||
}
|
||||
|
||||
public static int getMaxTotal() {
|
||||
return MAX_TOTAL;
|
||||
}
|
||||
|
||||
public static void setMaxTotal(int maxTotal) {
|
||||
MAX_TOTAL = maxTotal;
|
||||
}
|
||||
|
||||
public static int getRouteMaxTotal() {
|
||||
return ROUTE_MAX_TOTAL;
|
||||
}
|
||||
|
||||
public static void setRouteMaxTotal(int routeMaxTotal) {
|
||||
ROUTE_MAX_TOTAL = routeMaxTotal;
|
||||
}
|
||||
|
||||
public static int getMaxRetry() {
|
||||
return MAX_RETRY;
|
||||
}
|
||||
|
||||
public static void setMaxRetry(int maxRetry) {
|
||||
MAX_RETRY = maxRetry;
|
||||
}
|
||||
|
||||
public static boolean isSslVerify() {
|
||||
return SSL_VERIFY;
|
||||
}
|
||||
|
||||
public static void setSslVerify(boolean sslVerify) {
|
||||
SSL_VERIFY = sslVerify;
|
||||
}
|
||||
|
||||
public static String getProxyIp() {
|
||||
return PROXY_IP;
|
||||
}
|
||||
|
||||
public static void setProxyIp(String proxyIp) {
|
||||
PROXY_IP = proxyIp;
|
||||
}
|
||||
|
||||
public static int getProxyPort() {
|
||||
return PROXY_PORT;
|
||||
}
|
||||
|
||||
public static void setProxyPort(int proxyPort) {
|
||||
PROXY_PORT = proxyPort;
|
||||
}
|
||||
|
||||
public static String getProxyAgreement() {
|
||||
return PROXY_AGREEMENT;
|
||||
}
|
||||
|
||||
public static void setProxyAgreement(String proxyAgreement) {
|
||||
PROXY_AGREEMENT = proxyAgreement;
|
||||
}
|
||||
|
||||
public static boolean getOpenProxy() {
|
||||
return OPEN_PROXY;
|
||||
}
|
||||
|
||||
public static void setOpenProxy(boolean openProxy) {
|
||||
OPEN_PROXY = openProxy;
|
||||
}
|
||||
|
||||
public static String getProxyUsername() {
|
||||
return PROXY_USERNAME;
|
||||
}
|
||||
|
||||
public static void setProxyUserame(String proxyUsername) {
|
||||
PROXY_USERNAME = proxyUsername;
|
||||
}
|
||||
|
||||
public static String getProxyPassword() {
|
||||
return PROXY_PASSWORD;
|
||||
}
|
||||
|
||||
public static void setProxyPassword(String proxyPassword) {
|
||||
PROXY_PASSWORD = proxyPassword;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 不允许外部创建实例
|
||||
*/
|
||||
private EsignHttpCfgHelper() {
|
||||
}
|
||||
|
||||
//------------------------------公有方法start--------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* @description 发起HTTP / HTTPS 请求
|
||||
*
|
||||
* @param reqType
|
||||
* {@link EsignRequestType} 请求类型 GET、 POST 、 DELETE 、 PUT
|
||||
* @param httpUrl
|
||||
* {@link String} 请求目标地址
|
||||
* @param headers
|
||||
* {@link Map} 请求头
|
||||
* @param param
|
||||
* {@link Object} 参数
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
* @author 澄泓
|
||||
*/
|
||||
public static EsignHttpResponse sendHttp(EsignRequestType reqType, String httpUrl, Map<String, String> headers, Object param, boolean debug)
|
||||
throws EsignInterfacException {
|
||||
HttpRequestBase reqBase=null;
|
||||
if(httpUrl.startsWith("http")){
|
||||
reqBase=reqType.getHttpType(httpUrl);
|
||||
}else{
|
||||
throw new EsignInterfacException("请求url地址格式错误");
|
||||
}
|
||||
if(debug){
|
||||
LOGGER.info("请求头:{}",headers+"\n");
|
||||
LOGGER.info("请求参数\n{}", param+"\n");
|
||||
LOGGER.info("请求地址\n:{}\n请求方式\n:{}",reqBase.getURI(),reqType+"\n");
|
||||
}
|
||||
//请求方法不是GET或者DELETE时传入body体,否则不传入。
|
||||
String[] methods = {"DELETE", "GET"};
|
||||
if(param instanceof String&&Arrays.binarySearch(methods, reqType.name())<0){//POST或者PUT请求
|
||||
((HttpEntityEnclosingRequest) reqBase).setEntity(
|
||||
new StringEntity(String.valueOf(param), ContentType.create("application/json", "UTF-8")));
|
||||
}
|
||||
//参数时字节流数组
|
||||
else if(param instanceof byte[]) {
|
||||
reqBase=reqType.getHttpType(httpUrl);
|
||||
byte[] paramBytes = (byte[])param;
|
||||
((HttpEntityEnclosingRequest) reqBase).setEntity(new ByteArrayEntity(paramBytes));
|
||||
}
|
||||
//参数是form表单时
|
||||
else if(param instanceof List){
|
||||
((HttpEntityEnclosingRequest) reqBase).setEntity(new UrlEncodedFormEntity((Iterable<? extends NameValuePair>) param));
|
||||
}
|
||||
httpClient = getHttpClient();
|
||||
config(reqBase);
|
||||
|
||||
//设置请求头
|
||||
if(headers != null &&headers.size()>0) {
|
||||
for(Map.Entry<String, String> entry :headers.entrySet()) {
|
||||
reqBase.setHeader(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
//响应对象
|
||||
CloseableHttpResponse res = null;
|
||||
//响应内容
|
||||
String resCtx = null;
|
||||
int status;
|
||||
EsignHttpResponse esignHttpResponse = new EsignHttpResponse();
|
||||
try {
|
||||
//执行请求
|
||||
res = httpClient.execute(reqBase);
|
||||
status=res.getStatusLine().getStatusCode();
|
||||
|
||||
//获取请求响应对象和响应entity
|
||||
HttpEntity httpEntity = res.getEntity();
|
||||
if(httpEntity != null) {
|
||||
resCtx = EntityUtils.toString(httpEntity,"utf-8");
|
||||
}
|
||||
if(debug) {
|
||||
LOGGER.info("响应\n{}", resCtx + "\n");
|
||||
LOGGER.info("----------------------------end------------------------");
|
||||
}
|
||||
} catch (NoHttpResponseException e) {
|
||||
throw new EsignInterfacException("服务器丢失了",e);
|
||||
} catch (SSLHandshakeException e){
|
||||
String msg = MessageFormat.format("SSL握手异常", e);
|
||||
EsignInterfacException ex = new EsignInterfacException(msg, e);
|
||||
throw ex;
|
||||
} catch (UnknownHostException e){
|
||||
EsignInterfacException ex = new EsignInterfacException("服务器找不到", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch(ConnectTimeoutException e){
|
||||
EsignInterfacException ex = new EsignInterfacException("连接超时", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch(SSLException e){
|
||||
EsignInterfacException ex = new EsignInterfacException("SSL异常",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch (ClientProtocolException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("请求头异常",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch (IOException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("网络请求失败",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} finally {
|
||||
if(res != null) {
|
||||
try {
|
||||
res.close();
|
||||
} catch (IOException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("--->>关闭请求响应失败",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
esignHttpResponse.setStatus(status);
|
||||
esignHttpResponse.setBody(resCtx);
|
||||
return esignHttpResponse;
|
||||
}
|
||||
//------------------------------公有方法end----------------------------------------------
|
||||
|
||||
//------------------------------私有方法start--------------------------------------------
|
||||
|
||||
/**
|
||||
* @description 请求头和超时时间配置
|
||||
*
|
||||
* @param httpReqBase
|
||||
* @author 澄泓
|
||||
*/
|
||||
private static void config(HttpRequestBase httpReqBase) {
|
||||
// 配置请求的超时设置
|
||||
RequestConfig.Builder builder = RequestConfig.custom()
|
||||
.setConnectionRequestTimeout(MAX_TIMEOUT)
|
||||
.setConnectTimeout(MAX_TIMEOUT)
|
||||
.setSocketTimeout(MAX_TIMEOUT);
|
||||
if(OPEN_PROXY){
|
||||
HttpHost proxy=new HttpHost(PROXY_IP,PROXY_PORT,PROXY_AGREEMENT);
|
||||
builder.setProxy(proxy);
|
||||
}
|
||||
RequestConfig requestConfig = builder.build();
|
||||
httpReqBase.setConfig(requestConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 连接池配置
|
||||
*
|
||||
* @return
|
||||
* @author 澄泓
|
||||
*/
|
||||
private static void cfgPoolMgr() throws EsignInterfacException {
|
||||
ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
|
||||
LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();
|
||||
if(!SSL_VERIFY){
|
||||
sslsf=sslConnectionSocketFactory();
|
||||
}
|
||||
|
||||
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
|
||||
.register("http", plainsf)
|
||||
.register("https", sslsf)
|
||||
.build();
|
||||
|
||||
//连接池管理器
|
||||
connMgr = new PoolingHttpClientConnectionManager(registry);
|
||||
//请求池最大连接数
|
||||
connMgr.setMaxTotal(MAX_TOTAL);
|
||||
//但域名最大的连接数
|
||||
connMgr.setDefaultMaxPerRoute(ROUTE_MAX_TOTAL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @description 设置重试机制
|
||||
*
|
||||
* @author 澄泓
|
||||
*/
|
||||
private static void cfgRetryHandler() {
|
||||
retryHandler = new HttpRequestRetryHandler() {
|
||||
|
||||
@Override
|
||||
public boolean retryRequest(IOException e, int excCount, HttpContext ctx) {
|
||||
//超过最大重试次数,就放弃
|
||||
if(excCount > MAX_RETRY) {
|
||||
return false;
|
||||
}
|
||||
//服务器丢掉了链接,就重试
|
||||
if(e instanceof NoHttpResponseException) {
|
||||
return true;
|
||||
}
|
||||
//不重试SSL握手异常
|
||||
if(e instanceof SSLHandshakeException) {
|
||||
return false;
|
||||
}
|
||||
//中断
|
||||
if(e instanceof InterruptedIOException) {
|
||||
return false;
|
||||
}
|
||||
//目标服务器不可达
|
||||
if(e instanceof UnknownHostException) {
|
||||
return false;
|
||||
}
|
||||
//连接超时
|
||||
//SSL异常
|
||||
if(e instanceof SSLException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HttpClientContext clientCtx = HttpClientContext.adapt(ctx);
|
||||
HttpRequest req = clientCtx.getRequest();
|
||||
//如果是幂等请求,就再次尝试
|
||||
if(!(req instanceof HttpEntityEnclosingRequest)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 忽略域名校验
|
||||
*/
|
||||
private static SSLConnectionSocketFactory sslConnectionSocketFactory() throws EsignInterfacException {
|
||||
try {
|
||||
SSLContext ctx = SSLContext.getInstance("TLS"); // 创建一个上下文(此处指定的协议类型似乎不是重点)
|
||||
X509TrustManager tm = new X509TrustManager() { // 创建一个跳过SSL证书的策略
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
|
||||
}
|
||||
};
|
||||
ctx.init(null, new TrustManager[] { tm }, null); // 使用上面的策略初始化上下文
|
||||
return new SSLConnectionSocketFactory(ctx, new String[] { "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" }, null, NoopHostnameVerifier.INSTANCE);
|
||||
}catch (Exception e){
|
||||
EsignInterfacException ex = new EsignInterfacException("忽略域名校验失败",e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取单例HttpClient
|
||||
*
|
||||
* @return
|
||||
* @author 澄泓
|
||||
*/
|
||||
private static synchronized CloseableHttpClient getHttpClient() throws EsignInterfacException {
|
||||
if(httpClient==null) {
|
||||
CredentialsProvider credsProvider = new BasicCredentialsProvider();
|
||||
credsProvider.setCredentials(new AuthScope(PROXY_IP,PROXY_PORT),new UsernamePasswordCredentials(PROXY_USERNAME, PROXY_PASSWORD));
|
||||
cfgPoolMgr();
|
||||
cfgRetryHandler();
|
||||
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
|
||||
httpClient = httpClientBuilder.setDefaultCredentialsProvider(credsProvider).setConnectionManager(connMgr).setRetryHandler(retryHandler).build();
|
||||
}
|
||||
return httpClient;
|
||||
|
||||
}
|
||||
//------------------------------私有方法end----------------------------------------------
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @description Http 请求 辅助类
|
||||
* @author 澄泓
|
||||
* @since JDK1.7
|
||||
*/
|
||||
public class EsignHttpHelper {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(EsignHttpHelper.class);
|
||||
|
||||
/**
|
||||
* 不允许外部创建实例
|
||||
*/
|
||||
private EsignHttpHelper() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 发送常规HTTP 请求
|
||||
*
|
||||
* @param reqType 请求方式
|
||||
* @param url 请求路径
|
||||
* @param paramStr 请求参数
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
* @author 澄泓
|
||||
*/
|
||||
public static EsignHttpResponse doCommHttp(String host, String url,EsignRequestType reqType, Object paramStr ,Map<String,String> httpHeader,boolean debug) throws EsignInterfacException {
|
||||
return EsignHttpCfgHelper.sendHttp(reqType, host+url,httpHeader, paramStr, debug);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description 发送文件流上传 HTTP 请求
|
||||
*
|
||||
* @param reqType 请求方式
|
||||
* @param uploadUrl 请求路径
|
||||
* @param param 请求参数
|
||||
* @param fileContentMd5 文件fileContentMd5
|
||||
* @param contentType 文件MIME类型
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
* @author 澄泓
|
||||
*/
|
||||
public static EsignHttpResponse doUploadHttp( String uploadUrl,EsignRequestType reqType,byte[] param, String fileContentMd5,
|
||||
String contentType, boolean debug) throws EsignInterfacException {
|
||||
Map<String, String> uploadHeader = buildUploadHeader(fileContentMd5, contentType);
|
||||
if(debug){
|
||||
LOGGER.info("----------------------------start------------------------");
|
||||
LOGGER.info("fileContentMd5:{}",fileContentMd5);
|
||||
LOGGER.info("contentType:{}",contentType);
|
||||
}
|
||||
return EsignHttpCfgHelper.sendHttp(reqType,uploadUrl, uploadHeader, param,debug);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @description 构建一个签名鉴权+json数据的esign请求头
|
||||
* @return
|
||||
* @author 澄泓
|
||||
*/
|
||||
public static Map<String, String> buildSignAndJsonHeader(String projectId,String contentMD5,String accept,String contentType,String authMode) {
|
||||
|
||||
Map<String, String> header = new HashMap<>();
|
||||
header.put("X-Tsign-Open-App-Id", projectId);
|
||||
header.put("X-Tsign-Open-Version-Sdk",EsignCoreSdkInfo.getSdkVersion());
|
||||
header.put("X-Tsign-Open-Ca-Timestamp", EsignEncryption.timeStamp());
|
||||
header.put("Accept",accept);
|
||||
header.put("Content-MD5",contentMD5);
|
||||
header.put("Content-Type", contentType);
|
||||
header.put("X-Tsign-Open-Auth-Mode", authMode);
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名计算并且构建一个签名鉴权+json数据的esign请求头
|
||||
* @param httpMethod
|
||||
* * The name of a supported {@linkplain java.nio.charset.Charset
|
||||
* * charset}
|
||||
* @return
|
||||
*/
|
||||
public static Map<String,String> signAndBuildSignAndJsonHeader(String projectId, String secret,String paramStr,String httpMethod,String url,boolean debug) throws EsignInterfacException {
|
||||
String contentMD5="";
|
||||
//统一转大写处理
|
||||
httpMethod = httpMethod.toUpperCase();
|
||||
if("GET".equals(httpMethod)||"DELETE".equals(httpMethod)){
|
||||
paramStr=null;
|
||||
contentMD5="";
|
||||
} else if("PUT".equals(httpMethod)||"POST".equals(httpMethod)){
|
||||
//对body体做md5摘要
|
||||
contentMD5=EsignEncryption.doContentMD5(paramStr);
|
||||
}else{
|
||||
throw new EsignInterfacException(String.format("不支持的请求方法%s",httpMethod));
|
||||
}
|
||||
//构造一个初步的请求头
|
||||
Map<String, String> esignHeaderMap = buildSignAndJsonHeader(projectId, contentMD5, EsignHeaderConstant.ACCEPT.VALUE(), EsignHeaderConstant.CONTENTTYPE_JSON.VALUE(), EsignHeaderConstant.AUTHMODE.VALUE());
|
||||
//排序
|
||||
url=EsignEncryption.sortApiUrl(url);
|
||||
//传入生成的bodyMd5,加上其他请求头部信息拼接成字符串
|
||||
String message = EsignEncryption.appendSignDataString(httpMethod, esignHeaderMap.get("Content-MD5"),esignHeaderMap.get("Accept"),esignHeaderMap.get("Content-Type"),esignHeaderMap.get("Headers"),esignHeaderMap.get("Date"), url);
|
||||
//整体做sha256签名
|
||||
String reqSignature = EsignEncryption.doSignatureBase64(message, secret);
|
||||
//请求头添加签名值
|
||||
esignHeaderMap.put("X-Tsign-Open-Ca-Signature",reqSignature);
|
||||
if(debug){
|
||||
LOGGER.info("----------------------------start------------------------");
|
||||
LOGGER.info("待计算body值:{}", paramStr+"\n");
|
||||
LOGGER.info("MD5值:{}",contentMD5+"\n");
|
||||
LOGGER.info("待签名字符串:{}",message+"\n");
|
||||
LOGGER.info("签名值:{}",reqSignature+"\n");
|
||||
}
|
||||
return esignHeaderMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description 构建一个Token鉴权+jsons数据的esign请求头
|
||||
* @return
|
||||
* @author 澄泓
|
||||
*/
|
||||
public static Map<String, String> buildTokenAndJsonHeader(String appid,String token) {
|
||||
Map<String, String> esignHeader = new HashMap<>();
|
||||
esignHeader.put("X-Tsign-Open-Version-Sdk",EsignCoreSdkInfo.getSdkVersion());
|
||||
esignHeader.put("Content-Type", EsignHeaderConstant.CONTENTTYPE_JSON.VALUE());
|
||||
esignHeader.put("X-Tsign-Open-App-Id", appid);
|
||||
esignHeader.put("X-Tsign-Open-Token", token);
|
||||
return esignHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 构建一个form表单数据的esign请求头
|
||||
* @return
|
||||
* @author 澄泓
|
||||
*/
|
||||
public static Map<String, String> buildFormDataHeader(String appid) {
|
||||
Map<String, String> esignHeader = new HashMap<>();
|
||||
esignHeader.put("X-Tsign-Open-Version-Sdk",EsignCoreSdkInfo.getSdkVersion());
|
||||
esignHeader.put("X-Tsign-Open-Authorization-Version","v2");
|
||||
esignHeader.put("Content-Type", EsignHeaderConstant.CONTENTTYPE_FORMDATA.VALUE());
|
||||
esignHeader.put("X-Tsign-Open-App-Id", appid);
|
||||
return esignHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建文件流上传 请求头
|
||||
*
|
||||
* @param fileContentMd5
|
||||
* @param contentType
|
||||
* @return
|
||||
* @author 澄泓
|
||||
*/
|
||||
public static Map<String, String> buildUploadHeader(String fileContentMd5, String contentType) {
|
||||
Map<String, String> header = new HashMap<>();
|
||||
header.put("Content-MD5", fileContentMd5);
|
||||
header.put("Content-Type", contentType);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
// ------------------------------私有方法end----------------------------------------------
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
/**
|
||||
* 网络请求的response类
|
||||
* @author 澄泓
|
||||
* @date 2022/2/21 17:28
|
||||
* @version
|
||||
*/
|
||||
public class EsignHttpResponse {
|
||||
private int status;
|
||||
private String body;
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
|
||||
/**
|
||||
* description 自定义全局异常
|
||||
*/
|
||||
public class EsignInterfacException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 4359180081622082792L;
|
||||
private Exception e;
|
||||
|
||||
public EsignInterfacException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public EsignInterfacException(String msg, Throwable cause) {
|
||||
super(msg,cause);
|
||||
}
|
||||
|
||||
public EsignInterfacException(){
|
||||
|
||||
}
|
||||
|
||||
public Exception getE() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void setE(Exception e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
|
||||
import org.apache.http.client.methods.*;
|
||||
|
||||
/**
|
||||
* @description 请求类型
|
||||
* @author 澄泓
|
||||
* @since JDK1.7
|
||||
*/
|
||||
public enum EsignRequestType {
|
||||
|
||||
POST{
|
||||
@Override
|
||||
public HttpRequestBase getHttpType(String url) {
|
||||
return new HttpPost(url);
|
||||
}
|
||||
},
|
||||
GET{
|
||||
@Override
|
||||
public HttpRequestBase getHttpType(String url) {
|
||||
return new HttpGet(url);
|
||||
}
|
||||
},
|
||||
DELETE{
|
||||
@Override
|
||||
public HttpRequestBase getHttpType(String url) {
|
||||
return new HttpDelete(url);
|
||||
}
|
||||
},
|
||||
PUT{
|
||||
@Override
|
||||
public HttpRequestBase getHttpType(String url) {
|
||||
return new HttpPut(url);
|
||||
}
|
||||
},
|
||||
;
|
||||
|
||||
public abstract HttpRequestBase getHttpType(String url);
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @description 文件转换类
|
||||
*/
|
||||
public class FileTransformation {
|
||||
|
||||
/**
|
||||
* 传入本地文件路径转二进制byte
|
||||
*
|
||||
* @param srcFilePath 本地文件路径
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
*/
|
||||
public static byte[] fileToBytes(String srcFilePath) throws EsignInterfacException {
|
||||
return getBytes(srcFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片转base64
|
||||
*
|
||||
* @param filePath 本地文件路径
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
*/
|
||||
public static String fileToBase64(String filePath) throws EsignInterfacException {
|
||||
byte[] bytes;
|
||||
String base64 = null;
|
||||
bytes = fileToBytes(filePath);
|
||||
base64 = Base64.encodeBase64String(bytes);
|
||||
base64 = base64.replaceAll("\r\n", "");
|
||||
return base64;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws EsignInterfacException {
|
||||
System.out.println(getFileContentMD5("D:\\文档\\PLT2022-02124CT.pdf"));
|
||||
}
|
||||
|
||||
/***
|
||||
* 计算文件内容的Content-MD5
|
||||
* @param filePath 文件路径
|
||||
* @return
|
||||
*/
|
||||
public static String getFileContentMD5(String filePath) throws EsignInterfacException {
|
||||
// 获取文件MD5的二进制数组(128位)
|
||||
byte[] bytes = getFileMD5Bytes128(filePath);
|
||||
// 对文件MD5的二进制数组进行base64编码
|
||||
return new String(Base64.encodeBase64String(bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*
|
||||
* @param httpUrl 网络文件地址url
|
||||
* @return
|
||||
*/
|
||||
public static boolean downLoadFileByUrl(String httpUrl, String dir) throws EsignInterfacException {
|
||||
InputStream fis = null;
|
||||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
URL url = new URL(httpUrl);
|
||||
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
|
||||
httpConn.connect();
|
||||
fis = httpConn.getInputStream();
|
||||
fileOutputStream = new FileOutputStream(new File(dir));
|
||||
byte[] md5Bytes = null;
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int length = -1;
|
||||
while ((length = fis.read(buffer, 0, 1024)) != -1) {
|
||||
fileOutputStream.write(buffer, 0, length);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("获取文件流异常", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} finally {
|
||||
try {
|
||||
if (fis != null) {
|
||||
fis.close();
|
||||
}
|
||||
if (fileOutputStream != null) {
|
||||
fileOutputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("关闭文件流异常", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 网络文件转二进制MD5数组并获取文件大小
|
||||
*
|
||||
* @param fileUrl 网络文件地址url
|
||||
* @return
|
||||
*/
|
||||
public static Map fileUrlToBytes(String fileUrl) throws EsignInterfacException {
|
||||
HashMap<String, Object> map = new HashMap<String, Object>();
|
||||
try {
|
||||
URL url = new URL(fileUrl);
|
||||
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
|
||||
httpConn.connect();
|
||||
InputStream fis = httpConn.getInputStream();
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
outStream.close();
|
||||
map.put("fileSize", fis.available());
|
||||
byte[] md5Bytes = null;
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
byte[] buffer = new byte[1024];
|
||||
int length = -1;
|
||||
while ((length = fis.read(buffer, 0, 1024)) != -1) {
|
||||
md5.update(buffer, 0, length);
|
||||
outStream.write(buffer, 0, length);
|
||||
}
|
||||
md5Bytes = md5.digest();
|
||||
byte[] fileData = outStream.toByteArray();
|
||||
map.put("fileData", fileData);
|
||||
outStream.close();
|
||||
fis.close();
|
||||
map.put("md5Bytes", md5Bytes);
|
||||
} catch (IOException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("获取文件流异常", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("文件计算异常", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/***
|
||||
* 获取文件MD5的二进制数组(128位)
|
||||
* @param filePath
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
*/
|
||||
public static byte[] getFileMD5Bytes128(String filePath) throws EsignInterfacException {
|
||||
FileInputStream fis = null;
|
||||
byte[] md5Bytes = null;
|
||||
try {
|
||||
File file = new File(filePath);
|
||||
fis = new FileInputStream(file);
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
byte[] buffer = new byte[1024];
|
||||
int length = -1;
|
||||
while ((length = fis.read(buffer, 0, 1024)) != -1) {
|
||||
md5.update(buffer, 0, length);
|
||||
}
|
||||
md5Bytes = md5.digest();
|
||||
fis.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("文件找不到", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("不支持此算法", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} catch (IOException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("输入流或输出流异常", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} finally {
|
||||
if (fis != null) {
|
||||
try {
|
||||
fis.close();
|
||||
} catch (IOException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("关闭文件输入流失败", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
return md5Bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
* @description 根据文件路径,获取文件base64
|
||||
* @author 宫清
|
||||
* @date 2019年7月21日 下午4:22:08
|
||||
*/
|
||||
public static String getBase64Str(String path) throws EsignInterfacException {
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = new FileInputStream(new File(path));
|
||||
byte[] bytes = new byte[is.available()];
|
||||
is.read(bytes);
|
||||
return Base64.encodeBase64String(bytes);
|
||||
} catch (Exception e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("获取文件输入流失败", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("关闭文件输入流失败", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path 文件路径
|
||||
* @return
|
||||
* @description 获取文件名称
|
||||
* @author 宫清
|
||||
* @date 2019年7月21日 下午8:21:16
|
||||
*/
|
||||
public static String getFileName(String path) {
|
||||
return new File(path).getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param filePath {@link String} 文件地址
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
* @description 获取文件字节流
|
||||
* @date 2019年7月10日 上午9:17:00
|
||||
* @author 宫清
|
||||
*/
|
||||
public static byte[] getBytes(String filePath) throws EsignInterfacException {
|
||||
File file = new File(filePath);
|
||||
FileInputStream fis = null;
|
||||
byte[] buffer = null;
|
||||
try {
|
||||
fis = new FileInputStream(file);
|
||||
buffer = new byte[(int) file.length()];
|
||||
fis.read(buffer);
|
||||
} catch (Exception e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("获取文件字节流失败", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
} finally {
|
||||
if (fis != null) {
|
||||
try {
|
||||
fis.close();
|
||||
} catch (IOException e) {
|
||||
EsignInterfacException ex = new EsignInterfacException("关闭文件字节流失败", e);
|
||||
ex.initCause(e);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
package com.ruoyi.wisdomarbitrate.utils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.ruoyi.wisdomarbitrate.domain.SealSignRecord;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SignAward {
|
||||
|
||||
private static String eSignHost= EsignApplicaConfig.EsignHost;
|
||||
private static String eSignAppId=EsignApplicaConfig.EsignAppId;
|
||||
private static String eSignAppSecret=EsignApplicaConfig.EsignAppSecret;
|
||||
// public static String fileId = "95d0c307d91e4985bdb8874f6f84daa5";
|
||||
public static String fileId = "a0c2ad21065f48ff8b872412c39d5d3a";
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) throws EsignInterfacException {
|
||||
Gson gson = new Gson();
|
||||
|
||||
SealSignRecord sealSignRecord = new SealSignRecord();
|
||||
|
||||
sealSignRecord.setFileid("a808f1f39a744357a2f018e4ab34c55d");
|
||||
sealSignRecord.setFilename("23893bfd3f2249ffa5c82850c11c482e.pdf");
|
||||
sealSignRecord.setSignFlowid("41e6732b48c54c63a91b2379c352212d");
|
||||
|
||||
|
||||
sealSignRecord.setPensonAccount("18209231185");
|
||||
sealSignRecord.setPensonName("秦桃则");
|
||||
sealSignRecord.setOrgnizeName("西安云美电子科技有限公司");
|
||||
sealSignRecord.setOrgnizeNamePsnAccount("17691338406");
|
||||
sealSignRecord.setOrgnizeNamepsnName("韩超勃");
|
||||
sealSignRecord.setPositionPagepsn("2");
|
||||
|
||||
sealSignRecord.setPositionXpsn(279+20);
|
||||
sealSignRecord.setPositionYpsn(216.336-20);
|
||||
|
||||
sealSignRecord.setPositionPageorg("2");
|
||||
|
||||
sealSignRecord.setPositionXorg(342+30);
|
||||
sealSignRecord.setPositionYorg(185.136);
|
||||
|
||||
|
||||
|
||||
|
||||
/* 发起签署*/
|
||||
// EsignHttpResponse createByFile = createByFile(sealSignRecord);
|
||||
// JsonObject createByFileJsonObject = gson.fromJson(createByFile.getBody(), JsonObject.class);
|
||||
// JsonObject createByFileData = createByFileJsonObject.getAsJsonObject("data");
|
||||
// String signFlowId = createByFileData.get("signFlowId").getAsString();
|
||||
// System.err.println("流程id:"+signFlowId);
|
||||
|
||||
/* 获取文件签名印章位置*/
|
||||
// EsignHttpResponse positions = getPositions(sealSignRecord);
|
||||
// JsonObject positionsJsonObject = gson.fromJson(positions.getBody(), JsonObject.class);
|
||||
// JsonObject positionsData = positionsJsonObject.getAsJsonObject("data");
|
||||
// JsonArray keywordPositions = positionsData.get("keywordPositions").getAsJsonArray();
|
||||
// System.out.println("获取文件签名印章位置:" +keywordPositions.toString());
|
||||
|
||||
// String signFlowId = "c9955453716344f9971d308abdc13464";
|
||||
//获取合同文件签名链接
|
||||
// EsignHttpResponse signUrl = signUrl(sealSignRecord);
|
||||
// JsonObject signUrlJsonObject = gson.fromJson(signUrl.getBody(), JsonObject.class);
|
||||
// JsonObject signUrlData = signUrlJsonObject.getAsJsonObject("data");
|
||||
// String shortUrl = signUrlData.get("shortUrl").getAsString();
|
||||
// String url = signUrlData.get("url").getAsString();
|
||||
// System.out.println("签署短链接:" +shortUrl);
|
||||
// System.out.println("签署长链接:"+url);
|
||||
|
||||
//获取合同文件用印链接
|
||||
EsignHttpResponse usesealUrl = usesealUrl(sealSignRecord);
|
||||
JsonObject usesealUrlJsonObject = gson.fromJson(usesealUrl.getBody(), JsonObject.class);
|
||||
JsonObject usesealUrlData = usesealUrlJsonObject.getAsJsonObject("data");
|
||||
String shortusesealUrl = usesealUrlData.get("shortUrl").getAsString();
|
||||
String sealUrl = usesealUrlData.get("url").getAsString();
|
||||
System.out.println("签署长链接:" +shortusesealUrl);
|
||||
System.out.println("签署短链接:"+sealUrl);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发起签署
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
*/
|
||||
public static EsignHttpResponse createByFile(SealSignRecord sealSignRecord) throws EsignInterfacException {
|
||||
String apiaddr = "/v3/sign-flow/create-by-file";
|
||||
|
||||
String fileId = sealSignRecord.getFileid();
|
||||
String fileName = sealSignRecord.getFilename();
|
||||
|
||||
String psnAccount = sealSignRecord.getPensonAccount();
|
||||
String psnName = sealSignRecord.getPensonName();
|
||||
|
||||
String orgName = sealSignRecord.getOrgnizeName();
|
||||
String orgNamePsnAccount = sealSignRecord.getOrgnizeNamePsnAccount();
|
||||
String orgNamepsnName = sealSignRecord.getOrgnizeNamepsnName();
|
||||
|
||||
String positionPagepsn = sealSignRecord.getPositionPagepsn();
|
||||
double positionXpsn = sealSignRecord.getPositionXpsn();
|
||||
double positionYpsn = sealSignRecord.getPositionYpsn();
|
||||
|
||||
String positionPageorg = sealSignRecord.getPositionPageorg();
|
||||
double positionXorg = sealSignRecord.getPositionXorg();
|
||||
double positionYorg = sealSignRecord.getPositionYorg();
|
||||
|
||||
|
||||
String jsonParm = "{\n" +
|
||||
" \"docs\": [\n" +
|
||||
" {\n" +
|
||||
|
||||
// " \"fileId\": \"5bd34a81e8084acaab3287c019e82fe8\",\n" +
|
||||
" \"fileId\": \"" + fileId + "\",\n" +
|
||||
|
||||
// " \"fileName\": \"477470a7741b4536a200c792b6ddf966.pdf\"\n" +
|
||||
" \"fileName\": \"" + fileName + "\"\n" +
|
||||
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"signFlowConfig\": {\n" +
|
||||
" \"signFlowTitle\": \"测试合同\",\n" +
|
||||
" \"autoStart\": true,\n" +
|
||||
" \"authConfig\": {\n" +
|
||||
" \"willingnessAuthModes\": [\n" +
|
||||
" \"CODE_SMS\"\n" +
|
||||
" ],\n" +
|
||||
" \"psnAvailableAuthModes\": [\n" +
|
||||
" \"PSN_MOBILE3\"\n" +
|
||||
" ],\n" +
|
||||
" \"orgAvailableAuthModes\": [\n" +
|
||||
" \"ORG_LEGALREP\"\n" +
|
||||
" ]\n" +
|
||||
" },\n" +
|
||||
" \"autoFinish\": true\n" +
|
||||
" },\n" +
|
||||
|
||||
" \"signers\": [\n" +
|
||||
|
||||
" {\n" +
|
||||
|
||||
" \"psnSignerInfo\": {\n" +
|
||||
|
||||
// " \"psnAccount\": \"18209231185\",\n" +
|
||||
" \"psnAccount\": \"" + psnAccount + "\",\n" +
|
||||
|
||||
" \"psnInfo\": {\n" +
|
||||
|
||||
// " \"psnName\": \"秦桃则\"\n" +
|
||||
" \"psnName\": \"" + psnName + "\"\n" +
|
||||
" }\n" +
|
||||
|
||||
|
||||
" },\n" +
|
||||
|
||||
|
||||
" \"signFields\": [\n" +
|
||||
" {\n" +
|
||||
|
||||
// " \"fileId\": \"5bd34a81e8084acaab3287c019e82fe8\",\n" +
|
||||
" \"fileId\": \"" + fileId + "\",\n" +
|
||||
|
||||
" \"normalSignFieldConfig\": {\n" +
|
||||
" \"autoSign\": false,\n" +
|
||||
" \"freeMode\": false,\n" +
|
||||
" \"movableSignField\": false,\n" +
|
||||
" \"signFieldPosition\": {\n" +
|
||||
|
||||
// " \"positionPage\": \"2\",\n" +
|
||||
" \"positionPage\": \"" + positionPagepsn + "\",\n" +
|
||||
|
||||
// " \"positionX\": 310.0,\n" +
|
||||
" \"positionX\": " + positionXpsn + ",\n" +
|
||||
|
||||
// " \"positionY\": 247.536\n" +
|
||||
" \"positionY\": " + positionYpsn + "\n" +
|
||||
|
||||
" },\n" +
|
||||
" \"signFieldStyle\": 1\n" +
|
||||
" },\n" +
|
||||
" \"signFieldType\": 0\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"signerType\": 0\n" +
|
||||
" },\n" +
|
||||
|
||||
|
||||
" {\n" +
|
||||
" \"orgSignerInfo\": {\n" +
|
||||
|
||||
// " \"orgName\": \"西安云美电子科技有限公司\",\n" +
|
||||
" \"orgName\": \"" + orgName + "\",\n" +
|
||||
|
||||
" \"transactorInfo\": {\n" +
|
||||
|
||||
|
||||
// " \"psnAccount\": \"17691338406\",\n" +
|
||||
" \"psnAccount\": \"" + orgNamePsnAccount + "\",\n" +
|
||||
|
||||
" \"psnInfo\": {\n" +
|
||||
|
||||
// " \"psnName\": \"韩超勃\"\n" +
|
||||
" \"psnName\": \"" + orgNamepsnName + "\"\n" +
|
||||
" }\n" +
|
||||
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
|
||||
" \"signFields\": [\n" +
|
||||
" {\n" +
|
||||
|
||||
// " \"fileId\": \"5bd34a81e8084acaab3287c019e82fe8\",\n" +
|
||||
" \"fileId\": \"" + fileId + "\",\n" +
|
||||
|
||||
" \"normalSignFieldConfig\": {\n" +
|
||||
" \"autoSign\": false,\n" +
|
||||
" \"freeMode\": false,\n" +
|
||||
|
||||
" \"signFieldPosition\": {\n" +
|
||||
|
||||
// " \"positionPage\": \"2\",\n" +
|
||||
" \"positionPage\": \"" + positionPageorg + "\",\n" +
|
||||
|
||||
// " \"positionX\": 340.0,\n" +
|
||||
" \"positionX\": " + positionXorg + ",\n" +
|
||||
|
||||
// " \"positionY\": 340.736\n" +
|
||||
" \"positionY\": " + positionYorg + "\n" +
|
||||
" },\n" +
|
||||
" \"signFieldStyle\": 1\n" +
|
||||
" },\n" +
|
||||
" \"signFieldType\": 0\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"signerType\": 1\n" +
|
||||
" }\n" +
|
||||
|
||||
" ]\n" +
|
||||
"}";
|
||||
|
||||
//请求方法
|
||||
EsignRequestType requestType = EsignRequestType.POST;
|
||||
//生成请求签名鉴权方式的Header
|
||||
Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
|
||||
//发起接口请求
|
||||
return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取合同文件签名链接
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
*/
|
||||
public static EsignHttpResponse signUrl(SealSignRecord sealSignRecord) throws EsignInterfacException {
|
||||
|
||||
String signFlowId = sealSignRecord.getSignFlowid();
|
||||
String psnAccount = sealSignRecord.getPensonAccount();
|
||||
|
||||
String apiaddr = "/v3/sign-flow/" + signFlowId + "/sign-url";
|
||||
String jsonParm = "{\n" +
|
||||
" \"operator\": {\n" +
|
||||
// " \"psnAccount\":\"18209231185\"\n" +
|
||||
" \"psnAccount\": \"" + psnAccount + "\"\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
//请求方法
|
||||
EsignRequestType requestType = EsignRequestType.POST;
|
||||
//生成请求签名鉴权方式的Header
|
||||
Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
|
||||
//发起接口请求
|
||||
return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取合同文件用印链接
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
*/
|
||||
public static EsignHttpResponse usesealUrl(SealSignRecord sealSignRecord) throws EsignInterfacException {
|
||||
String signFlowId = sealSignRecord.getSignFlowid();
|
||||
String apiaddr = "/v3/sign-flow/" + signFlowId + "/sign-url";
|
||||
|
||||
String psnAccount = sealSignRecord.getOrgnizeNamePsnAccount();
|
||||
String orgName = sealSignRecord.getOrgnizeName();
|
||||
|
||||
String jsonParm = "{\n" +
|
||||
// " \"needLogin\": true,\n" +
|
||||
" \"operator\": {\n" +
|
||||
|
||||
// " \"psnAccount\":\"17691338406\"\n" +
|
||||
" \"psnAccount\": \"" + psnAccount + "\"\n" +
|
||||
" },\n" +
|
||||
" \"organization\": {\n" +
|
||||
|
||||
// " \"orgName\": \"西安云美电子科技有限公司\"\n" +
|
||||
" \"orgName\": \"" + orgName + "\"\n" +
|
||||
|
||||
" }\n" +
|
||||
"}";
|
||||
//请求方法
|
||||
EsignRequestType requestType = EsignRequestType.POST;
|
||||
//生成请求签名鉴权方式的Header
|
||||
Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
|
||||
//发起接口请求
|
||||
return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件签名印章位置
|
||||
* @return
|
||||
* @throws EsignInterfacException
|
||||
*/
|
||||
public static EsignHttpResponse getPositions(SealSignRecord sealSignRecord) throws EsignInterfacException {
|
||||
String fileId = sealSignRecord.getFileid();
|
||||
String apiaddr = "/v3/files/" + fileId + "/keyword-positions";
|
||||
String jsonParm = "{\n" +
|
||||
" \"keywords\": [\n" +
|
||||
" \"仲裁员:\",\n" +
|
||||
" \"(仲裁委员会盖章)\"\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
//请求方法
|
||||
EsignRequestType requestType = EsignRequestType.POST;
|
||||
//生成请求签名鉴权方式的Header
|
||||
Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
|
||||
//发起接口请求
|
||||
return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user