工具类-httpClient工具类

httpClient工具类

1.httpClient工具类(http/https、重发、超时、连接数的设置)

package com.xxxxxxx.xxxx.xxxx.payutil;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
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.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
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.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;


/**
 * {@code HttpClient}为HTTP请求客户端,负责将报文发送至指定URL。
 *
 * <p>{@code HttpClient}提供了丰富的http/https请求功能,根据实际应用场景可以向服务器发送多种请求实体。</p>
 *
 * <p>通过注解@Autowired可以注入实例对象。</p>
 *
 * <p>使用时根据实际情况在配置文件配置:
 * 	<dl>
 * 		<dd>连接池最大连接数:httpClient.maxConnTotal,未配置默认50</dd>
 * 		<dd>每个路由最大连接数:httpClient.maxConnPerRoute,未配置默认为最大连接数的一半</dd>
 * 		<dd>超时时间(单位秒):httpClient.timeout,未配置默认30秒</dd>
 * 		<dd>重发次数:httpClient.retryCount,未配置默认3次</dd>
 * 	</dl>
 * </p>
 *
 * <blockquote>参数说明如下:每个路由最大连接数:httpClient.maxConnPerRoute
 * 如配置为2时,意味着请求到http://www.baidu.com的最大连接数只能为2,即使连接池还有1000个可用连接!
 * </blockquote>
 *
 * <p><strong>设计思路:</strong>
 * HTTP请求客户端组件主要封装{@code Apache HttpClient},为接入着提供定制化的{@code HttpClient}实例并提供向服务器发送各种格式请求的方法。
 * ?HTTP客户端组件需要满足发送{@code http}和{@code https}请求的能力,在实现过程中需要向注册器注册{@code http}工厂和{@code https}工厂。
 * ?鉴于不同服务器对请求参数编码不同,每个方法需要提供接收编码格式的参数,如果未要求编码格式,默认采用{@code UTF-8}。

 */
public class HttpClient {


    private static final String CHARSET_UTF_8 = "UTF-8";

    /** 连接池最大连接数 **/
    private int maxConnTotal = 50;

    /** 每个路由最大连接数 **/
    private int maxConnPerRoute = 0;

    /** 超时时间,秒 **/
    private int timeout= 50;

    /** 重发次数 **/
    private int retryCount = 5;

    /** 连接客户端 **/
    private CloseableHttpClient closeableHttpClient;

    /**
     * 构造方法
     * @throws KeyManagementException
     * @throws NoSuchAlgorithmException
     */
    public HttpClient() throws KeyManagementException, NoSuchAlgorithmException{
        //超时时间,单位秒
        int httpReqTimeOut = timeout * 1000;

        /**
         * maxConnPerRoute为每个路由的最大连接数,如:maxConnPerRoute=2时,
         * 请求到www.baidu.com的最大连接数只能为2,即使连接池还有1000个可用连接!
         */
        if (maxConnPerRoute == 0)
            maxConnPerRoute = maxConnTotal / 2;


        SSLContext sslContext = SSLContext.getInstance("TLS");
        // 初始化SSL上下文
        sslContext.init(null, new TrustManager[] { tm }, null);
        // SSL套接字连接工厂,NoopHostnameVerifier为信任所有服务器
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
        // 注册http套接字工厂和https套接字工厂
        Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", sslsf)
                .build();
        // 连接池管理器
        PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager(r);
        pcm.setMaxTotal(maxConnTotal);//连接池最大连接数
        pcm.setDefaultMaxPerRoute(maxConnPerRoute);//每个路由最大连接数
        /**
         *  请求参数配置
         *  connectionRequestTimeout:
         *  						从连接池中获取连接的超时时间,超过该时间未拿到可用连接,
         *  						会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
         *  connectTimeout:
         *  				连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
         *  socketTimeout:
         *  				服务器返回数据(response)的时间,超过该时间抛出read timeout
         */
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(httpReqTimeOut)
                .setConnectTimeout(httpReqTimeOut)
                .setSocketTimeout(httpReqTimeOut)
                .build();
        /**
         * 构造closeableHttpClient对象
         */
        closeableHttpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(pcm)
                .setRetryHandler(retryHandler)
                .build();


    }

    @PostConstruct
    public void init() throws Exception {
        //超时时间,单位秒
        int httpReqTimeOut = timeout * 1000;

        /**
         * maxConnPerRoute为每个路由的最大连接数,如:maxConnPerRoute=2时,
         * 请求到www.baidu.com的最大连接数只能为2,即使连接池还有1000个可用连接!
         */
        if (maxConnPerRoute == 0)
            maxConnPerRoute = maxConnTotal / 2;


        SSLContext sslContext = SSLContext.getInstance("TLS");
        // 初始化SSL上下文
        sslContext.init(null, new TrustManager[] { tm }, null);
        // SSL套接字连接工厂,NoopHostnameVerifier为信任所有服务器
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
        // 注册http套接字工厂和https套接字工厂
        Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", sslsf)
                .build();
        // 连接池管理器
        PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager(r);
        pcm.setMaxTotal(maxConnTotal);//连接池最大连接数
        pcm.setDefaultMaxPerRoute(maxConnPerRoute);//每个路由最大连接数
        /**
         *  请求参数配置
         *  connectionRequestTimeout:
         *  						从连接池中获取连接的超时时间,超过该时间未拿到可用连接,
         *  						会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
         *  connectTimeout:
         *  				连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
         *  socketTimeout:
         *  				服务器返回数据(response)的时间,超过该时间抛出read timeout
         */
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(httpReqTimeOut)
                .setConnectTimeout(httpReqTimeOut)
                .setSocketTimeout(httpReqTimeOut)
                .build();
        /**
         * 构造closeableHttpClient对象
         */
        closeableHttpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(pcm)
                .setRetryHandler(retryHandler)
                .build();
    }

    /**
     * post 数据,数据以key、value存放在Map中
     * @param url http请求地址
     * @param paramMap 请求参数
     * @return 请求响应消息字符串
     * @throws IOException
     * @throws ParseException
     * @throws ClientProtocolException
     * @throws Exception
     */
    public String postMap(String url, Map<String, String> paramMap) throws ClientProtocolException, ParseException, IOException {
        return postMap(url, paramMap, CHARSET_UTF_8);
    }

