auth.md 13 KB

企业微信认证方法文档

概述

WxworkAuth 是一个灵活的企业微信认证工具类,提供可自由搭配的用户信息验证和登录方法。相比路由守卫 WxworkAuthGuard 的强制性限制,WxworkAuth 允许在页面中灵活调用,实现页面先加载、再执行用户信息同步和注册的流程。

文件位置: fmode-ng/core.ts


主要特性

  1. 灵活可组合: 提供独立的方法,可根据需求自由搭配使用
  2. 页面内调用: 可在组件的 constructor 或生命周期钩子中调用
  3. 自动登录注册: 使用 userid 作为用户名,后6位作为密码自动注册和登录
  4. 支持多种场景:
    • 只获取用户信息(不登录)
    • 只同步用户信息到数据库(不登录)
    • 自动登录/注册
    • 一站式完整流程

快速开始

1. 基础引入

import { WxworkAuth } from 'fmode-ng/core';

// 初始化
const wxAuth = new WxworkAuth({
  cid: 'cDL6R1hgSi',  // 公司帐套ID
  appId: 'crm'        // 应用ID,可选,默认为 'crm'
});

2. 在组件中使用(推荐场景)

import { Component } from '@angular/core';
import { WxworkAuth } from 'fmode-ng/core';

@Component({
  selector: 'app-my-page',
  templateUrl: './my-page.component.html'
})
export class MyPageComponent {
  wxAuth: WxworkAuth;
  userInfo: any;

  constructor() {
    this.wxAuth = new WxworkAuth({ cid: 'cDL6R1hgSi' });

    // 页面加载后执行用户认证
    this.initAuth();
  }

  async initAuth() {
    try {
      // 方案1: 一站式认证和登录
      const { userInfo, profile, user } = await this.wxAuth.authenticateAndLogin();
      console.log('用户信息:', userInfo);
      console.log('Profile ID:', profile.id);
      console.log('登录用户:', user?.get('username'));

      this.userInfo = userInfo;
    } catch (error) {
      console.error('认证失败:', error);
    }
  }
}

API 文档

构造函数

constructor(options: {
  cid: string;      // 公司帐套ID,必填
  appId?: string;   // 应用ID,可选,默认为 'crm'
})

示例:

const wxAuth = new WxworkAuth({ cid: 'cDL6R1hgSi' });

方法列表

1. getUserInfo(code?: string): Promise<any>

获取企业微信用户信息(不登录)

参数:

  • code (可选): 授权码,如果不提供则尝试从缓存或URL获取

返回值: 企业微信用户信息对象

{
  userid?: string;           // 企业员工ID
  external_userid?: string;  // 外部联系人ID
  openid?: string;           // 微信OpenID
  name?: string;             // 姓名
  mobile?: string;           // 手机号
  email?: string;            // 邮箱
  avatar?: string;           // 头像URL
  gender?: number;           // 性别 (1:男, 2:女)
  // ... 其他字段
}

使用场景: 只需要获取用户信息,不需要登录系统

示例:

const userInfo = await wxAuth.getUserInfo();
console.log('用户ID:', userInfo.userid);
console.log('姓名:', userInfo.name);
console.log('手机:', userInfo.mobile);

2. syncUserInfo(userInfo?: any): Promise<any>

同步用户信息到 Profile/UserSocial 表(不登录)

参数:

  • userInfo (可选): 用户信息对象,如果不提供则自动调用 getUserInfo() 获取

返回值: ProfileUserSocial Parse Object

使用场景: 只需要同步用户信息到数据库,不需要登录系统

示例:

// 方式1: 自动获取用户信息并同步
const profile = await wxAuth.syncUserInfo();
console.log('同步成功,Profile ID:', profile.id);

// 方式2: 使用已有的用户信息
const userInfo = await wxAuth.getUserInfo();
const profile = await wxAuth.syncUserInfo(userInfo);

3. autoLogin(userInfo?: any): Promise<FmodeUser | null>

自动登录或注册用户(使用 userid 和后6位作为密码)

参数:

  • userInfo (可选): 用户信息对象,如果不提供则自动获取

返回值: FmodeUser 对象或 null

登录逻辑:

  1. 检查是否已登录,如果已登录直接返回当前用户
  2. 使用 useridexternal_useridopenid 作为用户名
  3. 使用用户名的后6位作为密码
  4. 尝试登录,如果用户不存在则自动注册
  5. 同步 user 指针到 Profile/UserSocial

