微信支付——微信公众号内支付 代码

官方文档:https://pay.weixin.qq.com/wiki/doc/api/index.html

引入jdom-1.1.3.jar包

HttpClientUtil.java
package weixinpay;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
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.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;


public class HttpClientUtil {
    
    private static class SingletonHolder{
        private final static  HttpClientUtil INSTANCE=new HttpClientUtil();
    }   
    
    private HttpClientUtil(){}
    
    public static HttpClientUtil getInstance(){
        return SingletonHolder.INSTANCE;
    }
    
    public  String get(String url){
        CharsetHandler handler = new CharsetHandler("UTF-8");
         CloseableHttpClient client = null;
        try {
            HttpGet httpget = new HttpGet(new URI(url));
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
            client= httpClientBuilder.build();  
            client = (CloseableHttpClient) wrapClient(client);
            return client.execute(httpget, handler);
        } catch (Exception e) {
            //e.printStackTrace();
            return "";
        }finally {
            try {
                if(client!=null){
                    client.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
       }
    }
    
    public static String post(String url, String params,String contentType)
       {
        
          //创建HttpClientBuilder  
          HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
          //HttpClient  
          CloseableHttpClient client = httpClientBuilder.build();
          client = (CloseableHttpClient) wrapClient(client);
          
          
           HttpPost post = new HttpPost(url);
           CloseableHttpResponse res = null;
           try
           {
               StringEntity s = new StringEntity(params,"UTF-8");
               if(StringUtils.isBlank(contentType)){
                   s.setContentType("application/json");
               }
               s.setContentType(contentType);
               s.setContentEncoding("utf-8");
               post.setEntity(s);
               res = client.execute(post);
               HttpEntity entity = res.getEntity();
               return EntityUtils.toString(entity, "utf-8");
           }
           catch (Exception e)
           {
               e.printStackTrace();
           } finally {
                try {
                    res.close();
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
           }
        return "";
     }
    
    public static String post(String urlStr,String xmlInfo) {
        String line1 = "";  
        try {  
            URL url = new URL(urlStr);  
            URLConnection con = url.openConnection();  
            con.setDoOutput(true);  
            //con.setRequestProperty("Pragma:", "no-cache");  
            con.setRequestProperty("Cache-Control", "no-cache");  
            con.setRequestProperty("Content-Type", "text/xml"); 
        
            OutputStreamWriter out = new OutputStreamWriter(con  
            .getOutputStream());           
            out.write(new String(xmlInfo.getBytes("utf-8")));  
            out.flush();  
            out.close();  
            BufferedReader br = new BufferedReader(new InputStreamReader(con  
            .getInputStream()));  
            String line = "";  
            for (line = br.readLine(); line != null; line = br.readLine()) {  
                line1+=line;  
            } 
            return new String(line1.getBytes(),"utf-8");
            } catch (MalformedURLException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }
            return null;  
        }
    
    private class CharsetHandler implements ResponseHandler<String> {
        private String charset;

        public CharsetHandler(String charset) {
            this.charset = charset;
        }

        public String handleResponse(HttpResponse response)
                throws ClientProtocolException, IOException {
            StatusLine statusLine = response.getStatusLine();
            if (statusLine.getStatusCode() >= 300) {
                throw new HttpResponseException(statusLine.getStatusCode(),
                        statusLine.getReasonPhrase());
            }
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                if (!StringUtils.isBlank(charset)) {
                    return EntityUtils.toString(entity, charset);
                } else {
                    return EntityUtils.toString(entity);
                }
            } else {
                return null;
            }
        }
    }

    private static HttpClient wrapClient(HttpClient base) {
        try {
            SSLContext ctx = SSLContext.getInstance("TLSv1");
            X509TrustManager tm = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] xcs,
                        String string) throws CertificateException {
                }
    
                public void checkServerTrusted(X509Certificate[] xcs,
                        String string) throws CertificateException {
                }
    
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[] { "TLSv1" }, null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            return httpclient;
           
        } catch (Exception ex) {
            return null;
        }
    }

}

Num62.java

package weixinpay;

/**
 * 62进制数字
 */
