实际开发过程
关于小程序的用户信息获取,是可以通过两个接口来获取的
- 第一种wx.getUserInfo({}) 可以获取用户的信息,引导用户点击确定授权弹出框,获取用户信息,但是这个api是不能直接获取到用户私密的数据的,openid 和手机号等,所以这种方式我很少用于正式的项目,一般都是下面这种方式编写代码
- 第二种wx.login({})结合wx.getUserInfo()用户登录,
接下来我们看看小程序的流程图,
小程序授权的流程图(官网的图写的其实已经很详细了)
1.前端调用wx.login得到code,发送请求到后端,后端通过小程序的appid和appsecret,cdoe参数请求微信的接口来换取session_key和openid,同时根据openid等生成token
- 前端得到 token,缓存,每次请求带上token,后端解析token,得到openid继续后面等操作
- 关于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)
}
}
业务代码
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 {
//后端调用微信接口通过code,appid,appscret获取openid,unionid
const { openid, unionid } = await openidAndSessionKey(code)
//读取数据库,做业务判断
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等参数生成token
ctx.body = {
success: true,
data: {
nickname: nickname,
avatarUrl: avatarUrl
}
}
} catch (err) {
ctx.body = {
success: false,
err: err
}
}
}
结束
总体来说小程序的登录结合后端的token的发送流程就这么回事
1.参考https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
- gayhub:https://github.com/leibocode/miniapp-shoppingMall 这个小程序也是这种方式,大家初次接触可以做个参考哈