微信支付和h5支付詳解與示例

----------------------------------------------------------------------------------------------------------------------------

(下圖:微信支付流程圖)

 

2 微信公衆號支付的基本邏輯如下

  《1》---配置好一個url,直接通過window.location.href的方式訪問  ,與此同時會重定向到配置好的redicturl中,微信會給改url自動加上兩個參數:code和state
  《2》---前端截取到code參數,訪問後端接口拿到如下參數
     "appId":self.appId,     //公衆號名稱,由商戶傳入     
                    "nonceStr":self.nonceStr, //隨機串     
                    "package":self.package,     
                    "paySign":self.paySign,//微信簽名 
                    "signType":self.signType,         //微信簽名方式:
                    "timeStamp":self.timeStamp, 
 《3》拿到後端給與的參數以後,就可以監聽微信提供的事件來喚醒微信支付,只要微信提供的事件被監聽到,就會出現金額彈窗進行支付
    如下:
    onBridgeReady(){
                let self=this
                WeixinJSBridge.invoke(
                        'getBrandWCPayRequest', {
                        "appId":self.appId,     //公衆號名稱,由商戶傳入     
                        "nonceStr":self.nonceStr, //隨機串     
                        "package":self.package,     
                        "paySign":self.paySign,//微信簽名 
                        "signType":self.signType,         //微信簽名方式:
                        "timeStamp":self.timeStamp,         //時間戳,自1970年以來的秒數     
                        },
                        function(res){
                            if(res.err_msg == "get_brand_wcpay_request:ok" ){
                                console.log("支付成功",res)
                                window.location.href=`http://http://testaa.bb.net/#/pay?orderCode=${decodeURIComponent(self.orderCode)}&isWxPayOk=true`
                        }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
                                console.log("取消支付")
                                window.location.href='http://testaa.bb.net/#/pay/#/myOrder/1'
                        }else if(res.err_msg == "get_brand_wcpay_request:fail"){
                                console.log("支付失敗")
                                // WeixinJSBridge.call('closeWindow');
                                window.location.href=`http://testaa.bb.net/#/pay?orderCode=cls${decodeURIComponent(self.orderCode)}`
                    }
            }); 
        },
    
再說一說h5支付。h5支付再喚醒微信支付時候的邏輯基本一致,都是先有一個配置好的url然後重定向到對應 的
redirecturl地址然後獲取code,再向後端發請求拿到appid等參數,最後通過這些參數調用微信提供的方法喚醒微信支付。
但是在配置url時有一個地方卻迥然不同。
對於微信瀏覽器,
const wxurl="https://open.weixin.qq.com/connect/oauth2/authorize"
 let deCodeUrl=encodeURIComponent('http://testaa.bb.net/#/pay')---->這裏是你要重定向的頁面地址
const httpWxUrl=wxurl+`?appid=wx12345678&redirect_uri=${deCodeUrl}&response_type=code&scope=snsapi_base&state=123#wechat_redirect`
然後通過window.location.href=httpWxUrl
而對於其他瀏覽器而言:
這個wxurl地址卻並非我們寫死的。是需要後端提供的。所以h5支付在喚醒微信支付的時候流程應該是這樣的:
(1)請求後端接口獲取到一個url,本例中的mwebUrl,
(2)拼接一個帶有redirectur的新的地址,本例中的url
(3)重定向到這個地址,頁面打開獲取code---->請求接口獲取appid等參數---->調用微信提供的WeixinJSBridgeReady方法在改方法內通過 WeixinJSBridge.invoke的回調內處理成功或失敗的跳轉邏輯
let orderCode=db.ls.get("vuex").user.orderCode
let res= await orderApi.wxCreateOrder({...data,tradeType:'MWEB'})
console.log("獲取微信支付參數,",res.data.data.mwebUrl)
let mwebUrl=res.data.data.mwebUrl||""
let url=`${mwebUrl}&redirect_url=${encodeURIComponent('http://testaa.bb.net/#/pay?orderCode='+orderCode+'&isWxPayOk=true')}`
window.location.href=url

接下來說一說踩坑

1 微信支付的回調函數
  onBridgeReady(){
            let self=this
            WeixinJSBridge.invoke(
                'getBrandWCPayRequest', {
                    "appId":self.appId,     //公衆號名稱,由商戶傳入     
                    "nonceStr":self.nonceStr, //隨機串     
                    "package":self.package,     
                    "paySign":self.paySign,//微信簽名 
                    "signType":self.signType,         //微信簽名方式:
                    "timeStamp":self.timeStamp,         //時間戳,自1970年以來的秒數     
                },
                function(res){
    if(res.err_msg == "get_brand_wcpay_request:ok" ){
                        console.log("支付成功",res)
                        window.location.href=`http://testaa.bb.net/#/pay/#/pay?orderCode=${decodeURIComponent(self.orderCode)}&isWxPayOk=true`
                        // self.$router.push({path:"/pay",query:{orderCode:decodeURIComponent(self.orderCode),isWxPayOk:true}})
                    }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
                        console.log("取消支付")
                        window.location.href=`http://testaa.bb.net/#/pay?orderCode=${decodeURIComponent(self.orderCode)}`
                    }else if(res.err_msg == "get_brand_wcpay_request:fail"){
                        console.log("支付失敗")
                        // WeixinJSBridge.call('closeWindow');
                        window.location.href=`http://testaa.bb.net/#/pay?orderCode=cls${decodeURIComponent(self.orderCode)}`
                    }    

對於微信瀏覽器內打開的網頁進行支付,取消支付,支付成功,和支付失敗都會有觸發,也就是裏面的console.log()
但是對於h5支付而言。也即是除了微信瀏覽器而言。不管是取消還是成功或是失敗。都會都get_brand_wcpay_request:ok"成功的回調。
也正是如此,微信官方希望在取消支付或者支付成功的redirecturl裏開發者自己設計一個彈窗,讓用戶手動點擊,而點擊的時候走自己後端的接口
從而確定訂單是否真實完成。

既然上面提到了獲取code需要通過重定向一個頁面。然後通過該頁面的url截取到code。那容易就想到做一箇中間頁面,這樣在點擊支付的時候
跳轉到該頁面獲取到code,但是這也是坑的開始。因爲每次在支付成功以後返回都會退回到這個中間頁,再返回才能回到之前的支付頁面。而正常的交互
顯然不是這樣的,用戶支付成功以後點擊退回應該是支付頁面纔對。而且還有一個問題是因爲返回到了中間頁,而中間頁此時url沒有code,(只有正常點擊
支付按鈕走支付進入到中間頁此時中間頁的url纔會出現code,所以獲取不到code。也就意味着請求後端的接口走不通),這時就會出現一旦用戶取消獲取支付成功
以後返回就會報錯appid不存在之類的。
所以能不能不走中間頁,直接在點擊支付的前一個頁面獲取到code
所以正確的流程應該是

在進入支付頁面的前一個頁面進行重定向,在支付頁面獲取code 

 在這個頁面重定向

代碼如下:主要要區分下h5瀏覽器還是微信瀏覽器

 

在支付頁面

1 獲取code 

2 通過code請求後端接口獲取openid

3用戶點擊支付 ,先走後端接口,傳入openid和其他參數,獲取到appid,nonceStr,signType等參數

4 在步驟3的成功回調裏拿到appid,nonceStr,signType等參數,觸發微信內置的函數喚醒微信支付

5觸發步驟4的函數邏輯裏將有成功,失敗,取消等相應,前端進行相應的邏輯跳轉

發佈了34 篇原創文章 · 獲贊 12 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章