public class Num62 {
    /**
     * 62个字母和数字,含大小写
     */
    public static final char[] N62_CHARS = { ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘,
            ‘7‘, ‘8‘, ‘9‘, ‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘, ‘F‘, ‘G‘, ‘H‘, ‘I‘, ‘J‘,
            ‘K‘, ‘L‘, ‘M‘, ‘N‘, ‘O‘, ‘P‘, ‘Q‘, ‘R‘, ‘S‘, ‘T‘, ‘U‘, ‘V‘, ‘W‘,
            ‘X‘, ‘Y‘, ‘Z‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, ‘g‘, ‘h‘, ‘i‘, ‘j‘,
            ‘k‘, ‘l‘, ‘m‘, ‘n‘, ‘o‘, ‘p‘, ‘q‘, ‘r‘, ‘s‘, ‘t‘, ‘u‘, ‘v‘, ‘w‘,
            ‘x‘, ‘y‘, ‘z‘ };
    /**
     * 36个小写字母和数字
     */
    public static final char[] N36_CHARS = { ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘,
            ‘7‘, ‘8‘, ‘9‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, ‘g‘, ‘h‘, ‘i‘, ‘j‘,
            ‘k‘, ‘l‘, ‘m‘, ‘n‘, ‘o‘, ‘p‘, ‘q‘, ‘r‘, ‘s‘, ‘t‘, ‘u‘, ‘v‘, ‘w‘,
            ‘x‘, ‘y‘, ‘z‘ };
    
    /**
     * 10 个数字
     */
    public static final char[] N10_CHARS = { ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘,
            ‘7‘, ‘8‘, ‘9‘ };
    /**
     * 长整型用N36表示的最大长度
     */
    public static final int LONG_N36_LEN = 13;
    /**
     * 长整型用N62表示的最大长度
     */
    public static final int LONG_N62_LEN = 11;

    /**
     * 长整型转换成字符串
     * 
     * @param l
     * @param chars
     * @return
     */
    private static StringBuilder longToNBuf(long l, char[] chars) {
        int upgrade = chars.length;
        StringBuilder result = new StringBuilder();
        int last;
        while (l > 0) {
            last = (int) (l % upgrade);
            result.append(chars[last]);
            l /= upgrade;
        }
        return result;
    }

    /**
     * 长整数转换成N62
     * 
     * @param l
     * @return
     */
    public static String longToN62(long l) {
        return longToNBuf(l, N62_CHARS).reverse().toString();
    }

    /**
     * 长整型转换成N36
     * 
     * @param l
     * @return
     */
    public static String longToN36(long l) {
        return longToNBuf(l, N36_CHARS).reverse().toString();
    }

    /**
     * 长整数转换成N62
     * 
     * @param l
     * @param length
     *            如不足length长度,则补足0。
     * @return
     */
    public static String longToN62(long l, int length) {
        StringBuilder sb = longToNBuf(l, N62_CHARS);
        for (int i = sb.length(); i < length; i++) {
            sb.append(‘0‘);
        }
        return sb.reverse().toString();
    }

    /**
     * 长整型转换成N36
     * 
     * @param l
     * @param length
     *            如不足length长度,则补足0。
     * @return
     */
    public static String longToN36(long l, int length) {
        StringBuilder sb = longToNBuf(l, N36_CHARS);
        for (int i = sb.length(); i < length; i++) {
            sb.append(‘0‘);
        }
        return sb.reverse().toString();
    }

    /**
     * N62转换成整数
     * 
     * @param n62
     * @return
     */
    public static long n62ToLong(String n62) {
        return nToLong(n62, N62_CHARS);
    }

    /**
     * N36转换成整数
     * 
     * @param n36
     * @return
     */
    public static long n36ToLong(String n36) {
        return nToLong(n36, N36_CHARS);
    }

    private static long nToLong(String s, char[] chars) {
        char[] nc = s.toCharArray();
        long result = 0;
        long pow = 1;
        for (int i = nc.length - 1; i >= 0; i--, pow *= chars.length) {
            int n = findNIndex(nc[i], chars);
            result += n * pow;
        }
        return result;
    }

    private static int findNIndex(char c, char[] chars) {
        for (int i = 0; i < chars.length; i++) {
            if (c == chars[i]) {
                return i;
            }
        }
        throw new RuntimeException("N62(N36)非法字符:" + c);
    }

    public static void main(String[] args) {
        System.out.println(longToN62(Long.MAX_VALUE));
    }
}

微信支付支付参数配置类

PaymentConfig.java

package weixinpay;

