你的位置:首页 > Java教程

[Java教程]微信支付(JSAPI)


最近客栈订房,当然是需要微信支付的,官方微信支付文档什么的,只想说 去你妈的文档

so, 经过两天不懈的努力和网上大牛文档,终于做出来了,下面具体来说说,希望能对各位看客有点帮助

 

放大招,直接上代码

1. Configure.java 文件

 1 package com.kzb.website.core.wechat.common; 2  3 import java.util.Calendar; 4 import java.util.Date; 5  6 import org.apache.commons.lang3.StringUtils; 7  8 public class Configure { 9  10   private static String token = null; 11   private static Date tokenTime = null; 12   private static String jsapiTicket = null; 13   private static Date jsapiTicketTime = null; 14  15   public static String MD5 = "MD5"; 16   public static String EMPTY = ""; 17   public static String SUCCESS = "SUCCESS"; 18   public static String HEX_FORMAT = "%02x"; 19   public static String TRADE_TYPE = "JSAPI"; 20   public static String MIDDLE_LINE = "-"; 21   public static String CHARTSET_UTF8 = "UTF-8"; 22  23   public static String NOTIFY_SUCCESS = "<; 24   public static String NOTIFY_FAIL = "<; 25  26   private static String key = "API密钥(32位,在微信商户平台下的API安全栏下)"; 27   // 微信分配的公众号ID(开通公众号之后可以获取到) 28   private static String appID = "XXXXXXXXXXXXXX"; 29   private static String appSecret = "XXXXXXXXXXXXXX"; 30   // 微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到) 31   private static String mchID = "1349019501"; 32   // 机器IP 33   private static String ip = "127.0.0.1"; 34  35   // 以下是几个API的路径: 36   // 统一下单 37   public static String UNIFIEDORDER_API = "https://api.mch.weixin.qq.com/pay/unifiedorder"; 38   // access_token API 39   public static String TOKEN_API = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential"; 40   // 临时票据API 41   public static String TICKET_API = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"; 42   // 微信OPENID API 43   public static String OPENID_API = "https://api.weixin.qq.com/sns/oauth2/access_token"; 44  45   public static void setKey(String key) { 46     Configure.key = key; 47   } 48  49   public static void setAppID(String appID) { 50     Configure.appID = appID; 51   } 52  53   public static void setMchID(String mchID) { 54     Configure.mchID = mchID; 55   } 56  57   public static void setIp(String ip) { 58     Configure.ip = ip; 59   } 60  61   public static String getKey(){ 62     return key; 63   } 64    65   public static String getAppid(){ 66     return appID; 67   } 68    69   public static String getMchid(){ 70     return mchID; 71   } 72  73   public static String getIP(){ 74     return ip; 75   } 76  77   public static String getAppSecret() { 78     return appSecret; 79   } 80  81   public static void setAppSecret(String appSecret) { 82     Configure.appSecret = appSecret; 83   } 84  85   public static String getToken() { 86     return token; 87   } 88  89   public static void setToken(String token) { 90     Configure.token = token; 91     Configure.tokenTime = new Date(); 92   } 93  94   public static String getJsapiTicket() { 95     return jsapiTicket; 96   } 97  98   public static void setJsapiTicket(String jsapiTicket) { 99     Configure.jsapiTicket = jsapiTicket;100     Configure.jsapiTicketTime = new Date();101   }102 103   public static boolean checkToken() {104     if (!StringUtils.isEmpty(Configure.token)) {105       Calendar calendar = Calendar.getInstance();106       calendar.setTime(tokenTime);107       calendar.add(Calendar.SECOND, 7200);108       return calendar.before(new Date());109     }110     return true;111   }112 113   public static boolean checkJsapiTicket() {114     if (!StringUtils.isEmpty(Configure.jsapiTicket)) {115       Calendar calendar = Calendar.getInstance();116       calendar.setTime(jsapiTicketTime);117       calendar.add(Calendar.SECOND, 7200);118       return calendar.before(new Date());119     }120     return true;121   }122 }

View Code

 

2. SignMD5.java文件

 1 package com.kzb.website.core.wechat.common; 2  3 import java.io.UnsupportedEncodingException; 4 import java.security.MessageDigest; 5 import java.security.NoSuchAlgorithmException; 6 import java.util.Formatter; 7 import java.util.UUID; 8  9 import org.springframework.security.crypto.password.PasswordEncoder;10 11 public class SignMD5 implements PasswordEncoder {12   public static String byteToHex(final byte[] hash) {13     Formatter formatter = new Formatter();14     for (byte b : hash) {15       formatter.format(Configure.HEX_FORMAT, b);16     }17     String result = formatter.toString();18     formatter.close();19     return result;20   }21 22   @Override23   public String encode(CharSequence charSequence) {24     try {25       MessageDigest crypt = MessageDigest.getInstance(Configure.MD5);26       crypt.reset();27       crypt.update(charSequence.toString().getBytes(Configure.CHARTSET_UTF8));28       return byteToHex(crypt.digest());29     } catch (NoSuchAlgorithmException e) {30       e.printStackTrace();31     } catch (UnsupportedEncodingException e) {32       e.printStackTrace();33     }34     return Configure.EMPTY;35   }36 37   @Override38   public boolean matches(CharSequence charSequence, String encodedPassword) {39     return encode(charSequence).equals(encodedPassword);40   }41 42   public String createNonceStr() {43     return UUID.randomUUID().toString().replaceAll(Configure.MIDDLE_LINE,Configure.EMPTY);44   }45 46   public String createTimeStamp() {47     return Long.toString(System.currentTimeMillis() / 1000);48   }49 50 }

View Code

 

3. WechatNotify.java文件

 1 package com.kzb.website.core.wechat.common; 2  3 import java.io.Serializable; 4  5 import javax. 6  7 @) 8 public class WechatNotify implements Serializable{ 9  10   private static final long serialVersionUID = 8047707600433551023L; 11   private String appid; 12   private String attach; 13   private String bank_type; 14   private String fee_type; 15   private String is_subscribe; 16   private String mch_id; 17   private String nonce_str; 18   private String openid; 19   private String out_trade_no; 20   private String result_code; 21   private String return_code; 22   private String sign; 23   private String sub_mch_id; 24   private String time_end; 25   private String total_fee; 26   private String trade_type; 27   private String transaction_id; 28  29   public String getAppid() { 30     return appid; 31   } 32  33   public void setAppid(String appid) { 34     this.appid = appid; 35   } 36  37   public String getAttach() { 38     return attach; 39   } 40  41   public void setAttach(String attach) { 42     this.attach = attach; 43   } 44  45   public String getBank_type() { 46     return bank_type; 47   } 48  49   public void setBank_type(String bank_type) { 50     this.bank_type = bank_type; 51   } 52  53   public String getFee_type() { 54     return fee_type; 55   } 56  57   public void setFee_type(String fee_type) { 58     this.fee_type = fee_type; 59   } 60  61   public String getIs_subscribe() { 62     return is_subscribe; 63   } 64  65   public void setIs_subscribe(String is_subscribe) { 66     this.is_subscribe = is_subscribe; 67   } 68  69   public String getMch_id() { 70     return mch_id; 71   } 72  73   public void setMch_id(String mch_id) { 74     this.mch_id = mch_id; 75   } 76  77   public String getNonce_str() { 78     return nonce_str; 79   } 80  81   public void setNonce_str(String nonce_str) { 82     this.nonce_str = nonce_str; 83   } 84  85   public String getOpenid() { 86     return openid; 87   } 88  89   public void setOpenid(String openid) { 90     this.openid = openid; 91   } 92  93   public String getOut_trade_no() { 94     return out_trade_no; 95   } 96  97   public void setOut_trade_no(String out_trade_no) { 98     this.out_trade_no = out_trade_no; 99   }100 101   public String getResult_code() {102     return result_code;103   }104 105   public void setResult_code(String result_code) {106     this.result_code = result_code;107   }108 109   public String getReturn_code() {110     return return_code;111   }112 113   public void setReturn_code(String return_code) {114     this.return_code = return_code;115   }116 117   public String getSign() {118     return sign;119   }120 121   public void setSign(String sign) {122     this.sign = sign;123   }124 125   public String getSub_mch_id() {126     return sub_mch_id;127   }128 129   public void setSub_mch_id(String sub_mch_id) {130     this.sub_mch_id = sub_mch_id;131   }132 133   public String getTime_end() {134     return time_end;135   }136 137   public void setTime_end(String time_end) {138     this.time_end = time_end;139   }140 141   public String getTotal_fee() {142     return total_fee;143   }144 145   public void setTotal_fee(String total_fee) {146     this.total_fee = total_fee;147   }148 149   public String getTrade_type() {150     return trade_type;151   }152 153   public void setTrade_type(String trade_type) {154     this.trade_type = trade_type;155   }156 157   public String getTransaction_id() {158     return transaction_id;159   }160 161   public void setTransaction_id(String transaction_id) {162     this.transaction_id = transaction_id;163   }164 }

