app微信支付-java服务端接口 支付-查询-退款

时间:2024-01-18 15:35:08

个人不怎么看得懂微信的文档,看了很多前辈的写法,终于调通了,在这里做一下记录。

首先来定义各种处理类(微信支付不需要特殊jar包,很多处理需要自己封装,当然也可以自己写完打个jar包)

参数要用jdom解析   自行导入jar包

或者在maven pom.xml中导入

<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>1.1.3</version>
</dependency>
version根据自己maven库中版本号进行设置

1、常用参数类

/**
* 微信支付请求常量
* Created by HQ on 2017/12/11 0011.
*/
public class ConstantUtil {
/**
* 微信开发平台应用ID
*/
public static final String APP_ID="***";
/**
* 应用对应的凭证
*/
public static final String APP_SECRET="***";
/**
* 应用对应的密钥
*/
public static final String APP_KEY="***";
/**
* 微信支付商户号
*/
public static final String MCH_ID="***";
/**
* 商品描述
*/
public static final String BODY="***";
/**
* 商户号对应的密钥
*/
public static final String PARTNER_key="***";
/**
* 商户id 我是用的与商户号相同
*/
public static final String PARTNER_ID="***";
/**
* 常量固定值 可自定义
*/
public static final String GRANT_TYPE="client_credential";
/**
* 获取预支付id的接口url 微信端提供的预支付信息生成借口
*/
public static String GATEURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
/**
* 获取支付订单信息url 微信端提供的查询订单接口
*/
public static String GATESELECTURL = "https://api.mch.weixin.qq.com/pay/orderquery";
/**
* 微信退款url 微信端提供的退款接口
*/
public static String GATEREFUNDURL = "https://api.mch.weixin.qq.com/secapi/pay/refund"; /**
* 微信服务器回调通知url 编写的回调借口 根据自己框架的url访问方式配置
* 我们的url格式是 http://ip:端口/项目名/controller.do?方法requestMap
*/
public static String NOTIFY_URL=".do?weiXinNotify";

2、http客户端工具类

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map; public class HttpClientUtil {
/**
* http客户端工具类
*
*/
public static final String SunX509 = "SunX509";
public static final String JKS = "JKS";
public static final String PKCS12 = "PKCS12";
public static final String TLS = "TLS"; /**
* get HttpURLConnection
* @param strUrl url地址
* @return HttpURLConnection
* @throws java.io.IOException
*/
public static HttpURLConnection getHttpURLConnection(String strUrl)
throws IOException {
URL url = new URL(strUrl);
HttpURLConnection httpURLConnection = (HttpURLConnection) url
.openConnection();
return httpURLConnection;
} /**
* get HttpsURLConnection
* @param strUrl url地址ַ
* @return HttpsURLConnection
* @throws IOException
*/
public static HttpsURLConnection getHttpsURLConnection(String strUrl)
throws IOException {
URL url = new URL(strUrl);
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url
.openConnection();
return httpsURLConnection;
} /**
* 获取不带查询串的url
* @param strUrl
* @return String
*/
public static String getURL(String strUrl) { if(null != strUrl) {
int indexOf = strUrl.indexOf("?");
if(-1 != indexOf) {
return strUrl.substring(0, indexOf);
} return strUrl;
} return strUrl; } /**
* 获取查询串
* @param strUrl
* @return String
*/
public static String getQueryString(String strUrl) { if(null != strUrl) {
int indexOf = strUrl.indexOf("?");
if(-1 != indexOf) {
return strUrl.substring(indexOf+1, strUrl.length());
} return "";
} return strUrl;
} /**
* 查询字符串转化为map
* name1=key1&name2=key2&...
* @param queryString
* @return
*/
public static Map queryString2Map(String queryString) {
if(null == queryString || "".equals(queryString)) {
return null;
} Map m = new HashMap();
String[] strArray = queryString.split("&");
for(int index = 0; index < strArray.length; index++) {
String pair = strArray[index];
HttpClientUtil.putMapByPair(pair, m);
} return m; } /**
* 把键值添加到map
* pair:name=value
* @param pair name=value
* @param m
*/
public static void putMapByPair(String pair, Map m) { if(null == pair || "".equals(pair)) {
return;
} int indexOf = pair.indexOf("=");
if(-1 != indexOf) {
String k = pair.substring(0, indexOf);
String v = pair.substring(indexOf+1, pair.length());
if(null != k && !"".equals(k)) {
m.put(k, v);
}
} else {
m.put(pair, "");
}
}
/**
* BufferedReader转换成String<br/>
* 注意:流关闭需要自行处理
* @param reader
* @return
* @throws IOException
*/
public static String bufferedReader2String(BufferedReader reader) throws IOException {
StringBuffer buf = new StringBuffer();
String line = null;
while( (line = reader.readLine()) != null) {
buf.append(line);
buf.append("\r\n");
} return buf.toString();
}
/**
* 处理输出<br/>
* 注意:流关闭需要自行处理
* @param out
* @param data
* @param len
* @throws IOException
*/
public static void doOutput(OutputStream out, byte[] data, int len)
throws IOException {
int dataLen = data.length;
int off = 0;
while (off < data.length) {
if (len >= dataLen) {
out.write(data, off, dataLen);
off += dataLen;
} else {
out.write(data, off, len);
off += len;
dataLen -= len;
} // ˢ�»�����
out.flush();
} }
/**
* 获取SSLContext
* @param trustFileInputStream
* @param trustPasswd
* @param keyFileInputStream
* @param keyPasswd
* @return
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
* @throws IOException
* @throws CertificateException
* @throws UnrecoverableKeyException
* @throws KeyManagementException
*/
public static SSLContext getSSLContext(
FileInputStream trustFileInputStream, String trustPasswd,
FileInputStream keyFileInputStream, String keyPasswd)
throws NoSuchAlgorithmException, KeyStoreException,
CertificateException, IOException, UnrecoverableKeyException,
KeyManagementException { // ca
TrustManagerFactory tmf = TrustManagerFactory.getInstance(HttpClientUtil.SunX509);
KeyStore trustKeyStore = KeyStore.getInstance(HttpClientUtil.JKS);
trustKeyStore.load(trustFileInputStream, HttpClientUtil
.str2CharArray(trustPasswd));
tmf.init(trustKeyStore); final char[] kp = HttpClientUtil.str2CharArray(keyPasswd);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(HttpClientUtil.SunX509);
KeyStore ks = KeyStore.getInstance(HttpClientUtil.PKCS12);
ks.load(keyFileInputStream, kp);
kmf.init(ks, kp); SecureRandom rand = new SecureRandom();
SSLContext ctx = SSLContext.getInstance(HttpClientUtil.TLS);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), rand); return ctx;
} /**
* 字符串转换成char数组
* @param str
* @return char[]
*/
public static char[] str2CharArray(String str) {
if(null == str) return null; return str.toCharArray();
} public static InputStream String2Inputstream(String str) {
return new ByteArrayInputStream(str.getBytes());
} /**
* InputStream转换成Byte
* 注意:流关闭需要自行处理
* @param in
* @return byte
* @throws Exception
*/
public static byte[] InputStreamTOByte(InputStream in) throws IOException{ int BUFFER_SIZE = 4096;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] data = new byte[BUFFER_SIZE];
int count = -1; while((count = in.read(data,0,BUFFER_SIZE)) != -1)
outStream.write(data, 0, count); data = null;
byte[] outByte = outStream.toByteArray();
outStream.close(); return outByte;
} /**
* InputStream转换成String
* 注意:流关闭需要自行处理
* @param in
* @param encoding 编码
* @return String
* @throws Exception
*/
public static String InputStreamTOString(InputStream in,String encoding) throws IOException{ return new String(InputStreamTOByte(in),encoding); }

