1.socket
1.1 client
1.1.1 方式1
public static String signAndVerify(String message, String signServeHost, int signServePort) {
LOGGER.info("签名验签请求:" + message);
Socket socket = null;
OutputStream outs = null;
BufferedOutputStream bouts = null;
InputStream ins = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
socket = new Socket();
// 设置连接请求超时时间10s
socket.connect(new InetSocketAddress(signServeHost, signServePort), MAX_TIMEOUT);
// 设置读操作超时时间15s,setSoTimeout()设置的是读取数据时阻塞链路的超时时间,原文(Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. With this option set to a non-zero timeout, a read() call on the InputStream associated with this Socket will block for only this amount of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid. The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.)
socket.setSoTimeout(MAX_TIMEOUT);
// 获取输出流
outs = socket.getOutputStream();
/* 写入请求数据 */
bouts = new BufferedOutputStream(outs);
bouts.write(message.getBytes("GBK"));
bouts.flush();
// 结束发送
socket.shutdownOutput();
// 获取输入流
ins = socket.getInputStream();
isr = new InputStreamReader(ins, "GBK");
br = new BufferedReader(isr);
/* 读取返回数据 */
StringBuffer sb = new StringBuffer();
String info = null;
while ((info = br.readLine()) != null) {
sb.append(info);
}
String resultMsg = sb.toString();
LOGGER.info("返回:" + resultMsg);
return resultMsg;
} catch (Exception e) {
LOGGER.error("失败", e);
BankAdapterException te = new BankAdapterException("失败" + e.getMessage(), e);
te.setErrorCode(String.valueOf(ErrorCode.RECEIVE_FROM_BANK_ERROR));
throw te;
} finally {
try {
br.close();
isr.close();
ins.close();
socket.close();
} catch (IOException e) {
LOGGER.error("释放异常");
}
}
}
1.1.2 方式2
public String sendMessageRequest(String message, String bankFrontIP, int bankFrontPort) throws BankAdapterException {
Socket socket = null;
OutputStream outs = null;
PrintWriter pw = null;
InputStream ins = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
try {
// 建立sockt连接
socket = new Socket();
// 设置连接请求超时时间15s
socket.connect(new InetSocketAddress(bankFrontIP, bankFrontPort), 15000);
// 设置读操作超时时间30s
socket.setSoTimeout(30000);
// 获取输出流
outs = socket.getOutputStream();
/* 写入请求数据 */
pw = new PrintWriter(outs);
pw.print(message);
pw.flush();
socket.shutdownOutput();
} catch (Exception e) {
LOGGER.error("报文发送异常", e);
BankAdapterException te = new BankAdapterException("报文发送异常:" + e.getMessage(), e);
te.setErrorCode(String.valueOf(ErrorCode.SEND_TO_BANK_ERROR));
throw te;
}
try {
// 获取输入流
ins = socket.getInputStream();
isr = new InputStreamReader(ins);
br = new BufferedReader(isr);
/* 读取返回数据 */
StringBuffer sb = new StringBuffer();
String info = null;
while ((info = br.readLine()) != null) {
sb.append(info);
}
return sb.toString();
} catch (Exception e) {
LOGGER.error("接收回复异常", e);
BankAdapterException te = new BankAdapterException("接收回复异常:" + e.getMessage(), e);
te.setErrorCode(String.valueOf(ErrorCode.RECEIVE_FROM_BANK_ERROR));
throw te;
}
}finally {
try {
socket.shutdownInput();
ins.close();
isr.close();
br.close();
} catch (IOException e) {
LOGGER.error("关闭输入流失败");
}
try {
LOGGER.info("正在关闭套接字");
socket.close();
} catch (IOException e) {
LOGGER.error("关闭套接字失败");
}
}
}
1.2 server
2.http
2.1 client
2.2 server
3.https
3.1 client
3.3.1 不校验证书
public String sendBankServer(String postData, String reqUrl) throws Exception {
LOGGER.info("\n请求银行URL:" + reqUrl + "\n发送银行内容:" + postData);
CloseableHttpClient httpClient = getIgnoredCertHttpClient();
StringEntity stringEntity = new StringEntity(postData, "GBK");
stringEntity.setContentEncoding("GBK");
stringEntity.setContentType("text/xml; charset=GBK");
HttpPost httpPost = new HttpPost(reqUrl);
httpPost.setHeader("Content-Type", "text/xml; charset=GBK");
httpPost.setHeader("Host", BANK_HOST);
httpPost.setEntity(stringEntity);
String responseBody = "";
try {
// 执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponse response = httpClient.execute(httpPost);
// 获取结果实体
HttpEntity httpEntity = response.getEntity();
if (httpEntity != null) {
// 按指定编码转换结果实体为String类型
responseBody = EntityUtils.toString(httpEntity, "GBK");
}
// 释放httpEntity占用的所有资源,实质是释放底层的流并将连接归还连接池
EntityUtils.consume(httpEntity);
// 释放链接
response.close();
} finally {
httpClient.close();
}
LOGGER.info("收到银行回复:" + responseBody);
return responseBody;
}
public CloseableHttpClient getIgnoredCertHttpClient() throws KeyManagementException, NoSuchAlgorithmException {
// 实现一个X509TrustManager接口,信任证书用于绕过验证,不用修改里面的方法
X509TrustManager trustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
};
SSLContext sslContext = SSLContext.getInstance("SSLv3");
// 采用绕过验证的方式处理https请求
sslContext.init(null, new TrustManager[] { trustManager }, null);
// 设置协议http和https对应的处理socket链接工厂的对象
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
// 不校验主机名
.register("https", new SSLConnectionSocketFactory(sslContext, new AllowAllHostnameVerifier()))
.build();
//创建http连接池管理器
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
// 请求参数设置
RequestConfig requestConfig = RequestConfig.custom()
// 从连接池中获取连接的超时时间
.setConnectionRequestTimeout(MAX_TIMEOUT)
// 与服务器连接超时时间:httpclient会创建一个异步线程用以创建socket连接,此处设置该socket的连接超时时间
.setConnectTimeout(MAX_TIMEOUT)
// socket读取数据时阻塞链路的超时时间,即从服务器获取响应数据的超时时间
.setSocketTimeout(MAX_TIMEOUT)
// 在提交请求之前测试连接是否可用The stale connection check can cause up to 30 millisecond overhead per request
//.setStaleConnectionCheckEnabled(true)
// 不做认证
.setAuthenticationEnabled(false)
.build();
// 创建自定义的httpclient对象
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connManager)
.setDefaultRequestConfig(requestConfig)
.build();
return httpClient;
}
3.1.2使用证书
public CloseableHttpClient getHttpClient(String certFilePath,String keyStoryPwd) {
FileInputStream instream = null;
CloseableHttpClient httpclient = null;
try {
// 指定读取证书格式为PKCS12
KeyStore keyStore = KeyStore.getInstance("PKCS12");
// 读取本机存放的PKCS12证书文件
instream = new FileInputStream(new File(certFilePath));
// 指定PKCS12的密码(商户ID)
keyStore.load(instream, keyStoryPwd.toCharArray());
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, keyStoryPwd.toCharArray()).build();
// 指定TLS版本
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
// 设置httpclient的SSLSocketFactory
httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
} catch (KeyStoreException e) {
LOGGER.error("私钥文件异常", e);
} catch (FileNotFoundException e) {
LOGGER.error("证书文件未找到", e);
}catch (NoSuchAlgorithmException e) {
LOGGER.error("算法异常", e);
} catch (CertificateException e) {
LOGGER.error("证书异常", e);
} catch (IOException e) {
LOGGER.error("读取证书文件异常", e);
} catch (KeyManagementException e) {
LOGGER.error("KeyManagementException异常", e);
} catch (UnrecoverableKeyException e) {
LOGGER.error("UnrecoverableKeyException异常", e);
}finally{
if(instream !=null){
try {
instream.close();
} catch (IOException e) {
LOGGER.error("inputStream close IOException:" + e.getMessage());
}
}
}
return httpclient;
}
protected String postRequest(String urlAddr, String reqXml) throws Exception {
String responseXML = null;
//import httpclient-4.3.6.jar
CloseableHttpResponse response = null;
String keyStoryPwd = "证书密钥";
String certFilePath = "证书地址";
CloseableHttpClient httpclient = getHttpClient(certFilePath,keyStoryPwd);
try {
HttpPost httppost = new HttpPost(urlAddr);
StringEntity pentity = new StringEntity(reqXml, Charset.forName("UTF-8"));
pentity.setContentEncoding("UTF-8");
pentity.setContentType("text/xml");
httppost.setEntity(pentity);
response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
if (entity != null) {
//import httpcore-4.3.3.jar EntityUtils
byte[] buff = EntityUtils.toByteArray(entity);
responseXML = new String(buff, "UTF-8");
}
LOGGER.info("receive:" + responseXML);
return responseXML;
} catch (IOException e) {
LOGGER.error("读返回信息失败" + e.getMessage());
} finally {
try {
response.close();
} catch (IOException e) {
LOGGER.error("response close IOException:" + e.getMessage());
}
try {
httpclient.close();
} catch (IOException e) {
LOGGER.error("httpclient close IOException:" + e.getMessage());
}
}
return null;
}