微信登录步骤 (登录流程时序)
实现说明
1、前端调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
2、后端调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 、 用户在微信开放平台帐号下的唯一标识UnionID(若当前小程序已绑定到微信开放平台帐号) 和 会话密钥 session_key。
之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份
后端调用auth.code2Session
本接口应在服务器端调用,详细说明参见服务端API。
登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。更多使用方法详见 小程序登录。
请求地址
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
请求参数
属性 类型 默认值 必填 说明
appid string 是 小程序 appId
secret string 是 小程序 appSecret
js_code string 是 登录时获取的 code
grant_type string 是 授权类型,此处只需填写 authorization_code
返回值
Object
返回的 JSON 数据包
属性 类型 说明
openid string 用户唯一标识
session_key string 会话密钥
unionid string 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回,详见 UnionID 机制说明。
errcode number 错误码
errmsg string 错误信息
errcode 的合法值
值 说明 最低版本
-1 系统繁忙,此时请开发者稍候再试
0 请求成功
40029 code 无效
45011 频率限制,每个用户每分钟100次
40226 高风险等级用户,小程序登录拦截 。风险等级详见用户安全解方案
Egg.js实现的后端代码
(1)第一种
app/controller/wx.js
'use strict';
const Controller = require('egg').Controller;
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
const wxConfig = {
appid: 'wx******************8',
appSecret: '91*******************f'
}
class WxMinniController extends Controller {
// 获取用户openid
// 通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程
async openid() {
const { ctx } = this;
const urlStr = 'https://api.weixin.qq.com/sns/jscode2session'
const data = {
appid: wxConfig.appid, // 小程序 appId
secret: wxConfig.appSecret, // 小程序 appSecret
js_code: ctx.query.code, // 登录时获取的 code
grant_type: 'authorization_code' // 授权类型,此处只需填写 authorization_code
}
const result = await ctx.curl(urlStr, {
data: data,
dataType: 'json',
});
if(result.data.errmsg){
ctx.body = {
status: 101,
msg: '操作失败',
errcode: result.data.errcode,
errmsg: result.data.errmsg
};
/*
errcode: 40163
errmsg: "code been used, hints: [ req_id: NfjCxzNre- ]"
msg: "操作失败"
status: 101
*/
}else{
ctx.body = {
status: 100,
msg: '操作成功',
openid: result.data.openid,
session_key: result.data.session_key
};
/*
msg: "操作成功"
openid: "oC4Dk5NfT-I-joYZGQSPHOpD2PYQ"
session_key: "Qheu52JzXVhZuAK372micw=="
status: 100
*/
}
}
}
module.exports = WxMinniController;
(2)第二种
controller层
app/controller/wx.js
async getopenid(){
const { ctx } = this;
const {code}=ctx.request.body
let APP_ID=config.XIAO.APP_ID
let APP_SECRET= config.XIAO.APP_SECRET
const url = 'https://api.weixin.qq.com/sns/jscode2session?appid=' + APP_ID + '&secret=' + APP_SECRET + '&js_code=' + code + '&grant_type=authorization_code';
const detail=await ctx.service.xiao.getopenid({url})
ctx.body=detail
}
service层
app/service/wx.js
async getopenid({url}){
const { ctx } = this;
const res = await ctx.curl(url, {
dataType: 'json',
});
if (res.data.openid) {
return {
openid: res.data.openid,
code: 1,
sessionKey: res.data.session_key,
};
}
return { // 忽略网络请求失败
msg: res.data.errmsg,
code: 0,
};
}
config
config/config.default.js
const config = {
YOUR_SECRET_STRING: '',
XIAO:{
APP_ID:'',
APP_SECRET:''
},
}
module.exports = config
前端实现逻辑
wx.login({
success (res) {
wx.request({
url: 'http://localhost:7001/wxmini/openid',
data: {
// code: res.code
code: '021J2usK0lrC0a2t5vrK0aMCsK0J2usw'
},
success (res) {
console.log('openid = ', res.data.openid)
}
})
},
fail (err){
}
})