微信小程序的默認(rèn)demo其中有一段是涉及到用戶的用戶信息的,我們在小程序里也看到了我的頭像和昵稱信息。
研究下他的代碼,主要在 app.js 文件中。
//app.js
App({
onLaunch: function () {
//調(diào)用API從本地緩存中獲取數(shù)據(jù)
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{
//調(diào)用登錄接口
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行開始涉及到調(diào)用登錄接口。這里調(diào)用了小程序的api: wx.login 。這里說明下,小程序給開發(fā)者封裝好的API都是直接使用js的方法來調(diào)用,開發(fā)者直接使用類似 wx.login() 的方法就可以與微信的服務(wù)器進行交互,開發(fā)者不需要知道小程序框架到底調(diào)用了哪個地址,傳了哪些參數(shù)。
緊接著調(diào)用 wx.getUserInfo 接口,該接口可直接返回用戶數(shù)據(jù).具體調(diào)用方法可參考 官方文檔
為了查看返回結(jié)果,我們在代碼18行位置插入兩句打印日志代碼,可以查看具體的結(jié)果。
wx.getUserInfo({
success: function (res) {
console.log(res.userInfo)
console.log(res.encryptedData)
that.globalData.userInfo = res.userInfo
|
可以看到控制臺中打印出了對應(yīng)的結(jié)果。

接下來的例子小豬將使用官方hello world的例子,一般在我們的程序中不會將用戶的標(biāo)識直接展示給用戶,作為演示,我們將本來顯示昵稱的位置的下方顯示出該小程序?qū)?yīng)該用戶的openid。
這里我們看到通過上述接口獲取的信息都是一些比較基本的信息,包括:昵稱、頭像地址、性別等公開的數(shù)據(jù)。這些數(shù)據(jù)可以方便的顯示在用戶界面上,可是有時候我們需要系統(tǒng)的識別出該用戶,也就是需要該用戶的辨識。
在小程序的代碼中,服務(wù)器端代碼有兩種方式來獲取到用戶的openID。
直接調(diào)用 wx.login 接口,該接口會返回一個code字段,利用該code值可以向微信服務(wù)器開放的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 () {
//調(diào)用API從本地緩存中獲取數(shù)據(jù)
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{
//調(diào)用登錄接口
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: {}, // 設(shè)置請求的 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的小程序代碼大致邏輯為:
在調(diào)用 wx.login 并且執(zhí)行成功之后將請求到的code值post到我們自己的服務(wù)器上面,在服務(wù)器上請求微信服務(wù)器的API,微信服務(wù)器得到正確值之后會得給到openid和session_key。
如下圖:

在之前的公眾號開發(fā)時,我們可以直接使用openId來作為用戶的標(biāo)識,在小程序中我們同樣可以使用該字段。只是該字段沒有顯式的表示出來,而是通過res.encryptedData里。
通過之前的截圖可以看出,encryptedData是通過加密的數(shù)據(jù),根據(jù) 官方文檔 解釋,我們只要使用指定的算法來解密就可以得到我們想要的openID。
解密算法如下:
官方也給出了幾種語言的 demo解密程序
通過這種方式不僅可以獲取到用戶的openid,也可以獲取到用戶的unionId。
方式一可以直接獲取到了用戶的openid,但是沒辦法獲取到unionId,如果咱們程序需要用到unionId的話就沒有辦法,肯定得用第二種方法了,如果只是為了獲取到openId那可以使用方式一來獲取。
不過方式二相比方式一相對復(fù)雜,需要通過第一步獲取到的session_key,再解密數(shù)據(jù)。也就是想要使用第二種方式的話其實第一種方法也得走一遍。
最后,從安全性來將當(dāng)然方式二更安全一點。
下面附上小程序的index.js和index.wxml:
var app = getApp()
Page({
data: {
motto: 'Hello World',
userInfo: {},
openid:null
},
//事件處理函數(shù)
bindViewTap: function() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad: function () {
console.log('onLoad')
var that = this
//調(diào)用應(yīng)用實例的方法獲取全局?jǐn)?shù)據(jù)
app.getUserInfo(function(userInfo){
//更新數(shù)據(jù)
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的兩種方式,并使用第一種方式結(jié)合flask框架寫了一個demo程序。
其中還用到了小程序API當(dāng)中的一個非常重要的接口,就是 wx.request 。也就是通過該接口向我們自身的業(yè)務(wù)服務(wù)器請求數(shù)據(jù),有點類似js中的ajax的作用,從《微信web開發(fā)者工具》的調(diào)試界面也可以看出其實際上就是通過xhr的方式來請求我們的業(yè)務(wù)服務(wù)器。
另外需要說明的是微信的小程序本身禁止使用ajax來請求網(wǎng)絡(luò)資源。
下一篇小豬將重點介紹使用方式二來解密用戶的數(shù)據(jù),服務(wù)器端代碼同樣使用flask來實現(xiàn)。