微信公众号支付 (三、配置JS-SDK)

来源:互联网 发布:string数组倒序 编辑:程序博客网 时间:2024/05/20 01:35

4.1微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包,通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的功能。

JS-SDK使用步骤:

1.登录微信公众号平台,进入公众号设置,设置JS接口安全域名。支付接口要确保支付目录在支付安全域名下。必须为1级域名

2.在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js

3.所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。

wx.config({    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。    appId: '', // 必填,公众号的唯一标识    timestamp: , // 必填,生成签名的时间戳    nonceStr: '', // 必填,生成签名的随机串    signature: '',// 必填,签名,见附录1    jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2});


重点在于签名。附录1中详细的解释了如何获取jsapi_ticket,有效时间为7200,通过access_token来获取。公众号调取jsapi_ticket有次数上限所以

要全局缓存做判断。只给出方法获取和判断jsapi_ticket的方法。

连接:”https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=“




代码如下:


/* * 获取jsSDK配置参数 */public static Map<String, String> getJsSDKConfig(String url) throws Exception {String jsApiTicket = getJsApiTicket();if (!jsApiTicket.equals("") && jsApiTicket != null) {return sign(jsApiTicket, url);} else {throw new Exception("获取到的jsApiTicket为空");}}/* * 获取微信jsApiTicket */public static String getJsApiTicket() throws Exception {if (jsApiTicket == null || System.currentTimeMillis() >= jsApiTicketExpiresTime) {return getNewJsApiTicket();} else {return jsApiTicket;}}/* * 刷新jsApiTicket */public static String getNewJsApiTicket() throws Exception {long start = System.currentTimeMillis();String accessToken = getAccessToken();if (!accessToken.equals("") && accessToken != null) {String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";String result = null;try {result = Http.sendGet(url, "utf-8", 1000);} catch (Exception e) {e.printStackTrace();throw new Exception("发起网络请求出错");}if (!result.equals("") && result != null) {JSONObject json = JSON.parseObject(result);if (json.getString("ticket") != null) {jsApiTicket = json.getString("ticket");jsApiTicketExpiresTime = System.currentTimeMillis() + (json.getLongValue("expires_in") * 1000) - 120 * 1000;System.out.println("调用获取jsApiTicket接口耗时-->" + (System.currentTimeMillis() - start) + "毫秒");return jsApiTicket;} else {System.out.println("调用获取jsApiTicket接口失败-->" + result);throw new Exception(result);}} else {throw new Exception("调用获取jsApiTicket接口返回数据为空");}} else {throw new Exception("获取到的accessToken为空");}}/* * 获取基本AccessToken */public static String getAccessToken() throws Exception {if (accessToken == null || System.currentTimeMillis() >= accessTokenExpiresTime) {return getNewAccessToken();} else {long expires = System.currentTimeMillis() - lastCheckaccessTokenTime;// 5分钟检查一次accessToken是否有效if (expires < 300000 || checkAccessToken()) {return accessToken;} else {return getNewAccessToken();}}}/* * 获取最新accessToken */public static String getNewAccessToken() throws Exception {long start = System.currentTimeMillis();String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + WeiXinUtils.APP_ID + "&secret=" + WeiXinUtils.AppSecret;String result = null;try {result = Http.sendGet(url, "utf-8", 1000);} catch (Exception e) {e.printStackTrace();throw new Exception("发起网络请求出错");}if (!result.equals("") && result != null) {JSONObject json = JSON.parseObject(result);if (json.getString("access_token") != null) {accessToken = json.getString("access_token");accessTokenExpiresTime = System.currentTimeMillis() + (json.getLongValue("expires_in") * 1000) - 120 * 1000;lastCheckaccessTokenTime = System.currentTimeMillis();System.out.println("调用获取公众号accessToken接口耗时-->" + (System.currentTimeMillis() - start) + "毫秒");return accessToken;} else {System.out.println("调用获取公众号accessToken接口失败-->" + result);throw new Exception(result);}} else {throw new Exception("调用获取公众号accessToken接口返回数据为空");}}/* * 获取基本AccessToken */public static String getAccessToken() throws Exception {if (accessToken == null || System.currentTimeMillis() >= accessTokenExpiresTime) {return getNewAccessToken();} else {long expires = System.currentTimeMillis() - lastCheckaccessTokenTime;// 5分钟检查一次accessToken是否有效if (expires < 300000 || checkAccessToken()) {return accessToken;} else {return getNewAccessToken();}}}


获取到jsapi_ticket就可以生成签名。




签名由jsapi_ticket,noncestr,timestamp,url组成


代码如下:

/* * 调用微信JSSDK文档必须生成签名 *  * 详情请查阅微信API */public static Map<String, String> sign(String jsapi_ticket, String url) {Map<String, String> ret = new HashMap<String, String>();String nonce_str = create_nonce_str();String timestamp = create_timestamp();String string1;String signature = "";// 注意这里参数名必须全部小写,且必须有序string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url;System.out.println(string1);try {MessageDigest crypt = MessageDigest.getInstance("SHA-1");crypt.reset();crypt.update(string1.getBytes("UTF-8"));signature = byteToHex(crypt.digest());} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}ret.put("url", url);ret.put("jsapi_ticket", jsapi_ticket);ret.put("nonceStr", nonce_str);ret.put("timestamp", timestamp);ret.put("signature", signature);return ret;}


生成字符串和时间戳的方法


代码如下:


/* * 微信JSSDK参数 随机字符串 */public static String create_nonce_str() {return UUID.randomUUID().toString().replaceAll("-", "");}/* * 微信JSSDK参数 时间戳 */public static String create_timestamp() {return Long.toString(System.currentTimeMillis() / 1000);}


填写config接口参数。chooseWXPay 为微信支付接口。如需微信其他接口更改jsSpiList的参数即可。


代码如下:

Map<String, String> signData = WeiXinUtil.getJsSDKConfig(url); if (signData != null) { Map<String,Object> map = new HashMap<String, Object>(); // debug参数为调试模式,开启时会返回参数,调试时开启 map.put("debug", false);  map.put("appId",WeiXinUtils.APP_ID);  map.put("timestamp", signData.get("timestamp")); map.put("nonceStr", signData.get("nonceStr"));  map.put("signature",signData.get("signature"));  map.put("jsApiList", "['chooseWXPay']"); // 写入request 前端页面取出Struts2Utils.getRequest().setAttribute("wxconfig", JSON.toJSON(map)); }

  前端取参数。wx.config(<%=request.getAttribute("wxconfig")%>);


  配置好js后。回到微信支付方法中。返回SUCCESS后获取到prepay_id。配置微信支付接口。



代码如下:

SortedMap<String, String> par = new TreeMap<String, String>();par.put("appId", WeiXinUtils.APP_ID);par.put("timeStamp", WeiXinUtil.create_timestamp());par.put("nonceStr", WeiXinUtil.create_nonce_str());par.put("package", "prepay_id=" + resultMap.get("prepay_id"));par.put("signType", "MD5");String signSuccess = Sign.sign(par);par.put("paySign", signSuccess);System.out.println(signSuccess);System.out.println("prepay_id=" + resultMap.get("prepay_id"));// 将SortedMap转为json 前台取参数Struts2Utils.renderJson(par);

此时代码都已经结束。最后一个就是配置微信支付路径。

在商户平台配置,比如说你的路径是:http://www.asdf.com/abc/pay/abc      那你应该填为:http://www.asdf.com/abc/pay

这是微信支付公众号的连接(里面介绍了微信中需要配置的域名等):https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3