微信小程序的默認demo其中有一段是涉及到用戶的用戶信息的,我們在小程序里也看到了我的頭像和昵稱信息。
研究下他的代碼,主要在 app.js 文件中。
//app.js App({ onLaunch: function () { //調用API從本地緩存中獲取數據 var logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs) }, getUserInfo:function(cb){ var that = this if(this.globalData.userInfo){ typeof cb == "function" && cb(this.globalData.userInfo) }else{ //調用登錄接口 wx.login({ success: function () { wx.getUserInfo({ success: function (res) { that.globalData.userInfo = res.userInfo typeof cb == "function" && cb(that.globalData.userInfo) } }) } }) } }, globalData:{ userInfo:null } }) |
上述代碼從15行開始涉及到調用登錄接口。這里調用了小程序的api: wx.login 。這里說明下,小程序給開發者封裝好的API都是直接使用js的方法來調用,開發者直接使用類似 wx.login() 的方法就可以與微信的服務器進行交互,開發者不需要知道小程序框架到底調用了哪個地址,傳了哪些參數。
緊接著調用 wx.getUserInfo 接口,該接口可直接返回用戶數據.具體調用方法可參考 官方文檔
為了查看返回結果,我們在代碼18行位置插入兩句打印日志代碼,可以查看具體的結果。
wx.getUserInfo({ success: function (res) { console.log(res.userInfo) console.log(res.encryptedData) that.globalData.userInfo = res.userInfo |
可以看到控制臺中打印出了對應的結果。
接下來的例子小豬將使用官方hello world的例子,一般在我們的程序中不會將用戶的標識直接展示給用戶,作為演示,我們將本來顯示昵稱的位置的下方顯示出該小程序對應該用戶的openid。
這里我們看到通過上述接口獲取的信息都是一些比較基本的信息,包括:昵稱、頭像地址、性別等公開的數據。這些數據可以方便的顯示在用戶界面上,可是有時候我們需要系統的識別出該用戶,也就是需要該用戶的辨識。
在小程序的代碼中,服務器端代碼有兩種方式來獲取到用戶的openID。
直接調用 wx.login 接口,該接口會返回一個code字段,利用該code值可以向微信服務器開放的API請求用戶的openid,例如下列flask代碼:
fromflaskimportFlask, request importrequests app = Flask(__name__) appid = 'wx8fa41e5f33e*****' secret = '47d4ed43a683f800e66169c09dd*****' @app.route('/user/getuserinfo', methods=['GET', 'POST']) defgetuserinfo(): code = request.data printcode url = 'https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code' % (appid, secret, code) r = requests.get(url) result = r.text return result if __name__ == '__main__': app.run(debug=True) |
配合小程序的代碼:
//app.js App({ onLaunch: function () { //調用API從本地緩存中獲取數據 var logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs) }, getUserInfo:function(cb){ var that = this if(this.globalData.userInfo){ typeof cb == "function" && cb(this.globalData.userInfo) }else{ //調用登錄接口 wx.login({ success: function (r) { console.log(r) wx.request({ url: 'https://***.smallerpig.com/user/getuserinfo', data: r.code, method: 'POST', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT // header: {}, // 設置請求的 header success: function(res){ console.log('success') that.globalData.openid = res.data.openid console.log(res.data.openid) // success }, fail: function(res) { console.log('fail') console.log(res) // fail }, complete: function(res) { console.log('complete') console.log(res) // complete } }) wx.getUserInfo({ success: function (res) { that.globalData.userInfo = res.userInfo typeof cb == "function" && cb(that.globalData.userInfo) } }) } }) } }, globalData:{ userInfo:null, openid:null } }) |
上述js的小程序代碼大致邏輯為:
在調用 wx.login 并且執行成功之后將請求到的code值post到我們自己的服務器上面,在服務器上請求微信服務器的API,微信服務器得到正確值之后會得給到openid和session_key。
如下圖:
在之前的公眾號開發時,我們可以直接使用openId來作為用戶的標識,在小程序中我們同樣可以使用該字段。只是該字段沒有顯式的表示出來,而是通過res.encryptedData里。
通過之前的截圖可以看出,encryptedData是通過加密的數據,根據 官方文檔 解釋,我們只要使用指定的算法來解密就可以得到我們想要的openID。
解密算法如下:
官方也給出了幾種語言的 demo解密程序
通過這種方式不僅可以獲取到用戶的openid,也可以獲取到用戶的unionId。
方式一可以直接獲取到了用戶的openid,但是沒辦法獲取到unionId,如果咱們程序需要用到unionId的話就沒有辦法,肯定得用第二種方法了,如果只是為了獲取到openId那可以使用方式一來獲取。
不過方式二相比方式一相對復雜,需要通過第一步獲取到的session_key,再解密數據。也就是想要使用第二種方式的話其實第一種方法也得走一遍。
最后,從安全性來將當然方式二更安全一點。
下面附上小程序的index.js和index.wxml:
var app = getApp() Page({ data: { motto: 'Hello World', userInfo: {}, openid:null }, //事件處理函數 bindViewTap: function() { wx.navigateTo({ url: '../logs/logs' }) }, onLoad: function () { console.log('onLoad') var that = this //調用應用實例的方法獲取全局數據 app.getUserInfo(function(userInfo){ //更新數據 that.setData({ userInfo:userInfo, openid:app.globalData.openid }) }) } }) <!--index.wxml--> <viewclass="container"> <view bindtap="bindViewTap" class="userinfo"> <imageclass="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image> <textclass="userinfo-nickname">{{userInfo.nickName}}</text> <textclass="userinfo-nickname">{{openid}}</text> </view> <viewclass="usermotto"> <textclass="user-motto">{{motto}}</text> </view> </view> |
這一篇介紹了獲取用戶openid的兩種方式,并使用第一種方式結合flask框架寫了一個demo程序。
其中還用到了小程序API當中的一個非常重要的接口,就是 wx.request 。也就是通過該接口向我們自身的業務服務器請求數據,有點類似js中的ajax的作用,從《微信web開發者工具》的調試界面也可以看出其實際上就是通過xhr的方式來請求我們的業務服務器。
另外需要說明的是微信的小程序本身禁止使用ajax來請求網絡資源。
下一篇小豬將重點介紹使用方式二來解密用戶的數據,服務器端代碼同樣使用flask來實現。