使用场景: 需要用户登录系统才能访问功能

示例:

const user = await wxAuth.autoLogin();
if (user) {
  console.log('登录成功,用户名:', user.get('username'));
} else {
  console.log('登录失败');
}

4. authenticateAndLogin(code?: string): Promise<{ userInfo, profile, user }>

一站式方法:获取用户信息、同步、并自动登录/注册

参数:

  • code (可选): 授权码

返回值:

{
  userInfo: any;           // 企业微信用户信息
  profile: any;            // Profile 或 UserSocial 对象
  user: FmodeUser | null;  // 登录的用户对象
}

执行流程:

  1. 获取企业微信用户信息
  2. 同步到 Profile/UserSocial
  3. 自动登录/注册用户

使用场景: 最常用的场景,一次调用完成所有认证流程

示例:

const { userInfo, profile, user } = await wxAuth.authenticateAndLogin();
console.log('用户信息:', userInfo);
console.log('Profile ID:', profile.id);
console.log('登录用户:', user?.get('username'));

5. oauth(scope?, renew?): Promise<string | null>

触发 OAuth 授权流程

参数:

  • scope (可选): 授权类型
    • 'snsapi_base': 静默授权(默认)
    • 'snsapi_privateinfo': 敏感信息授权
  • renew (可选): 是否强制重新授权(清除缓存),默认 false

返回值: 授权码或 null(如果跳转)

使用场景: 需要手动触发授权流程

示例:

// 静默授权
await wxAuth.oauth('snsapi_base');

// 敏感信息授权
await wxAuth.oauth('snsapi_privateinfo');

// 强制重新授权
await wxAuth.oauth('snsapi_base', true);

6. loginPC(): Promise<string>

PC端登录(弹出扫码面板)

返回值: 授权码

使用场景: PC端扫码登录

示例:

const code = await wxAuth.loginPC();
console.log('获得授权码:', code);

7. getSDK(): WxworkSDK

获取 WxworkSDK 实例(用于高级操作)

返回值: WxworkSDK 实例

使用场景: 需要使用 SDK 的其他高级功能

示例:

const sdk = wxAuth.getSDK();

// 获取当前聊天对象
const { GroupChat, Contact } = await sdk.getCurrentChatObject();

// 同步群聊信息
const group = await sdk.syncGroupChat(groupInfo);

使用场景示例

场景1: 页面加载后自动登录

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html'
})
export class DashboardComponent implements OnInit {
  wxAuth: WxworkAuth;
  currentUser: any;

  constructor() {
    this.wxAuth = new WxworkAuth({ cid: 'cDL6R1hgSi' });
  }

  async ngOnInit() {
    // 页面加载后自动认证和登录
    const { user } = await this.wxAuth.authenticateAndLogin();
    this.currentUser = user;

    if (!user) {
      // 处理登录失败的情况
      console.error('用户登录失败');
    }
  }
}

场景2: 只获取用户信息显示,不登录

@Component({
  selector: 'app-profile-preview',
  templateUrl: './profile-preview.component.html'
})
export class ProfilePreviewComponent implements OnInit {
  wxAuth: WxworkAuth;
  userInfo: any;

  constructor() {
    this.wxAuth = new WxworkAuth({ cid: 'cDL6R1hgSi' });
  }

  async ngOnInit() {
    // 只获取用户信息,不登录
    this.userInfo = await this.wxAuth.getUserInfo();
    console.log('用户名:', this.userInfo.name);
  }
}

场景3: 分步骤执行认证流程

@Component({
  selector: 'app-onboarding',
  templateUrl: './onboarding.component.html'
})
export class OnboardingComponent {
  wxAuth: WxworkAuth;
  step = 1;
  userInfo: any;
  profile: any;

  constructor() {
    this.wxAuth = new WxworkAuth({ cid: 'cDL6R1hgSi' });
  }

  async step1_getUserInfo() {
    this.userInfo = await this.wxAuth.getUserInfo();
    this.step = 2;
  }

  async step2_syncProfile() {
    this.profile = await this.wxAuth.syncUserInfo(this.userInfo);
    this.step = 3;
  }

  async step3_login() {
    const user = await this.wxAuth.autoLogin(this.userInfo);
    if (user) {
      console.log('登录成功!');
      // 跳转到主页
    }
  }
}

场景4: 检查登录状态,未登录时才执行认证

import { FmodeParse } from 'projects/fmode-ng/src/lib/core/parse';

const Parse = FmodeParse.with("nova");