public class PaymentConfig {
    /*******微信支付参数*********/
    //公众账号ID
    public static final String appid="wxd";
    //密钥
    public static final String appKey="h";
    //商户号
    public static final String mch_id="1584";
    //接口地址
    public static final String pay_url="https://api2.mch.weixin.qq.com/pay/unifiedorder";


    public static final String wxRetrun="";
    //交易场景信息
//    public static final String scene_info = "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"https://pay.qq.com\",\"wap_name\": \"传媒学院在线报名\"}} ";
    public static final String scene_info = "{\"store_info\" : {\"id\": \"zxbm\",\"name\": \"买车预约\",\"area_code\": \"430000\",\"address\": \"东风鸿泰汽车\" }}";

    public static final int ENROLL_PRICE = 200;
    
}

PayUtil.java

package weixinpay;

import org.apache.commons.lang.StringUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import java.io.*;
import java.security.MessageDigest;
import java.util.*;


public class PayUtil {




    /**
    * 将需要传递给微信的参数转成xml格式
    * @param parameters
    * @return
    */
    public static String assembParamToXml(Map<String,String> parameters){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set<String> es = parameters.keySet();
        List<Object> list=new ArrayList<Object>(es);
        Object[] ary =list.toArray();
        Arrays.sort(ary);
        list=Arrays.asList(ary);
        Iterator<Object> it = list.iterator();
        while(it.hasNext()) {
            String key =  (String) it.next();
            String val=(String) parameters.get(key);
            if ("attach".equalsIgnoreCase(key)||"body".equalsIgnoreCase(key)||"sign".equalsIgnoreCase(key)) {
                sb.append("<"+key+">"+"<![CDATA["+val+"]]></"+key+">");
            }else {
                sb.append("<"+key+">"+val+"</"+key+">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }
    

    /**
    * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
    * @param strxml
    * @return
    * @throws JDOMException
    * @throws IOException
    */
    public static Map parseXMLToMap(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 =PayUtil.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(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }
        return sb.toString();
    }

    /**
    * 微信支付签名sign
    * @param param
    * @param key
    * @return
    */
    @SuppressWarnings("unchecked")
    public static String createSign(Map<String, String> param,String key){
        //签名步骤一:按字典排序参数
        List list=new ArrayList(param.keySet());
        Object[] ary =list.toArray();
        Arrays.sort(ary);
        list=Arrays.asList(ary);
        String str="";
        for(int i=0;i<list.size();i++){
            str+=list.get(i)+"="+param.get(list.get(i)+"")+"&";
        }
        //签名步骤二:加上key
        str+="key="+key;
        //步骤三:加密并大写
        str=PayUtil.MD5Encode(str,"utf-8").toUpperCase();
        return str;
    }

    public static String MD5Encode(String origin,String charsetName){
        String resultString=null;
        try{
            resultString=new String(origin);
            MessageDigest md=MessageDigest.getInstance("MD5");
            if(StringUtils.isBlank(charsetName)){
                resultString=byteArrayToHexString(md.digest(resultString.getBytes()));
            }else{
                resultString=byteArrayToHexString(md.digest(resultString.getBytes(charsetName)));
            }
        }catch(Exception e){
        
        }
        return resultString;
    }

    public static String byteArrayToHexString(byte b[]){
        StringBuffer resultSb=new StringBuffer();
        for(int i=0;i<b.length;i++){
            resultSb.append(PayUtil.byteToHexString(b[i]));
        }
        return resultSb.toString();
    }

    public static String byteToHexString(byte b){
        int n=b;
        if(n<0){
            n+=256;
        }
        int d1=n/16;
        int d2=n%16;
        return PayUtil.hexDigits[d1]+PayUtil.hexDigits[d2];
    }

    public static final String hexDigits[]={ "0", "1", "2", "3", "4", "5",  
    "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };


    /**
     * 元转换为分
     * @param amount
     */
    public static String changeY2F(Double amount){    
            String currency =  amount.toString();  
            int index = currency.indexOf(".");    
            int length = currency.length();    
            Long amLong = 0l;    
            if(index == -1){    
                amLong = Long.valueOf(currency+"00");    
            }else if(length - index >= 3){    
                amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));    
            }else if(length - index == 2){    
                amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);    
            }else{    
                amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");    
            }    
            return amLong.toString();    
    }

}

WeixinPay.java

package weixinpay;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.ui.ModelMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;


public class WeixinPay {


    /**
     * 微信统一下单
     *
     * @param trade_type 交易类型
     * @param openId     用户的openId
     * @param request
     * @param wxRetrun   微信支付异步回调地址
     * @param orderNo    订单号
     * @param price      订单金额
     * @return
     */
    public static Map<String, String> weixinUniformOrder(String trade_type, String openId,
                                                         HttpServletRequest request, String wxRetrun, String orderNo, Double price) {
        Map<String, String> paramMap = new HashMap<String, String>();
        // 微信分配的公众账号ID(企业号corpid即为此appId)[必填]
        paramMap.put("appid", PaymentConfig.appid);
        // 微信支付分配的商户号 [必填]
        paramMap.put("mch_id", PaymentConfig.mch_id);
        // 终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB" [非必填]
        paramMap.put("device_info", "WEB");
        // 随机字符串,不长于32位。 [必填]
        paramMap.put("nonce_str", RandomStringUtils.random(10, Num62.N62_CHARS));
        // 商品或支付单简要描述 [必填]
        paramMap.put("body", PaymentConfig.mch_id);
        // 商户系统内部的订单号,32个字符内、可包含字母, [必填]
        paramMap.put("out_trade_no", orderNo);
        // 符合ISO 4217标准的三位字母代码,默认人民币:CNY. [非必填]
        paramMap.put("fee_type", "CNY");

        // 金额必须为整数 单位为分 [必填]
        paramMap.put("total_fee", PayUtil.changeY2F(price));
        // APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP [必填]
        paramMap.put("spbill_create_ip", request.getRemoteAddr());
        // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。 [必填]
        paramMap.put("notify_url", wxRetrun);
        // 交易类型{取值如下:JSAPI,NATIVE,APP,(JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付)}
        // [必填]
        paramMap.put("trade_type", trade_type);
        //openid trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
        paramMap.put("openid", openId);
        // 商品ID{trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。}
        paramMap.put("product_id", "商品ID");
        // 根据微信签名规则,生成签名
        paramMap.put("sign", PayUtil.createSign(paramMap, PaymentConfig.appKey));
        // 把参数转换成XML数据格式
        String xmlWeChat = PayUtil.assembParamToXml(paramMap);
        String resXml = HttpClientUtil.post(wxRetrun, xmlWeChat);
        Map<String, String> map = new HashMap<String, String>();
        try {
            if (StringUtils.isNotBlank(resXml)) {
                map = PayUtil.parseXMLToMap(resXml);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }


    /**
     * 微信公众号支付(手机端)
     *
     * @param wxRetrun 微信支付异步回调地址
     * @param openId   用户的openid
     * @param orderNo  订单号
     * @param price    订单金额
     * @param request
     * @param response
     * @param model
     * @return
     */
    public static String weixinPayByMobile(String wxRetrun, String openId, String orderNo, Double price,
                                           HttpServletRequest request, HttpServletResponse response,
                                           ModelMap model) {
        Map<String, String> map = weixinUniformOrder("JSAPI", openId,
                request, wxRetrun, orderNo, price);
        String returnCode = map.get("return_code");
        if (returnCode.equalsIgnoreCase("FAIL")) {

            //调用失败操作
            //当return_code为FAIL时返回信息为错误原因 ,例如 签名失败、参数格式校验错误
            map.get("return_msg");

        } else if (returnCode.equalsIgnoreCase("SUCCESS")) {
            if (map.get("err_code") != null) {

                //支付失败操作
                //错误代码描述
                map.get("err_code_des");


            } else if (map.get("result_code").equalsIgnoreCase(
                    "SUCCESS")) {
                String prepay_id = map.get("prepay_id");
                Long time = System.currentTimeMillis() / 1000;
                String nonceStr = RandomStringUtils.random(16, Num62.N10_CHARS);
                //公众号appid
                model.addAttribute("appId", PaymentConfig.appid);
                //时间戳 当前的时间 需要转换成秒
                model.addAttribute("timeStamp", time);
                //随机字符串  不长于32位
                model.addAttribute("nonceStr", nonceStr);
                //订单详情扩展字符串 统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***
                model.addAttribute("package", "prepay_id=" + prepay_id);
                //签名方式 签名算法,暂支持MD5
                model.addAttribute("signType", "MD5");
                Map<String, String> paramMap = new HashMap<String, String>();
                paramMap.put("appId", PaymentConfig.appid);
                paramMap.put("timeStamp", time.toString());
                paramMap.put("nonceStr", nonceStr);
                paramMap.put("package", "prepay_id=" + prepay_id);
                paramMap.put("signType", "MD5");
                //签名
                model.addAttribute("paySign", PayUtil.createSign(paramMap, PaymentConfig.appKey));

                //跳转到 weixin_prepay.html
                return "weixin_prepay.html";
            }
        }
        // 失败提示跳转页面,自己设计
        return "error.html";
    }


    //通知微信正确接收
    public static String getSuccessXml() {
        String xml = "<xml>" +
                "<return_code><![CDATA[SUCCESS]]></return_code>" +
                "<return_msg><![CDATA[OK]]></return_msg>" +
                "</xml>";
        return xml;
    }

}

微信公众号支付跳转页面主要逻辑代码

weixin_prepay.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>微信支付</title>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js" type="text/javascript"></script>
    <script type="text/javascript">
        wx.config({
            debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: ‘${appId!}‘, // 必填,公众号的唯一标识
            timestamp: "${timeStamp!}", // 必填,生成签名的时间戳
            nonceStr: ‘${nonceStr!}‘, // 必填,生成签名的随机串
            signature: "${paySign!}", // 必填,签名,见附录1
            jsApiList: [‘chooseWXPay‘] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
        });
        wx.ready(function () {
            wx.chooseWXPay({
                appId: "${appId!}",
                timestamp: "${timeStamp!}",
                nonceStr: "${nonceStr!}",
                package: "${package!}",
                signType: "MD5",
                paySign: "${paySign!}",
                success: function (res) {
                    alert("成功");
                    window.location.href = "成功之后跳转地址";
                },
                cancel: function () {
                    alert("用户已取消");
                },
                error: function (e) {
                    alert("失败");
                }
            });
        });
    </script>
</head>
<body>
<div class="w1187b">
    <div class="w1173">
    </div>
</div>
</body>
</html>

后台控制器调用类

WeixinPayAct.java

package weixinpay;


import org.apache.commons.lang.StringUtils;
import org.jdom.JDOMException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import weixin.XMLUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;


@Controller
public class WeixinPayAct {

    /**
     * 微信支付
     *
     * @param request
     * @param response
     * @param model
     * @return
     */
    @RequestMapping(value = "weixin_Pay.jspx")
    public String selectPay(HttpServletRequest request,
                            HttpServletResponse response, ModelMap model) {

        String wxRetrun = "微信支付异步回调地址";
        String orderNo = "订单号";
        String openId = "用户的openId";
        //支付金额
        Double price = 0.01;

        return WeixinPay.weixinPayByMobile(wxRetrun, openId, orderNo, price,
                request, response, model);

    }


    /**
     * 微信支付通知
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/wechart_notice.jspx")
    public String wechartNotice(HttpServletRequest request, HttpServletResponse response, ModelMap model) {
        String result = "";
        try {
            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();
            result = new String(outSteam.toByteArray(), "utf-8");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //判断返回报文是否为空
        if (StringUtils.isNotBlank(result)) {
            try {
                Map<String, String> map = XMLUtil.doXMLParse(result);
                //获取商家订单编号 对应orderID
                String orderNo = map.get("out_trade_no");
                //String orderNo = RequestUtils.getQueryParam(request,"orderNo");
                //获取微信支付订单号
                String transaction_id = map.get("transaction_id");

                Order order = orderMng.findByOrderNo(orderNo);
                //判断支付是否成功
                if ("SUCCESS".equals(map.get("result_code"))) {
                    //支付成功,这里之所以加了一个判断,是因为这个回调可能会有多次,所以我们只有当订单状态时未支付的情况下,才执行下面操作
                    if (!Constants.ORDER_SUCCESS.equals(order.getStatus())) {
                        //当微信支付成功后,把订单支付状态改为已支付
                        order.setStatus(Constants.ORDER_SUCCESS);
                    }
                    //处理业务逻辑
                } else {
                    //支付失败
                    order.setStatus(Constants.ORDER_FAIL);
                }
                orderMng.update(order);
            } catch (JDOMException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return WeixinPay.getSuccessXml();
    }


}

相关推荐