前言
完成微信h5支付的你,繼續(xù)公眾號(hào)的支付也許更簡(jiǎn)單哦胆剧。
場(chǎng)景
微信瀏覽器中的應(yīng)用支付必須依賴于公眾號(hào)支付,下面就公眾號(hào)支付中的一些技術(shù)點(diǎn)進(jìn)行詳細(xì)的解析。
準(zhǔn)備工作
基本配置申請(qǐng)
參考資料:微信公眾號(hào)開通支付功能--百度經(jīng)驗(yàn)教程
基本信息
- 服務(wù)號(hào)捉片,服務(wù)號(hào)綁定的管理員號(hào)
- 開通支付賬號(hào),并記住支付賬號(hào)汞舱,與支付賬號(hào)綁定的微信號(hào)
- appid,秘鑰
- 支付賬號(hào)開通支付目錄(直接支付地址的上一級(jí)目錄)
- 設(shè)置了頁面授權(quán)域名伍纫,并且是你的站點(diǎn)域名地址
- 基本接口權(quán)限,尤其是jssdk部分權(quán)限昂芜,保證盡可能都開通
業(yè)務(wù)流程圖解以及時(shí)序圖
與微信h5基本相同莹规,唯一不同的是這次微信返回的需要喚起微信sdk支付的參數(shù)列表。
技術(shù)問題
獲取openid
網(wǎng)站應(yīng)用微信登錄是基于OAuth2.0協(xié)議標(biāo)準(zhǔn)構(gòu)建的微信OAuth2.0授權(quán)登錄系統(tǒng)泌神。獲取openid分為兩步良漱,獲取code,然后根據(jù)code獲取openid欢际,建議這兩部分請(qǐng)求由后端發(fā)起母市,前端直接請(qǐng)求會(huì)涉及到跨域問題。后端直接把這兩個(gè)方法定義為工具方法损趋,使用方便窒篱,便于其他場(chǎng)景的復(fù)用。
一 :請(qǐng)求獲取code,如果不想浪費(fèi)時(shí)間請(qǐng)直接復(fù)制粘貼使用
-
標(biāo)準(zhǔn)格式拼接代碼:
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`
-
請(qǐng)求參數(shù)說明
參數(shù) 是否必須 說明 appid 是 應(yīng)用唯一標(biāo)識(shí) redirect_uri 是 請(qǐng)使用urlEncode對(duì)鏈接進(jìn)行處理 response_type 是 填code scope 是 應(yīng)用授權(quán)作用域墙杯,擁有多個(gè)作用域用逗號(hào)(,)分隔配并,網(wǎng)頁應(yīng)用目前僅填寫snsapi_login即可,這里用的 snsapi_userinfo state 否 用于保持請(qǐng)求和回調(diào)的狀態(tài)高镐,授權(quán)請(qǐng)求后原樣帶回給第三方溉旋。該參數(shù)可用于防止csrf攻擊(跨站請(qǐng)求偽造攻擊),建議第三方帶上該參數(shù)嫉髓,可設(shè)置為簡(jiǎn)單的隨機(jī)數(shù)加session進(jìn)行校驗(yàn) 返回說明:
用戶允許授權(quán)后观腊,將會(huì)重定向到redirect_uri的網(wǎng)址上,并且?guī)蟘ode和state參數(shù)
redirect_uri?code=CODE&state=STATE
若用戶禁止授權(quán)算行,則重定向后不會(huì)帶上code參數(shù)梧油,僅會(huì)帶上state參數(shù)
redirect_uri?state=STATE
二 根據(jù)code獲取openid
-
一個(gè)用戶針對(duì)一個(gè)公眾號(hào)openid是固定的,所以獲取到一樣的不用懷疑州邢,涉及到部分敏感的公眾號(hào)的秘鑰等儡陨,建議是后端處理發(fā)起請(qǐng)求,這樣也可以避免前端跨域的問題。
//網(wǎng)關(guān)或者后端的設(shè)置(以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 傳入對(duì)象的形式量淌,改造通用的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), //前端的寫法骗村,好處是避免暴露公眾號(hào)的相關(guān)信息 this.$api.post("order/getOpenId", { code: this.code }).then(res => { // 正確獲取openid的情況下 請(qǐng)求后臺(tái)參數(shù)得到對(duì)應(yīng)的返回參數(shù),目前只需要openid if (res.openid) { this.openId = res.openid; //準(zhǔn)備條件足夠的話 可以喚起支付 this.topay() }else { //請(qǐng)求失敗或者沒有對(duì)應(yīng)的字段 }
-
請(qǐng)求參數(shù)說明,通過code獲取access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
參數(shù) 是否必須 說明 appid 是 應(yīng)用唯一標(biāo)識(shí)呀枢,在微信開放平臺(tái)提交應(yīng)用審核通過后獲得 secret 是 應(yīng)用密鑰AppSecret胚股,在微信開放平臺(tái)提交應(yīng)用審核通過后獲得 code 是 填寫第一步獲取的code參數(shù) grant_type 是 填authorization_code -
返回結(jié)果說明
//正確的返回 { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" } //錯(cuò)誤的返回 {"errcode":40029,"errmsg":"invalid code"}
刷新fresh-token有效期
如果token失效了,可以用refresh_token重新獲取一個(gè)裙秋。
微信支付sdk
方式一 :官網(wǎng)的方式
invoke方法 琅拌,簡(jiǎn)單有效,直接根據(jù)接口返回參數(shù)喚起摘刑。以下代碼實(shí)例是vue環(huán)境下的进宝,其他環(huán)境請(qǐng)自行匹配,僅供參考泣侮。
// 準(zhǔn)備好微信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準(zhǔn)備完成
onBridgeReady() {
// 觸發(fā)微信支付
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
appId: this.payOption.appId, //公眾號(hào)名稱即彪,由商戶傳入
timeStamp: this.payOption.timeStamp, //時(shí)間戳紧唱,自1970年以來的秒數(shù)
nonceStr: this.payOption.nonceStr, //隨機(jī)串
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="http://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需要)--結(jié)合接口返回參數(shù)--喚起wxpay。(比較麻煩漏益,不推薦使用)
參考文檔: