微信 H5 支付流程以及一些坑

原文:https://blog.niceue.com/front-end-development/wechat-h5-payment-process-as-well-as-some-pits.htmljavascript

最近作的 SPA 網站集成了微信支付,使用的是微信 H5 調起支付API接口。作完後對微信 H5 支付的流程有了進一步的瞭解,在先後端調試接口的過程當中也遇到了一些問題,在這裏記錄下來。php

支付流程

  1. 在訂單頁 ajax 請求後端發起下單,後端掛起請求
  2. 後端根據訂單號結合微信支付相關配置參數向微信服務器發起統一下單
  3. 下單成功,微信通知前面傳遞的 notify_url,返回 prepay_id (預支付交易會話標識)
  4. 後端返回前端 JSAPI 調用的參數
  5. 前端使用 JSSDK 的 wx.chooseWXPay 發起支付
wx.chooseWXPay({ timestamp: '', // 支付簽名時間戳 nonceStr: '', // 支付簽名隨機串 package: '', // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***) signType: 'MD5', // 簽名方式 paySign: '', // 支付簽名 })

這裏看起來是 5 步,但其實還少了一步。調用「統一下單」接口的時候須要微信用戶的 openid。html

openid 是什麼?

官方解釋前端

加密後的微信號,每一個用戶對每一個公衆號的 openid 是惟一的。對於不一樣公衆號,同一用戶的 openid 不一樣

這個 openid 只能在微信環境經過重定向拿到。可是在下單的時候用的是 ajax 請求,還用重定向用戶體驗就比較差。因此須要在進入微信的時候就經過重定向拿到 openid 緩存起來,後面就能夠直接使用了。因此入口頁面就要作點小動做。java

獲取 openid

官方有OpenID的獲取指引。對於 H5 應用,獲取方式分 3 步走:ajax

1. 後端重定向到獲取 code 接口

後端能夠定義一個 /wechat/redirect 接口,例如:後端

http://yoursite.com/wechat/redirect?url=home_url

用這個地址重定向獲取 code 地址,其中的 url 參數爲最終的重定向地址,在拿到 openid 後跳轉到該 urlapi

2. 獲取 code:

接口地址緩存

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirec

接口參數:服務器

  • appid: 公衆帳號ID
  • redirect_uri: 接收 code 的回調地址(請UrlEncode)
  • response_type: 固定值 code
  • scope: 應用受權做用域,填 snsapi_base 或者 snsapi_login(可獲取用戶信息,如頭像、暱稱等)
  • state: 用於保持請求和回調的狀態,防止 csrf 攻擊,可設置爲簡單的隨機數加 session 進行校驗

提示:snsapi_login 會跳轉到受權頁讓用戶受權
微信接着會重定向三次,第三次重定向返回到 redirect_uri 地址,而且帶上了 code 參數

3. 經過 code 獲取 openid 和 access_token

接口地址

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

獲取到 openid 後注意在 session 中緩存起來

一些須要注意的坑

1. 獲取 code 的接口地址

OpenID的獲取指引文檔,請注意黑色標題「微信公衆平臺」和「微信開放平臺」。兩個地方獲取 code 的接口地址不同,但參數是同樣的。最開始後端看錯了文檔使用的是「網站應用微信登陸」文檔裏面提供的獲取 code 的接口,這樣子怎麼都是調不通的。

// 微信公衆平臺是
https://open.weixin.qq.com/connect/oauth2/authorize
// 微信開放平臺是
https://open.weixin.qq.com/connect/qrconnect

2. 後端簽名用 timeStamp,而前端調用支付接口使用全小寫 timestamp

微信官方網頁端調起支付API這個接口文檔參數卻誤導觀衆,寫的是駝峯的 timeStamp
後端爲了方便返回給前端的也是 timeStamp,因此在前端須要轉換
解決辦法:

if (!data.timestamp) data.timestamp = data.timeStamp

3. iOS 和 Android 版微信對「支付受權目錄」的檢測不一樣

http://yousite.com/mobile/#!/checkout

以上路徑,iOS 微信識別正確:http://yousite.com/mobile/
而 Android 微信識別出的目錄是:http://yousite.com/mobile/#!/checkout
這應該是 Android 版微信的 Bug
解決辦法是在 # 前添加一個 ?http://yousite.com/mobile/?#!/checkout

相關文章
相關標籤/搜索