View Code

 

4. WechatPayModel.java文件

 1 package com.kzb.website.core.wechat.common; 2  3 import javax. 4  5 import org.springframework.security.crypto.password.PasswordEncoder; 6  7 @) 8 public class WechatPayModel { 9  10   private String appid; 11   private String mch_id; 12   private String nonce_str; 13   private String body; 14   private String out_trade_no; 15   private String total_fee; 16   private String spbill_create_ip; 17   private String notify_url; 18   private String trade_type; 19   private String openid; 20   private String sign; 21  22   public String getAppid() { 23     return appid; 24   } 25  26   public void setAppid(String appid) { 27     this.appid = appid; 28   } 29  30   public String getMch_id() { 31     return mch_id; 32   } 33  34   public void setMch_id(String mch_id) { 35     this.mch_id = mch_id; 36   } 37  38   public String getNonce_str() { 39     return nonce_str; 40   } 41  42   public void setNonce_str(String nonce_str) { 43     this.nonce_str = nonce_str; 44   } 45  46   public String getOut_trade_no() { 47     return out_trade_no; 48   } 49  50   public void setOut_trade_no(String out_trade_no) { 51     this.out_trade_no = out_trade_no; 52   } 53  54   public String getTotal_fee() { 55     return total_fee; 56   } 57  58   public void setTotal_fee(String total_fee) { 59     this.total_fee = total_fee; 60   } 61  62   public String getSpbill_create_ip() { 63     return spbill_create_ip; 64   } 65  66   public void setSpbill_create_ip(String spbill_create_ip) { 67     this.spbill_create_ip = spbill_create_ip; 68   } 69  70   public String getNotify_url() { 71     return notify_url; 72   } 73  74   public void setNotify_url(String notify_url) { 75     this.notify_url = notify_url; 76   } 77  78   public String getTrade_type() { 79     return trade_type; 80   } 81  82   public void setTrade_type(String trade_type) { 83     this.trade_type = trade_type; 84   } 85  86   public String getBody() { 87     return body; 88   } 89  90   public void setBody(String body) { 91     this.body = body; 92   } 93  94   public String getSign() { 95     return sign; 96   } 97  98   public void setSign(String sign) { 99     this.sign = sign;100   }101 102   public String getOpenid() {103     return openid;104   }105 106   public void setOpenid(String openid) {107     this.openid = openid;108   }109 110   public void sign(PasswordEncoder encoder) {111     StringBuilder stringBuilder = new StringBuilder();112     stringBuilder.append("appid=").append(getAppid());113     stringBuilder.append("&body=").append(getBody());114     stringBuilder.append("&mch_id=").append(getMch_id());115     stringBuilder.append("&nonce_str=").append(getNonce_str());116     stringBuilder.append("&notify_url=").append(getNotify_url());117     stringBuilder.append("&openid=").append(getOpenid());118     stringBuilder.append("&out_trade_no=").append(getOut_trade_no());119     stringBuilder.append("&spbill_create_ip=").append(getSpbill_create_ip());120     stringBuilder.append("&total_fee=").append(getTotal_fee());121     stringBuilder.append("&trade_type=").append(getTrade_type());122     stringBuilder.append("&key=").append(Configure.getKey());123     this.sign = encoder.encode(stringBuilder.toString());124   }125 126   @Override127   public String toString() {128     return "<129         "<appid><![CDATA[" + appid + "]]></appid>" +130         "<body><![CDATA[" + body + "]]></body>" +131         "<mch_id><![CDATA[" + mch_id + "]]></mch_id>" +132         "<nonce_str><![CDATA[" + nonce_str + "]]></nonce_str>" +133         "<notify_url><![CDATA[" + notify_url + "]]></notify_url>" +134         "<openid><![CDATA[" + openid + "]]></openid>" +135         "<out_trade_no><![CDATA[" + out_trade_no + "]]></out_trade_no>" +136         "<spbill_create_ip><![CDATA[" + spbill_create_ip + "]]></spbill_create_ip>" +137         "<trade_type><![CDATA[" + trade_type + "]]></trade_type>" +138         "<total_fee><![CDATA[" + total_fee + "]]></total_fee>" +139         "<sign><![CDATA[" + sign + "]]></sign>" +140         "</;141   }142 }