    /**
     * post 数据,数据以key、value存放在Map中
     * @param url http请求地址
     * @param paramMap 请求参数
     * @param charsetName 编码格式
     * @return 请求响应消息字符串
     * @throws IOException
     * @throws ParseException
     * @throws ClientProtocolException
     * @throws Exception
     */
    public String postMap(String url, Map<String, String> paramMap, String charsetName) throws ClientProtocolException, ParseException, IOException {
        // post请求
        HttpPost post = new HttpPost(url);

        // 设置参数
        List<NameValuePair> formParams = new ArrayList<NameValuePair>();
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }

        // 对参数进行编码
        post.setEntity(new UrlEncodedFormEntity(formParams, Charset.forName(charsetName)));

        return httpRequest(post, charsetName);
    }

    /**
     * 根据约定往商户发送报文,报文属性为xmldata
     * @param url 发送报文地址
     * @param xmldata 发送报文的xml String
     * @return 请求响应消息字符串
     * @throws IOException
     * @deprecated 使用{@link #postMap(String, Map)}
     */
    @Deprecated
    public String sendMerchantMsg(String url, String xmldata) throws IOException {
        return sendMerchantMsg(url, xmldata, CHARSET_UTF_8);
    }

    /**
     * 根据约定往商户发送报文,报文属性为xmldata
     * @param url 发送报文地址
     * @param xmldata 发送报文的xml String
     * @param charsetName 编码格式
     * @param charsetName 编码格式
     * @return 请求响应消息字符串
     * @throws IOException
     * @deprecated 使用{@link #postMap(String, Map, String)}
     */
    @Deprecated
    public String sendMerchantMsg(String url, String xmldata, String charsetName) throws IOException {
        // post请求
        HttpPost httpost = new HttpPost(url);

        // 设置参数
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("xmldata", xmldata));

        // 对参数进行编码
        httpost.setEntity(new UrlEncodedFormEntity(params, Charset.forName(charsetName)));

        //发起请求
        String responseText = httpRequest(httpost, charsetName);
        return responseText;
    }

    /**
     * 根据与省端约定发送报文,报文格式为xmlhead和xmlbody
     * @param url 报文地址
     * @param xmlHead 报文头
     * @param xmlBody 报文体
     * @return 请求响应消息字符串
     * @throws IOException
     * @throws ParseException
     * @throws ClientProtocolException
     */
    public String sendCrmMsg(String url, String xmlHead, String xmlBody) throws ClientProtocolException, ParseException, IOException {
        return sendCrmMsg(url, xmlHead, xmlBody, CHARSET_UTF_8);
    }

    /**
     * 根据与省端约定发送报文,报文格式为xmlhead和xmlbody
     * @param url 报文地址
     * @param xmlHead 报文头
     * @param xmlBody 报文体
     * @param charsetName 编码格式
     * @return 请求响应消息字符串
     * @throws IOException
     * @throws ParseException
     * @throws ClientProtocolException
     */
    public String sendCrmMsg(String url, String xmlHead, String xmlBody, String charsetName) throws ClientProtocolException, ParseException, IOException {
        StringBody head = null;
        StringBody body = null;

      /*  head = new StringBody(xmlHead, ContentType.create("text/plain", Charset.forName(charsetName)));
        body = new StringBody(xmlBody, ContentType.create("text/plain", Charset.forName(charsetName)));*/
        head = new StringBody(xmlHead);
        body = new StringBody(xmlBody);

        HttpEntity entity = MultipartEntityBuilder.create()
                .addPart("xmlhead", head)
                .addPart("xmlbody", body)
                .setCharset(Charset.forName(charsetName))
                .build();

        HttpPost httpost = new HttpPost(url);
        httpost.setEntity(entity);

        return httpRequest(httpost, charsetName);
    }

    /**
     * 发送字符串消息到指定url
     * @param url 消息接收的url
     * @param msg 请求消息
     * @return 请求响应消息字符串
     * @throws IOException
     * @throws ParseException
     * @throws ClientProtocolException
     */
    public String sendStringMsg(String url, String msg) throws ClientProtocolException, ParseException, IOException {
        return sendStringMsg(url, msg, CHARSET_UTF_8);
    }

    /**
     * 发送字符串消息到指定url
     * @param url 消息接收的url
     * @param msg 请求消息
     * @return 请求响应消息字符串
     * @throws IOException
     * @throws ParseException
     * @throws ClientProtocolException
     */
    public String sendStringMsg(String url, String msg, String charsetName) throws ClientProtocolException, ParseException, IOException {
        //字符串Entity
        StringEntity entity = null;
        entity = new StringEntity(msg, Charset.forName(charsetName));
        //http post请求
        HttpPost httpost = new HttpPost(url);
        httpost.setEntity(entity);

        return httpRequest(httpost, charsetName);
    }

    /**
     * http 请求
     * @param request
     * @return 请求响应消息字符串
     * @throws
     * @throws IOException
     * @throws ParseException
     */
    private String httpRequest(HttpUriRequest request, String charsetName)
            throws ClientProtocolException, ParseException, IOException {
        String responseText = null;
        CloseableHttpResponse response = null;
        HttpEntity entitys = null;
        try {
            response = closeableHttpClient.execute(request);
            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
                entitys = response.getEntity();
                if (entitys != null) {
                    // 将返回实体转换为字符串
                    responseText = EntityUtils.toString(entitys, Charset.forName(charsetName));
                }
            } else {
                // 放弃连接
                request.abort();
            }
        } catch (ClientProtocolException e) {
            throw e;
        } catch (ParseException e) {
            throw e;
        } catch (IOException e) {
            throw e;
        } finally {
            if (entitys != null) {
                try {
                    //释放资源可用触发连接放回连接池
                    EntityUtils.consume(entitys);
                } catch (IOException e) {
                    throw e;
                }
            }
        }
        return responseText;
    }

    /**
     * 重发处理器
     */
    private HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() {

        public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
            // 打印警告信息
//			logger.warn(String.format("HttpClient向%s发起请求失败,出现异常%s,第%d次进入重发处理器判断是否需要重发。", context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST), exception,executionCount));
            if (executionCount >= retryCount) {
                // Do not retry if over max retry count
                return false;
            }
            if (exception instanceof ConnectTimeoutException) {
                // Connection refused
                return true;
            }
            if (exception instanceof UnknownHostException) {
                // Unknown host
                return true;
            }
            if (exception instanceof InterruptedIOException) {
                // Timeout
                return true;
            }
            if (exception instanceof SSLException) {
                // SSL handshake exception
                return false;
            }
            HttpClientContext clientContext = HttpClientContext.adapt(context);
            HttpRequest request = clientContext.getRequest();
            boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
            if (idempotent) {
                // 必须是幂等性的才能进行重发
                return true;
            }
            return false;
        }
    };

    /**
     * 信任管理器
     */
    private static X509TrustManager tm = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };

    public int getMaxConnTotal() {
        return maxConnTotal;
    }

    public void setMaxConnTotal(int maxConnTotal) {
        this.maxConnTotal = maxConnTotal;
    }

    public int getMaxConnPerRoute() {
        return maxConnPerRoute;
    }

    public void setMaxConnPerRoute(int maxConnPerRoute) {
        this.maxConnPerRoute = maxConnPerRoute;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public int getRetryCount() {
        return retryCount;
    }

    public void setRetryCount(int retryCount) {
        this.retryCount = retryCount;
    }

}