async function ensureAuthenticated() {
  const currentUser = Parse.User.current();

  if (currentUser) {
    console.log('用户已登录:', currentUser.get('username'));
    return currentUser;
  }

  // 未登录,执行认证
  const wxAuth = new WxworkAuth({ cid: 'cDL6R1hgSi' });
  const { user } = await wxAuth.authenticateAndLogin();

  return user;
}

与路由守卫的区别

WxworkAuthGuard (路由守卫)

特点:

  • 在路由激活前强制执行认证
  • 阻塞页面加载,直到认证完成
  • 适合需要强制登录的路由

限制:

  • 页面无法先加载
  • 灵活性较低
  • 无法根据页面逻辑自定义认证流程

使用方式:

const routes: Routes = [
  {
    path: 'protected',
    component: ProtectedComponent,
    canActivate: [WxworkAuthGuard]
  }
];

WxworkAuth (认证工具类)

特点:

  • 页面可以先加载
  • constructor 或生命周期钩子中灵活调用
  • 可根据页面逻辑自定义认证流程
  • 可选择性执行部分认证步骤

优势:

  • 更好的用户体验(页面先显示)
  • 灵活可组合
  • 适合复杂的业务逻辑

使用方式:

// 在组件中直接调用
const wxAuth = new WxworkAuth({ cid: 'cDL6R1hgSi' });
await wxAuth.authenticateAndLogin();

最佳实践

1. 统一认证服务

创建一个 Angular Service 来统一管理认证逻辑:

import { Injectable } from '@angular/core';
import { WxworkAuth } from 'fmode-ng/core';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private wxAuth: WxworkAuth;

  constructor() {
    // 从环境变量或配置中获取 cid
    this.wxAuth = new WxworkAuth({ cid: 'cDL6R1hgSi' });
  }

  async authenticate() {
    return await this.wxAuth.authenticateAndLogin();
  }

  async getUserInfo() {
    return await this.wxAuth.getUserInfo();
  }
}

在组件中使用:

@Component({
  selector: 'app-my-page',
  templateUrl: './my-page.component.html'
})
export class MyPageComponent implements OnInit {
  constructor(private authService: AuthService) {}

  async ngOnInit() {
    const { user } = await this.authService.authenticate();
    console.log('当前用户:', user?.get('username'));
  }
}

2. 错误处理

async initAuth() {
  try {
    const { user } = await this.wxAuth.authenticateAndLogin();

    if (!user) {
      // 认证成功但登录失败
      this.showMessage('登录失败,请稍后再试');
      return;
    }

    // 登录成功
    this.onLoginSuccess(user);
  } catch (error: any) {
    // 认证失败
    console.error('认证错误:', error);

    if (error.message?.includes('无法获取用户信息')) {
      this.showMessage('无法获取用户信息,请检查网络');
    } else {
      this.showMessage('认证失败,请重试');
    }
  }
}

3. 配置管理

使用环境变量管理不同环境的配置:

// environment.ts
export const environment = {
  production: false,
  wxwork: {
    cid: 'cDL6R1hgSi',
    appId: 'crm'
  }
};

// 使用
import { environment } from 'src/environments/environment';

const wxAuth = new WxworkAuth({
  cid: environment.wxwork.cid,
  appId: environment.wxwork.appId
});

注意事项

  1. cid 配置: 确保 cidWxworkSDK.companyMap 中有对应的配置
  2. 错误处理: 所有方法都会抛出错误,请使用 try-catch 捕获
  3. 缓存机制: getUserInfo() 会优先使用 localStorage 缓存,传入 code 可强制刷新
  4. 密码规则: 自动登录使用 userid 后6位作为密码,确保 userid 长度 ≥ 6
  5. 类型转换: Parse.User 需要转换为 FmodeUser 类型:user as FmodeUser

相关文件

  • 认证工具类: fmode-ng/core.ts
  • 路由守卫: projects/fmode-ng/src/lib/social/wxwork/wxwork-auth.guard.ts
  • SDK: projects/fmode-ng/src/lib/core/social/wxwork/wxwork.sdk.ts
  • 企业API: projects/fmode-ng/src/lib/core/social/wxwork/wxwork.corp.ts

技术支持

如遇问题,请检查:

  1. 企业微信配置是否正确(corpId, agentId, suiteId
  2. 回调域名是否已配置
  3. cid 是否在 companyMap 中存在
  4. 网络请求是否正常
  5. 浏览器控制台是否有错误信息