3、MD5加密类

import java.security.MessageDigest;

/**
* Created by HQ on 2017/12/11 0011.
*/
public class MD5Util {
/**
* MD5加密
* @param b
* @return
*/
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;
} private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; public static String getMessageDigest(byte[] buffer) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
try {
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(buffer);
byte[] md = mdTemp.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) {
return "异常";
}
} }

4、订单号生成类    这个可以自行判断要不要(只要不重复就行)    我是提前有个订单信息 前端直接给我订单号,当然订单号也是用这个类生成的。

import org.jeecgframework.core.util.DateUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Random; /**
* Created by HQ on 2017/12/11 0011.
*/
public class OrderNumUtil {
private static Date date = new Date();
private static StringBuilder buf = new StringBuilder();
private static int seq = 0;
private static final int ROTATION = 99999; public static synchronized String next() {
if (seq > ROTATION)
seq = 0;
buf.delete(0, buf.length());
date.setTime(System.currentTimeMillis());
String str = String.format("%1$tY%1$tm%1$td%1$tk%1$tM%1$tS%2$05d", date, seq++);
return str;
} public static synchronized String orderDatrNum() {
String randNum ="";
try {
Random rand = new Random();
int shu2 = rand.nextInt(9);
randNum+= DateUtils.getDate("yyyyMMddHHmmss") + shu2;// DateUtils 是项目中统一处理时间的 没有的话可自行处理 就是个时间格式转换
} catch (Exception e) {
e.printStackTrace();
}
return randNum;
}
}

5、获取支付prypPayId请求类

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import java.util.Map;
import java.util.Set; /**
* 微信支付处理
* Created by HQon 2017/12/11 0011.
*/
public class PrepayIdRequestHandler extends RequestHandler{
public PrepayIdRequestHandler(HttpServletRequest request,
HttpServletResponse response) {
super(request, response);
} public String createMD5Sign() {
StringBuffer sb = new StringBuffer();
Set es = super.getAllParameters().entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append(k + "=" + v + "&");
}
String params=sb.append("key="+ ConstantUtil.APP_KEY).substring(0);
String sign = MD5Util.MD5Encode(params, "utf8");
return sign.toUpperCase();
} // 提交预支付
public String sendPrepay() throws Exception {
String prepayid = "";
Set es=super.getAllParameters().entrySet();
Iterator it=es.iterator();
StringBuffer sb = new StringBuffer("<xml>");
while(it.hasNext()){
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append("<"+k+">"+v+"</"+k+">");
}
sb.append("</xml>");
String params=sb.substring(0);
System.out.println("请求参数:"+params);
String requestUrl = super.getGateUrl();
System.out.println("请求url:"+requestUrl);
TenpayHttpClient httpClient = new TenpayHttpClient();
httpClient.setReqContent(requestUrl);
String resContent = "";
if (httpClient.callHttpPost(requestUrl, params)) {
resContent = httpClient.getResContent();
System.out.println("获取prepayid的返回值:"+resContent);
Map<String,String> map=XMLUtil.doXMLParse(resContent);
if(map.containsKey("prepay_id"))
prepayid=map.get("prepay_id");
}
return prepayid;
}
}