View Code

 

5. WechatUtil.java文件

 1 package com.kzb.website.core.wechat.common; 2  3 import java.io.DataInputStream; 4 import java.io.IOException; 5  6 import javax.servlet.http.HttpServletRequest; 7  8 import com.kzb.website.core.utils. 9 10 public class WechatUtil {11 12   /**13    * 微信回调成功后 将 14    * 15    * @param request16    * @return WechatNotify 对象17   */18   public static WechatNotify getNotifyBean(HttpServletRequest request){19     try {20       DataInputStream in = new DataInputStream(request.getInputStream());21       byte[] dataOrigin = new byte[request.getContentLength()];22       // 根据长度,将消息实体的内容读入字节数组dataOrigin中23       in.readFully(dataOrigin); 24       // 关闭数据流25       in.close();26       // 从字节数组中得到表示实体的字符串27       String new String(dataOrigin);28       // 将 29       Object object = class, 30       if (object != null && object instanceof WechatNotify) {31         WechatNotify notify = (WechatNotify) object;32         return notify;33       } else {return null;}34     } catch (IOException e) {35       e.printStackTrace();36       return null;37     }38   }39 }

View Code

 

6.

 1 package com.kzb.website.core.utils; 2  3 import java.io.StringReader; 4  5 import javax. 6 import javax. 7 import javax. 8  9 public class 10 11   /**12    * 将 13    * 14    * @param clazz 要转换对象的 class15    * @param 16    * @return 转换后的对象17   */18   public static Object  clazz, String 19     try {20       JAXBContext jc = JAXBContext.newInstance(clazz);21       Unmarshaller us = jc.createUnmarshaller();22       return us.unmarshal(new StringReader(23     } catch (JAXBException e) {24       e.printStackTrace();25       return null;26     }27   }28 }

View Code

 

7. pay_choose.jsp 页面,这个页面是一个支付选择画面,用来获取code,和回调到支付画面

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"%> 2 <!DOCTYPE html> 3 <html> 4 <head> 5   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 6   <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> 7   <title>支付选择画面</title> 8   <meta name="keywords" content="关键字,关键字"> 9   <meta name="description" content="">10   <style type="text/css">11     *{margin: 0;padding: 0;}12     body{font-size:12px;font-family:"微软雅黑";color:#666;}13   </style>14 </head>15 <body>16   <div style="margin:40px auto;width:400px;">17     <a href="javascript:wechat();">微信支付</a><br/><br/><br/>18     <a href="javascript:ali();">支付宝支付</a>19   </div>20 <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>21 <script type="text/javascript">22 function wechat(){23   var redirect_uri = "http://www.xxxxx.com/wxpay/payment.htm?hotelId=14501";24   var href = "https://open.weixin.qq.com/connect/oauth2/authorize?redirect_uri=" + encodeURIComponent(redirect_uri);25   href += "&appid=wx73997299f6dba700&response_type=code&scope=snsapi_base";26   window.location.href = href;27 }28 function ali(){29   30 }31 </script>32 </body>33 </html>

View Code

 

8. wechat_pay.jsp 页面

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"%> 2 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 3 <!DOCTYPE html> 4 <html> 5 <head> 6   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 7   <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> 8   <title>微信支付</title> 9   <meta name="keywords" content="关键字,关键字">10   <meta name="description" content="">11 <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>12 <script type="text/javascript" charset="UTF-8" src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>13 <script type="text/javascript">14 function pay(){15   //config16   var appId = $('#appId').val();17   var timeStamp = $('#timeStamp').val();18   var nonceStr = $('#nonceStr').val();19   var signature = $('#signature').val();20   21   var signType = $('#signType').val();22   var pk = $('#package').val();23   var paySign = $('#paySign').val();24 25   wx.config({26     debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。27     appId: appId, // 必填,公众号的唯一标识28     timestamp: timeStamp , // 必填,生成签名的时间戳29     nonceStr: nonceStr, // 必填,生成签名的随机串30     signature: signature,// 必填,签名,见附录131     jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录232   });33 34   wx.ready(function(res){35     // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。36     wx.chooseWXPay({37       timestamp: timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符38       nonceStr: nonceStr, // 支付签名随机串,不长于 32 位39       package: pk, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)40       signType: signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'41       paySign: paySign, // 支付签名42       success: function (res) {43         location.href = 'http://www.xxxxxxx.net/success.htm';44       },45       cancel: function (res) {46         location.href = 'http://www.xxxxxxx.net/success.htm';47       },48       fail: function (res) {49         location.href = 'http://www.xxxxxxx.net/success.htm';50       }51     });52   });53 54   wx.error(function (res) {55     alert("error:" + JSON.stringify(res));56   });57 }58 </script>59 </head>60 <body onload="pay()">61   <h1>正在进行微信支付....62     <br/>63     <small>请不要关闭</small>64   </h1>65   <input id="appId" type="hidden" value="${start.appId}" /><br/>66   <input id="timeStamp" type="hidden" value="${start.timestamp}" /><br/>67   <input id="nonceStr" type="hidden" value="${start.nonceStr}" /><br/>68   <input id="signature" type="hidden" value="${start.signature}" /><br/>69   70   <input id="signType" type="hidden" value="${pay.signType}" /><br/>71   <input id="package" type="hidden" value="${pay.packageStr}" /><br/>72   <input id="paySign" type="hidden" value="${pay.paySign}" /><br/>73 </body>74 </html>

 

9. WechatPayService.java 页面

 1 package com.kzb.website.web.wechat; 2  3 import java.util.HashMap; 4 import java.util.Map; 5  6 import org.apache.commons.lang3.StringUtils; 7 import org.springframework.stereotype.Service; 8 import org.springframework.ui.Model; 9 import org.springframework.web.client.RestTemplate; 10  11 import com.alibaba.fastjson.JSONArray; 12 import com.faster 13 import com.faster 14 import com.kzb.website.core.wechat.common.Configure; 15 import com.kzb.website.core.wechat.common.SignMD5; 16 import com.kzb.website.core.wechat.common.WechatPayModel; 17  18 @Service 19 public class WechatPayService { 20   SignMD5 encoder = new SignMD5(); 21   RestTemplate restTemplate = new RestTemplate(); 22  23   /** 24    * 微信支付统一下单接口 25    *  26    * @param notifyUrl 支付成功后回调路径 27    * @param openId 用户的 openId 28    * @param body 商品描述 29    * @param total 支付金额(单位分) 30    * @param out_trade_no 订单唯一订单号 31    * @return 32   */ 33   public String unifiedorder(String notifyUrl, String openId, String body, String total, String out_trade_no) { 34     WechatPayModel new WechatPayModel(); 35      36      37      38      39      40      41      42      43      44      45      46     return restTemplate.postForObject(Configure.UNIFIEDORDER_API, class); 47   } 48  49   /** 50    * 调起微信支付 51    *  52    * @param model 53    * @param res 预支付订单 字符串 54    * @param url 微信支付 url 55   */ 56   public void wechatPay(Model model, String res,String url) { 57     try { 58       Map<String, String> start = new HashMap<>(); 59       StringBuilder startSign = new StringBuilder(); 60  61       Map<String, String> pay = new HashMap<>(); 62       StringBuilder paySign = new StringBuilder(); 63       new  64       JsonNode node =  65       if (StringUtils.equals(node.get("return_code").asText(), Configure.SUCCESS)) { 66         // 得到的预支付订单,重新生成微信支付参数 67         String prepay_id = node.get("prepay_id").asText(); 68         String jsapi_ticket = jsapiTicket(); 69         // 生成 微信支付 config 参数 70         start.put("appId", Configure.getAppid()); 71         start.put("nonceStr", encoder.createNonceStr()); 72         start.put("timestamp", encoder.createTimeStamp()); 73         // 生成 config 签名 74         startSign.append("jsapi_ticket=").append(jsapi_ticket); 75         startSign.append("&noncestr=").append(start.get("nonceStr")); 76         startSign.append("&timestamp=").append(start.get("timestamp")); 77         startSign.append("&url=").append(url); 78         start.put("signature", encoder.encode(startSign.toString())); 79          80         // config信息验证后会执行ready方法的参数 81         pay.put("signType", Configure.MD5); 82         pay.put("packageStr", "prepay_id=" + prepay_id); 83         // 生成支付签名 84         paySign.append("appId=").append(start.get("appId")); 85         paySign.append("&nonceStr=").append(start.get("nonceStr")); 86         paySign.append("&package=").append(pay.get("packageStr")); 87         paySign.append("&signType=").append(pay.get("signType")); 88         paySign.append("&timeStamp=").append(start.get("timestamp")); 89         paySign.append("&key=").append(Configure.getKey()); 90         pay.put("paySign", encoder.encode(paySign.toString())); 91         // 将微信支参数放入 model 对象中以便前端使用 92         model.addAttribute("start", start); 93         model.addAttribute("pay", pay); 94       } 95     } catch (Exception e) { 96       model.addAttribute("wechatMessage", "微信授权失败!"); 97       e.printStackTrace(); 98     } 99   }100 101   /**102    * 微信授权,获取 access_token103    * 104    * @return access_token105   */106   public String getToken() {107     if (Configure.checkToken()) {108       // 声明 获取 access_token 路径109       StringBuilder tokenBuilder = new StringBuilder();110       tokenBuilder.append(Configure.TOKEN_API);111       tokenBuilder.append("&appid=").append(Configure.getAppid());112       tokenBuilder.append("&secret=").append(Configure.getAppSecret());113       // 获取 token114       Map<?, ?> token = restTemplate.getForObject(tokenBuilder.toString(), Map.class);115       Configure.setToken((String) token.get("access_token"));116     }117     return Configure.getToken();118   }119 120   /**121    * 获取微信 JSAPI 支付的临时票据122    * 123    * @return 临时票据124   */125   public String jsapiTicket() {126     if (Configure.checkJsapiTicket()) {127       // 声明 获取临时票据路径128       StringBuilder ticketBuilder = new StringBuilder();129       ticketBuilder.append(Configure.TICKET_API);130       ticketBuilder.append("?access_token=").append(getToken());131       ticketBuilder.append("&type=jsapi");132       // 获取 临时票据133       Map<?, ?> jsapiTicket = restTemplate.getForObject(ticketBuilder.toString(), Map.class);134       Configure.setJsapiTicket((String) jsapiTicket.get("ticket"));135     }136     return Configure.getJsapiTicket();137   }138 139   /**140    * 获取用的 OPENID141    * 142    * @param code 微信认证回调的 code143    * @return144   */145   public String takeOpenId(String code) {146     // 声明 获取OPENID路径147     StringBuilder openidBuilder = new StringBuilder();148     openidBuilder.append(Configure.OPENID_API);149     openidBuilder.append("?appid=").append(Configure.getAppid());150     openidBuilder.append("&secret=").append(Configure.getAppSecret());151     openidBuilder.append("&code=").append(code);152     openidBuilder.append("&grant_type=authorization_code");153     // 获取 OPENID154     String res = restTemplate.getForObject(openidBuilder.toString(), String.class);155     Map<?, ?> map = JSONArray.parseObject(res, Map.class);156     return String.valueOf(map.get("openid"));157   }158 }

 

10. WechatPayController.java 页面

 1 package com.kzb.website.web.wechat; 2  3 import java.util.Date; 4  5 import javax.servlet.http.HttpServletRequest; 6  7 import org.apache.commons.lang3.StringUtils; 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.stereotype.Controller;10 import org.springframework.ui.Model;11 import org.springframework.web.bind.annotation.RequestMapping;12 import org.springframework.web.bind.annotation.RequestMethod;13 import org.springframework.web.bind.annotation.RequestParam;14 import org.springframework.web.bind.annotation.ResponseBody;15 16 import com.kzb.website.core.wechat.common.Configure;17 import com.kzb.website.core.wechat.common.WechatNotify;18 import com.kzb.website.core.wechat.common.WechatUtil;19 20 @RequestMapping("wxpay")21 @Controller22 public class WechatPayController {23 24   @Autowired25   private PayService payService;26 27   @RequestMapping("payment.htm")28   public String payment(@RequestParam(required = false) String code, Model model, HttpServletRequest request){29     String openId = payService.takeOpenId(code);30     if (StringUtils.isEmpty(openId)) {31       return "pay/wxpay_error";32     }33     String notify = "http://www.xxxxxx.net/wxpay/notify.htm";34     String body = "商品支付内容";35     String total = "1"; // 单位分36     String out_trade_no = new Date().getTime() + "";37     38     String res = payService.unifiedorder(notify, openId, body, total, out_trade_no);39 40     String url = "http://www.xxxxxx.net/wxpay/payment.htm";41     payService.wechatPay(model,res,url);42     return "pay/wxpay";43   }44 45   /**46    * 微信支付成功后的回调函数47    * 48    * @param request49    * @return50   */51   @RequestMapping(value="notify.htm",method=RequestMethod.POST)52   @ResponseBody53   public String wechatNotify(HttpServletRequest request){54     // 从 request 对象中获取 WechatNotify 对象55     WechatNotify notify = WechatUtil.getNotifyBean(request);56     // 如果 notify 对象不为空 并且 result_code 和 return_code 都为 'SUCCESS' 则表示支付成功57     if (notify != null58         && StringUtils.equals(notify.getResult_code(), Configure.SUCCESS)59         && StringUtils.equals(notify.getReturn_code(), Configure.SUCCESS)) {60 61       return Configure.NOTIFY_SUCCESS;62     }63     return Configure.NOTIFY_FAIL;64   }65 }

 

现在就只需要放入服务器测试啦,赶快行动起来,试试吧

下面还有几篇来说说微信支付中遇到的那些 操蛋 的问题吧