微信支付之微信公众号网页支付(各种总结)
微信支付除了坑,就是坑!!!
網上也還是好多吐槽的,各種簽名問題,文檔也比較亂。重點是,安卓最后報錯就只報chooseWXPay failed。什么具體錯誤也不顯示。最后還是喊朋友的蘋果機遠程幫忙測試(蘋果機會返回錯誤信息)。
一:簽名問題
微信網頁支付。需要3個簽名。后面2個簽名的文檔總連接頁面,開發前一定要仔細看。https://mp.weixin.qq.com/wiki/11/74ad127cc054f6b80759c40f77ec03db.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82 ? ? ? ?第一個,獲取prepay_id的時候需要一個,那個按照文檔來沒問題。第二個簽名。再調用JS種需要,需要conf配置。那個也是需要生成一個授權簽名的。
所有需要使用JS-SDK的頁面必須先注入配置信息,否則將無法調用(同一個url僅需調用一次,對于變化url的SPA的web app可在每次url變化時進行調用,目前Android微信客戶端不支持pushState的H5新特性,所以使用pushState來實現web app的頁面會導致簽名失敗,此問題會在Android6.2中修復)。
所有需要使用JS-SDK的頁面必須先注入配置信息,否則將無法調用(同一個url僅需調用一次,對于變化url的SPA的web app可在每次url變化時進行調用,目前Android微信客戶端不支持pushState的H5新特性,所以使用pushState來實現web app的頁面會導致簽名失敗,此問題會在Android6.2中修復)。
上面這個,簽名請去看那個連接的附錄1。這個算法是附錄1有的。和簽名的不一樣。
第三個簽名:
發起一個微信支付請求
wx.chooseWXPay({timestamp: 0, // 支付簽名時間戳,注意微信jssdk中的所有使用timestamp字段均為小寫。但最新版的支付后臺生成簽名使用的timeStamp字段名需大寫其中的S字符nonceStr: '', // 支付簽名隨機串,不長于 32 位package: '', // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***)signType: '', // 簽名方式,默認為'SHA1',使用新版支付需傳入'MD5'paySign: '', // 支付簽名success: function (res) {// 支付成功后的回調函數} });備注:prepay_id 通過微信支付統一下單接口拿到,paySign 采用統一的微信支付 Sign 簽名生成方法,注意這里 appId 也要參與簽名,appId 與 config 中傳入的 appId 一致,即最后參與簽名的參數有appId, timeStamp, nonceStr, package, signType。
請注意該接口只能在你配置的支付目錄下調用,同時需確保支付目錄在JS接口安全域名下。
微信支付開發文檔:https://pay.weixin.qq.com/wiki/doc/api/index.html
上面的這個paySign就是最后一次簽名(第三次),參數有appId, timeStamp, nonceStr, package, signType這三個參數。第一個簽名的代碼:
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>(); parameters.put("appid", appid); parameters.put("mch_id", mch_id);parameters.put("nonce_str",nonce_str); parameters.put("body", body); parameters.put("out_trade_no", out_trade_no);parameters.put("total_fee", total_fee);parameters.put("spbill_create_ip", spbill_create_ip);parameters.put("notify_url",notify_url);parameters.put("trade_type", trade_type);parameters.put("openid", openid);System.out.println("ip:"+spbill_create_ip);String mysign=WeChatPayUtils.createSign("UTF-8", parameters);System.out.println("我的簽名是:"+mysign);
第一個簽名獲得后,就可以獲取到prepay_id了。
HttpPost post=new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");String xml="<xml>"+ "<appid>"+appid+"</appid>"+"<body>"+body+"</body>"+"<mch_id>"+mch_id+"</mch_id>"+"<nonce_str>"+nonce_str+"</nonce_str>"+"<notify_url>"+notify_url+"</notify_url>"+"<openid>"+openid+"</openid>"+"<out_trade_no>"+out_trade_no+"</out_trade_no>"+"<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"+"<total_fee>"+total_fee+"</total_fee>"+"<trade_type>"+trade_type+"</trade_type>"+"<sign>"+mysign+"</sign>"+"</xml>";post.setEntity(new StringEntity(xml,"UTF-8"));HttpResponse execute = httpClient.execute(post);HttpEntity entity = execute.getEntity();String responseContent = EntityUtils.toString(entity,"utf-8");String prepay_id=WeChatPayUtils.getPrepay_id(responseContent);
到現在為止,已經獲取到prepay_id了。
第二次JS授權簽名:
System.out.println("獲取到的prepay_id為:"+prepay_id);Token token=WeChatPayUtils.getToken() ;String jsapi_ticket = WeChatPayUtils.getJsapi_ticket(token);SortedMap<Object,Object> quanXianParameters = new TreeMap<Object,Object>();quanXianParameters.put("noncestr",nonce_str);quanXianParameters.put("jsapi_ticket",jsapi_ticket);quanXianParameters.put("timestamp",timeStamp);quanXianParameters.put("url",quanXianUrl);String quanXianSign = WeChatPayUtils.createSignWithNoKey("UTF-8", quanXianParameters);//調用JS權限簽名SHA1第三次支付授權
SortedMap<Object,Object> wePayparameters = new TreeMap<Object,Object>();wePayparameters.put("appId", appid);wePayparameters.put("timeStamp", timeStamp);wePayparameters.put("nonceStr", nonceStr);wePayparameters.put("signType", signType);wePayparameters.put("package","prepay_id="+prepay_id_package);String wePaySign=WeChatPayUtils.createSign("utf-8", wePayparameters);//支付簽名MD5且大寫
大概就需要的這些參數。當時我遇到最煩的就說第三次授權那個,那個應該是wePayparameters.put("package","prepay_id="+prepay_id_package);
前臺代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%> <!DOCTYPE html> <html class="no-js"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="description" content=""> <meta name="keywords" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>微信支付</title> <jsp:include page="../../common/include_head_css.jsp"></jsp:include> <script type="text/javascript"src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <style type="text/css"> </style> <script type="text/javascript"> var appId = "${appId}"; var timestamp ="${timeStamp}"; var nonceStr = "${nonceStr}"; var signType = "${signType}"; var paySign ="${wePaySign}"; var prepay_id="${prepay_id}"; var signature="${quanXianSign}"; wx.config({debug: true, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。appId: appId, // 必填,公眾號的唯一標識timestamp:timestamp, // 必填,生成簽名的時間戳nonceStr: nonceStr, // 必填,生成簽名的隨機串signature: signature,// 必填,簽名,見附錄1jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表,所有JS接口列表見附錄2 }); function pay(){alert("進了pay prepay_id:"+prepay_id+"timeStamp:"+timestamp);wx.chooseWXPay({'appId':appId,'timestamp' : timestamp, // 支付簽名時間戳,注意微信jssdk中的所有使用timestamp字段均為小寫。但最新版的支付后臺生成簽名使用的timeStamp字段名需大寫其中的S字符'nonceStr' : nonceStr, // 支付簽名隨機串,不長于 32 位'package' : 'prepay_id='+prepay_id, // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***)'signType' : signType, // 簽名方式,默認為'SHA1',使用新版支付需傳入'MD5''paySign' : paySign, // 支付簽名success : function(res) {alert("結果:" + res);}}); }</script> </head> <body><button class="am-btn am-btn-success" onClick="pay()">點擊支付</button> </body> </html>后臺應該要把那些appid等信息傳到session種,這樣前面jsp才能獲取。
wechatpayutils類種的核心代碼:
/** * 微信支付簽名算法sign 默認帶key* @param characterEncoding * @param parameters * @return */ public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){ StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet();//所有參與傳參的參數按照accsii排序(升序) Iterator it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); Object v = entry.getValue(); if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + WeChatPayUtils.key); System.out.println("創建sign的字符串未MD5加密前:"+sb.toString());String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); return sign; } /** * 微信支付簽名算法sign 默認不帶key* @param characterEncoding * @param parameters * @return */ public static String createSignWithNoKey(String characterEncoding,SortedMap<Object,Object> parameters){ StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet();//所有參與傳參的參數按照accsii排序(升序) Iterator it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); Object v = entry.getValue(); if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb=new StringBuffer(sb.substring(0, sb.length()-1));System.out.println("創建sign不用key未MD5加密前:"+sb.toString());String sign = SHA1.encode(sb.toString());return sign; } public static String getJsapi_ticket(Token token){String result="";String url=WeChatPayUtils.jsapi_ticket;HttpClient client=HttpClients.createDefault();HttpGet get=new HttpGet(url.replace("ACCESS_TOKEN", token.getAccessToken()));try {HttpResponse execute = client.execute(get);HttpEntity entity = execute.getEntity();String responseContent = EntityUtils.toString(entity,"UTF-8");System.out.println();System.out.println("獲取jsapi_ticket返回的json串:"+responseContent);System.out.println();JSONObject jsonResult=new JSONObject(responseContent);result=(String) jsonResult.get("ticket");} catch (ClientProtocolException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (JSONException e) {// TODO Auto-generated catch blocke.printStackTrace();}return result;}
MD5utils工具類中的核心代碼:
比如請求路徑為:www.xxx.com/pay/pay_index
那就是填寫上面那個www.xxx.com/pay。而不是填寫www.xxx.com/pay/pay_index。這個pay_index是錯的哦!!
湊合看。這個是可以的。我測試成功了。折騰了好幾天。如果你還不懂,留言看到了會回復的。自己都感覺亂。。。
總結
以上是生活随笔為你收集整理的微信支付之微信公众号网页支付(各种总结)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《林超:给年轻人的跨学科通识课》导图 0
- 下一篇: PC端微信dat还原工具源码分享【福利】