写点什么

微信授权全链路打通指南

  • 2024-12-17
    福建
  • 本文字数:4724 字

    阅读完需:约 15 分钟

从用户登录到权限获取,我们细致入微地梳理并实现了每一项授权机制,确保了用户体验的流畅与安全。


微信小程序授权




授权流程:


  1. 用户在小程序中点击登录按钮,触发 wx.login() 获取 code

  2. 小程序将 code 发送到后端服务器。

  3. 后端通过微信接口 jscode2session 使用 code 获取 session_key 和 openid

  4. 后端返回 session_key 和 openid 给前端。

  5. 前端获取 session_key 和 openid,使用 wx.getUserProfile() 获取用户信息(如昵称、头像等)。

  6. 如果需要,可以将用户信息(如昵称、头像等)发送到后端进行存储或处理。


wx.login({  success: function(res) {    if (res.code) {      // 将 code 发送到服务器      wx.request({        url: 'https://localhost:8080/api/login',        method: 'POST',        data: {          code: res.code        },        success: function(response) {          // 处理服务器返回的数据          console.log(response.data);        }      });    }  }});
复制代码


下面是 Nest 伪代码实现


import { Injectable } from '@nestjs/common';import { HttpService } from '@nestjs/axios';import { firstValueFrom } from 'rxjs';
interface MiniProgramLoginResponse { openid: string; session_key: string; unionid?: string; errcode?: number; errmsg?: string;}
@Injectable() export class MiniProgramAuthService { constructor(private readonly httpService: HttpService) {}
async login(code: string): Promise<MiniProgramLoginResponse> { const url = 'https://api.weixin.qq.com/sns/jscode2session';
try { const response = await firstValueFrom( this.httpService.get(url, { params: { appid: process.env.MINIPROGRAM_APPID, secret: process.env.MINIPROGRAM_APPSECRET, js_code: code, grant_type: 'authorization_code' } }) );
return response.data; } catch (error) { throw new Error('小程序登录失败'); } }
// 解密用户敏感信息 async decryptUserInfo(sessionKey: string, encryptedData: string, iv: string) { // 实现微信小程序用户信息解密逻辑 // 通常需要使用第三方加密库如 crypto-js } }
复制代码


微信网页授权(OAuth 2.0)


网页授权是通过微信官方提供的 OAuth2.0 认证方式,使第三方网站或应用能够获取用户基本信息,实现用户身份识别。




授权流程


  1. 发起授权用户点击登录/授权按钮生成授权链接跳转至微信授权页面

  2. 用户确认用户选择是否授权确认后获取临时授权码 code

  3. 换取 Access Token 服务端使用 code 换取 access_token获取用户的 openid 和 access_token

  4. 获取用户信息使用 access_token 和 openid调用微信接口获取用户详细信息

  5. 系统内部处理创建或更新用户信息生成系统内部登录态


import { Injectable } from '@nestjs/common';import { HttpService } from '@nestjs/axios';import { firstValueFrom } from 'rxjs';
// 用户授权信息接口定义interface WechatUserInfo { openid: string; // 用户唯一标识 nickname: string; // 用户昵称 sex: number; // 用户性别 province: string; // 省份 city: string; // 城市 country: string; // 国家 headimgurl: string; // 头像地址 privilege: string[]; // 用户特权信息 unionid?: string; // 开放平台唯一标识}
@Injectable()export class WebAuthService { constructor(private readonly httpService: HttpService) {}
// 生成授权链接 generateAuthUrl(redirectUri: string, scope: 'snsapi_base' | 'snsapi_userinfo' = 'snsapi_userinfo') { const baseUrl = 'https://open.weixin.qq.com/connect/oauth2/authorize'; const params = new URLSearchParams({ appid: process.env.WECHAT_APPID, redirect_uri: redirectUri, response_type: 'code', scope: scope, state: 'STATE#wechat_redirect' // 自定义参数,用于回传 }); return `${baseUrl}?${params}#wechat_redirect`; }
// 获取 Access Token async getAccessToken(code: string) { const url = 'https://api.weixin.qq.com/sns/oauth2/access_token'; try { const response = await firstValueFrom( this.httpService.get(url, { params: { appid: process.env.WECHAT_APPID, secret: process.env.WECHAT_APPSECRET, code: code, grant_type: 'authorization_code' } }) );
return response.data; } catch (error) { throw new Error('获取 Access Token 失败'); } }
// 获取用户信息 async getUserInfo(accessToken: string, openid: string): Promise<WechatUserInfo> { const url = 'https://api.weixin.qq.com/sns/userinfo'; try { const response = await firstValueFrom( this.httpService.get(url, { params: { access_token: accessToken, openid: openid, lang: 'zh_CN' } }) );
return response.data; } catch (error) { throw new Error('获取用户信息失败'); } }}
复制代码


微信开放平台授权



特点:


  • 适用于第三方应用

  • 支持移动应用、网站应用等

  • 需要开发者资质认证


import { Injectable } from '@nestjs/common';import { HttpService } from '@nestjs/axios';import { firstValueFrom } from 'rxjs';
// 定义开放平台授权响应接口interface OpenPlatformAuthResponse { access_token: string; // 接口调用凭证 expires_in: number; // access_token 过期时间 refresh_token: string; // 刷新 token openid: string; // 授权用户唯一标识 scope: string; // 用户授权的作用域 unionid: string; // 开放平台唯一标识}
@Injectable()export class OpenPlatformAuthService { constructor(private readonly httpService: HttpService) {}
/** * 获取 access_token * @param code 授权码 * @returns 授权响应信息 */ async getAccessToken(code: string): Promise<OpenPlatformAuthResponse> { // 微信获取 access_token 的接口地址 const url = 'https://api.weixin.qq.com/sns/oauth2/access_token'; try { // 使用授权码换取 access_token const response = await firstValueFrom( this.httpService.get(url, { params: { // 从环境变量读取开放平台 AppID appid: process.env.OPEN_PLATFORM_APPID, // 从环境变量读取开放平台密钥 secret: process.env.OPEN_PLATFORM_APPSECRET, // 授权码 code: code, // 授权类型,固定值 grant_type: 'authorization_code' } }) );
return response.data; } catch (error) { // 捕获并抛出授权失败的错误 throw new Error('开放平台授权失败'); } }
/** * 刷新 access_token * @param refreshToken 刷新 token * @returns 新的授权信息 */ async refreshAccessToken(refreshToken: string) { // 微信刷新 access_token 的接口地址 const url = 'https://api.weixin.qq.com/sns/oauth2/refresh_token'; try { // 使用 refresh_token 换取新的 access_token const response = await firstValueFrom( this.httpService.get(url, { params: { // 开放平台 AppID appid: process.env.OPEN_PLATFORM_APPID, // 授权类型,固定值 grant_type: 'refresh_token', // 用于刷新的 token refresh_token: refreshToken } }) );
return response.data; } catch (error) { // 捕获并抛出刷新 Token 失败的错误 throw new Error('刷新 Token 失败'); } }}
复制代码


企业微信授权


企业微信授权是针对企业内部应用和员工的身份认证机制,提供更严格和精细的权限控制。




特点:


  • 主要面向企业内部应用

  • 更强的权限控制

  • 安全性更高


授权流程


  1. 发起授权员工访问企业内部应用触发登录机制(扫码/输入)生成企业微信授权链接

  2. 身份验证跳转企业微信登录页员工确认身份获取临时授权码

  3. 换取用户信息服务端使用 code 换取用户标识获取 userid调用接口获取用户详细信息

  4. 系统内部处理验证员工身份检查权限状态生成系统内部登录态


import { Injectable } from '@nestjs/common';import { HttpService } from '@nestjs/axios';import { firstValueFrom } from 'rxjs';
// 定义企业微信授权响应接口interface EnterpriseWechatAuthResponse { access_token: string; // 企业接口调用凭证 expires_in: number; // access_token 过期时间 user_ticket?: string; // 用户票据(可选) user_info?: { userid: string; // 企业成员 ID name: string; // 成员名称 department: number[]; // 部门 ID 列表 };}
@Injectable()export class EnterpriseWechatAuthService { constructor(private readonly httpService: HttpService) {}
/** * 获取企业微信用户信息 * @param code 临时授权码 * @returns 用户信息和 access_token */ async getUserInfo(code: string): Promise<EnterpriseWechatAuthResponse> { // 获取企业 access_token 的接口地址 const tokenUrl = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken'; // 获取用户信息的接口地址 const userInfoUrl = 'https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo';
// 第一步:获取企业 access_token // 需要使用企业 ID 和应用的秘钥 const tokenResponse = await firstValueFrom( this.httpService.get(tokenUrl, { params: { // 从环境变量读取企业 ID corpid: process.env.ENTERPRISE_CORPID, // 从环境变量读取企业应用秘钥 corpsecret: process.env.ENTERPRISE_CORPSECRET } }) );
// 从响应中提取 access_token const accessToken = tokenResponse.data.access_token;
// 第二步:使用 access_token 和临时授权码获取用户信息 const userInfoResponse = await firstValueFrom( this.httpService.get(userInfoUrl, { params: { // 企业 access_token access_token: accessToken, // 临时授权码 code: code } }) );
return userInfoResponse.data; }}
复制代码


文章转载自:程序员海军

原文链接:https://www.cnblogs.com/HaiJun-Aion/p/18609286

体验地址:http://www.jnpfsoft.com/?from=infoq

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
微信授权全链路打通指南_微信_不在线第一只蜗牛_InfoQ写作社区