6、签名请求类

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
/**
* Created by HQ on 2017/12/11 0011.
*/
public class RequestHandler {
/** 网关url地址 */
private String gateUrl; /** 密钥 */
private String key; /** 请求的参数 */
private SortedMap parameters; protected HttpServletRequest request; protected HttpServletResponse response; /**
* 构造函数
* @param request
* @param response
*/
public RequestHandler(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response; this.gateUrl = "https://gw.tenpay.com/gateway/pay.htm";
this.key = "";
this.parameters = new TreeMap();
} /**
*初始化函数。
*/
public void init() {
//nothing to do
} /**
*获取入口地址,不包含参数值
*/
public String getGateUrl() {
return gateUrl;
}
/**
*设置入口地址,不包含参数值
*/
public void setGateUrl(String gateUrl) {
this.gateUrl = gateUrl;
} /**
*获取密钥
*/
public String getKey() {
return key;
} /**
*设置密钥
*/
public void setKey(String key) {
this.key = key;
} /**
* 获取参数值
* @param parameter 参数名称
* @return String
*/
public String getParameter(String parameter) {
String s = (String)this.parameters.get(parameter);
return (null == s) ? "" : s;
} /**
* 设置参数值
* @param parameter 参数名称
* @param parameterValue 参数值
*/
public void setParameter(String parameter, Object parameterValue) {
String v = "";
if(null != parameterValue) {
if(parameterValue instanceof String)
v = ((String) parameterValue).trim();
}
this.parameters.put(parameter, v);
} /**
* 返回所有的参数
* @return SortedMap
*/
public SortedMap getAllParameters() {
return this.parameters;
} /**
* 获取带参数的请求URL
* @return String
* @throws UnsupportedEncodingException
*/
public String getRequestURL() throws UnsupportedEncodingException { this.createSign(); StringBuffer sb = new StringBuffer();
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue(); if(!"spbill_create_ip".equals(k)) {
sb.append(k + "=" + URLEncoder.encode(v, enc) + "&");
} else {
sb.append(k + "=" + v.replace("\\.", "%2E") + "&");
}
} //去掉最后一个&
String reqPars = sb.substring(0, sb.lastIndexOf("&")); return this.getGateUrl() + "?" + reqPars; } public void doSend() throws UnsupportedEncodingException, IOException {
this.response.sendRedirect(this.getRequestURL());
} /**
* 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
*/
protected void createSign() {
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + this.getKey());
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
String sign = MD5Util.MD5Encode(sb.toString(), enc).toUpperCase(); this.setParameter("sign", sign); } protected HttpServletRequest getHttpServletRequest() {
return this.request;
} protected HttpServletResponse getHttpServletResponse() {
return this.response;
}
}

7、响应参数处理类

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.*; /**
* Created by HQ on 2017/12/11 0011.
*/
public class ResponseHandler {
/** 密钥 */
private String key; /** 应答的参数 */
private SortedMap parameters; private HttpServletRequest request; private HttpServletResponse response; private String uriEncoding; /**
* 构造函数
*
* @param request
* @param response
*/
public ResponseHandler(HttpServletRequest request,
HttpServletResponse response) {
this.request = request;
this.response = response; this.key = "";
this.parameters = new TreeMap();
this.uriEncoding = ""; Map m = this.request.getParameterMap();
Iterator it = m.keySet().iterator();
while (it.hasNext()) {
String k = (String) it.next();
String v = ((String[]) m.get(k))[0];
this.setParameter(k, v);
} } /**
*获取密钥
*/
public String getKey() {
return key;
} /**
*设置密钥
*/
public void setKey(String key) {
this.key = key;
} /**
* 获取参数值
* @param parameter 参数名称
* @return String
*/
public String getParameter(String parameter) {
String s = (String)this.parameters.get(parameter);
return (null == s) ? "" : s;
} /**
* 设置参数值
* @param parameter 参数名称
* @param parameterValue 参数值
*/
public void setParameter(String parameter, String parameterValue) {
String v = "";
if(null != parameterValue) {
v = parameterValue.trim();
}
this.parameters.put(parameter, v);
} /**
* 返回所有的参数
* @return SortedMap
*/
public SortedMap getAllParameters() {
return this.parameters;
} /**
* 是否财付通签名,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
* @return boolean
*/
public boolean isTenpaySign() {
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(!"sign".equals(k) && null != v && !"".equals(v)) {
sb.append(k + "=" + v + "&");
}
} sb.append("key=" + this.getKey()); //算出摘要
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase(); String tenpaySign = this.getParameter("sign").toLowerCase(); return tenpaySign.equals(sign);
} /**
* 返回处理结果给财付通服务器。
* @param msg: Success or fail。
* @throws IOException
*/
public void sendToCFT(String msg) throws IOException {
String strHtml = msg;
PrintWriter out = this.getHttpServletResponse().getWriter();
out.println(strHtml);
out.flush();
out.close(); } /**
* 获取uri编码
* @return String
*/
public String getUriEncoding() {
return uriEncoding;
} /**
* 设置uri编码
* @param uriEncoding
* @throws UnsupportedEncodingException
*/
public void setUriEncoding(String uriEncoding)
throws UnsupportedEncodingException {
if (!"".equals(uriEncoding.trim())) {
this.uriEncoding = uriEncoding; // 编码转换
String enc = TenpayUtil.getCharacterEncoding(request, response);
Iterator it = this.parameters.keySet().iterator();
while (it.hasNext()) {
String k = (String) it.next();
String v = this.getParameter(k);
v = new String(v.getBytes(uriEncoding.trim()), enc);
this.setParameter(k, v);
}
}
} protected HttpServletRequest getHttpServletRequest() {
return this.request;
} protected HttpServletResponse getHttpServletResponse() {
return this.response;
} }

