app微信支付-java服務端接口 支付-查詢-退款

我的不怎麼看得懂微信的文檔,看了不少前輩的寫法,終於調通了,在這裏作一下記錄。前端

首先來定義各類處理類(微信支付不須要特殊jar包,不少處理須要本身封裝,固然也能夠本身寫完打個jar包)java

參數要用jdom解析   自行導入jar包   git

或者在maven pom.xml中導入 apache

<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>1.1.3</version>
</dependency>
version根據本身maven庫中版本號進行設置

一、經常使用參數類

/**
 * 微信支付請求常量
 * 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";

二、http客戶端工具類

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;

public class HttpClientUtil {
    /**
     * http客戶端工具類
     *
     */
    public static final String SunX509 = "SunX509";
    public static final String JKS = "JKS";
    public static final String PKCS12 = "PKCS12";
    public static final String TLS = "TLS";

    /**
     * get HttpURLConnection
     * @param strUrl url地址
     * @return HttpURLConnection
     * @throws java.io.IOException
     */
    public static HttpURLConnection getHttpURLConnection(String strUrl)
            throws IOException {
        URL url = new URL(strUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url
                .openConnection();
        return httpURLConnection;
    }

    /**
     * get HttpsURLConnection
     * @param strUrl url地址ַ
     * @return HttpsURLConnection
     * @throws IOException
     */
    public static HttpsURLConnection getHttpsURLConnection(String strUrl)
            throws IOException {
        URL url = new URL(strUrl);
        HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url
                .openConnection();
        return httpsURLConnection;
    }

    /**
     * 獲取不帶查詢串的url
     * @param strUrl
     * @return String
     */
    public static String getURL(String strUrl) {

        if(null != strUrl) {
            int indexOf = strUrl.indexOf("?");
            if(-1 != indexOf) {
                return strUrl.substring(0, indexOf);
            }

            return strUrl;
        }

        return strUrl;

    }

    /**
     * 獲取查詢串
     * @param strUrl
     * @return String
     */
    public static String getQueryString(String strUrl) {

        if(null != strUrl) {
            int indexOf = strUrl.indexOf("?");
            if(-1 != indexOf) {
                return strUrl.substring(indexOf+1, strUrl.length());
            }

            return "";
        }

        return strUrl;
    }

    /**
     * 查詢字符串轉化爲map
     * name1=key1&name2=key2&...
     * @param queryString
     * @return
     */
    public static Map queryString2Map(String queryString) {
        if(null == queryString || "".equals(queryString)) {
            return null;
        }

        Map m = new HashMap();
        String[] strArray = queryString.split("&");
        for(int index = 0; index < strArray.length; index++) {
            String pair = strArray[index];
            HttpClientUtil.putMapByPair(pair, m);
        }

        return m;

    }

    /**
     * 把鍵值添加到map
     * pair:name=value
     * @param pair name=value
     * @param m
     */
    public static void putMapByPair(String pair, Map m) {

        if(null == pair || "".equals(pair)) {
            return;
        }

        int indexOf = pair.indexOf("=");
        if(-1 != indexOf) {
            String k = pair.substring(0, indexOf);
            String v = pair.substring(indexOf+1, pair.length());
            if(null != k && !"".equals(k)) {
                m.put(k, v);
            }
        } else {
            m.put(pair, "");
        }
    }
    /**
     * BufferedReader轉換成String<br/>
     * 注意:流關閉須要自行處理
     * @param reader
     * @return
     * @throws IOException
     */
    public static String bufferedReader2String(BufferedReader reader) throws IOException {
        StringBuffer buf = new StringBuffer();
        String line = null;
        while( (line = reader.readLine()) != null) {
            buf.append(line);
            buf.append("\r\n");
        }

        return buf.toString();
    }
    /**
     * 處理輸出<br/>
     * 注意:流關閉須要自行處理
     * @param out
     * @param data
     * @param len
     * @throws IOException
     */
    public static void doOutput(OutputStream out, byte[] data, int len)
            throws IOException {
        int dataLen = data.length;
        int off = 0;
        while (off < data.length) {
            if (len >= dataLen) {
                out.write(data, off, dataLen);
                off += dataLen;
            } else {
                out.write(data, off, len);
                off += len;
                dataLen -= len;
            }

            // ˢ�»�����
            out.flush();
        }

    }
    /**
     * 獲取SSLContext
     * @param trustFileInputStream
     * @param trustPasswd
     * @param keyFileInputStream
     * @param keyPasswd
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyStoreException
     * @throws IOException
     * @throws CertificateException
     * @throws UnrecoverableKeyException
     * @throws KeyManagementException
     */
    public static SSLContext getSSLContext(
            FileInputStream trustFileInputStream, String trustPasswd,
            FileInputStream keyFileInputStream, String keyPasswd)
            throws NoSuchAlgorithmException, KeyStoreException,
            CertificateException, IOException, UnrecoverableKeyException,
            KeyManagementException {

        // ca
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(HttpClientUtil.SunX509);
        KeyStore trustKeyStore = KeyStore.getInstance(HttpClientUtil.JKS);
        trustKeyStore.load(trustFileInputStream, HttpClientUtil
                .str2CharArray(trustPasswd));
        tmf.init(trustKeyStore);

        final char[] kp = HttpClientUtil.str2CharArray(keyPasswd);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(HttpClientUtil.SunX509);
        KeyStore ks = KeyStore.getInstance(HttpClientUtil.PKCS12);
        ks.load(keyFileInputStream, kp);
        kmf.init(ks, kp);

        SecureRandom rand = new SecureRandom();
        SSLContext ctx = SSLContext.getInstance(HttpClientUtil.TLS);
        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), rand);

        return ctx;
    }

    /**
     * 字符串轉換成char數組
     * @param str
     * @return char[]
     */
    public static char[] str2CharArray(String str) {
        if(null == str) return null;

        return str.toCharArray();
    }

    public static InputStream String2Inputstream(String str) {
        return new ByteArrayInputStream(str.getBytes());
    }

    /**
     * InputStream轉換成Byte
     * 注意:流關閉須要自行處理
     * @param in
     * @return byte
     * @throws Exception
     */
    public static byte[] InputStreamTOByte(InputStream in) throws IOException{

        int BUFFER_SIZE = 4096;
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] data = new byte[BUFFER_SIZE];
        int count = -1;

        while((count = in.read(data,0,BUFFER_SIZE)) != -1)
            outStream.write(data, 0, count);

        data = null;
        byte[] outByte = outStream.toByteArray();
        outStream.close();

        return outByte;
    }

    /**
     * InputStream轉換成String
     * 注意:流關閉須要自行處理
     * @param in
     * @param encoding 編碼
     * @return String
     * @throws Exception
     */
    public static String InputStreamTOString(InputStream in,String encoding) throws IOException{

        return new String(InputStreamTOByte(in),encoding);

    }