2.证书加解密(获取证书信息、加解密、随机生成秘钥等)

package com.xxxxx.util;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;



public class SecurityUtil {
	
	/**
	 * 按指定的字符集进行 Base64编码
	 * @param text		原码
	 * @param charset	字符集
	 * @return String	编码
	 * @throws Exception
	 */
	public static String encodeBase64(String text, String charset) throws Exception {
		String retData = null;
		
		if (StringUtils.isNotBlank(text)) {
			byte[] b = null;
			if (StringUtils.isBlank(charset)) {
				b = encodeBase64(text.getBytes());
			} else {
				b = encodeBase64(text.getBytes(charset));
			}
			retData = new String(b);
		}
		
		return retData;
	}
	/**
	 * 对Base64编码进行解码
	 * @param data		原码
	 * @return byte[]	编码
	 * @throws Exception
	 */
	public static byte[] encodeBase64(byte[] data) throws Exception {
		if (data != null && data.length > 0) {
			return Base64.encodeBase64(data);
		} else {
			return null;
		}
	}
	/**
	 * 按指定的字符集对 Base64编码进行解码
	 * @param text		编码
	 * @param charset	字符集
	 * @return String	原码
	 * @throws Exception
	 */
	public static String decodeBase64(String text, String charset) throws Exception {
		String retData = null;
		
		if (StringUtils.isNotBlank(text)) {
			byte[] b = decodeBase64(text.getBytes());
			if (StringUtils.isBlank(charset)) {
				retData = new String(b);
			} else {
				retData = new String(b, charset);
			}
		}
		
		return retData;
	}
	/**
	 * 对Base64编码进行解码
	 * @param data		编码
	 * @return byte[]	原码
	 * @throws Exception
	 */
	public static byte[] decodeBase64(byte[] data) throws Exception {
		if (data != null && data.length > 0) {
			return Base64.decodeBase64(data);
		} else {
			return null;
		}
	}
	
	
	/**
	 * 将字节数组转换成16进制的字符串
	 * @param bytes		字节数组
	 * @return String	16进制字符串
	 * @throws Exception
	 */
	public static String encodeByte2HexString(byte[] bytes) throws Exception {
		if (bytes != null && bytes.length > 0) {
			return new String(Hex.encodeHex(bytes));
		} else {
			return null;
		}
	}
	/**
	 * 将16进制的字符串转换成字节数组
	 * @param text		16进制字符串
	 * @return byte[]	字节数组
	 * @throws Exception
	 */
	public static byte[] decodeHexString2Byte(String text) throws Exception {
		if (StringUtils.isNotBlank(text)) {
			return Hex.decodeHex(text.toCharArray());
		} else {
			return null;
		}
	}
	
	
	/**
	 * 根据指定的密钥和算法转换格式对数据进行加密,算法转换格式为:算法或算法/模式/填充,其中:
	 * 算法可:AES、DES、DESede、RC2、RSA;
	 * 模式可:NONE、CBC、CFB|CFBx、 CTR、CTS、ECB、OFB、OFBx、PCBC;
	 * 填充可:NoPadding、ISO10126Padding、OAEPPadding、OAEPWith<digest>And<mgf>Padding、PKCS1Padding、 PKCS5Padding、SSL3Padding
	 * @param data		原文数据
	 * @param key		加密密钥
	 * @param transformation	转换格式
	 * @return byte[] 	密文数据
	 * @throws Exception
	 */
	public static byte[] encrypt(byte[] data, byte[] key, String transformation) throws Exception {
		if (data == null || data.length == 0 || key == null || key.length == 0 || StringUtils.isBlank(transformation)) {
			throw new Exception("加密数据或加密密钥或加密算法为空");
		}
		String algorithm = null;
		if (transformation.indexOf('/') > 0) {
			algorithm = transformation.substring(0, transformation.indexOf('/'));
		} else {
			algorithm = transformation;
		}
		Cipher cipher = Cipher.getInstance(transformation);
		if (algorithm.startsWith("RSA")) {
			KeyFactory factory = KeyFactory.getInstance("RSA");
			RSAPublicKey rpk = (RSAPublicKey)factory.generatePublic(new X509EncodedKeySpec(key));
			cipher.init(Cipher.ENCRYPT_MODE, rpk);
		}else if (algorithm.startsWith("DES")) {
			 // 生成一个可信任的随机数源  
	        SecureRandom sr = new SecureRandom();  
	        // 从原始密钥数据创建DESKeySpec对象  
	        DESKeySpec dks = new DESKeySpec(key);  

	        // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象  
	        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);  
	        SecretKey securekey = keyFactory.generateSecret(dks);  

	        // 用密钥初始化Cipher对象  
	        cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);  
		} else {
			SecretKeySpec sks = new SecretKeySpec(key, algorithm);
			cipher.init(Cipher.ENCRYPT_MODE, sks);
		}
		return cipher.doFinal(data);
	}
	/**
	 * 根据指定的密钥和算法转换格式对数据进行加密,算法转换格式为:算法或算法/模式/填充,其中:
	 * 算法可:AES、DES、DESede、RC2、RSA;
	 * 模式可:NONE、CBC、CFB|CFBx、 CTR、CTS、ECB、OFB、OFBx、PCBC;
	 * 填充可:NoPadding、ISO10126Padding、OAEPPadding、OAEPWith<digest>And<mgf>Padding、PKCS1Padding、 PKCS5Padding、SSL3Padding
	 * @param text		原文数据
	 * @param charset	报文字符集
	 * @param key		加密密钥
	 * @param transformation	转换格式
	 * @return String 	经Base64转码的密文数据
	 * @throws Exception
	 */
	public static String encrypt(String text, String charset, byte[] key, String transformation) throws Exception {
		String ciphertxt = null;
		
		if (StringUtils.isNotBlank(text)) {
			byte[] data = null;
			if (StringUtils.isBlank(charset)) {
				data = text.getBytes();
			} else {
				data = text.getBytes(charset);
			}
			byte[] cipher = encrypt(data, key, transformation);
			
			/*if (transformation.startsWith("DES")) {
				 String strs = new BASE64Encoder().encode(cipher);
			     return strs;  
			}else {*/
				ciphertxt = new String(encodeBase64(cipher));
				cipher = decodeBase64(ciphertxt.getBytes());
			/*}*/
		       
		}
		
		return ciphertxt;
	}
	/**
	 * 根据指定的密钥和算法转换格式对加密数据进行解密,其中算法转换格式为:算法或算法/模式/填充,其中
	 * 算法:AES、DES、DESede、RC2、RSA;
	 * 模式:NONE、CBC、CFB|CFBx、CTR、CTS、ECB、OFB、OFBx、PCBC;
	 * 填充:NoPadding、ISO10126Padding、OAEPPadding、OAEPWith<digest>And<mgf>Padding、PKCS1Padding、 PKCS5Padding、SSL3Padding
	 * @param data		密文数据
	 * @param key		加密密钥
	 * @param transformation	转换格式
	 * @return byte[] 	原文数据
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] data, byte[] key, String transformation) throws Exception {
		if (data == null || data.length == 0 || key == null || key.length == 0 || StringUtils.isBlank(transformation)) {
			throw new Exception("解密数据或解密密钥或解密算法为空");
		}
		String algorithm = null;
		if (transformation.indexOf('/') > 0) {
			algorithm = transformation.substring(0, transformation.indexOf('/'));
		} else {
			algorithm = transformation;
		}
		Cipher cipher = Cipher.getInstance(transformation);
		if (algorithm.startsWith("RSA")) {
			KeyFactory factory = KeyFactory.getInstance("RSA");
			RSAPrivateKey rpk = (RSAPrivateKey)factory.generatePrivate(new PKCS8EncodedKeySpec(key));
			cipher.init(Cipher.DECRYPT_MODE, rpk);
		}else if (algorithm.startsWith("DES")) {
			 // 生成一个可信任的随机数源  
	        SecureRandom sr = new SecureRandom();  
	        // 从原始密钥数据创建DESKeySpec对象  
	        DESKeySpec dks = new DESKeySpec(key);  
	        // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象  
	        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);  
	        SecretKey securekey = keyFactory.generateSecret(dks);  

	        // Cipher对象实际完成解密操作  
	        cipher = Cipher.getInstance(algorithm);  

	        // 用密钥初始化Cipher对象  
	        cipher.init(Cipher.DECRYPT_MODE, securekey, sr);  
		} else {
			SecretKeySpec sks = new SecretKeySpec(key, algorithm);
			cipher.init(Cipher.DECRYPT_MODE, sks);
		}
		return cipher.doFinal(data);
	}
	/**
	 * 根据指定的密钥和算法转换格式对加密数据进行解密,其中算法转换格式为:算法或算法/模式/填充,其中
	 * 算法:AES、DES、DESede、RC2、RSA;
	 * 模式:NONE、CBC、CFB|CFBx、CTR、CTS、ECB、OFB、OFBx、PCBC;
	 * 填充:NoPadding、ISO10126Padding、OAEPPadding、OAEPWith<digest>And<mgf>Padding、PKCS1Padding、 PKCS5Padding、SSL3Padding
	 * @param ciphertxt	经Base64转码的密文数据
	 * @param charset	报文字符集
	 * @param key		加密密钥
	 * @param transformation	转换格式
	 * @return String 	原文数据
	 * @throws Exception
	 */
	public static String decrypt(String ciphertxt, String charset, byte[] key, String transformation) throws Exception {
		String text = null;
		
		if (StringUtils.isNotBlank(ciphertxt)) {
			byte[] cipher = decodeBase64(ciphertxt.getBytes());
			byte[] data = decrypt(cipher, key, transformation);
			if (StringUtils.isBlank(charset)) {
				text = new String(data);
			} else {
				text = new String(data, charset);
			}
		}
		
		return text;
	}
	
	
	/**
	 * 根据指定的算法(MD2、MD5、SHA1、SHA256、SHA384、SHA512)进行报文摘要
	 * @param data		原始报文
	 * @param algorithm	摘要算法
	 * @return byte[]	报文摘要
	 * @throws Exception
	 */
	public static byte[] messageDigest(byte[] data, String algorithm) throws Exception {
		byte[] digest = null;
		
		if (data != null && data.length > 0) {
			MessageDigest md = MessageDigest.getInstance(algorithm);
			digest = md.digest(data);
		}
		
		return digest;
	}
	/**
	 * 根据指定的算法(MD2、MD5、SHA1、SHA256、SHA384、SHA512)和指定的报文字符集进行报文摘要
	 * @param text		原始报文
	 * @param charset	报文字符集
	 * @param algorithm	摘要算法
	 * @return byte[]	报文摘要
	 * @throws Exception
	 */
	public static String messageDigestHex(String text, String charset, String algorithm) throws Exception {
		byte[] digest = null;
		
		if (StringUtils.isNotBlank(text)) {
			byte[] data = null;
			if (StringUtils.isBlank(charset)) {
				data = text.getBytes();
			} else {
				data = text.getBytes(charset);
			}
			digest = messageDigest(data, algorithm);
		}
		
		return encodeByte2HexString(digest);
	}

	
	/**
	 * 根据指定的算法(NONEwithRSA、MD2withRSA、MD5withRSA、SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA)和密钥对报文数据进行数字签名
	 * @param data		报文数据
	 * @param algorithm	签名算法
	 * @param Key		签名私钥
	 * @return byte[]	数字签名
	 * @throws Exception
	 */
	public static byte[] sign(byte[] data, String algorithm, PrivateKey key) throws Exception {
		if (data == null || data.length == 0 || StringUtils.isBlank(algorithm) || key == null) {
			throw new Exception("待签名数据或签名算法或签名私钥为空");
		}
		Signature sign = Signature.getInstance(algorithm);
		sign.initSign(key);
		sign.update(data);

		return sign.sign();
	}
	/**
	 * 根据指定的算法(NONEwithRSA、MD2withRSA、MD5withRSA、SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA)和经过16进制转码、Base64编码的密钥对报文数据进行数字签名
	 * @param text		报文数据
	 * @param charset	字符集
	 * @param algorithm	签名算法
	 * @param Key		签名私钥
	 * @return String	经16进制转码后的数字签名
	 * @throws Exception
	 */
	public static String sign(String text, String charset, String algorithm, byte[] key) throws Exception {
	//public static String sign(String text, String charset, String algorithm, PrivateKey privateKey) throws Exception {
		byte[] data = null;
		if (StringUtils.isBlank(charset)) {
			data = text.getBytes();
		} else {
			data = text.getBytes(charset);
		}
		String keyAlgorithm = null;
		KeySpec keySpec = null;
		if (algorithm.endsWith("RSA")) {
			keyAlgorithm = "RSA";
			keySpec = new PKCS8EncodedKeySpec(key);
		} else {
			keyAlgorithm = algorithm;
			keySpec = new X509EncodedKeySpec(key);
		}
		KeyFactory factory = KeyFactory.getInstance(keyAlgorithm);
		PrivateKey privateKey = factory.generatePrivate(keySpec);
		byte[] signData = sign(data, algorithm, privateKey);
				
		return encodeByte2HexString(signData);
	}
	/**
	 * 根据指定的算法(NONEwithRSA、MD2withRSA、MD5withRSA、SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA)和密钥对数字签名进行验证
	 * @param data		报文数据
	 * @param signature	数字签名
	 * @param algorithm	签名算法
	 * @param Key		验签公钥
	 * @return boolean	验签结果:true 验签通过; false 验签失败
	 * @throws Exception
	 */
	public static boolean verify(byte[] data, byte[] signature, String algorithm, PublicKey key) throws Exception {
		if (signature == null || signature.length == 0 || StringUtils.isBlank(algorithm) || key == null) {
			throw new Exception("签名数据或签名算法或签名钥为空");
		}
		Signature sign = Signature.getInstance(algorithm);
		sign.initVerify(key);
		sign.update(data);
		return sign.verify(signature);
	}
	/**
	 * 根据指定的算法(NONEwithRSA、MD2withRSA、MD5withRSA、SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA)和经16进制转码、Base64编码的密钥对数字签名进行验证
	 * @param text		报文数据
	 * @param charset	字符集
	 * @param signature	经16进制转码的数字签名
	 * @param algorithm	签名算法
	 * @param Key		验签公钥
	 * @return boolean	验签结果:true 验签通过; false 验签失败
	 * @throws Exception
	 */
   	public static boolean verify(String text, String charset, String signature, String algorithm, byte[] key) throws Exception {
		//public static boolean verify(String text, String charset, String signature, String algorithm, PublicKey publicKey) throws Exception {
		byte[] data = null;
		if (StringUtils.isBlank(charset)) {
			data = text.getBytes();
		} else {
			data = text.getBytes(charset);
		}
		String keyAlgorithm = null;
		if (algorithm.endsWith("RSA")) {
			keyAlgorithm = "RSA";
		} else {
			keyAlgorithm = algorithm;
		}
		KeySpec keySpec = new X509EncodedKeySpec(key);
		KeyFactory factory = KeyFactory.getInstance(keyAlgorithm);
		PublicKey publicKey = factory.generatePublic(keySpec);
		return verify(data, decodeHexString2Byte(signature), algorithm, publicKey);
	}
	
	
	/**
	 * 根据指定的算法(DSA、RSA、EC、DiffieHellman)创建加密密钥
	 * @param algorithm	算法
	 * @param keysize	密钥大小
	 * @return SecretKey	密钥
	 * @throws Exception
	 */
	public static SecretKey generateKey(String algorithm, int keysize) throws Exception {
		if (StringUtils.isBlank(algorithm) || keysize < 0) {
			throw new Exception("产生密钥的算法为空或密钥长度为空");
		}
		KeyGenerator generator = KeyGenerator.getInstance(algorithm);
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
		if (keysize > 0) {
			generator.init(keysize, random);
		} else {
			generator.init(random);
		}
		
		return generator.generateKey();
	}
	/**
	 * 根据指定的算法(DSA、RSA、EC、DiffieHellman)创建加密密钥
	 * @param algorithm	算法
	 * @param keysize	密钥大小
	 * @return String	经16进制转码的密钥
	 * @throws Exception
	 */
	public static String generateSecretKey(String algorithm, int keysize) throws Exception {
		String key = null;
		
		SecretKey secretKey = generateKey(algorithm, keysize);
		if (secretKey != null) {
			key = encodeByte2HexString(secretKey.getEncoded());
		}
		
		return  key;
	}
	/**
	 * 根据指定的算法(DSA、RSA、EC、DiffieHellman)创建一组随机密钥对(公钥、私钥)
	 * @param algorithm	算法
	 * @param keysize	密钥大小
	 * @return KeyPair	密钥对
	 * @throws Exception
	 */
	public static KeyPair generateKeyPair(String algorithm, int keysize) throws Exception {
		if (StringUtils.isBlank(algorithm) || keysize <= 0) {
			throw new Exception("产生密钥的算法为空或密钥长度为空");
		}
		KeyPairGenerator generator = KeyPairGenerator.getInstance(algorithm);
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
		generator.initialize(keysize, random);
		
		return generator.genKeyPair();
	}
	/**
	 * 根据指定的算法(DSA、RSA、EC、DiffieHellman)创建一组随机密钥对(公钥、私钥),并将密钥转换16进制字符串再进行Base64编码
	 * @param algorithm	摘要算法
	 * @param keysize	密钥大小
	 * @return String[]	密钥数组,密钥存放次序:公钥、私钥
	 * @throws Exception
	 */
	public static String[] generateSecretKeys(String algorithm, int keysize) throws Exception {
		String[] keys = null;
		
		KeyPair keyPair = generateKeyPair(algorithm, keysize);
		if (keyPair != null) {
			keys = new String[2];
			byte[] key = keyPair.getPublic().getEncoded();
			keys[0] = encodeByte2HexString(key);
			key = keyPair.getPrivate().getEncoded();
			keys[1] = encodeByte2HexString(key);
		}
		
		return keys;
	}
	

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T646EF4A-1583828869664)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1583828516492.png)]

读取私钥代码

KeyStore ks = KeyStore.getInstance("JKS");
				//File file = FileUtil.getFile("cmsz_keystore");
				File file = FileUtil.getFile(ConfigUtil.getProperty("keyStoreFile"));
				FileInputStream fis = new FileInputStream(file);
				ks.load(fis, ConfigUtil.getProperty("keyStorePwd").toCharArray());
				privateKey = (PrivateKey) ks.getKey(ConfigUtil.getProperty("alias"), ConfigUtil.getProperty("keyPwd").toCharArray());

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zzp0Wurd-1583828869666)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1583828567302.png)]

读取公钥代码

CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
				File file = FileUtil.getFile(ConfigUtil.getProperty("caCertificateFile"));
				FileInputStream fis = new FileInputStream(file);
				X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(fis);
				
			    publicKey = certificate.getPublicKey();

在这里插入图片描述

具体代码:

package com.xxxx.util;

import java.io.File;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Map;
import java.util.Random;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


import com.xxxx.util.XmlUtil;

public class SignUtil {
	
	private static Log log = LogFactory.getLog(SignUtil.class);
	
	
	/**
	 * 数字签名:将Map对象转换成Xml报文,并添加采用SHA1WithRSA算法进行的数字签名,
	 * @param map			Map对象
	 * @param transactionId	交易流水号
	 * @param channelId		渠道id
	 * @param isExtSystem	是否外部系统签名
	 * @return String		16进制转码后的数字签名
	 * @throws Exception
	 */
	public static String sign(Map map, String transactionId, String channelId, boolean isExtSystem) throws Exception {
		//String ADVPAY = "AdvPay";//业务平台根节点
		String xml = XmlUtil.format(map, "AdvPay", "GBK");
		//String BUSI_DATA = "BusiData";
		String message = transactionId + XmlUtil.getElementXml(xml, "BusiData").trim();
		String signature = sign(message, channelId, isExtSystem);
		//String VERIFY_CODE = "VerifyCode";//验证码
		xml = XmlUtil.setElementValue(xml, "VerifyCode", signature);
		
		return xml;
	}
	
	
	
