前言
完成微信h5支付的你,繼續公眾號的支付也許更簡單哦。
場景
微信瀏覽器中的應用支付必須依賴於公眾號支付,下面就公眾號支付中的一些技術點進行詳細的解析。
準備工作
基本配置申請
參考資料:微信公眾號開通支付功能--百度經驗教程
基本資訊
- 服務號,服務號繫結的管理員號
- 開通支付賬號,並記住支付賬號,與支付賬號繫結的微訊號
- appid,祕鑰
- 支付賬號開通支付目錄(直接支付地址的上一級目錄)
- 設定了頁面授權域名,並且是你的站點域名地址
- 基本介面許可權,尤其是jssdk部分許可權,保證儘可能都開通
業務流程圖解以及時序圖
與微信h5基本相同,唯一不同的是這次微信返回的需要喚起微信sdk支付的引數列表。
技術問題
獲取openid
網站應用微信登入是基於OAuth2.0協議標準構建的微信OAuth2.0授權登入系統。獲取openid分為兩步,獲取code,然後根據code獲取openid,建議這兩部分請求由後端發起,前端直接請求會涉及到跨域問題。後端直接把這兩個方法定義為工具方法,使用方便,便於其他場景的複用。
一 :請求獲取code,如果不想浪費時間請直接複製貼上使用
-
標準格式拼接程式碼:
let encodeUrl=encodeURIComponent(`http://xxx/xhxwxpay?productId=${productId}&orderNo=${orderNo}`) let tempUrl=`https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx6f5de09c8ef178a7&redirect_uri=${encodeUrl}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect` 複製程式碼
-
請求引數說明
引數 是否必須 說明 appid 是 應用唯一標識 redirect_uri 是 請使用urlEncode對連結進行處理 response_type 是 填code scope 是 應用授權作用域,擁有多個作用域用逗號(,)分隔,網頁應用目前僅填寫snsapi_login即可,這裡用的 snsapi_userinfo state 否 用於保持請求和回撥的狀態,授權請求後原樣帶回給第三方。該引數可用於防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該引數,可設定為簡單的隨機數加session進行校驗 -
返回說明: 使用者允許授權後,將會重定向到redirect_uri的網址上,並且帶上code和state引數
redirect_uri?code=CODE&state=STATE
若使用者禁止授權,則重定向後不會帶上code引數,僅會帶上state引數redirect_uri?state=STATE
-
參考文件:微信中web網站獲取code參考文件
二 根據code獲取openid
-
一個使用者針對一個公眾號openid是固定的,所以獲取到一樣的不用懷疑,涉及到部分敏感的公眾號的祕鑰等,建議是後端處理髮起請求,這樣也可以避免前端跨域的問題。
//閘道器或者後端的設定(以koa框架的為例) *post_getOpenId(){ let reqData = this.request.body; let param = { appid:'wxxxx', secret:'affsdcsdvdsvfv6', code:reqData.code, grant_type:'authorization_code' } let result = yield this.api.getOpenId(param); this.body = result; } // 獲取openid 傳入物件的形式,改造通用的api方法 getOpenId: function* (apiParam, json = true) { // 獲取token的地址 let apiUrl='https://api.weixin.qq.com/sns/oauth2/access_token' let response = yield request.get(apiUrl, { qs: apiParam, json: json }); return responseHandle(response, apiUrl, apiParam); }.bind(this), //前端的寫法,好處是避免暴露公眾號的相關資訊 this.$api.post("order/getOpenId", { code: this.code }).then(res => { // 正確獲取openid的情況下 請求後臺引數得到對應的返回引數,目前只需要openid if (res.openid) { this.openId = res.openid; //準備條件足夠的話 可以喚起支付 this.topay() }else { //請求失敗或者沒有對應的欄位 } 複製程式碼
-
請求引數說明,通過code獲取access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code 複製程式碼
引數 是否必須 說明 appid 是 應用唯一標識,在微信開放平臺提交應用稽核通過後獲得 secret 是 應用金鑰AppSecret,在微信開放平臺提交應用稽核通過後獲得 code 是 填寫第一步獲取的code引數 grant_type 是 填authorization_code -
返回結果說明
//正確的返回 { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" } //錯誤的返回 {"errcode":40029,"errmsg":"invalid code"} 複製程式碼
-
重新整理fresh-token有效期 如果token失效了,可以用refresh_token重新獲取一個。
微信支付sdk
方式一 :官網的方式
invoke方法 ,簡單有效,直接根據介面返回引數喚起。以下程式碼例項是vue環境下的,其他環境請自行匹配,僅供參考。
// 準備好微信sdk部分
jsSdk(){
// 判斷微信的WeixinJSBridge
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', this.onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', this.onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', this.onBridgeReady);
}
}else{
this.onBridgeReady();
}
},
// 支付sdk準備完成
onBridgeReady() {
// 觸發微信支付
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
appId: this.payOption.appId, //公眾號名稱,由商戶傳入
timeStamp: this.payOption.timeStamp, //時間戳,自1970年以來的秒數
nonceStr: this.payOption.nonceStr, //隨機串
package: this.payOption.package, //prepay_id用等式的格式
signType: this.payOption.signType, //微信簽名方式:
paySign: this.payOption.paySign, //微信簽名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
// 支付成功 返回成功頁
let tempUrl="//paysucc"
location.href=tempUr
} else{
// 取消支付或者其他情況 get_brand_wcpay_request:cancel get_brand_wcpay_request:fail
let tempUrl='//topay'
location.href=tempUrl
}
}
);
},
複製程式碼
方式二 : 需要引入js-weixin的模組,流程如下:
引入模組--ready--獲取access-token--獲取ticket--生成簽名(wx.config需要)--結合介面返回引數--喚起wxpay。(比較麻煩,不推薦使用) 參考文件: