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

首先来定义各种处理类(微信支付不需要特殊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"

    /**
* 微信退款
* 此处用的 自己生成的订单号 就是上面支付中生成的订单号
* @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;
}
												

app微信支付-java服务端接口 支付-查询-退款的更多相关文章

  1. app支付宝支付java服务端代码

    app支付java服务端生成支付单文档 public String aliPay(String amount,Map<String,Object> body){ //实例化客户端 Alip ...

  2. IOS IAP APP内支付 Java服务端代码

    IOS IAP APP内支付 Java服务端代码   场景:作为后台需要为app提供服务,在ios中,app内进行支付购买时需要进行二次验证. 基础:可以参考上一篇转载的博文In-App Purcha ...

  3. api服务端接口安全

    api服务端接口安全性解析 http://blog.csdn.net/tenfyguo/article/details/8225279 常用的基于token的实现方案 http://blog.csdn ...

  4. 移动端与PHP服务端接口通信流程设计(增强版)

    前面讲过:移动端与PHP服务端接口通信流程设计(基础版) 对于 api_token 的校验,其安全性还可再增强: 增强地方一: 再增加2张表,一个接口表,一个授权表,设计参考如下: 接口表 字段名 字 ...

  5. 移动端与PHP服务端接口通信流程设计(基础版)

    针对 --->非开放性平台 --->公司内部产品 接口特点汇总: 1.因为是非开放性的,所以所有的接口都是封闭的,只对公司内部的产品有效: 2.因为是非开放性的,所以OAuth那套协议是行 ...

  6. 移动端与PHP服务端接口通信流程设计(基础版)

    转载自:http://blog.snsgou.com/post-766.html --->非开放性平台 --->公司内部产品 接口特点汇总: 1.因为是非开放性的,所以所有的接口都是封闭的 ...

  7. 移动端与PHP服务端接口通信流程设计(增强版)

    增强地方一: 再增加2张表,一个接口表,一个授权表,设计参考如下: 接口表 字段名 字段类型 注释 api_id int 接口ID api_name varchar(120) 接口名,以"/ ...

  8. java服务宕机原因查询

    背景 在java服务项目上线之后经常会出现宕机的情况 常见原因 内存溢出 1.查到服务进程号 [root@wms ~]# ps -ef|grep java root 6399 6069 0 08:57 ...

  9. App架构设计经验谈:服务端接口的设计

    App与服务器的通信接口如何设计得好,需要考虑的地方挺多的,在此根据我的一些经验做一些总结分享,旨在抛砖引玉. 安全机制的设计 现在,大部分App的接口都采用RESTful架构,RESTFul最重要的 ...

随机推荐

  1. (译)MySQL的10个基本性能技巧

    原文出处:https://www.infoworld.com/article/3210905/sql/10-essential-performance-tips-for-mysql.html MySQ ...

  2. getBoundingClientRect获取元素在页面上的位置

    getBoundingClientRect用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置. getBoundingClientRect是DOM元素到浏览器可视范围的距离(不包含文档卷起 ...

  3. kruskal(拓展)

    kruskal是最小生成树的一种做法,即严格按照贪心思想将边从小到大排序,一个一个枚举能不能加入图中,知道生成一棵树,显然树为最小树. 鄙人觉得kruskal做法远不止如此,那种严格从小到大选边的做法 ...

  4. 项目(一)ftp搭建

    FTP服务 FTP两种模式: 主动模式服务器向客户端敲门,然后客户端开门 被动模式客户端向服务器敲门,然后服务器开门 传输模式:可以是文本模式,也可以是二进制模式,二进制模式更适合传输图片等非文本字符 ...

  5. mysql访问视图提示:找不到视图

    原因: 1.不存在 2.视图区分大小写(有的不区分) 3.权限问题

  6. java之JUC

    1.JUC简介 java的JUC即java.util.concurrent包,

  7. Web用户登录---验证码的设计与实现

    在开发中验证码是比较常用到有效防止这种问题对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试的方式. 验证码生成步骤:1.获得随机生成的颜色,画出随机线条生成背景底.2.String cod ...

  8. Kubernetes的三种外部访问方式:NodePort、LoadBalancer和Ingress

    NodePort,LoadBalancer和Ingress之间的区别.它们都是将集群外部流量导入到集群内的方式,只是实现方式不同. ClusterIP ClusterIP服务是Kubernetes的默 ...

  9. 第二篇 Flask 中的 Render Redirect HttpResponse

    第二篇 Flask 中的 Render Redirect HttpResponse   1.Flask中的HTTPResponse 在Flask 中的HttpResponse 在我们看来其实就是直接返 ...

  10. codecombat之地牢关卡Python代码

    1.地牢 # 向宝石进发. # 小心撞墙! # 在下面输入你的代码. self.moveRight() self.moveDown() self.moveRight() 2.深藏的宝石 # 利用你的移 ...