使用weixin-java-tools完成微信授權(quán)登錄、微信支付的示例
本文為學(xué)習(xí)記錄weixin-java-tools實(shí)現(xiàn)公眾號(hào)微信支付.
碼云地址:點(diǎn)我
// 授權(quán)登錄用到 <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-mp</artifactId> <version>3.1.0</version> </dependency>
// 微信支付用到 <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-pay</artifactId> <version>3.1.0</version> </dependency>
授權(quán)登錄官方 api:點(diǎn)我
個(gè)人理解的授權(quán)登錄流程:引導(dǎo)用戶點(diǎn)擊喚起授權(quán)登錄的地址,打開(kāi)頁(yè)面后攜帶微信返回的code參數(shù);使用code參數(shù)獲取AccessToken;獲取用戶數(shù)據(jù)。
引導(dǎo)客戶打開(kāi)授權(quán)登錄地址后,攜帶code跳轉(zhuǎn)到指定頁(yè)面在指定頁(yè)面調(diào)用方法:
public Result getAccessToken(@RequestParam(name = "code") String code, HttpServletRequest request, HttpServletResponse response) { if (StringUtils.isBlank(code)) { return Result.error("code不存在"); } try { WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code); String accessToken = wxMpOAuth2AccessToken.getAccessToken(); // 獲取用戶微信賬戶信息 WxMpUser wxMpUser = wxMpService.getUserService().userInfo(wxMpOAuth2AccessToken.getOpenId()); if (StringUtils.isBlank(wxMpUser.getOpenId())) { return Result.error("用戶數(shù)據(jù)不存在"); } return Result.success(wxMpUser); } catch (WxErrorException e) { e.printStackTrace(); log.info("授權(quán)異常:{}", e); return Result.error("授權(quán)登錄失敗"); } catch (Exception e) { e.printStackTrace(); return Result.error("登錄失敗"); } }
前端保存下用戶信息就完事了。
個(gè)人理解的微信支付流程:用戶頁(yè)面點(diǎn)擊<微信支付>按鈕 后端調(diào)用 <微信統(tǒng)一下單> 統(tǒng)一下單返回參數(shù) ,前端使用 <統(tǒng)一下單>返回的參數(shù)喚起微信支付。
商戶中需要在api安全中設(shè)置很多東西... 就不一一贅述了
微信支付官方api 前端:點(diǎn)我
后端api點(diǎn)我
商戶登錄地址 點(diǎn)我
public Result pay(Long orderNo, HttpServletRequest request) { //查詢訂單信息 Order order = orderService.findByOrderNo(orderNo); try { WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest(); //獲取當(dāng)前用戶 UserInfo userInfo = RequestContextHolderUtil.getUserInfo(); orderRequest.setBody("支付內(nèi)容的說(shuō)明"); //商戶號(hào) orderRequest.setMchId(mchId); orderRequest.setAttach("xxx公司"); orderRequest.setOutTradeNo(orderNo.toString()); orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(order.getPayment().toString()));//元轉(zhuǎn)成分 orderRequest.setOpenid(userInfo.getOpenId()); orderRequest.setSpbillCreateIp(HttpUtils.getIp(request)); //我這里是微信公眾號(hào)內(nèi)打開(kāi)的h5頁(yè)面 type使用 JSAPI 根據(jù)業(yè)務(wù)場(chǎng)景變更 orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI); // 支付成功后跳轉(zhuǎn)頁(yè)面 這里需要對(duì)url進(jìn)行編碼 orderRequest.setNotifyUrl("http://xxxxxxxxx"); orderRequest.setAppid(appId); // 調(diào)用sdk提供的統(tǒng)一下單方法 createOrder會(huì)返回重新組裝后的對(duì)象 建議使用這個(gè) Object unOrder = wxService.createOrder(orderRequest); // 這個(gè)可能是偏向原生一點(diǎn)的統(tǒng)一下單,返回的參數(shù)有很多沒(méi)用的 或者null值 建議使用 createOrder下單 // wxService.unifiedOrder(orderRequest); return Result.success(unOrder); } catch (Exception e) { log.error("微信支付失??!訂單號(hào):{},原因:{}", orderNo, e.getMessage()); e.printStackTrace(); return Result.error("支付失敗,請(qǐng)稍后重試!"); } }
前端js代碼:
前端喚起微信支付的時(shí)候可能會(huì)出一些問(wèn)題,這里建議使用 console.log(res.err_desc);輸出錯(cuò)誤信息
res.err_msg 只會(huì)提示支付失敗... desc會(huì)提示一些具體信息
function onBridgeReady(){ WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId":"wx31fd1e1bad23db37", //公眾號(hào)名稱(chēng),由商戶傳入 "timeStamp":wxData.timeStamp, //時(shí)間戳,自1970年以來(lái)的秒數(shù) "nonceStr":wxData.nonceStr, //隨機(jī)串 "package":wxData.packageValue, "signType":wxData.signType, //微信簽名方式: "paySign":wxData.paySign //微信簽名 }, function(res){ console.log(res.err_desc) if(res.err_msg == "get_brand_wcpay_request:ok" ){ // 使用以上方式判斷前端返回,微信團(tuán)隊(duì)鄭重提示: //res.err_msg將在用戶支付成功后返回ok,但并不保證它絕對(duì)可靠。 } }); } var wxData={}; function pay(orderId){ $.ajax({ url:"統(tǒng)一下單方法url", type:'get', data:{orderNo:orderId}, beforeSend: function (xhr) { xhr.setRequestHeader("token", $.cookie("token")); }, crossDomain: true, success:function(result){ wxData=result.data; if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } } else { onBridgeReady(); } } }); }
注:商戶中心支付路徑設(shè)置 所有調(diào)起微信支付的頁(yè)面都要在此注冊(cè),否則微信支付會(huì)一閃而過(guò)。
微信開(kāi)發(fā)工具上可以模擬授權(quán)登錄,但是無(wú)法模擬微信支付,所以微信支付在微信開(kāi)發(fā)工具上出現(xiàn)的錯(cuò)誤都不用管,直接拿到真機(jī)上去測(cè)試!
使用了sdk后的支付和授權(quán)還是很方便的,麻煩的是微信方面的一些配置和流程... 很坑。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js限制文本框只能輸入整數(shù)或者帶小數(shù)點(diǎn)的數(shù)字
如何用js限制文本框輸入,只允許輸入整數(shù)或帶一位小數(shù)的浮點(diǎn)數(shù),本文分享一例代碼,有需要的朋友參考下2015-04-04Bootstrap打造一個(gè)左側(cè)折疊菜單的系統(tǒng)模板(一)
這篇文章主要介紹了Bootstrap打造一個(gè)左側(cè)折疊菜單的系統(tǒng)模板(一)的相關(guān)資料,需要的朋友可以參考下2016-05-05IE6、IE7中setAttribute不支持class/for/rowspan/colspan等屬性
IE6、IE7中setAttribute不支持class/for/rowspan/colspan等屬性的說(shuō)明,需要的朋友可以參考下。2011-08-08JavaScript中實(shí)現(xiàn)sprintf、printf函數(shù)
這篇文章主要介紹了JavaScript中實(shí)現(xiàn)sprintf、printf函數(shù),這兩個(gè)函數(shù)在大多數(shù)編程語(yǔ)言中都有,但JS中卻沒(méi)有,本文介紹在js中實(shí)現(xiàn)這兩個(gè)函數(shù)功能,需要的朋友可以參考下2015-01-01JS打開(kāi)層/關(guān)閉層/移動(dòng)層動(dòng)畫(huà)效果的實(shí)例代碼
JS打開(kāi)層/關(guān)閉層/移動(dòng)層動(dòng)畫(huà)效果的實(shí)例代碼,需要的朋友可以參考一下2013-05-05使用不同的方法結(jié)合/合并兩個(gè)JS數(shù)組
這是一篇關(guān)于JavaScript數(shù)組使用的一些技巧,我們將使用不同的方法結(jié)合/合并兩個(gè)JS數(shù)組,以及討論每個(gè)方法的優(yōu)點(diǎn)/缺點(diǎn)2014-09-09找出字符串中出現(xiàn)次數(shù)最多的字母和出現(xiàn)次數(shù)精簡(jiǎn)版
找出字符串中出現(xiàn)次數(shù)最多的字母和出現(xiàn)次數(shù)精簡(jiǎn)版,有需求的朋友可以參考下2012-11-11詳解使用grunt完成requirejs的合并壓縮和js文件的版本控制
這篇文章主要介紹了詳解使用grunt完成requirejs的合并壓縮和js文件的版本控制 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03js實(shí)現(xiàn)簡(jiǎn)單模態(tài)窗口,背景灰顯
昨天中午做項(xiàng)目需要一個(gè)模態(tài)窗口,想起上一個(gè)公司的項(xiàng)目經(jīng)理曾經(jīng)做過(guò)一個(gè)比較牛的模態(tài)窗口,至今沒(méi)用搞清楚實(shí)現(xiàn)原理,平時(shí)也沒(méi)有時(shí)間去分析,試著自己做了一個(gè),用了一天的時(shí)間終于完成了,給大家一起分享, 也希望高手多提意見(jiàn)。第一次在博客園上發(fā)文章,挺高興的。2008-11-11