最近由於公司業務一直在作微信小程序的項目,趁此機會將最近踩過的一些坑總結記錄下前端
appid 小程序惟一標識
secret 小程序的 app secret
js_code 登陸時獲取的 code
grant_type 填寫爲 authorization_code
openid 用戶惟一標識
session_key 會話密鑰iosopenid 是用戶惟一標識,但不建議直接用作後端服務器的各用戶標示符。
session_key 是針對用戶數據進行加密簽名的密匙。session_key 在文件校驗,獲取用戶具體信息時均需使用通常爲了安全起見,這兩個數據都不會發往客戶端。npm
//app.js const NOLOGINCODE = 1000003 //未登陸 const SUCCESS = 1000001 //成功 App({ onLaunch: function () { var loginFlag = wx.getStorageSync('sessionId'); var that = this; if (loginFlag) { // 檢查 session_key 是否過時 wx.checkSession({ // session_key 有效(未過時) success: function () { var userInfo = wx.getStorageSync('wxUserInfo') if (userInfo) { that.globalData.hasUserInfo = true } }, // session_key 過時 fail: function () { // session_key過時,從新登陸 that.doLogin(); } }); } else { // 無skey,做爲首次登陸 this.doLogin(); } }, doLogin() { this.log().then(res => { this.$post('/auth', { code: res.code, }, false).then(data => { wx.setStorageSync('sessionId', data.sessionId); }) }) }, /** *微信登陸 獲取code值,並將code傳遞給服務器 * @returns */ log() { return new Promise(resolve => { wx.login({ success(res) { if (res.errMsg === "login:ok") { resolve(res) } else { wx.showToast({ title: '微信登陸失敗', icon: 'none', duration: 1200 }) } }, fail() { wx.showToast({ title: '微信登陸接口調用失敗', icon: 'none', duration: 1200 }) } }) }) }, globalData: { baseurl: 'https://www.fake.shop' } })
補充json
微信小程序中網絡請求的api是wx.request(),可是這個請求是個異步回調的形式,每次發請求都要寫好長一串,並且若是是嵌套的發請求,就會發現代碼寫的及其臃腫,因此將其 Promisefy是及其有必要的。
代碼以下:小程序
$get(url, data = {}, needToken = true) { let SUCCESS = 200 var that = this needToken ? (data.token = wx.getStorageSync('ToKen')) : '' return new Promise((resolve, reject) => { wx.request({ url: that.globalData.baseurl + url, method: "GET", header: { 'content-type': 'application/json' }, data: data, success(e) { if (e.data.code == SUCCESS) { resolve(e.data) return } }, fail(e) { wx.showModal({ title: '提示', content: '請求失敗', showCancel: false }) reject(e) } }) }) }, $post(url, data = {}, needToken = true) { let that = this let SUCCESS = 200 let TimeOut = 1000 var that = this needToken ? (data.token = wx.getStorageSync('ToKen')) : '' return new Promise((resolve, reject) => { wx.request({ url: that.globalData.baseurl + url, method: "POST", //此處能夠根據接口文檔設置header頭 // header: { // 'content-type': 'application/x-www-form-urlencoded' // }, data: data, success(e) { if (e.statusCode == SUCCESS) { if (e.data.code == SUCCESS) { resolve(e.data) } else { reject(e) wx.showModal({ title: '提示', content: e.data.msg, showCancel: false, success: function (res) { if (res.confirm) { if (e.data.code == TimeOut) { //根據實際業務返回的code碼判斷是否過時 // 登陸過時 that.doLogin(); } } } }) } } else { wx.showModal({ title: '提示', content: e.data.error, showCancel: false }) reject(e) } }, fail(e) { console.log(e) wx.showModal({ title: '提示', content: '請求失敗', showCancel: false }) reject(e) }, complete(e) { } }) }) },
繼續以前的代碼更新😊😊😊後端
雖然是寫小程序踩坑指南,可是仍是抑制不住想吐槽的心情,由於調了一下午的公共號支付,仍是在同事已經寫完大部分邏輯的基礎上😭,裏面真的有幾個坑爹的地方,聽我慢慢道來😂微信小程序
UnionID:爲了識別用戶,每一個用戶針對每一個公衆號會產生一個安全的 OpenID,若是須要在多公衆號、移動應用之間作用戶共通,則需前往微信開放平臺,將這些公衆號和應用綁定到一個開放平臺帳號下,綁定後,一個用戶雖然對多個公衆號和應用有多個不一樣的 OpenID,但他對全部這些同一開放平臺帳號下的公衆號和應用,只有一個 UnionID
網頁受權: 一些複雜的業務場景下,須要以網頁的形式提供服務,經過網頁受權能夠獲取用戶的openid(注:獲取用戶的 OpenID 是無需用戶贊成的,獲取用戶的基本信息則需用戶贊成)
微信 JS-SDK:是開發者在網頁上經過 JavaScript 代碼使用微信原生功能的工具包,開發者可使用它在網頁上錄製和播放微信語音、監聽微信分享、上傳手機本地圖片、拍照等許多能力。
網頁內引入jssdk,主要有兩種api
npm install weixin-js-sdk ;
var wx = require('weixin-js-sdk');
網頁受權跨域
網站應用微信登陸是基於 OAuth2.0 協議標準構建的微信 OAuth2.0 受權登陸系統。獲取 openid 分爲兩步瀏覽器
業務流程 舉例: 支付頁面地址: payUrl => "http://www.foo.com/pay"
注:
URLEncoder.encode(payUrl)是很是有必要的
state參數: 用於保持請求和回調的狀態,受權請求後原樣帶回給第三方。該參數可用於防止 csrf 攻擊(跨站請求僞造攻擊),建議第三方帶上該參數,可設置爲簡單的隨機數加 session 進行校驗
後端獲取openid的緣由: 由於我是前端,不想搞這個(開玩笑的😜),其實主要多是由於這部分邏輯部分敏感的 公衆號的祕鑰等以及爲了不前端跨域的問題。
code的是時限: code做爲換取access_token的票據,每次用戶受權帶上的code將不同,code只能使用一次,5分鐘未被使用自動過時。 因此每次進行支付的時候都須要進行以上邏輯
代碼以下:
//this.wechaConfig 裏面保存的是後端調用預支付api 之後傳遞給前端用來調用getBrandWCPayRequest 的配置項。 let config = { appId: this.wechaConfig.appId + '', // 公衆號名稱,由商戶傳入 timeStamp: this.wechaConfig.timeStamp + '', // 時間戳,自 1970 年以來的秒數 nonceStr: this.wechaConfig.nonceStr + '', // 隨機串 package: this.wechaConfig.package + '', // 統一下單接口返回的 prepay_id 參數值,提交格式如:prepay_id=*** signType: this.wechaConfig.signType + '', // 微信簽名方式: paySign: this.wechaConfig.paySign + '', // 微信簽名 } // config = JSON.parse(JSON.stringify(config)) WeixinJSBridge.invoke( 'getBrandWCPayRequest', config, function(res) { if (res.err_msg == 'get_brand_wcpay_request:ok') { // 使用以上方式判斷前端返回, 微信團隊鄭重提示:res.err_msg 將在用戶支付成功後返回 ok,但並不保證它絕對可靠。 this.$router.push({ name: 'payResult', query: { status: true, id: this.addOrder.orderId, }, }) } else { this.$router.push({ name: 'payResult', query: { status: false, }, }) } }.bind(this) )
須要注意如下幾點
查到的比較有用的一個是 問題在於支付的時候 JSON 參數,必須所有是字符串。
好比個人錯誤是參數中 {"timeStamp":12312312},時間戳的值爲整型,雖然 Android 上能夠支付,可是 IOS 上就不行了,必須嚴格按文檔上說的,鍵和值所有是字符串!這樣 {"timeStamp":"12312312"} >纔對! 傳送門