	/**
	 * 数字签名:将Map对象转换成Xml报文,并添加采用SHA1WithRSA算法进行的数字签名,
	 * @param map			Map对象
	 * @param transactionId	交易流水号
	 * @param channelId		渠道id
	 * @return String		16进制转码后的数字签名
	 * @throws Exception
	 */
	public static String sign(Map map, String transactionId, String channelId) throws Exception {
		return sign(map,transactionId,channelId,false);
	}

	/**
	 * 数字签名:根据指定的渠道编号、密钥类型从密钥配置表中获取相关密钥,再使用该密钥对报文数据进行SHA1WithRSA算法的签名
	 * @param message		报文
	 * @param channelId		渠道id
	 * @param isExtSystem	是否外部系统签名
	 * @return String		16进制转码后的数字签名
	 * @throws Exception
	 */
	public static String sign(String message, String channelId, boolean isExtSystem) throws Exception {
		String signature = null;
		
		if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(channelId)) {
			log.error("待签名数据:" + message);
			/*IBsKeyManageSV sv = (IBsKeyManageSV)ServiceFactory.getSeviceOfLocal(IBsKeyManageSV.class);
			IBOBsKeyManageValue value = sv.getBsKeyManageByChannelId(channelId);*/
			String value="true";
			if (value == null) {
				throw new Exception("渠道编号["+channelId+"]密钥不存在!");
			}
			String key = null;
			PrivateKey privateKey =null;
		
			if (isExtSystem) {
				KeyStore ks = KeyStore.getInstance("JKS");
				//File file = FileUtil.getFile("cmsz_keystore");
				File file = FileUtil.getFile(ConfigUtil.getProperty("keyStoreFile"));
				FileInputStream fis = new FileInputStream(file);
				ks.load(fis, ConfigUtil.getProperty("keyStorePwd").toCharArray());
				privateKey = (PrivateKey) ks.getKey(ConfigUtil.getProperty("alias"), ConfigUtil.getProperty("keyPwd").toCharArray());
				//是外部系统私钥
				byte[] encoded = privateKey.getEncoded();
				char[] encodeHex = Hex.encodeHex(encoded);
				StringBuffer sb=new StringBuffer();
				for (char c : encodeHex) {
					sb.append(c+"");
					
				}
			    key=sb.toString();
				System.out.println("-----key----"+key);
				//key ="30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100a9d1c7d8add8fe191f4f6008cd28b745238e71d6f06734e8bd785add6e98a629a4410176b370f12f3777eef656088f6ec37206a38f38f722439fa70f20f7162a9812e04645e272b6a8c7c6fdff47e7ecc85a69203bee8fc63198838a4f4cd0e9314d75d1ef92daa7a2630c9ed21dc9da82abfde2aca0ef38f1589fab811e91eb0203010001028180680f5b75c439e6a2c053e456205965cc6118655bbf5e8ec65b6c07ca0e7e4dbbd0a1e0e2badc677e766ff0a7545ad4819c14204b537525c3024b2f948eafba0d866e6cf06c29475da9742ede90697b3691dcd1c7b879ecc6dbad5e37c619fd6c54f595555ddd60c4f4dc9b4082c08ba1b725d268474e7b80c5b9fa57a1a93fc9024100f77369ae906c3c45186cdf97de13de37ab6b746899777a879c458fd740daea4e5362bcc9c0716eb721ba627f5450e5889d8e684c97f954e908b19abc20460245024100afafc12871e2c9f5c3439d7e24292be83e6299d63311fab06320e616b0b9e63529c0199538e2aa5a04afee5181c8bef331c6184ded7f268086e1249b5c399e6f02410080b616ad874fd555b76bc22df384f01c92dcb4d347a85f22b4c576196811b6b8812525bfe78ad92506b53550b7e1d052ec694b9533a3ac67fe6eab66d97eb0e50241009e2d122e94e2c84ca2227560c5b3dfd93899d3c1bbb75b4a85e56fe34bf803a127d6d1f1bd06aeb35f76fa8d9dd91cba9ebca8d33899fb134adcd7f59cc22fb7024100c71a9943caa962b6f5c147289ab0e41796ad07fa425d7cd1ad9998984cc69045de99382c007c566a5104c0d98018136e23e18f567dada06f2826db524cebbe11";
			} else {
				//key = value.getPayPrivateKey();
			}
			byte[] k = SecurityUtil.decodeHexString2Byte(key);
			signature = SecurityUtil.sign(message, null, "SHA1WithRSA", k);
			log.error("签名结果:" + signature);
		}
		
		return signature;
	}
	
	/**
	 * 签名验证:根据指定的渠道编号、密钥类型从密钥配置表中获取相关密钥,再使用该密钥和报文数据对数字签名进行SHA1WithRSA算法的签名验证
	 * @param message		报文
	 * @param signature		16进制转码后的数字签名
	 * @param channelId		渠道id
	 * @param isExtSystem	是否外部系统签名验证
	 * @return boolean		数字签名验证结果:true 验证通过;false 验证失败
	 * @throws Exception
	 */
	public static boolean verify(String message, String signature, String channelId, boolean isExtSystem) throws Exception {
		boolean verifyResult = false;
		
		if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(channelId)) {
			log.error("待验签数据:" + message);
		/*	IBsKeyManageSV sv = (IBsKeyManageSV)ServiceFactory.getSeviceOfLocal(IBsKeyManageSV.class);
			IBOBsKeyManageValue value = sv.getBsKeyManageByChannelId(channelId);*/
			String value="key";
			if (value == null) {
				throw new Exception("渠道编号["+channelId+"]密钥不存在!");
			}
			String key = null;
			PublicKey publicKey=null;
			if (isExtSystem) {
				CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
				File file = FileUtil.getFile(ConfigUtil.getProperty("caCertificateFile"));
				FileInputStream fis = new FileInputStream(file);
				X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(fis);
				
			    publicKey = certificate.getPublicKey();
			    byte[] encoded = publicKey.getEncoded();
			    char[] encodeHex = Hex.encodeHex(encoded);
			    StringBuffer bf=new StringBuffer();
			    for (char c : encodeHex) {
			    	bf.append(c+"");
				}
			    System.out.println("---pubkey----"+bf.toString());
				//获取外部系统公钥
			    key=bf.toString();
				//key = "30819f300d06092a864886f70d010101050003818d0030818902818100a9d1c7d8add8fe191f4f6008cd28b745238e71d6f06734e8bd785add6e98a629a4410176b370f12f3777eef656088f6ec37206a38f38f722439fa70f20f7162a9812e04645e272b6a8c7c6fdff47e7ecc85a69203bee8fc63198838a4f4cd0e9314d75d1ef92daa7a2630c9ed21dc9da82abfde2aca0ef38f1589fab811e91eb0203010001".trim();
			} else {
				//key = value.getPayPublicKey();
			}
			byte[] k = SecurityUtil.decodeHexString2Byte(key);
			verifyResult = SecurityUtil.verify(message, null, signature, "SHA1WithRSA", k);
			log.error("签名结果:" + verifyResult);
		}
		
		return verifyResult;
	}
	
	/**
	 * 报文加密:根据渠道编号、密钥类型从密钥配置表中查询相关加密密钥,再使用该密钥对报文数据进行RSA算法加密
	 * @param message		原文
	 * @param channelId		渠道id
	 * @param isExtSystem	是否外部系统签名
	 * @return String		16进制转码后的加密密文
	 * @throws Exception
	 */
	public static String encrypt(String message, String channelId, boolean isExtSystem) throws Exception {
		String ciphertxt = null;
		
		if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(channelId)) {
			/*IBsKeyManageSV sv = (IBsKeyManageSV)ServiceFactory.getSeviceOfLocal(IBsKeyManageSV.class);
			IBOBsKeyManageValue value = sv.getBsKeyManageByChannelId(channelId);*/
			String key = null;
			if (isExtSystem) {
				//key = value.getExtPublicKey();
			} else {
				//key = value.getPayPublicKey();
			}
			byte[] k = SecurityUtil.decodeHexString2Byte(key);
			ciphertxt = SecurityUtil.encrypt(message, "GBK", k, "RSA/ECB/PKCS1Padding");
		}
		
		return ciphertxt;
	}
	
	/**
	 * 密文解密:根据渠道编号、密钥类型从密钥配置表中查询相关加密密钥,再使用该密钥对加密报文数据进行RSA算法解密
	 * @param ciphertxt		16进制转码后的加密密文
	 * @param channelId		渠道id
	 * @param isExtSystem	是否外部系统签名
	 * @return String		原文
	 * @throws Exception
	 */
	public static String decrypt(String ciphertxt, String channelId, boolean isExtSystem) throws Exception {
		String message = null;
		
		if (StringUtils.isNotBlank(ciphertxt) && StringUtils.isNotBlank(channelId)) {
		/*	IBsKeyManageSV sv = (IBsKeyManageSV)ServiceFactory.getSeviceOfLocal(IBsKeyManageSV.class);
			IBOBsKeyManageValue value = sv.getBsKeyManageByChannelId(channelId);*/
			String key = null;
			if (isExtSystem) {
			//	key = value.getExtPrivateKey();
			} else {
			//	key = value.getPayPrivateKey();
			}
			byte[] k = SecurityUtil.decodeHexString2Byte(key);
			message = SecurityUtil.decrypt(ciphertxt, "GBK", k, "RSA/ECB/PKCS1Padding");
		}
		
		return message;
	}
	
	/**
	 * 生成一个随机数并通过MD5算法进行报文摘要
	 * @param ciphertxt		16进制转码后的加密密文
	 * @param channelId		渠道id
	 * @param isExtSystem	是否外部系统签名
	 * @return String		原文
	 * @throws Exception
	 */
	public static String getNonceStr() throws Exception {
		Random random = new Random();
		return SecurityUtil.messageDigestHex(String.valueOf(random.nextInt(10000)), null, "MD5");
	}

	/**
	 * 按Map对象中Key的子字符串次序从小到大排序生成URL参数串,其格式为:key1=value1&key2=value2…
	 * @param map			Map对象
	 * @param encode		编码格式
	 * @return String		URL参数串
	 * @throws Exception
	 */
	public static String createUrlQueryString(Map<String, String> map, String encode) throws Exception {
		Object[] keys = map.keySet().toArray();
		Arrays.sort(keys);
		StringBuffer sb = new StringBuffer();
		for (Object key : keys) {
			String value = map.get(key);
			if (value != null) {
				if (sb.length() > 0) {
					sb.append("&");
				}
				sb.append(key.toString()).append('=');
				if (StringUtils.isBlank(encode)) {
					sb.append(value);
				} else {
					sb.append(URLEncoder.encode(value, encode));
				}
			}
		}
		return sb.toString();
	}
	
