zoukankan      html  css  js  c++  java
  • 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 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("
    ");
            }
    
            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(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 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; }
    
    
  • 相关阅读:
    数据库三,exec内置函数
    HDU 1003:Max Sum(DP,连续子段和)
    HDU 1024:Max Sum Plus Plus(DP,最大m子段和)
    Codeforces 698A:Vacations(DP)
    牛客多校第五场 J:Plan
    51Nod 1091:线段的重叠(贪心)
    ZZNU 2125:A + B 普拉斯(傻逼题+大数加法)
    HDU 1010:Tempter of the Bone(DFS+奇偶剪枝+回溯)
    HDU 1176:免费馅饼(DP,自认为很详细的解释)
    POJ 2312:Battle City(BFS)
  • 原文地址:https://www.cnblogs.com/Spirit612/p/8081786.html
Copyright © 2011-2022 走看看