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

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

首先来定义各种处理类(微信支付不需要特殊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 mhc on 2018/12/20*/
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 {// caTrustManagerFactory 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 mhc on 2018/12/20*/
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()));elseresultString = 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 mhc on 2018/12/20*/
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 mhc on 2018/12/20*/
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 mhc on 2018/12/20*/
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 mhc on 2018/12/20*/
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 mhc on 2018/12/20*/
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-Typeconn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");BufferedOutputStream out = new BufferedOutputStream(conn.getOutputStream());final int len = 1024; // 1KBHttpClientUtil.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 mhc on 2018/12/20*/
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 mhc on 2018/12/20*/
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 {//商户idString MCH_ID = ConstantUtil.MCH_ID;//指定读取证书格式为PKCS12KeyStore 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的SSLSocketFactoryCloseableHttpClient 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);// 创建一个新的SAXBuilderSAXBuilder sb = new SAXBuilder();// 通过输入源构造一个DocumentDocument 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 blocke.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 mhc on 2018/12/20*/
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(0, 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 mhc on 2018/12/20*/
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")@ResponseBodypublic 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")@ResponseBodypublic 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. yy直播接口开发手册php,微信小程序 服务端接口·直播间接口

    [小程序直播]直播间管理接口 名称 功能说明 创建直播间 该接口可直接创建直播间,创建成功后直播间将在直播间列表展示 获取直播房间列表 该接口可获取直播房间列表 获取直播间回放 该接口可在直播结束后拿 ...

  2. SpringBoot 服务端接口公网远程调试,并实现 HTTP 服务监听

    前后端分离项目中,在调用接口调试时候,可以通过cpolar内网穿透将本地服务端接口模拟公共网络环境远程调用调试,本次教程以Java服务端接口为例. 1. 本地环境搭建 1.1 环境参数 JDK1.8 ...

  3. 支付宝APP支付Java服务端

    支付宝APP支付Java服务端: 公司项目要求对接支付宝进行支付功能,这边做出整理方便以后使用(支付宝的支付对接还是很简单的). 1):去支付宝开放平台,-1.注册账号,2.创建应用 3.配置应用 4 ...

  4. 微信个人号客服系统淘宝客发单机器人sdk服务端接口列表

    微信个人号客服系统淘宝客发单机器人sdk服务端接口列表 case HeartBeatReq: {// 客户端发送的心跳包heartBeatReqHandler.handleMsg(ctx, msgVo ...

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

    为什么80%的码农都做不了架构师?>>>    针对 --->非开放性平台 --->公司内部产品 接口特点汇总: 1.因为是非开放性的,所以所有的接口都是封闭的,只对公司 ...

  6. 全新版个人博客小程序,无需开发服务端接口即可使用

    介绍: 全新版个人博客小程序,服务端使用的是Bmob后端云,无需开发服务端接口即可使用,快速便捷,代码简洁,功能包括文章列表,文章分类列表,赞赏功能,签到,收藏文章,查看文章,点赞文章,消息通知,评论 ...

  7. RemObjects(一)客户端远程调用服务端接口过程

    RemObjects SDK 是高度封装的产物,对OOP发挥极致. 本文将以RemObjects SDK最简单的DEMO--FirstSample为例, 介绍客户端是如何完成远程调用服务端接口的全过程 ...

  8. 接口-服务端接口客户端接口

    记得刚工作就开始纠结接口这个问题,纠结到现在,总算是从头到尾摸索了一遍. 首先,服务端接口,是指我这个系统作为服务,然后其他的系统来调我.首先,接口,双方会定义一定的规范,即我这个系统,和调用我这个系 ...

  9. 微信支付java服务端开发(APP)

    我这边是针对微信商户支付功能开发.其他的未涉及到. 当你所有的准备工作准备好后:微信支付申请成功,api_key 配置好,等等一系列. 那么让我们进入java开发吧. 微信支付demo下载: http ...

最新文章

  1. 科研文献|了解多个含水层中微生物砷的迁移:DNA 和 RNA 分析的见解
  2. Xamarin iOS教程之警告视图
  3. 机房收费系统--登录窗体
  4. 【转】基于XML-RPC的BloggerAPI学习
  5. 2019年的web前端领域
  6. Vue.js项目去除url中的#/ - 解决篇
  7. 用js实现鼠标点击爱心特效
  8. Java7并发编程指南——第八章:测试并发应用程序
  9. centos7安装串口终端kermit
  10. 若依前后端分离如何写移动端接口_前后端分离架构概述
  11. 记号(notation)的学习
  12. Nvivo 自动编码语言包
  13. 浏览器右下角总是弹出广告
  14. word文档如何画线条流程图_Word中流程图如何画 手把手教你制作!
  15. MATLAB及Simulink----基本知识简介
  16. 怎样去提高效率,五步优化法
  17. The requested URL was not found on this server.
  18. Illegal group reference:非法组引用异常
  19. 机器学习分类光谱数据
  20. python panda是什么_如何最简单、通俗地理解Python的pandas库?

热门文章

  1. 解读:紫外杀菌棒如何申请EPA 认证
  2. 龙腾15寸液晶屏M150GNN2 R1规格资料
  3. 计算机存储器由半导体,半导体集成存储器
  4. python中如何画logistic_如何在 Python 中建立和训练线性和 logistic 回归 ML 模型?
  5. Software Craftsmanship可以做些什麼?
  6. 纯JAVA实现微信跳一跳刷分
  7. mysql数据库逆心_数据库系统基础笔记(7)--函数
  8. 小白也能轻松炒股的软件-2.0升级版发布
  9. python还房贷_宝妈玩转Python做出房贷计算系统,只因为……
  10. 谈编程是个什么玩意儿