三、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 "異常";
        }
    }

}

四、訂單號生成類    這個能夠自行判斷要不要(只要不重複就行)    我是提早有個訂單信息 前端直接給我訂單號,固然訂單號也是用這個類生成的。json

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;
    }
}

五、獲取支付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;
    }
}

六、簽名請求類

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;
    }
}

七、響應參數處理類

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;
    }

}

 

八、財付通請求客戶端

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();
    }
}

 

九、財付通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;
    }
}

 

十、其餘處理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()));
    }*/
}

 

十一、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;
    }

}

 

十二、支付接口

(生成簽名  獲取 prePayId) 返回給APP端api

此處參數除   都可根據具體業務自定義   只要可獲取平臺需支付的信息便可數組

返回參數與前端商量  此處返回的Map  也可返回json字符串  或者後臺統一的類型緩存

/**
     * 微信生成預支付訂單,獲取prepayId
     *
     * @param request
     * @param out_trade_no 訂單號
     * @param total_fee    支付金額
     * @param payType      支付類型  一、支付寶   二、微信
     * @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", ""); }

 

1三、去微信端查詢支付的訂單信息

 

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;
    }

 

 

1四、退款操做

退款是須要證書的,下載下來放在某個目錄服務器

調用 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; }
相關文章
相關標籤/搜索