weixu 发表于 2025-2-7 01:22:15

微信授权全链路打通指南

近期,我在致力于打造自己的小程序产品时,迎来了一项关键性的进展——微信相关授权流程的完整实现。从用户登录到权限获取,我们细致入微地梳理并实现了每一项授权机制,确保了用户体验的流畅与安全。
微信小程序授权



授权流程:


[*]用户在小程序中点击登录按钮,触发 wx.login() 获取 code。
[*]小程序将 code 发送到后端服务器。
[*]后端通过微信接口 jscode2session 使用 code 获取 session_key 和 openid。
[*]后端返回 session_key 和 openid 给前端。
[*]前端获取 session_key 和 openid,使用 wx.getUserProfile() 获取用户信息(如昵称、头像等)。
[*]如果需要,可以将用户信息(如昵称、头像等)发送到后端进行存储或处理。
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认证方式,使第三方网站或应用能够获取用户基本信息,实现用户身份识别。


授权流程


[*]发起授权

[*]用户点击登录/授权按钮
[*]生成授权链接
[*]跳转至微信授权页面

[*]用户确认

[*]用户选择是否授权
[*]确认后获取临时授权码 code

[*]换取 Access Token

[*]服务端使用 code 换取 access_token
[*]获取用户的 openid 和 access_token

[*]获取用户信息

[*]使用 access_token 和 openid
[*]调用微信接口获取用户详细信息

[*]系统内部处理

[*]创建或更新用户信息
[*]生成系统内部登录态

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 Tokenasync 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;   // 刷新 tokenopenid: 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 失败');    }}}企业微信授权

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


特点:


[*]主要面向企业内部应用
[*]更强的权限控制
[*]安全性更高
授权流程


[*]发起授权

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

[*]身份验证

[*]跳转企业微信登录页
[*]员工确认身份
[*]获取临时授权码

[*]换取用户信息

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

[*]系统内部处理

[*]验证员工身份
[*]检查权限状态
[*]生成系统内部登录态

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;}}各个平台授权小结

授权类型个人是否可用是否收费主要适用场景网页授权是免费网站、H5应用小程序授权是免费小程序登录、开放平台公众号授权部分可用免费+增值服务公众号相关应用(服务号、订阅号)企业微信否有费用企业内部协作
页: [1]
查看完整版本: 微信授权全链路打通指南