最近由於公司業務一直在作微信小程序的項目,趁此機會將最近踩過的一些坑總結記錄下。前端
附常見名詞解釋:ios
appid 小程序惟一標識 secret 小程序的 app secret js_code 登陸時獲取的 code grant_type 填寫爲 authorization_codenpm
openid 用戶惟一標識 session_key 會話密鑰json
openid 是用戶惟一標識,但不建議直接用作後端服務器的各標示符。 session_key 是針對用戶數據進行加密簽名的密 session_key 在文件校驗,獲取用戶具體信息時均需使用小程序
通常爲了安全起見,這兩個數據都不會發往客戶端。後端
//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'
}
})
複製代碼
微信小程序中網絡請求的 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) {
}
})
})
},
複製代碼
雖然是寫小程序踩坑指南,可是在微信內的 H5 頁面支付和小程序內掉起支付仍是有類似之處的,順便記錄一下。api
UnionID:爲了識別用戶,每一個用戶針對每一個公衆號會產生一個安全的 OpenID,若是須要在多公衆號、移動應用之間作用戶共通,則需前往微信開放平臺,將這些公衆號和應用綁定到一個開放平臺帳號下,綁定後,一個用戶雖然對多個公衆號和應用有多個不一樣的 OpenID,但他對全部這些同一開放平臺帳號下的公衆號和應用,只有一個 UnionID 網頁受權: 一些複雜的業務場景下,須要以網頁的形式提供服務,經過網頁受權能夠獲取用戶的 openid(注:獲取用戶的 OpenID 是無需用戶贊成的,獲取用戶的基本信息則需用戶贊成) 微信 JS-SDK:是開發者在網頁上經過 JavaScript 代碼使用微信原生功能的工具包,開發者可使用它在網頁上錄製和播放微信語音、監聽微信分享、上傳手機本地圖片、拍照等許多能力。跨域
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"} >纔對! 傳送門
以前寫這篇文章的初衷是想着記錄下本身踩過的坑,避免小夥伴們重複踩坑。如今看來內容仍是乾貨比較少,之後會持續更新的。。。