/* * @(#)HttpClientUtil.java 2012-5-19 * * @Company < www.360buy.com > */ package com.jd.jdx.x.sr.cms.domain.wxpay.util; import static org.apache.commons.httpclient.params.HttpMethodParams.SO_TIMEOUT; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.security.*; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.*; import com.jd.bk.common.util.json.JsonUtil; import org.apache.commons.collections.MapUtils; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import javax.net.ssl.KeyManagerFactory; /** * @version <1.0> * @Date <2012-5-19 下午2:32:19> * @description < 对HttpClient简单封装 > */ public class HttpClientUtils { private static final org.apache.logging.log4j.Logger logger = LogManager.getLogger(HttpClientUtils.class); /** * 默认编码为UTF-8 */ private static final String HTTP_CONTENT_CHARSET = "UTF-8"; public static final Integer MAX_TIME_OUT = 10000; public static final Integer MAX_IDLE_TIME_OUT = 60000; public static final Integer MAX_CONN = 100; public static HttpClient httpClient = null; static { MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); connectionManager.closeIdleConnections(MAX_IDLE_TIME_OUT); connectionManager.getParams().setParameter("http.connection-manager.max-total", MAX_CONN); httpClient = new HttpClient(connectionManager); httpClient.getParams().setParameter(SO_TIMEOUT, MAX_TIME_OUT); httpClient.getParams().setParameter("http.connection.timeout", MAX_TIME_OUT); httpClient.getParams().setParameter("http.connection-manager.timeout", MAX_TIME_OUT.longValue()); } /** * 发送HTTP请求 目前没有加入重复调用,业务需要可以再次加上 * * @param url * @param param * @return HTTP响应 */ public static String sendPostRequest(String url, Map<String, Object> param) { // HTTP方法,还有get,head,put,delete,connect,options(询问可用的选项) PostMethod post = new PostMethod(url); post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, HTTP_CONTENT_CHARSET); String contentType = "application/json;charset=UTF-8"; post.setRequestHeader("Content-Type", contentType); /*if (param != null) { for (Entry<String, Object> entry : param.entrySet()) { if (entry.getValue() != null) { post.addParameter(entry.getKey(), entry.getValue().toString()); } } }*/ try { // post.addRequestHeader(new Header("Connection", "close")); // post.addRequestHeader("Cookie", "ID=1"); //添加Cookie post.setRequestBody(JsonUtil3.toJSONString(param)); httpClient.executeMethod(post); if (post.getStatusCode() == HttpStatus.SC_OK) { return post.getResponseBodyAsString(); } else { post.abort(); System.out.println(post.getStatusCode()); logger.error("Http Comunication error!code-->" + post.getStatusCode()); } } catch (Exception e) { logger.error("Http post occur error!url=" + url + ",param=" + param, e); } finally { post.releaseConnection(); } return null; } private static String getToken(String method, String url, String body, WechatScorePayPaymentConfig config, PrivateKey key) { String nonceStr = CommonUtil.generateUUID32(); long timestamp = System.currentTimeMillis() / 1000; String message = buildMessage(method, url, timestamp, nonceStr, body); String signature = null; try { signature = sign(message.getBytes("utf-8"), key); } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new RuntimeException("签名出错"); } return "WECHATPAY2-SHA256-RSA2048 mchid=\"" + config.getMchId() + "\"," + "nonce_str=\"" + nonceStr + "\"," + "timestamp=\"" + timestamp + "\"," + "serial_no=\"" + config.getCertificateSerialNo() + "\"," + "signature=\"" + signature + "\""; } private static String sign(byte[] message, PrivateKey key) { Signature sign = null; String re = null; try { sign = Signature.getInstance("SHA256withRSA"); sign.initSign(key); sign.update(message); re = Base64.getEncoder().encodeToString(sign.sign()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); throw new RuntimeException("构造签名出错"); } catch (SignatureException e) { e.printStackTrace(); throw new RuntimeException("构造签名出错"); } catch (InvalidKeyException e) { e.printStackTrace(); throw new RuntimeException("构造签名出错"); } return re; } private static String buildMessage(String method, String url, long timestamp, String nonceStr, String body) { return method + "\n" + url + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n"; } public static void main(String[] args) { System.out.println(buildMessage("method","ll",124341351,"dqtqtqter","")); } /** * post签名验证 v3 * * @param url * @param param * @param method * @param config * @return */ public static String sendWechatScorePayPostJsonRequest(String url, String param, String method, WechatScorePayPaymentConfig config) { // HTTP方法,还有get,head,put,delete,connect,options(询问可用的选项) String canonicalUrl = getUrlRemoveHost(url); PostMethod post = new PostMethod(url); try { PrivateKey key = getPrivateKey(config); logger.error("Http Comunication error!config -->[{}],method-->[{}],param-->[{}]" , JsonUtil3.toJSONString(config),method,param); String authorizationStr = getToken(method, canonicalUrl, param, config, key); post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, HTTP_CONTENT_CHARSET); String contentType = "application/json;charset=UTF-8"; post.setRequestHeader("Content-Type", contentType); post.setRequestHeader("Accept", contentType); post.setRequestHeader("Authorization", authorizationStr); logger.error("Http Comunication error!Authorization -->[{}]" ,authorizationStr); post.setRequestBody(param); httpClient.executeMethod(post); System.out.println(post.getStatusCode()); System.out.println(post.getStatusText()); if (post.getStatusCode() == HttpStatus.SC_OK) { return post.getResponseBodyAsString(); } else { post.abort(); logger.error("Http Comunication error!ret [{}]", JsonUtil.toJson(post)); logger.error("Http Comunication error!code-->" + post.getStatusCode()); } } catch (Exception e) { logger.error("Http post occur error!url=" + url + ",param=" + param, e); } finally { post.releaseConnection(); } return null; } /** * @param url * @param param * @param method * @param config * @return */ public static String sendWechatScorePayPostRequest(String url, Map<String, Object> param, String method, WechatScorePayPaymentConfig config) { // HTTP方法,还有get,head,put,delete,connect,options(询问可用的选项) PostMethod post = new PostMethod(url); try { PrivateKey key = getPrivateKey(config); String authorizationStr = getToken(method, getUrlRemoveHost(url), JsonUtil3.toJSONString(param), config, key); post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, HTTP_CONTENT_CHARSET); String contentType = "application/json;charset=UTF-8"; post.setRequestHeader("Content-Type", contentType); post.setRequestHeader("Accept", contentType); post.setRequestHeader("Authorization", authorizationStr); post.setRequestBody(JsonUtil3.toJSONString(param)); httpClient.executeMethod(post); if (post.getStatusCode() == HttpStatus.SC_OK) { return post.getResponseBodyAsString(); } else { post.abort(); System.out.println(post.getStatusCode()); logger.error("Http Comunication error!code-->" + post.getStatusCode()); } } catch (Exception e) { logger.error("Http post occur error!url=" + url + ",param=" + param, e); } finally { post.releaseConnection(); } return null; } private static PrivateKey getPrivateKey(WechatScorePayPaymentConfig config) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException { InputStream instream; URL certUrl = new URL(config.getCertificateAddress()); HttpURLConnection connection = (HttpURLConnection) certUrl.openConnection(); //设置超时时间为3秒 connection.setConnectTimeout(5 * 1000); //防止屏蔽程序抓取而返回403错误 connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"); instream = connection.getInputStream(); KeyStore keyStore = KeyStore.getInstance("PKCS12"); char[] password = config.getMchId().toCharArray(); try { keyStore.load(instream, password); } finally { instream.close(); } Enumeration en = keyStore.aliases(); String pName = null; while (en.hasMoreElements()) { String n = (String) en.nextElement(); if (keyStore.isKeyEntry(n)) { pName = n; } } // 获取证书的私钥 return (PrivateKey) keyStore.getKey(pName, password); } /** * 发送HTTP请求 目前没有加入重复调用,业务需要可以再次加上 * * @param url * @param param * @return HTTP响应 */ public static String sendPostXMLRequest(String url, Map<String, Object> param) { // HTTP方法,还有get,head,put,delete,connect,options(询问可用的选项) PostMethod post = new PostMethod(url); post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, HTTP_CONTENT_CHARSET); String contentType = "application/xml;charset=UTF-8"; post.setRequestHeader("Content-Type", contentType); try { post.setRequestBody(CommonUtil.map2Xml(param)); httpClient.executeMethod(post); if (post.getStatusCode() == HttpStatus.SC_OK) { return post.getResponseBodyAsString(); } else { post.abort(); System.out.println(post.getStatusCode()); logger.error("Http Comunication error!code-->" + post.getStatusCode()); } } catch (Exception e) { logger.error("Http post occur error!url=" + url + ",param=" + param, e); } finally { post.releaseConnection(); } return null; } /** * 发送HTTP请求 * * @param url * @param content * @return HTTP响应 */ @SuppressWarnings("deprecation") public static String sendPostRequest(String url, String content) { // HTTP方法,还有get,head,put,delete,connect,options(询问可用的选项) PostMethod post = new PostMethod(url); post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, HTTP_CONTENT_CHARSET); if (StringUtils.isNotBlank(content)) { post.setRequestBody(content); } try { post.addRequestHeader(new Header("Connection", "close")); // post.addRequestHeader("Cookie", "ID=1"); //添加Cookie httpClient.executeMethod(post); if (post.getStatusCode() == HttpStatus.SC_OK) { return post.getResponseBodyAsString(); } else { post.abort(); logger.error("Http Comunication error!code-->" + post.getStatusCode()); } } catch (Exception e) { logger.error("Http post occur error!url=" + url + ",content=" + content, e); } finally { post.releaseConnection(); } return null; } /** * 发送HTTP请求 * * @param url * @return HTTP响应 */ public static String getRequest(String url) { // HTTP方法,还有get,head,put,delete,connect,options(询问可用的选项) GetMethod get = new GetMethod(url); get.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, HTTP_CONTENT_CHARSET); try { get.addRequestHeader(new Header("Connection", "close")); // post.addRequestHeader("Cookie", "ID=1"); //添加Cookie httpClient.executeMethod(get); if (get.getStatusCode() == HttpStatus.SC_OK) { return get.getResponseBodyAsString(); } else { get.abort(); logger.error("Http Comunication error!code-->" + get.getStatusCode()); } } catch (Exception e) { logger.error("Http post occur error!url=" + url, e); } finally { get.releaseConnection(); } return null; } /** * @param url * @param param * @return */ public static String sendWeChatPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; StringBuilder result = new StringBuilder(); if (logger.isInfoEnabled()) { logger.info("invoke http post[wechat] service, url: [" + url + "]\nparam: [" + param + "]"); } try { URL realUrl = new URL(url); URLConnection conn = realUrl.openConnection(); conn.setRequestProperty("Content-Type", "application/xml"); conn.setDoOutput(true); conn.setDoInput(true); out = new PrintWriter(conn.getOutputStream()); out.print(param); out.flush(); in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result.append(line); } } catch (Exception e) { logger.error("invoke http post[wechat] service error, because: [" + e.toString() + "]", e); throw new RuntimeException(e); } finally { try { if (in != null) { in.close(); } } catch (IOException e) { logger.error("invoke http post[wechat] service error, because: [" + e.toString() + "]", e); } if (out != null) { out.close(); } } if (logger.isInfoEnabled()) { logger.info("invoke http post[wechat] service finished, url: [" + url + "], response: [" + result.toString() + "]"); } return result.toString(); } public static String sendPostMethodFace(String uri, Map<String, String> map, String contentType) throws Exception { if (contentType == null) { contentType = "application/json;charset=UTF-8"; } String returnStr = ""; PostMethod post = new PostMethod(uri); post.setRequestHeader("Content-Type", contentType); List<NameValuePair> nameValuePairs = mapToNameValePair(map); for (NameValuePair nameValuePair : nameValuePairs) { post.addParameter(nameValuePair); } post.setDoAuthentication(false); post.setRequestHeader("Accept", "application/json"); HttpClient httpclient = new HttpClient(); try { logger.info("sendPostMethodFace--->begin post..."); int result = httpclient.executeMethod(post); logger.info("sendPostMethodFace--->between post..."); returnStr = post.getResponseBodyAsString(); logger.info("sendPostMethodFace--->end post..."); if (result != HttpStatus.SC_OK) { throw new RuntimeException(String.valueOf(post.getStatusCode()) + returnStr); } } catch (IOException e) { throw new RuntimeException(e); } finally { post.releaseConnection(); } logger.info("sendPostMethodFace--->end method and return..."); return returnStr; } /** * map转化到Web参数 * * @param map * @return */ private static List<NameValuePair> mapToNameValePair(Map<String, String> map) { List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); if (MapUtils.isNotEmpty(map)) { for (Map.Entry<String, String> entry : map.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); if (StringUtils.isBlank(key) || StringUtils.isBlank(value)) { continue; } NameValuePair pair = new NameValuePair(key, value); nameValuePairs.add(pair); } } return nameValuePairs; } public static Map<String, String> getUrlParams(String param) { Map<String, String> map = new HashMap<String, String>(0); if (StringUtils.isBlank(param)) { return map; } String[] params = param.split("&"); for (int i = 0; i < params.length; i++) { String[] p = params[i].split("="); if (p.length == 2) { map.put(p[0], p[1]); } } return map; } /** * 发送GET请求 * * @param url getURL * @param params 请求参数 * @return */ public static String doGet(String url, Map<String, String> params) { HttpClient httpCilent = new HttpClient(); url = getUrl(url, params); GetMethod getMethod = new GetMethod(url); String content = null; try { InputStream inputStream = null; try { if (httpCilent.executeMethod(getMethod) == HttpStatus.SC_OK) { inputStream = getMethod.getResponseBodyAsStream(); content = IOUtils.toString(inputStream, "utf-8"); } else { logger.warn("invoke http get service failed, http code: [{}]", getMethod.getStatusLine()); } } catch (Exception e) { logger.error("invoke http get service error, because: [" + e.toString() + "]", e); } finally { IOUtils.closeQuietly(inputStream); getMethod.releaseConnection(); } } catch (Exception e) { logger.error("invoke http get service error, because: [" + e.toString() + "]", e); } finally { getMethod.releaseConnection(); } return content; } /** * 发送GET请求 * * @param url getURL * @param params 请求参数 * @return */ public static String doGetForScorePay(String url, String canonicalUrl, Map<String, String> params, String method, WechatScorePayPaymentConfig config) { HttpClient httpCilent = new HttpClient(); url = getUrl(url, params); GetMethod getMethod = new GetMethod(url); String content = null; try { PrivateKey key = getPrivateKey(config); String authorizationStr = getToken(method, getUrlRemoveHost(url), "", config, key); String contentType = "application/json;charset=UTF-8"; getMethod.setRequestHeader("Content-Type", contentType); getMethod.setRequestHeader("Accept", contentType); getMethod.setRequestHeader("Authorization", authorizationStr); InputStream inputStream = null; try { if (httpCilent.executeMethod(getMethod) == HttpStatus.SC_OK) { inputStream = getMethod.getResponseBodyAsStream(); content = IOUtils.toString(inputStream, "utf-8"); } else { logger.warn("invoke http get service failed, ret [{}]", JsonUtil3.toJSONString(getMethod)); logger.warn("invoke http get service failed, http code: [{}]", getMethod.getStatusLine()); } } catch (Exception e) { logger.error("invoke http get service error, because: [" + e.toString() + "]", e); } finally { IOUtils.closeQuietly(inputStream); getMethod.releaseConnection(); } } catch (Exception e) { logger.error("invoke http get service error, because: [" + e.toString() + "]", e); } finally { getMethod.releaseConnection(); } return content; } /** * getUrl:获取. <br/> * * @param url 请求地址 * @param parameterMap 请求参数 * @return */ private static String getUrl(String url, Map<String, String> parameterMap) { if (parameterMap == null || parameterMap.size() == 0) { return url; } // 设置请求参数 // 采用更有效率的entryset modified by gaotianlin if (url.indexOf("?") == -1) { url += "?"; } StringBuffer bf = new StringBuffer(url); for (Map.Entry<String, String> key : parameterMap.entrySet()) { bf.append("&"); bf.append(key.getKey()); bf.append("="); bf.append(key.getValue()); } return bf.toString(); } private static String getUrlRemoveHost(String url) { //String url="https://api.mch.weixin.qq.com/v3/payscore/serviceorder"; String[] split = url.split("/"); String res = ""; for (int i = 0; i < split.length; i++) { if (i >= 3) { res += "/" + split[i]; } System.out.println(split[i]); } return res; } }