最近由于公司业务一直在作微信小程序的项目,趁此机会将最近踩过的一些坑总结记录下前端
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"} >才对! 传送门