公司項目須要,須要接入第三方支付,前先後後也搞了好久。雖然微信公衆平臺文檔已經寫得很清楚了,可是仍是記錄一下整個接入的流程。php
openid
是微信用戶在公衆號appid
下的惟一用戶標識(appid
不一樣,則獲取到的openid
就不一樣,因此不一樣的公衆號下有不一樣的openid
,),可用於永久標記一個用戶,同時也是微信公衆號支付的必傳參數。html
微信支付,須要用戶受權,獲取code,經過code
獲取網頁受權,實際上是要取得openid
,須要注意的是,code
只能使用一次,用戶每次受權帶上的code
都是不同的,而且五分鐘內不使用的話會自動過時。前端
咱們在進行支付時,點擊支付按鈕,首先會跳轉了頁面而後再跳轉回來,而後彈出框讓咱們輸入密碼,支付成功或者支付失敗。或者, 沒有跳轉頁面,直接就彈出密碼輸入框api
上面也說了,咱們獲取code
就是爲了獲取到openid
而後利用openid
這個必傳的參數才能成功喚起支付。瀏覽器
其實呢,讓用戶每次跳轉URL去獲取code
,而後傳code
參數給後臺也是能夠的。由於後臺的邏輯也是獲取了code
以後再利用code
去獲取openid
,而後進行進一步的操做。如今只是保存openid
這一操做,從後臺放到了前端。 只要咱們前端判斷openid
存在,咱們就沒必要再跳轉URL
進行受權從新獲取code
,能夠直接進行支付了。微信
因此能夠得出下圖:app
邏輯圖寫的雖然並不具體,可是很簡要。微信公衆平臺
接下來咱們就走一遍流程異步
點擊支付,第一次支付確定是不存在openid
的,那麼就要跳轉URL
獲取code
官方也已經寫得很明白 微信支付網頁受權函數
咱們須要拼接此連接:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
其中 APPID
是商戶的APPID,REDIRECT_URI
是頁面跳轉後跳回來的URL
,state
能夠放一些咱們自定義的內容,會帶在REDIRECT_URI
上。
例如:我要重定向的地址是https://baidu.com/testIndex.html/?#index
那麼,我要拼接的地址應該是https://open.weixin.qq.com/connect/oauth2/authorize?appi=XXXXX&redirect_uri=https://baidu.com/testIndex.html/?#index&response_type=code&scope=SCOPE&state={name:guo}#wechat_redirect
(URL
要進行編碼encodeURIComponent,這裏演示我就省略了)
那麼,重點來了,地址根據咱們拼接的地址跳轉過去,實際跳轉回來的地址會變成:https://baidu.com/testIndex.html?code=XXXX&state={name:guo}/?#index
(一樣須要解碼decodeURIComponent)
code=XXXX&state={name:guo}
這一坨東西跑到中間去了,那咱們嘗試把它取出來放到後面去
變成這樣子https://baidu.com/testIndex.html/?#index?code=XXXX&state={name:guo}
這樣一來,咱們就能用$route.query
取到參數了
//跳轉回來的URL修正,在地址跳轉回來的時候調用進行修正 var payUrlReplace = function() { //修正前: http://XXXX/?code=XXX&state=XXX/?#/XXX var codeReg = /(?:[?|&]code=)([\w\d]+)&{0,1}/; var statePayInfoReg= /(?:[?|&]*state=)({{1}.+}{1})&{0,1}/; var url = decodeURIComponent(window.location.href) //這裏是爲了確保#前有? if (url.indexOf('?#') < 0) { url = url.replace('#','?#'); } var urlReg = /\?#(.+)\?+/ //判斷URL掛載參數 if( codeReg.test(url) && statePayInfoReg.test(url) && url.match(statePayInfoReg).length > 0 && url.match(codeReg).length > 0 ){ var code = url.match(codeReg)[1] var state = url.match(statePayInfoReg)[1] url = url.replace(codeReg, '') url = url.replace(statePayInfoReg, '') if (urlReg.test(url)) { url = `${url}&payCode=${code}` }else { url = `${url}?payCode=${code}` } url = `${url}&payInfo=${state}` //修正後變成 http://XXX/?#/XXXX?payCode=XXX&payInfo=XXX,這裏我換了字段名 window.location.href = url } }
這樣,payCode
和payInfo
都能取到了。
有了code
,就能夠獲取openid
了,而後存在本地(這裏咱們的後臺專門寫了傳code
獲openid
的接口,這是異步操做)
上圖就說明了咱們傳code給後臺後,後臺再去獲取openid
, 後臺在傳給咱們前端。
而咱們要使用openid請求後臺接口獲取支付參數就要保證openid
必須存在,獲取openid
是異步操做,咱們必須保證前後順序。值得注意的是,openid一旦獲取保存在本地,以後支付就再也不須要獲取code了。
//檢查是否使用了微信支付 var payIsUse = function(query,callback){ //檢查這裏是否攜帶須要支付的參數 //?payCode=XXX&payInfo=XXX if(query && query.payCode){ var code = query.payCode if(query.payInfo){ var payInfo = JSON.parse(query.payInfo) } //判斷是否本地存在openID 若是存在則取消回調,由pay方法手動喚起支付 var openID = tokenServer.getOpenId(); if(openID){ return false; } //不存在openID用code去接口請求openID,在觸發回調去支付 payModel.saveOpenid({ code:code }).then(function(data){ if( tokenServer.setOpenId(data.data) ){ if(callback){ //將支付參數傳給回調函數 具體用的時候是傳給pay callback(payInfo) } } } }) } }
後臺接口,傳參得到的。
https://pay.weixin.qq.com/wik...
//微信JSDK喚起支付 var WeChatJSDKpay = function(config,onSuceess,onError){ var pay = function(){ WeixinJSBridge.invoke('getBrandWCPayRequest',{ "appId":config.appId, "timeStamp": config.timeStamp, "nonceStr": config.nonceStr, "package": config.package, "signType": config.signType, "paySign": config.paySign },function(res){ if(res.err_msg == "get_brand_wcpay_request:ok"){ //支付成功 onSuceess() }else{ //支付失敗 onError('支付失敗') } }); } if(typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function"){ pay() }else{ if (document.addEventListener) { document.addEventListener("WeixinJSBridgeReady", pay, false); } else if (document.attachEvent) { document.attachEvent("WeixinJSBridgeReady", pay); document.attachEvent("onWeixinJSBridgeReady", pay); } } }
/* *onSuccess 支付成功的回調 *onError 支付失敗的回調 *payInfo 支付參數 */ var pay = function(onSuceess,onError,payInfo) { var codeReg = /(?:[?|&]code=)([\w\d]+)&{0,1}/; var statePayInfoReg= /(?:[?|&]*state=)({{1}.+}{1})&{0,1}/; var payCodeReg = /(?:[?|&]payCode=)([\w\d]+)&{0,1}/; var payInfoReg = /(?:[?|&]*payInfo=)({{1}.+}{1})&{0,1}/; var url = decodeURIComponent(window.location.href) var openId = tokenServer.getOpenId() //openid存在 if (openId) { if (!payInfo){ return false; } //整理獲取微信支付參數的傳參 var defaultParams = { type: 1, //微信瀏覽器的標誌 openId: openId } var _payInfo = tool.extend(defaultParams, payInfo) (第三步驟-請求後臺接口獲取支付參數) payRequest(_payInfo).then(function(data) { modalLoadingServer.unload(); if(data.appId && data.status === 200){ //第四步驟-調起微信支付JSDK WeChatJSDKpay(data,function(){ //微信JSDK支付成功 返回驗證參數-流水號進行驗證 onSuceess(data.outTradeNo) },onError) }else{ console.error('獲取微信支付參數錯誤', _payInfo) onError('獲取微信支付參數錯誤,請稍候再試') } }) return false; } //若是已經存在 if(codeReg.test(url) && statePayInfoReg.test(url)){ window.location.reload(); return false; } //重複請求的話 if(payCodeReg.test(url) && payInfoReg.test(url)){ //處理下url從新請求 url = url.replace(payCodeReg,''); url = url.replace(payInfoReg,''); url = encodeURIComponent(url); }else{ //跳轉獲取code 回調url url = encodeURIComponent(window.location.href); } var statePay = {}; for(var key in payInfo){ //微信內支付不存在回調URL if(payInfo.hasOwnProperty(key) && payInfo[key] && key !== 'returnUrl'){ statePay[key] = payInfo[key] } } var statePay = encodeURIComponent(JSON.stringify(statePay)); var getCodeUrl = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxd9242c6d1e249d25&redirect_uri='+url+'&response_type=code&scope=snsapi_base&state='+statePay+'&connect_redirect=1#wechat_redirect'; //獲取`code`的跳轉連接 window.location.href = getCodeUrl }
以上是主要的代碼邏輯,也不是特別完整可以直接使用,可是可以獲得啓發。主要仍是要看具體的業務和接口怎麼給。有問題歡迎一塊兒交流~