實際開發(fā)過程
關(guān)于小程序的用戶信息獲取,是可以通過兩個接口來獲取的
- 第一種wx.getUserInfo({}) 可以獲取用戶的信息,引導(dǎo)用戶點擊確定授權(quán)彈出框,獲取用戶信息,但是這個api是不能直接獲取到用戶私密的數(shù)據(jù)的,openid 和手機號等,所以這種方式我很少用于正式的項目,一般都是下面這種方式編寫代碼
- 第二種wx.login({})結(jié)合wx.getUserInfo()用戶登錄,
接下來我們看看小程序的流程圖,
小程序授權(quán)的流程圖(官網(wǎng)的圖寫的其實已經(jīng)很詳細(xì)了)

流程圖
1.前端調(diào)用wx.login得到code,發(fā)送請求到后端,后端通過小程序的appid和appsecret,cdoe參數(shù)請求微信的接口來換取session_key和openid,同時根據(jù)openid等生成token
- 前端得到 token,緩存,每次請求帶上token,后端解析token,得到openid繼續(xù)后面等操作
- 關(guān)于token,我自己是通過jwt來做的
代碼(node為例子)
router文件
import { controller, get, post, required } from '../decorator/router'
import config from '../config'
import {
getUserAsync,
loginAsync
} from '../controllers/user'
import {
openidAndSessionKey,
WXBizDataCrypt
} from '../wechat-lib/mina'
import {
createOrderAsync,
paymentAsync
} from '../controllers/wechat'
@controller('/mina')
export class MinaController {
//通過code獲取session_key
@get('codeAndSessionKey')
@required({ query: ['code'] })
async getCodeAndSessionKey (ctx, next) {
const { code } = ctx.query
let res = await openidAndSessionKey(code)
ctx.body = {
success: true,
data: res
}
}
//獲取用戶信息
@get('user')
@required({ query: ['code', 'userInfo'] })
async getUser (ctx, next) {
await getUserAsync(ctx, next)
}
// 登錄
@post('login')
@required({ body: ['code', 'avatarUrl', 'nickName'] })
async login (ctx, next) {
await loginAsync(ctx, next)
}
}
業(yè)務(wù)代碼
import api from '../api'
import config from '../config'
import mongoose from 'mongoose'
import {
openidAndSessionKey,
WXBizDataCrypt
} from '../wechat-lib/mina'
const User = mongoose.model('User')
export const decryptUserAsync = async (code, userInfo) => {
const minaUser = await openidAndSessionKey(code)
let user = await User.findOne({
unionid: minaUser.unionid
}).exec()
if (!user) {
let pc = new WXBizDataCrypt(minaUser.session_key)
let data = pc.decryptData(userInfo.encryptedData, userInfo.iv)
user = await User.findOne({
unionid: data.unionId
})
if (!user) {
let _userData = userInfo.userInfo
user = new User({
avatarUrl: _userData.avatarUrl,
nickname: _userData.nickName,
unionid: data.unionid,
openid: [minaUser.openid],
sex: _userData.gender,
country: _userData.country,
province: _userData.province,
city: _userData.city
})
await user.save()
}
}
return user
}
export async function getUserAsync (ctx, next) {
const { code, userInfo } = ctx.query
let user
try {
user = await decryptUserAsync(code, userInfo)
} catch (err) {
return (ctx.body = {
success: false,
err: err
})
}
ctx.body = {
success: true,
data: {
nickname: user.nickname,
avatarUrl: user.avatarUrl,
sex: user.sex
}
}
}
//在我們前端是可以獲取到code 和用戶信息的,所以這塊也可以簡單的用loginAsync 方法就可以,
//其他的方法可以不用看,以loginAsync為例子
export async function loginAsync (ctx, next) {
//獲取從前端傳過來的code ,基本的用戶信息
const {
code,
avatarUrl,
nickName
} = ctx.request.body
try {
//后端調(diào)用微信接口通過code,appid,appscret獲取openid,unionid
const { openid, unionid } = await openidAndSessionKey(code)
//讀取數(shù)據(jù)庫,做業(yè)務(wù)判斷
let user = await User.findOne({
unionid
}).exec()
if (!user) {
user = new User({
openid: [openid],
nickname: nickName,
unionid,
avatarUrl
})
user = await user.save()
} else {
user.avatarUrl = avatarUrl
user.nickname = nickName
user = await user.save()
}
注意在這可以簡單寫返回的token ,通過openid或者unionid等參數(shù)生成token
ctx.body = {
success: true,
data: {
nickname: nickname,
avatarUrl: avatarUrl
}
}
} catch (err) {
ctx.body = {
success: false,
err: err
}
}
}
結(jié)束
總體來說小程序的登錄結(jié)合后端的token的發(fā)送流程就這么回事
1.參考https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
- gayhub:https://github.com/leibocode/miniapp-shoppingMall 這個小程序也是這種方式,大家初次接觸可以做個參考哈