8、财付通请求客户端

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection; /**
* Created by heqiao on 2017/12/11 0011.
*/
public class TenpayHttpClient {
/** 请求内容,无论post和get,都用get方式提供 */
private String reqContent; /** 应答内容 */
private String resContent; /** 请求方法 */
private String method; /** 错误信息 */
private String errInfo; /** 超时时间,以秒为单位 */
private int timeOut; /** http应答编码 */
private int responseCode; /** 字符编码 */
private String charset; private InputStream inputStream; public TenpayHttpClient() {
this.reqContent = "";
this.resContent = "";
this.method = "POST";
this.errInfo = "";
this.timeOut = 30;//30秒 this.responseCode = 0;
this.charset = "utf8"; this.inputStream = null;
} /**
* 设置请求内容
* @param reqContent 表求内容
*/
public void setReqContent(String reqContent) {
this.reqContent = reqContent;
} /**
* 获取结果内容
* @return String
* @throws IOException
*/
public String getResContent() {
try {
this.doResponse();
} catch (IOException e) {
this.errInfo = e.getMessage();
//return "";
} return this.resContent;
} /**
* 设置请求方法post或者get
* @param method 请求方法post/get
*/
public void setMethod(String method) {
this.method = method;
} /**
* 获取错误信息
* @return String
*/
public String getErrInfo() {
return this.errInfo;
} /**
* 设置超时时间,以秒为单位
* @param timeOut 超时时间,以秒为单位
*/
public void setTimeOut(int timeOut) {
this.timeOut = timeOut;
} /**
* 获取http状态码
* @return int
*/
public int getResponseCode() {
return this.responseCode;
} protected void callHttp() throws IOException { if("POST".equals(this.method.toUpperCase())) {
String url = HttpClientUtil.getURL(this.reqContent);
String queryString = HttpClientUtil.getQueryString(this.reqContent);
byte[] postData = queryString.getBytes(this.charset);
this.httpPostMethod(url, postData); return ;
} this.httpGetMethod(this.reqContent); } public boolean callHttpPost(String url, String postdata) {
boolean flag = false;
byte[] postData;
try {
postData = postdata.getBytes(this.charset);
this.httpPostMethod(url, postData);
flag = true;
} catch (IOException e1) {
e1.printStackTrace();
}
return flag;
} /**
* 以http post方式通信
* @param url
* @param postData
* @throws IOException
*/
protected void httpPostMethod(String url, byte[] postData)
throws IOException { HttpURLConnection conn = HttpClientUtil.getHttpURLConnection(url); this.doPost(conn, postData);
} /**
* 以http get方式通信
*
* @param url
* @throws IOException
*/
protected void httpGetMethod(String url) throws IOException { HttpURLConnection httpConnection =
HttpClientUtil.getHttpURLConnection(url); this.setHttpRequest(httpConnection); httpConnection.setRequestMethod("GET"); this.responseCode = httpConnection.getResponseCode(); this.inputStream = httpConnection.getInputStream(); } /**
* 以https get方式通信
* @param url
* @param sslContext
* @throws IOException
*/
protected void httpsGetMethod(String url, SSLContext sslContext)
throws IOException { SSLSocketFactory sf = sslContext.getSocketFactory(); HttpsURLConnection conn = HttpClientUtil.getHttpsURLConnection(url); conn.setSSLSocketFactory(sf); this.doGet(conn); } protected void httpsPostMethod(String url, byte[] postData,
SSLContext sslContext) throws IOException { SSLSocketFactory sf = sslContext.getSocketFactory(); HttpsURLConnection conn = HttpClientUtil.getHttpsURLConnection(url); conn.setSSLSocketFactory(sf); this.doPost(conn, postData); } /**
* 设置http请求默认属性
* @param httpConnection
*/
protected void setHttpRequest(HttpURLConnection httpConnection) { //设置连接超时时间
httpConnection.setConnectTimeout(this.timeOut * 1000); //不使用缓存
httpConnection.setUseCaches(false); //允许输入输出
httpConnection.setDoInput(true);
httpConnection.setDoOutput(true); } /**
* 处理应答
* @throws IOException
*/
protected void doResponse() throws IOException { if(null == this.inputStream) {
return;
} //获取应答内容
this.resContent=HttpClientUtil.InputStreamTOString(this.inputStream,this.charset); //关闭输入流
this.inputStream.close(); } /**
* post方式处理
* @param conn
* @param postData
* @throws IOException
*/
protected void doPost(HttpURLConnection conn, byte[] postData)
throws IOException { // 以post方式通信
conn.setRequestMethod("POST"); // 设置请求默认属性
this.setHttpRequest(conn); // Content-Type
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded"); BufferedOutputStream out = new BufferedOutputStream(conn
.getOutputStream()); final int len = 1024; // 1KB
HttpClientUtil.doOutput(out, postData, len); // 关闭流
out.close(); // 获取响应返回状态码
this.responseCode = conn.getResponseCode(); // 获取应答输入流
this.inputStream = conn.getInputStream(); } /**
* get方式处理
* @param conn
* @throws IOException
*/
protected void doGet(HttpURLConnection conn) throws IOException { //以GET方式通信
conn.setRequestMethod("GET"); //设置请求默认属性
this.setHttpRequest(conn); //获取响应返回状态码
this.responseCode = conn.getResponseCode(); //获取应答输入流
this.inputStream = conn.getInputStream();
}
}

