package com.zhx.guides.assistant.config.wechatpay;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.core.io.ClassPathResource;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
/**
* @Class WeChatConfigUtil
* @Version 1.0
* @Date 创建时间:2020-06-15 16:19
* @Copyright Copyright by
* @Direction 类说明
*/
public class WeChatConfigUtil {
private static byte[] certData;
/****
* @throws Exception
*/
static {
try {
//从微信商户平台下载的安全证书存放的目录
//String certPath = "D:\\config\\apiclient_cert.p12";
//File file = new File(certPath);
//InputStream certStream = new FileInputStream(file);
//使用springboot配置文件内读取的方式
ClassPathResource classPathResource = new ClassPathResource("\\user_key\\apiclient_cert.p12");
InputStream certStream = classPathResource.getInputStream();
WeChatConfigUtil.certData = IOUtils.toByteArray(certStream);
certStream.read(WeChatConfigUtil.certData);
certStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 开始退款操作
*
* @param mchId 商户ID
* @param url 请求URL
* @param data 退款参数
* @return
* @throws Exception
*/
public static String doRefund(String mchId, String url, String data) throws Exception {
/**
* 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
*/
KeyStore keyStore = KeyStore.getInstance("PKCS12");
//这里自行实现我是使用数据库配置将证书上传到了服务器可以使用 FileInputStream读取本地文件
//ByteArrayInputStream inputStream = FileUtil.getInputStream("https://############################.p12");
ByteArrayInputStream inputStream = new ByteArrayInputStream(WeChatConfigUtil.certData);
try {
//这里写密码..默认是你的MCHID
keyStore.load(inputStream, mchId.toCharArray());
} finally {
inputStream.close();
}
SSLContext sslcontext = SSLContexts.custom()
//这里也是写密码的
.loadKeyMaterial(keyStore, mchId.toCharArray())
.build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
try {
HttpPost httpost = new HttpPost(url);
httpost.setEntity(new StringEntity(data, "UTF-8"));
CloseableHttpResponse response = httpclient.execute(httpost);
try {
HttpEntity entity = response.getEntity();
//接受到返回信息
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
EntityUtils.consume(entity);
return jsonStr;
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}
/**
* 封装查询请求数据
* @param tradeRefund 退款订单请求信息
* @param path 数据访问PATH
* @return
*/
private static SortedMap refundData( TradeRefund tradeRefund , String path ) throws Exception {
//构建参数
Map dataMap = new HashMap<>();
dataMap.put("appid","wx#################");
dataMap.put("mch_id","137#############");
//自行实现该随机串
dataMap.put("nonce_str",Core.MD5("12344"));
dataMap.put("out_trade_no","P190808170038402889c5318502");
dataMap.put("out_refund_no","P190808170038402889c5318502");
dataMap.put("total_fee","1");
dataMap.put("refund_fee","1");
dataMap.put("refund_desc","退款");
//生成签名
String sign = PayToolUtil.createSign("UTF-8", dataMap , WeichatPayConfigure.API_KEY );
//WXPayUtil.generateSignature(dataMap, "rv4###################");
dataMap.put("sign", sign);
//map数据转xml
String requestXML = getRequestXml( dataMap );
logger.info( "订单退款请求参数:\n" + requestXML );
//发起退款
String responseXml = WeChatConfigUtil.doRefund( WeichatPayConfigure.MCH_ID , "https://api.mch.weixin.qq.com/secapi/pay/refund", requestXML );
}
/**
* @author
* @date 2016-4-22
* @Description:将请求参数转换为xml格式的string
* @param parameters
* 请求参数
* @return
*/
public static String getRequestXml(SortedMap
/**
* @author
* @date 2016-4-22
* @Description:sign签名
* @param characterEncoding
* 编码格式
* @param packageParams
* 请求参数
* @return
*/
public static String createSign(String characterEncoding, SortedMap
package com.zhx.guides.assistant.interfaces.pay.wechatpay.util;
import java.security.MessageDigest;
public class MD5Util {
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
}
/***
* 简化版本
* @param s
* @return
*/
public final static String MD5(String s) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
try {
byte[] btInput = s.getBytes("utf-8");
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
}
/**
* @author
* @date 2016-4-22
* @Description:将请求参数转换为xml格式的string
* @param parameters
* 请求参数
* @return
*/
public static String getRequestXml(SortedMap
wx2421b1c4370ec43b
10000100
6cefdb308e1e2e8aabd48cf79e546a02
1415701182
1415757673
1
1
FE56DD4AA85C0EECA82C35595A69E153
官方地址:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_4
需注意这两个参数我使用的是out_trade_no
import java.io.Serializable;
import org.apache.http.Header;
/**
* @Class HttpClientResponse
* @Author
* @Version 1.0
* @Date 创建时间:2019-04-23 15:11
* @Copyright Copyright by company
* @Direction 类说明
*/
public class HttpClientResponse implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String body ;
private Header[] headers ;
private String reasonPhrase ;
private int statusCode ;
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public Header[] getHeaders() {
return headers;
}
public void setHeaders(Header[] headers) {
this.headers = headers;
}
public String getReasonPhrase() {
return reasonPhrase;
}
public void setReasonPhrase(String reasonPhrase) {
this.reasonPhrase = reasonPhrase;
}
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
}
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @Class HttpClientResponse
* @Author
* @Version 1.0
* @Date 创建时间:2019-04-23 15:11
* @Copyright Copyright by company
* @Direction 类说明
*/
public class HttpClientUtil {
/**
* 发送http get请求
*/
public static HttpClientResponse httpGet(String url, Map headers, String encode){
HttpClientResponse response = new HttpClientResponse();
if(encode == null){
encode = "utf-8";
}
String content = null;
//since 4.3 不再使用 DefaultHttpClient
CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet(url);
//设置header
if (headers != null && headers.size() > 0) {
for (Map.Entry entry : headers.entrySet()) {
httpGet.setHeader(entry.getKey(),entry.getValue());
}
}
CloseableHttpResponse httpResponse = null;
try {
httpResponse = closeableHttpClient.execute(httpGet);
HttpEntity entity = httpResponse.getEntity();
content = EntityUtils.toString(entity, encode);
response.setBody(content);
response.setHeaders(httpResponse.getAllHeaders());
response.setReasonPhrase(httpResponse.getStatusLine().getReasonPhrase());
response.setStatusCode(httpResponse.getStatusLine().getStatusCode());
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
httpResponse.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try { //关闭连接、释放资源
closeableHttpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
/**
* 发送 http post 请求,参数以form表单键值对的形式提交。
*/
public static HttpClientResponse httpPostForm(String url,Map params, Map headers,String encode)throws Exception{
HttpClientResponse response = new HttpClientResponse();
if(encode == null){
encode = "utf-8";
}
//HttpClients.createDefault()等价于 HttpClientBuilder.create().build();
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
HttpPost httpost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(1000).setConnectTimeout(1500).build();//设置请求和传输超时时间
httpost.setConfig( requestConfig );
//设置header
if (headers != null && headers.size() > 0) {
for (Map.Entry entry : headers.entrySet()) {
httpost.setHeader(entry.getKey(),entry.getValue());
}
}
//组织请求参数
List paramList = new ArrayList ();
if(params != null && params.size() > 0){
Set keySet = params.keySet();
for(String key : keySet) {
paramList.add(new BasicNameValuePair(key, params.get(key)));
}
}
try {
httpost.setEntity(new UrlEncodedFormEntity(paramList, encode));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
String content = null;
CloseableHttpResponse httpResponse = null;
try {
httpResponse = closeableHttpClient.execute(httpost);
HttpEntity entity = httpResponse.getEntity();
content = EntityUtils.toString(entity, encode);
response.setBody(content);
response.setHeaders(httpResponse.getAllHeaders());
response.setReasonPhrase(httpResponse.getStatusLine().getReasonPhrase());
response.setStatusCode(httpResponse.getStatusLine().getStatusCode());
} catch (Exception e) {
throw e ;
}finally{
try {
httpResponse.close();
} catch (IOException e) {}
}
try { //关闭连接、释放资源
closeableHttpClient.close();
} catch (IOException e) {}
return response;
}
/**
* 发送 http post 请求,参数以原生字符串进行提交
* @param url
* @param encode
* @return
*/
public static HttpClientResponse httpPostRaw(String url,String stringJson,Map headers, String encode)throws Exception{
HttpClientResponse response = new HttpClientResponse();
if(encode == null){
encode = "utf-8";
}
//HttpClients.createDefault()等价于 HttpClientBuilder.create().build();
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
HttpPost httpost = new HttpPost(url);
//设置超时信息
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build();//设置请求和传输超时时间
httpost.setConfig(requestConfig);
//设置header
httpost.setHeader("Content-type", "application/json");
if (headers != null && headers.size() > 0) {
for (Map.Entry entry : headers.entrySet()) {
httpost.setHeader(entry.getKey(),entry.getValue());
}
}
//组织请求参数
StringEntity stringEntity = new StringEntity(stringJson, encode);
httpost.setEntity(stringEntity);
String content = null;
CloseableHttpResponse httpResponse = null;
try {
//响应信息
httpResponse = closeableHttpClient.execute(httpost);
HttpEntity entity = httpResponse.getEntity();
content = EntityUtils.toString(entity, encode);
response.setBody(content);
response.setHeaders(httpResponse.getAllHeaders());
response.setReasonPhrase(httpResponse.getStatusLine().getReasonPhrase());
response.setStatusCode(httpResponse.getStatusLine().getStatusCode());
} catch (Exception e) {
throw e ;
}finally{
try {
httpResponse.close();
} catch (Exception e) {}
}
try { //关闭连接、释放资源
closeableHttpClient.close();
} catch (Exception e) {
}
return response;
}
/**
* 发送 http put 请求,参数以原生字符串进行提交
* @param url
* @param encode
* @return
*/
public static HttpClientResponse httpPutRaw(String url,String stringJson,Map headers, String encode){
HttpClientResponse response = new HttpClientResponse();
if(encode == null){
encode = "utf-8";
}
//HttpClients.createDefault()等价于 HttpClientBuilder.create().build();
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
HttpPut httpput = new HttpPut(url);
//设置header
httpput.setHeader("Content-type", "application/json");
if (headers != null && headers.size() > 0) {
for (Map.Entry entry : headers.entrySet()) {
httpput.setHeader(entry.getKey(),entry.getValue());
}
}
//组织请求参数
StringEntity stringEntity = new StringEntity(stringJson, encode);
httpput.setEntity(stringEntity);
String content = null;
CloseableHttpResponse httpResponse = null;
try {
//响应信息
httpResponse = closeableHttpClient.execute(httpput);
HttpEntity entity = httpResponse.getEntity();
content = EntityUtils.toString(entity, encode);
response.setBody(content);
response.setHeaders(httpResponse.getAllHeaders());
response.setReasonPhrase(httpResponse.getStatusLine().getReasonPhrase());
response.setStatusCode(httpResponse.getStatusLine().getStatusCode());
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
httpResponse.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
closeableHttpClient.close(); //关闭连接、释放资源
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
}
Maven 引用
commons-httpclient
commons-httpclient
3.1