最近由于公司业务一直在作微信小程序的项目,趁此机会将最近踩过的一些坑总结记录下。前端
附常见名词解释: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"} >才对! 传送门
以前写这篇文章的初衷是想着记录下本身踩过的坑,避免小伙伴们重复踩坑。如今看来内容仍是干货比较少,之后会持续更新的。。。