9、财付通Util类

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date; /**
* Created by heqiao on 2017/12/11 0011.
*/
public class TenpayUtil {
/**
* 把对象转换成字符串
* @param obj
* @return String 转换成字符串,若对象为null,则返回空字符串.
*/
public static String toString(Object obj) {
if(obj == null)
return ""; return obj.toString();
} /**
* 把对象转换为int数值.
*
* @param obj
* 包含数字的对象.
* @return int 转换后的数值,对不能转换的对象返回0。
*/
public static int toInt(Object obj) {
int a = 0;
try {
if (obj != null)
a = Integer.parseInt(obj.toString());
} catch (Exception e) { }
return a;
} /**
* 获取当前时间 yyyyMMddHHmmss
* @return String
*/
public static String getCurrTime() {
Date now = new Date();
SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
String s = outFormat.format(now);
return s;
} /**
* 获取当前日期 yyyyMMdd
* @param date
* @return String
*/
public static String formatDate(Date date) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String strDate = formatter.format(date);
return strDate;
} /**
* 取出一个指定长度大小的随机正整数.
*
* @param length
* int 设定所取出随机数的长度。length小于11
* @return int 返回生成的随机数。
*/
public static int buildRandom(int length) {
int num = 1;
double random = Math.random();
if (random < 0.1) {
random = random + 0.1;
}
for (int i = 0; i < length; i++) {
num = num * 10;
}
return (int) ((random * num));
} /**
* 获取编码字符集
* @param request
* @param response
* @return String
*/
public static String getCharacterEncoding(HttpServletRequest request,
HttpServletResponse response) { if(null == request || null == response) {
return "gbk";
} String enc = request.getCharacterEncoding();
if(null == enc || "".equals(enc)) {
enc = response.getCharacterEncoding();
} if(null == enc || "".equals(enc)) {
enc = "gbk";
} return enc;
} /**
* 获取unix时间,从1970-01-01 00:00:00开始的秒数
* @param date
* @return long
*/
public static long getUnixTime(Date date) {
if( null == date ) {
return 0;
} return date.getTime()/1000;
} /**
* 时间转换成字符串
* @param date 时间
* @param formatType 格式化类型
* @return String
*/
public static String date2String(Date date, String formatType) {
SimpleDateFormat sdf = new SimpleDateFormat(formatType);
return sdf.format(date);
}
public static String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader( " x-forwarded-for " );
if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip)) {
ip = request.getHeader( " Proxy-Client-IP " );
}
if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip)) {
ip = request.getHeader( " WL-Proxy-Client-IP " );
}
if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}

10、其他处理Util类