package com.xxxx.xxxx.common.util;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * <p>Title: XML报文处理工具</p>
 * <p>Description: 提供各种XML报文数据与Map对象间的转换方法</p>
 * <p>Copyright: Copyright (c) 2015</p>
 * <p>Company: AI(NanJing)</p>
 * @author ZhouZH
 * @date 2015-09-21
 * @version 1.0
 */

public class XmlUtil {
	
	/**
	 * 将指定的Map对象转换成XML报文
	 * @param map			Map对象
	 * @param root		 	指定XML报文的根节点名称
	 * @param encoding		字符集
	 * @return String		转换后的XML报文
	 * @throws Exception
	 */
	public static String format(Map map, String root, String encoding) throws Exception {
		String xml = null;
		
		if (map != null && map.size() > 0) {
			Document document = DocumentHelper.createDocument();
			document.setXMLEncoding(encoding);
			Element rootElement = document.addElement(root);
			format(rootElement, map);
			xml = document.asXML();
		}
		
		return xml;
	}
	
	/**
	 * 将指定的XML报文转换成Map对象,忽略根节点
	 * @param xml			XML字符串
	 * @return String		转换后的XML报文
	 * @throws Exception
	 */
	public static Map parse(String xml) throws Exception {
		Map map = null;
		
		if (StringUtils.isNotBlank(xml)) {
			SAXReader reader = null;
			StringReader sr = null;
			try {
				reader = new SAXReader();
				sr = new StringReader(xml);
				Document document = reader.read(sr);
				Element root = document.getRootElement();
				map = (Map) parse(root);
				System.out.println(map);
			} finally {
				if (sr != null) {
					sr.close();
				}
			}
		}
		
		
		return map;
	}
	
