使用egg.js实现微信授权登录

434 阅读2分钟

微信登录步骤 (登录流程时序)

在这里插入图片描述

实现说明

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){

    }
  })