import com.sun.org.apache.bcel.internal.generic.RETURN;
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.hibernate.loader.custom.Return;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jeecgframework.core.util.ResourceUtil;
import org.xml.sax.InputSource; import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.StringReader;
import java.security.KeyStore;
import java.util.*; /**
* Created by heqiao on 2017/12/11 0011.
*/
public class WXUtil {
/**
* 生成随机字符串
* @return
*/
public static String getNonceStr() {
Random random = new Random();
return MD5Util.MD5Encode(String.valueOf(random.nextInt(10000)), "utf8");
}
/**
* 获取时间戳
* @return
*/
public static String getTimeStamp() {
return String.valueOf(System.currentTimeMillis() / 1000);
} /**
* 获取十位的时间戳
* @param d 时间
* @return
*/
public static String getTimeStamp(Date d) {
return String.valueOf(d.getTime() / 1000);
}
/**
* https双向签名认证,用于支付申请退款
*
* */
public static String payHttps(String url,String xml) throws Exception {
//商户id
String MCH_ID = ConstantUtil.MCH_ID;
//指定读取证书格式为PKCS12
KeyStore keyStore = KeyStore.getInstance("PKCS12");
String path = ResourceUtil.getConfigByName("pay.weixin.certificate.localaddress");
//读取本机存放的PKCS12证书文件
FileInputStream instream = new FileInputStream(new File(path));
try {
//指定PKCS12的密码(商户ID)
keyStore.load(instream, MCH_ID.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, MCH_ID.toCharArray()).build();
//指定TLS版本
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,new String[] { "TLSv1" },null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
//设置httpclient的SSLSocketFactory
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
try {
HttpPost httpost = new HttpPost(url); // 设置响应头信息
httpost.addHeader("Connection", "keep-alive");
httpost.addHeader("Accept", "*/*");
httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
httpost.addHeader("Host", "api.mch.weixin.qq.com");
httpost.addHeader("X-Requested-With", "XMLHttpRequest");
httpost.addHeader("Cache-Control", "max-age=0");
httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
httpost.setEntity(new StringEntity(xml, "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 request
* @return
*/
public static String getNotifyUrl(HttpServletRequest request) {
String url = request.getRequestURL().toString();
String domain = url.substring(0, url.length()-13);
//生产环境
return domain+ConstantUtil.NOTIFY_URL;
} public static Map parseXmlToMap(String xml) {
// Map retMap = new HashMap();
SortedMap<String, String> retMap = new TreeMap<>();
try {
StringReader read = new StringReader(xml);
// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
InputSource source = new InputSource(read);
// 创建一个新的SAXBuilder
SAXBuilder sb = new SAXBuilder();
// 通过输入源构造一个Document
Document doc = sb.build(source);
Element root = (Element) doc.getRootElement();// 指向根节点
List<Element> es = root.getChildren();
if (es != null && es.size() != 0) {
for (Element element : es) {
retMap.put(element.getName(), element.getValue());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return retMap;
}
/*public static void main(String[] args){ System.out.println(getTimeStamp(new Date()));
}*/
}

11、XML解析类

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder; import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.io.ByteArrayInputStream;
public class XMLUtil {
/**
* 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
* @param strxml
* @return
* @throws JDOMException
* @throws IOException
*/
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if(null == strxml || "".equals(strxml)) {
return null;
} Map m = new HashMap(); InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if(children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = XMLUtil.getChildrenText(children);
}
m.put(k, v);
} //关闭流
in.close(); return m;
} /**
* 获取子结点的xml
* @param children
* @return String
*/
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if(!children.isEmpty()) {
Iterator it = children.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if(!list.isEmpty()) {
sb.append(XMLUtil.getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
} return sb.toString();
} /**
* 获取xml编码字符集
* @param strxml
* @return
* @throws IOException
* @throws JDOMException
*/
public static String getXMLEncoding(String strxml) throws JDOMException, IOException {
InputStream in = HttpClientUtil.String2Inputstream(strxml);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
in.close();
return (String)doc.getProperty("encoding");
} /**
* 支付成功,返回微信那服务器
* @param return_code
* @param return_msg
* @return
*/
public static String setXML(String return_code, String return_msg) {
return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
} public static String createXML(Map<String,Object> map){
Set<Entry<String,Object>> set=map.entrySet();
set.iterator();
return null;
} }

12、支付接口

(生成签名  获取 prePayId) 返回给APP端

此处参数除   均可根据具体业务自定义   只要可获取平台需支付的信息即可

返回参数与前端商量  此处返回的Map  也可返回json字符串  或者后台统一的类型

/**
* 微信生成预支付订单,获取prepayId
*
* @param request
* @param out_trade_no 订单号
* @param total_fee 支付金额
* @param payType 支付类型 1、支付宝 2、微信
* @param couponId 优惠券id
* @param addressId 地址id
* @param response
* @return
* @throws Exception , method = RequestMethod.POST
*/
@ResponseBody
@RequestMapping(params = "getWeXinOrderString")
public Map<String, Object> getWeXinOrderString(HttpServletRequest request,
String out_trade_no,
Float total_fee,
String payType,
String couponId,
String addressId,
HttpServletResponse response) throws Exception {
Map<String, Object> map = new HashMap<>();
//第一步 判断信息是否有误 根据参数判断要支付的信息是否存在或有误 根据自己业务进行处理
// 第二步 获取生成预支付订单的请求类
PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);
int totalFee = (int) (total_fee * 100);//微信支付是以分为单位的
System.out.println("total_fee:" + totalFee);
prepayReqHandler.setParameter("appid", ConstantUtil.APP_ID);
prepayReqHandler.setParameter("body", ConstantUtil.BODY);
prepayReqHandler.setParameter("mch_id", ConstantUtil.MCH_ID);
String nonce_str = WXUtil.getNonceStr();
prepayReqHandler.setParameter("nonce_str", nonce_str);
//设置回调地址-获取当前的地址拼接回调地址
prepayReqHandler.setParameter("notify_url", WXUtil.getNotifyUrl(request));
String outTradeNo = out_trade_no;//OrderNumUtil.orderDatrNum();//新的订单号 若订单号是实时生成的则在此处修改
prepayReqHandler.setParameter("out_trade_no", outTradeNo);
prepayReqHandler.setParameter("spbill_create_ip", TenpayUtil.getIpAddr(request));//request.getRemoteAddr()
Date timestamp = new Date();//WXUtil.getTimeStamp(); //开始时间和结束时间可不填
prepayReqHandler.setParameter("time_start", DateUtils.formatDate(timestamp, "yyyyMMddHHmmss"));// 此处时间是微信规定的格式 请自己些工具类转换 格式为
prepayReqHandler.setParameter("time_expire", DateUtils.formatDate(DateUtils.getTimeByMinute(10), "yyyyMMddHHmmss"));// 此处是交易结束时间 可自定义
System.out.println(String.valueOf(total_fee));
prepayReqHandler.setParameter("total_fee", String.valueOf(totalFee));
prepayReqHandler.setParameter("trade_type", "APP");
/**
* 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)
*/
prepayReqHandler.setParameter("sign", prepayReqHandler.createMD5Sign());
prepayReqHandler.setGateUrl(ConstantUtil.GATEURL);
String prepayid = prepayReqHandler.sendPrepay();
// 若获取prepayid成功,将相关信息返回客户端
if (prepayid != null && !prepayid.equals("")) {//修改信息 此处根据业务自行处理 如商品支付信息为支付中 等信息 ,将当前订单号保存起来等 //第三步 生成返回给app端的签名 和其他信息
/**
* 签名方式与上面类似
*/
StringBuffer sb = new StringBuffer();
sb.append("appid=" + ConstantUtil.APP_ID);
sb.append("&noncestr=" + nonce_str);
sb.append("&package=" + "Sign=WXPay");
sb.append("&partnerid=" + ConstantUtil.PARTNER_ID);
sb.append("&prepayid=" + prepayid);
String ts = WXUtil.getTimeStamp(timestamp);//此处是十位的时间戳
sb.append("&timestamp=" + ts);
sb.append("&key=" + ConstantUtil.APP_KEY);
//sign使用自己拼接的字符创定义
String sign = MD5Util.getMessageDigest(sb.toString().getBytes(Charset.forName("utf-8"))).toUpperCase();//MD5Util.MD5Encode(sb.toString(),"").toUpperCase();
map.put("sign", sign);
map.put("appId", ConstantUtil.APP_ID);
map.put("nonceStr", nonce_str); //与请求prepayId时值一致
map.put("packageValue", "Sign=WXPay"); //固定常量
map.put("partnerId", ConstantUtil.PARTNER_ID);
map.put("timeStamp", ts);
map.put("code", 0);
map.put("out_trade_no", outTradeNo);
map.put("info", "success");
map.put("prepayId", prepayid);
} else {
map.put("code", 1);
map.put("info", "获取prepayid失败");
}
}
//net.sf.json.JSONObject json = net.sf.json.JSONObject.fromObject(map);
//json.toString();
// System.out.println("json=========="+json.toString());
return map;
}
/**
* 接收微信支付成功通知
* ConstantUtil 中的 NOTIFY_URL
* @param request
* @param response
* @throws IOException
*/
@ResponseBody
@RequestMapping(value = "weiXinNotify")
public void getnotify(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
System.out.println("微信支付回调");
PrintWriter writer = response.getWriter();
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
String result = new String(outSteam.toByteArray(), "utf-8");
System.out.println("微信支付通知结果:" + result);
Map<String, String> map = null;
try {
/**
* 解析微信通知返回的信息
*/
map = XMLUtil.doXMLParse(result);
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("=========:" + result);
// 若支付成功,则告知微信服务器收到通知
if (map.get("return_code").equals("SUCCESS")) {
if (map.get("result_code").equals("SUCCESS")) {
String out_trade_no = map.get("out_trade_no");
System.out.println("成功!" + out_trade_no);
//判断通知是否已处理,若已处理,则不予处理
// 根据订单号查询订单信息 做订单信息修改和支付信息修改
if (StringUtil.isNotEmpty(out_trade_no)) {
//根据订单号查询订单信息
//修改订单状态等信息   String notifyStr = XMLUtil.setXML("SUCCESS", ""); writer.write(notifyStr); writer.flush(); // return notifyStr;  } } }else{ String notifyStr = XMLUtil.setXML("FALSE", ""); writer.write(notifyStr); writer.flush(); } // return XMLUtil.setXML("FALSE", ""); }

13、去微信端查询支付的订单信息

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*; /**
* 微信支付查询 操作类
* Created by heqiao on 2017/12/19 0019.
*/
public class SelectReqHandler {
/** 网关url地址 */
private String gateSelectUrl; /** 密钥 */
private String key; /** 请求的参数 */
private SortedMap parameters; protected HttpServletRequest request; protected HttpServletResponse response; /**
* 构造函数
* @param request
* @param response
*/
public SelectReqHandler(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
this.gateSelectUrl = "https://api.mch.weixin.qq.com/pay/orderquery";
this.key = "";
this.parameters = new TreeMap();
} /**
*初始化函数。
*/
public void init() {
//nothing to do
} /**
*获取入口地址,不包含参数值
*/
public String getGateSelectUrl() {
return gateSelectUrl;
}
/**
*设置入口地址,不包含参数值
*/
public void setGateSelectUrl(String gateSelectUrl) {
this.gateSelectUrl = gateSelectUrl;
} /**
*获取密钥
*/
public String getKey() {
return key;
} /**
*设置密钥
*/
public void setKey(String key) {
this.key = key;
} /**
* 获取参数值
* @param parameter 参数名称
* @return String
*/
public String getParameter(String parameter) {
String s = (String)this.parameters.get(parameter);
return (null == s) ? "" : s;
} /**
* 设置参数值
* @param parameter 参数名称
* @param parameterValue 参数值
*/
public void setParameter(String parameter, Object parameterValue) {
String v = "";
if(null != parameterValue) {
if(parameterValue instanceof String)
v = ((String) parameterValue).trim();
}
this.parameters.put(parameter, v);
} /**
* 返回所有的参数
* @return SortedMap
*/
public SortedMap getAllParameters() {
return this.parameters;
} /**
* 获取带参数的请求URL
* @return String
* @throws UnsupportedEncodingException
*/
public String getRequestURL() throws UnsupportedEncodingException { this.createSign(); StringBuffer sb = new StringBuffer();
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue(); if(!"spbill_create_ip".equals(k)) {
sb.append(k + "=" + URLEncoder.encode(v, enc) + "&");
} else {
sb.append(k + "=" + v.replace("\\.", "%2E") + "&");
}
} //去掉最后一个&
String reqPars = sb.substring(, sb.lastIndexOf("&")); return this.getGateSelectUrl() + "?" + reqPars; } public void doSend() throws UnsupportedEncodingException, IOException {
this.response.sendRedirect(this.getRequestURL());
} /**
* 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
*/
protected void createSign() {
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + this.getKey());
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
String sign = MD5Util.MD5Encode(sb.toString(), enc).toUpperCase();
this.setParameter("sign", sign);
} protected HttpServletRequest getHttpServletRequest() {
return this.request;
} protected HttpServletResponse getHttpServletResponse() {
return this.response;
}
}
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import java.util.Map;
import java.util.Set; /**
* 微信订单查询 退款 等处理信息
* Created by HQ on 2017/12/11 0011.
*/
public class PreRequestHandler extends SelectReqHandler{
public PreRequestHandler(HttpServletRequest request,
HttpServletResponse response) {
super(request, response);
} public String createMD5Sign() {
StringBuffer sb = new StringBuffer();
Set es = super.getAllParameters().entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append(k + "=" + v + "&");
}
String params=sb.append("key="+ ConstantUtil.APP_KEY).substring(0);
String sign = MD5Util.MD5Encode(params, "utf8");
return sign.toUpperCase();
} // 提交
public Map<String,String> sendPreSelect() throws Exception {
Set es=super.getAllParameters().entrySet();
Iterator it=es.iterator();
StringBuffer sb = new StringBuffer("<xml>");
while(it.hasNext()){
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append("<"+k+">"+v+"</"+k+">");
}
sb.append("</xml>");
String params=sb.substring(0);
System.out.println("请求参数:"+params);
String requestUrl = super.getGateSelectUrl();
System.out.println("请求url:"+requestUrl);
TenpayHttpClient httpClient = new TenpayHttpClient();
httpClient.setReqContent(requestUrl);
String resContent = "";
if (httpClient.callHttpPost(requestUrl, params)) {
resContent = httpClient.getResContent();
System.out.println("获取select的返回值:"+resContent);
Map<String,String> map=XMLUtil.doXMLParse(resContent);
return map;
}
return null;
} /**
* xml 参数
* @return
* @throws Exception
*/
public String sendPreSelectXml() throws Exception {
Set es=super.getAllParameters().entrySet();
Iterator it=es.iterator();
StringBuffer sb = new StringBuffer("<xml>");
while(it.hasNext()){
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append("<"+k+">"+v+"</"+k+">");
}
sb.append("</xml>");
System.out.println("退款请求参数:"+sb.substring(0));
return sb.substring(0);
}
}
    /**
* 微信支出订单状态查询
* 此接口直接去查询支付情况 防止回调不成功无法获取支付状态
* @param request
* @param response
* @return 返回参数见微信支付查询订单
*/
@RequestMapping(params = "getWeiXinPayOrderSuccess")
@ResponseBody
public Page<Map<String, Object>> getWeiXinPayOrderSuccess(HttpServletRequest request,
HttpServletResponse response,
@RequestParam(required = false) String transactionId,
@RequestParam(required = false) String outTradeNo,
Page<Map<String, Object>> page) {
try {
// 获取生成预支付订单的请求类
PreRequestHandler preSelectReqHandler = new PreRequestHandler(request, response);
preSelectReqHandler.setParameter("appid", ConstantUtil.APP_ID);
preSelectReqHandler.setParameter("mch_id", ConstantUtil.MCH_ID);
String nonce_str = WXUtil.getNonceStr();
preSelectReqHandler.setParameter("nonce_str", nonce_str);
if (com.senta.base.utils.StringUtil.isNotEmpty(transactionId)) {
preSelectReqHandler.setParameter("transaction_id ", transactionId);
} else {
preSelectReqHandler.setParameter("out_trade_no", outTradeNo);
}
/**
* 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)
*/
preSelectReqHandler.setParameter("sign", preSelectReqHandler.createMD5Sign());
preSelectReqHandler.setGateSelectUrl(ConstantUtil.GATESELECTURL);
Map<String, String> preSelectMap = preSelectReqHandler.sendPreSelect();
//判断是否成功
if (com.senta.base.utils.StringUtil.isNotEmpty(preSelectMap.get("trade_state")) && "SUCCESS".equals(preSelectMap.get("trade_state"))) {
//处理订单信息 也可不处理 看具体业务 }
page.setSuccess(true);
}
//处理返回参数 page.setObj(preSelectMap);
} catch (Exception e) {
e.printStackTrace();
page.setMessage("异常!");
return page;
}
return page;
}

14、退款操作

退款是需要证书的,下载下来放在某个目录

调用 WXUtil.payHttps  方法时修改方法里的

String path = ResourceUtil.getConfigByName("pay.weixin.certificate.localaddress");

这里的path是我在配置文件里配的证书路径   改为自己的证书存放路径

ex: path="D:/weixinZS/apiclient_cert.p12"

app微信支付-java服务端接口 支付-查询-退款

    /**
* 微信退款
* 此处用的 自己生成的订单号 就是上面支付中生成的订单号
* @param request
* @param response
* @return 返回参数见微信支付查询订单
*/
@RequestMapping(params = "weiXinPayOrderRefund")
@ResponseBody
public Page<Map<String, Object>> weiXinPayOrderRefund(HttpServletRequest request,
HttpServletResponse response,
@RequestParam(required = false) String transactionId,
@RequestParam(required = false) String outTradeNo,
Page<Map<String, Object>> page) {
try {
          //transactionId为微信订单号   我没用这个号
//查询订单信息 根据订单号 这里是我自己的订单信息 此处换成自己 的
PayOrderEntity payOrder = getPayOrderByNo(outTradeNo);
if (payOrder == null || com.senta.base.utils.StringUtil.isEmpty(payOrder.getId()))
{ page.setMessage("订单号有误!"); }
else if (!"1".equals(payOrder.getStatus()))
{ page.setMessage("该订单不能进行退款!"); }
else {
// 获取生成预支付订单的请求类
PreRequestHandler preRefundReqHandler = new PreRequestHandler(request, response);
preRefundReqHandler.setParameter("appid", ConstantUtil.APP_ID);
preRefundReqHandler.setParameter("mch_id", ConstantUtil.MCH_ID);
String outRefundNo = payOrder.getOutRefundNo();
if (com.senta.base.utils.StringUtil.isEmpty(outRefundNo)) {
payOrder.setOutRefundNo(OrderNumUtil.orderDatrNum());
}
preRefundReqHandler.setParameter("out_refund_no", payOrder.getOutRefundNo());
String nonce_str = WXUtil.getNonceStr();
preRefundReqHandler.setParameter("nonce_str", nonce_str);
if (com.senta.base.utils.StringUtil.isNotEmpty(transactionId)) {
preRefundReqHandler.setParameter("transaction_id ", transactionId);
} else {
preRefundReqHandler.setParameter("out_trade_no", outTradeNo);
}
int total_fee = (payOrder.getCost().multiply(new BigDecimal(100))).intValue();//金额以分为单位
preRefundReqHandler.setParameter("total_fee", String.valueOf(total_fee));//订单金额
preRefundReqHandler.setParameter("refund_fee", String.valueOf(total_fee));//退款金额
/**
* 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)
*/
preRefundReqHandler.setParameter("sign", preRefundReqHandler.createMD5Sign());
preRefundReqHandler.setGateSelectUrl(ConstantUtil.GATEREFUNDURL);
String preSelectXml = preRefundReqHandler.sendPreSelectXml();
String retur = WXUtil.payHttps(ConstantUtil.GATEREFUNDURL, preSelectXml);
Map returnMap = new HashMap();
if (com.senta.base.utils.StringUtil.isNotEmpty(retur)) {
returnMap = WXUtil.parseXmlToMap(retur);
//判断是否成功
if (com.senta.base.utils.StringUtil.isNotEmpty(returnMap.get("result_code")) && "SUCCESS".equals(returnMap.get("result_code"))) {
//处理订单信息
//根据订单号查询订单信息//修改订单信息 修改支付状态 为退款状态
page.setSuccess(true);
}
}
//处理返回参数 也可不处理 这里处理 返回值参考微信文档 page.setObj(returnMap);
}
} catch (Exception e) {
e.printStackTrace();
page.setMessage("异常!");
return page;
}
return page;
}