	/**
	 * 从现有的XML报文中截取指定XML元素相关的内容
	 * @param xmlElmentName	XML元素名称
	 * @return Object		数据对象
	 * @throws Exception
	 */
	public static String getElementXml(String xml, String xmlElmentName) {
		String elementXml = null;
		
		if (StringUtils.isNotBlank(xml)) {
			String perfix = String.format("<%s>", xmlElmentName);
			String suffix = String.format("</%s>", xmlElmentName);
			int beginIndex = xml.indexOf(perfix);
			int endIndex = xml.indexOf(suffix);
			if (beginIndex >= 0 && endIndex >= 0 && endIndex > beginIndex) {
				elementXml = xml.substring(beginIndex, endIndex + suffix.length());
			}
		}
		
		return elementXml;
	}

	/**
	 * 从现有的XML报文中截取指定XML元素的值
	 * @param xml			XML报文
	 * @param xmlElmentName	XML元素名称
	 * @return String		数据对象
	 * @throws Exception
	 */
	public static String getElementValue(String xml, String xmlElmentName) {
		String value = null;
		
		String elementXml = getElementXml(xml, xmlElmentName);
		if (StringUtils.isNotBlank(elementXml)) {
			int beginIndex = elementXml.indexOf(">");
			int endIndex = elementXml.lastIndexOf("<");
			if (beginIndex >= 0 && endIndex >= 0 && endIndex > beginIndex) {
				value = elementXml.substring(beginIndex + 1, endIndex);
			}
		}
		
		return value;
	}

	/**
	 * 从现有的XML报文中截取指定XML元素的值
	 * @param xml			XML报文
	 * @param xmlElmentName	XML元素名称
	 * @param xmlElmentValueXML元素内容
	 * @return Object		数据对象
	 * @throws Exception
	 */
	public static String setElementValue(String xml, String xmlElmentName, String xmlElmentValue) {
		String value = null;
		
		if (StringUtils.isNotBlank(xml)) {
			String perfix = String.format("<%s>", xmlElmentName);
			String suffix = String.format("</%s>", xmlElmentName);
			int beginIndex = xml.indexOf(perfix);
			int endIndex = xml.indexOf(suffix);
			if (beginIndex >= 0 && endIndex >= 0 && endIndex > beginIndex) {
				value = xml.substring(0, beginIndex) + perfix + xmlElmentValue + xml.substring(endIndex);
			}
		}
		
		return value;
	}

	/**
	 * 将指定的数据对象转换成XML元素对象
	 * @param parent		XML元素对象的父节点
	 * @param object		数据对象
	 * @return void			无
	 * @throws Exception
	 */
	private static void format(Element parent, Object object) {
		if (object != null) {
			if (object instanceof Map) {
				Set set = ((Map)object).keySet();
				Iterator iterator = set.iterator();
				while (iterator.hasNext()) {
					Object key = iterator.next();
					Element child = parent.addElement(key.toString());
					Object value = ((Map) object).get(key);
					format(child, value);
				}
			} else if (object instanceof List) {
				Element p = parent.getParent();
				Iterator iterator = ((List)object).iterator();
				while (iterator.hasNext()) {
					Object value = iterator.next();
					Element child = parent.createCopy();
					p.add(child);
					format(child, value);
				}
			} else if (object instanceof Object[]) {
				Element p = parent.getParent();
				for(Object value : (Object[])object) {
					Element child = parent.createCopy();
					p.add(child);
					format(child, value);
				}
				p.remove(parent);
			} else {
				parent.setText(object.toString());
			}
		}
	}
	
	/**
	 * 将XML元素对象转换成数据对象
	 * @param element		XML元素对象
	 * @return Object		数据对象
	 * @throws Exception
	 */
	private static Object parse(Element element) {
		Object object = null;
		
		if (element != null && element.isTextOnly()) {
			object = element.getText();
		} else {
			Map map = new HashMap();
			Iterator iterator = element.elementIterator();
			while (iterator.hasNext()) {
				Element e = (Element) iterator.next();
				String key = e.getName();
				Object value = parse(e);
				Object v = map.get(key);
				if (v != null) {
					List list = null;
					if (v instanceof List) {
						list = (List)v;
					} else {
						list = new ArrayList();
						list.add(v);
						map.put(key, list);
					}
					list.add(value);
				} else {
					map.put(key, value);
				}
			}
			object = map;
		}
		
		return object;
	}
	
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值