• 作者:老汪软件技巧
  • 发表时间:2024-12-16 11:05
  • 浏览量:

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

微信小程序授权

近期,我在致力于打造自己的小程序产品时,迎来了一项关键性的进展——__近期,我在致力于打造自己的小程序产品时,迎来了一项关键性的进展——

近期,我在致力于打造自己的小程序产品时,迎来了一项关键性的进展——_近期,我在致力于打造自己的小程序产品时,迎来了一项关键性的进展——_

授权流程:用户在小程序中点击登录按钮,触发 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认证方式,使第三方网站或应用能够获取用户基本信息,实现用户身份识别。

近期,我在致力于打造自己的小程序产品时,迎来了一项关键性的进展——__近期,我在致力于打造自己的小程序产品时,迎来了一项关键性的进展——

授权流程发起授权用户确认换取 Access Token获取用户信息系统内部处理

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 失败'); } } }

企业微信授权

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

近期,我在致力于打造自己的小程序产品时,迎来了一项关键性的进展——_近期,我在致力于打造自己的小程序产品时,迎来了一项关键性的进展——_

特点:授权流程发起授权身份验证换取用户信息系统内部处理

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应用

小程序授权

免费

小程序登录、开放平台

公众号授权

部分可用

免费+增值服务