wecom-sdk-ai
v0.1.0
Published
企业微信 Node.js SDK - 基于原生 fetch API,支持 CommonJS 和 ES Module 引用
Downloads
103
Maintainers
Readme
WeCom SDK AI 完整说明文档
企业微信 Node.js SDK - 基于原生 fetch API
包名: wecom-sdk-ai
版本: 0.1.0
更新日期: 2026-03-24
⚠️ 重要提示
本 SDK 尚未在实际项目中测试使用,当前版本 0.1.0 为预览版本。
- 所有 API 调用已根据企业微信官方文档实现
- TypeScript 类型定义完整
- 单元测试覆盖核心模块
- 实际调用企业微信 API 的效果需要验证
目录
项目概述
WeCom SDK 是一个基于企业微信官方 API 的 Node.js 开发工具包,采用原生 fetch API 实现,无需额外依赖(如 axios)。
技术栈
| 技术 | 版本 | 说明 | |------|------|------| | TypeScript | ^5.0.0 | 类型支持 | | Node.js | >=18.0.0 | 运行时要求 | | Jest | ^29.7.0 | 测试框架 | | ts-jest | ^29.1.0 | TypeScript 编译 |
功能特性
核心功能
| 功能 | 说明 | |------|------| | 单企业支持 | 简单的 corpid/corpsecret 配置 | | 多企业支持 | 复杂的多企业多应用架构 | | Token 管理 | 自动缓存和刷新机制 | | HTTP 客户端 | 基于原生 fetch 的请求封装 | | 错误处理 | 完整的中文错误码映射 | | 消息加解密 | 回调消息签名验证和解密 |
业务模块
- 用户管理 - 成员的增删改查
- 部门管理 - 组织架构管理
- 标签管理 - 用户标签操作
- 消息推送 - 文本、图片、Markdown 等消息类型
- 媒体上传 - 图片、语音、视频、文件
- 打卡管理 - 打卡数据获取
- 会议管理 - 腾讯会议集成
- 审批流程 - 审批单据操作
- 外部联系人 - 客户管理
- 应用管理 - 企业应用配置
- 微盘 - 企业云盘操作
- 日程管理 - 日程创建和查询
- 教育模块 - 家校沟通、学生管理
- 支付模块 - 企业支付功能
- 智能表格 - 企微云文档
- 导出任务 - 数据导出
- 批量操作 - 批量任务提交
- 设备管理 - 硬件设备管理
- 客服模块 - 客服消息
安装引用
安装
npm install编译
npm run build引用方式
ES Module (import)
// 方式一: 命名导入
import { WeComClient } from 'wecom-sdk-ai';
// 方式二: 导入类
import WeComClient from 'wecom-sdk-ai';
// 导入其他模块
import { HttpClient, TokenManager, MemoryCache, WeComError } from 'wecom-sdk-ai';
import { verifySignature, decryptMessage, encryptMessage } from 'wecom-sdk-ai';CommonJS (require)
// 方式一: 解构导入
const { WeComClient } = require('wecom-sdk-ai');
// 方式二: 直接导入
const WeComClient = require('wecom-sdk-ai').default;
// 导入其他模块
const { HttpClient, TokenManager, MemoryCache, WeComError } = require('wecom-sdk-ai');
const { verifySignature, decryptMessage, encryptMessage } = require('wecom-sdk-ai');TypeScript 配置
确保 tsconfig.json 开启了相关选项:
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
}
}快速开始
配置
import { WeComClient } from 'wecom-sdk-ai';
// 单企业配置
const client = new WeComClient({
corpid: 'your-corpid',
corpsecret: 'your-corpsecret',
appId: 1000001, // 应用ID,可选
enterpriseId: 'ent1' // 企业标识,可选
});发送消息
// 发送文本消息
const result = await client.message.sendText(1000001, 'Hello World', {
touser: 'user1|user2' // 多个用户用 | 分隔
});
// 发送 Markdown
const result = await client.message.sendMarkdown(1000001, '## 标题\n内容');管理用户
// 创建用户
await client.user.create({
userid: 'zhangsan',
name: '张三',
mobile: '13800138000',
department: [1, 2]
});
// 获取用户详情
const user = await client.user.get('zhangsan');
// 批量获取部门用户
const users = await client.user.simpleList(1, 1); // 递归获取子部门管理部门
// 创建部门
const result = await client.department.create({
name: '技术部',
parentid: 1,
order: 1
});
// 获取部门列表
const depts = await client.department.list();API 参考
WeComClient
主入口类,提供所有业务模块的访问。
const client = new WeComClient(options);选项参数:
| 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | corpid | string | 是 | 企业ID | | corpsecret | string | 是 | 应用密钥 | | appId | number | 否 | 应用ID,默认 1000001 | | enterpriseId | string | 否 | 企业标识,默认 "default" | | cache | CacheProvider | 否 | 自定义缓存实现 |
属性:
| 属性 | 类型 | 说明 | |------|------|------| | user | UserModule | 用户管理模块 | | department | DepartmentModule | 部门管理模块 | | tag | TagModule | 标签管理模块 | | message | MessageModule | 消息推送模块 | | media | MediaModule | 媒体上传模块 | | ... | ... | 其他业务模块 |
消息类型
// 文本消息
{ msgtype: 'text', text: { content: string } }
// 图片消息
{ msgtype: 'image', image: { media_id: string } }
// 语音消息
{ msgtype: 'voice', voice: { media_id: string } }
// 视频消息
{ msgtype: 'video', video: { media_id: string, title?: string, description?: string } }
// 文件消息
{ msgtype: 'file', file: { media_id: string } }
// Markdown 消息
{ msgtype: 'markdown', markdown: { content: string } }
// 文本卡片
{ msgtype: 'textcard', textcard: { title: string, description: string, url: string, btntxt?: string } }
// 图文消息
{ msgtype: 'news', news: { articles: Array<{ title: string, description?: string, url: string, picurl?: string }> } }业务模块
UserModule - 用户管理
| 方法 | 说明 |
|------|------|
| create(data) | 创建用户 |
| get(userid) | 获取用户详情 |
| update(data) | 更新用户信息 |
| delete(userid) | 删除用户 |
| batchDelete(userids) | 批量删除用户 |
| simpleList(departmentId, fetchChild?) | 获取部门成员简单列表 |
| list(departmentId, fetchChild?) | 获取部门成员详情列表 |
| convertToOpenid(userid) | userid 转 openid |
| convertToUserid(openid) | openid 转 userid |
| getUseridByMobile(mobile) | 通过手机号获取 userid |
| getUseridByEmail(email, emailType?) | 通过邮箱获取 userid |
DepartmentModule - 部门管理
| 方法 | 说明 |
|------|------|
| create(data) | 创建部门 |
| update(data) | 更新部门信息 |
| delete(id) | 删除部门 |
| list(id?) | 获取部门列表 |
| simpleList(id?) | 获取部门简单列表 |
| get(id) | 获取部门详情 |
TagModule - 标签管理
| 方法 | 说明 |
|------|------|
| create(tagname, tagid?) | 创建标签 |
| update(tagid, tagname) | 更新标签 |
| delete(tagid) | 删除标签 |
| get(tagid) | 获取标签成员 |
| addUsers(tagid, userlist, partylist?) | 增加标签成员 |
| deleteUsers(tagid, userlist, partylist?) | 删除标签成员 |
MessageModule - 消息推送
| 方法 | 说明 |
|------|------|
| send(data) | 发送消息 |
| sendText(agentid, content, options?) | 发送文本消息 |
| sendImage(agentid, mediaId, options?) | 发送图片消息 |
| sendMarkdown(agentid, content, options?) | 发送 Markdown 消息 |
| recall(msgid) | 撤回消息 |
MediaModule - 媒体管理
| 方法 | 说明 |
|------|------|
| upload(type, filename, content) | 上传临时素材 |
| get(mediaId) | 获取临时素材 |
| uploadImg(file) | 上传图片 |
| uploadVoice(voice) | 上传语音 |
| uploadVideo(video) | 上传视频 |
| uploadFile(file) | 上传普通文件 |
其他模块
| 模块 | 说明 | |------|------| | BatchModule | 批量任务 | | ExportModule | 数据导出 | | ExternalModule | 外部联系人 | | OaModule | 审批流程 | | CheckinModule | 打卡数据 | | MeetingModule | 会议管理 | | WedriveModule | 企业微盘 | | PaymentModule | 企业支付 | | ServiceModule | 客服消息 | | SchoolModule | 教育模块 | | DeviceModule | 设备管理 | | AgentModule | 应用管理 | | SmartsheetModule | 智能表格 | | CallbackModule | 回调处理 |
核心模块
TokenManager - Token 管理
import { TokenManager } from 'wecom-sdk-ai';
// 单企业模式
const tokenManager = new TokenManager({
corpid: 'corp-id',
corpsecret: 'corp-secret',
appId: 1000001
});
// 多企业模式
const tokenManager = new TokenManager({
enterprise1: {
corpid: 'corp-1',
apps: [{ corpsecret: 'secret-1', appId: 1000001 }]
},
enterprise2: {
corpid: 'corp-2',
apps: [{ corpsecret: 'secret-2', appId: 1000002 }]
}
});
// 获取 Token
const token = await tokenManager.getAccessToken('enterprise1', 1000001);
// 刷新 Token
const newToken = await tokenManager.refreshToken('enterprise1', 1000001);HttpClient - HTTP 客户端
import { HttpClient } from 'wecom-sdk-ai';
const client = new HttpClient();
// GET 请求
const result = await client.get('/user/get', { userid: 'zhangsan' }, 'access-token');
// POST 请求
const result = await client.post('/user/create', { userid: 'zhangsan', name: '张三' }, {}, 'access-token');CacheProvider - 缓存接口
import { CacheProvider, MemoryCache } from 'wecom-sdk-ai';
// 使用内置内存缓存(默认)
const cache = new MemoryCache();
// 自定义缓存实现
class RedisCache implements CacheProvider {
async get(key: string): Promise<string | null> {
return await redis.get(key);
}
async set(key: string, value: string, ttlSeconds: number): Promise<void> {
await redis.setex(key, ttlSeconds, value);
}
async delete(key: string): Promise<void> {
await redis.del(key);
}
}工具函数
import { verifySignature, decryptMessage, encryptMessage, parseXml, buildXml } from 'wecom-sdk-ai';
// 验证回调签名
const isValid = verifySignature(config, signature, timestamp, nonce, echoStr);
// 解密消息
const message = decryptMessage(config, encryptedMsg);
// 加密消息
const { encrypted, signature, timestamp, nonce } = encryptMessage(config, message);
// XML 解析和构建
const data = parseXml(xmlString);
const xml = buildXml(data);WeComError - 错误处理
import { WeComError, ErrorCodeMap } from 'wecom-sdk-ai';
try {
await client.user.get('invalid-user');
} catch (error) {
if (error instanceof WeComError) {
console.log(`错误码: ${error.code}`);
console.log(`错误信息: ${error.message}`);
console.log(`中文描述: ${error.chineseMessage}`);
}
}测试结果
⚠️ 测试说明
注意: 以下测试为单元测试,仅验证代码逻辑正确性,不包含实际调用企业微信 API 的集成测试。
实际使用时,请务必在企业微信管理后台配置好相关应用权限,并验证 API 调用效果。
测试执行时间
2026-03-24
测试结果概览
Test Suites: 5 passed, 5 total
Tests: 44 passed, 44 total
Time: 4.035 s详细测试结果
1. error.test.ts ✅
| 测试用例 | 状态 | 耗时 | |----------|------|------| | 应正确设置错误码和消息 | ✅ 通过 | 5 ms | | 应包含中文错误信息 | ✅ 通过 | 1 ms | | 未知错误码应提供默认中文信息 | ✅ 通过 | - | | 应包含常见错误码映射 | ✅ 通过 | 1 ms | | 应返回格式化的错误信息 | ✅ 通过 | 1 ms |
模块覆盖率: 100%
2. client.test.ts ✅
| 测试用例 | 状态 | 耗时 | |----------|------|------| | 应正确发送 GET 请求 | ✅ 通过 | 8 ms | | 应正确附加 access_token | ✅ 通过 | 2 ms | | 应正确附加查询参数 | ✅ 通过 | 1 ms | | 应正确发送 POST 请求 | ✅ 通过 | 1 ms | | 应正确设置请求头 | ✅ 通过 | - | | 应正确处理 URL 查询参数 | ✅ 通过 | - | | HTTP 错误应抛出异常 | ✅ 通过 | 12 ms | | WeCom API 错误应抛出 WeComError | ✅ 通过 | - | | 应提供中文错误信息 | ✅ 通过 | - | | 应正确处理空参数 | ✅ 通过 | 1 ms | | 应正确处理数组参数 | ✅ 通过 | - |
模块覆盖率: 100%
3. modules/user.test.ts ✅
| 测试用例 | 状态 | 耗时 | |----------|------|------| | 应正确创建用户 | ✅ 通过 | 9 ms | | 应正确获取用户信息 | ✅ 通过 | - | | 应正确更新用户信息 | ✅ 通过 | 1 ms | | 应正确删除单个用户 | ✅ 通过 | - | | 应正确批量删除用户 | ✅ 通过 | 1 ms | | 应正确获取部门成员列表 | ✅ 通过 | 1 ms | | 应支持递归获取子部门成员 | ✅ 通过 | 1 ms | | 应正确获取部门成员详情 | ✅ 通过 | - | | 应通过手机号获取 userid | ✅ 通过 | 1 ms | | 应支持指定 enterpriseId 和 appId | ✅ 通过 | - |
模块覆盖率: 68.75%
4. utils.test.ts ✅
| 测试用例 | 状态 | 耗时 | |----------|------|------| | 应正确验证签名 | ✅ 通过 | 6 ms | | 错误签名应返回 false | ✅ 通过 | - | | 应正确解析 XML | ✅ 通过 | 1 ms | | 应正确构建 XML | ✅ 通过 | 1 ms | | 应生成指定长度的随机字符串 | ✅ 通过 | - | | 默认应生成 32 位随机字符串 | ✅ 通过 | - | | 应生成当前时间戳字符串 | ✅ 通过 | - | | 应正确解密加密的消息 | ✅ 通过 | 2 ms | | 应正确解密包含中文的消息 | ✅ 通过 | 1 ms |
模块覆盖率: 98.41%
5. token.test.ts ✅
| 测试用例 | 状态 | 耗时 | |----------|------|------| | 应使用 corpid 和 corpsecret 初始化 | ✅ 通过 | 5 ms | | 应生成正确的缓存 key | ✅ 通过 | 1 ms | | 应使用多企业配置初始化 | ✅ 通过 | 1 ms | | 应获取指定企业和应用的 token | ✅ 通过 | 1 ms | | 当企业不存在时应抛出错误 | ✅ 通过 | 8 ms | | 当应用不存在时应抛出错误 | ✅ 通过 | 1 ms | | 应从缓存获取 token | ✅ 通过 | - | | 缓存为空时应重新获取 token | ✅ 通过 | - | | 应强制刷新 token | ✅ 通过 | 1 ms |
模块覆盖率: 79.24%
代码覆盖率汇总
| 文件 | 语句覆盖 | 分支覆盖 | 函数覆盖 | 行覆盖 | |------|----------|----------|----------|---------| | 总体 | 83.5% | 69.64% | 76.19% | 83.93% | | src/cache.ts | 16.66% | 0% | 25% | 18.18% | | src/client.ts | 100% | 70.58% | 100% | 100% | | src/error.ts | 100% | 100% | 100% | 100% | | src/token.ts | 79.24% | 70.37% | 77.77% | 79.24% | | src/utils.ts | 98.41% | 71.42% | 100% | 98.41% | | src/modules/user.ts | 68.75% | 100% | 64.28% | 68.75% |
项目结构
wecom-sdk-ai/
├── src/
│ ├── index.ts # 主入口,导出所有模块
│ ├── client.ts # HTTP 客户端封装
│ ├── token.ts # Token 管理器
│ ├── cache.ts # 缓存接口和实现
│ ├── error.ts # 错误类和错误码映射
│ ├── utils.ts # 工具函数
│ ├── types/
│ │ └── index.ts # 共享类型定义
│ └── modules/
│ ├── user.ts # 用户管理
│ ├── department.ts # 部门管理
│ ├── tag.ts # 标签管理
│ ├── message.ts # 消息推送
│ ├── media.ts # 媒体上传
│ ├── batch.ts # 批量操作
│ ├── export.ts # 数据导出
│ ├── external.ts # 外部联系人
│ ├── oa.ts # 审批
│ ├── checkin.ts # 打卡
│ ├── meeting.ts # 会议
│ ├── wedrive.ts # 微盘
│ ├── payment.ts # 支付
│ ├── service.ts # 客服
│ ├── school.ts # 教育
│ ├── device.ts # 设备
│ ├── agent.ts # 应用
│ ├── smartsheet.ts # 智能表格
│ └── callback.ts # 回调处理
├── __tests__/
│ ├── client.test.ts
│ ├── token.test.ts
│ ├── error.test.ts
│ ├── utils.test.ts
│ └── modules/
│ └── user.test.ts
├── dist/ # 编译输出
├── package.json
├── tsconfig.json
├── jest.config.js
└── README.md # 说明文档使用示例
完整示例:发送图文消息
import { WeComClient } from 'wecom-sdk-ai';
const client = new WeComClient({
corpid: 'ww1234567890abcdef',
corpsecret: 'your-secret-here',
appId: 1000001
});
async function main() {
try {
// 发送图文消息
const result = await client.message.send({
msgtype: 'news',
agentid: 1000001,
touser: 'zhangsan|lisi',
news: {
articles: [
{
title: '公告',
description: '这是一条重要公告',
url: 'https://example.com/announcement',
picurl: 'https://example.com/image.jpg'
}
]
}
});
console.log('发送成功:', result.msgid);
} catch (error) {
if (error instanceof Error) {
console.error('发送失败:', error.message);
}
}
}
main();完整示例:管理企业部门
import { WeComClient } from 'wecom-sdk-ai';
const client = new WeComClient({
corpid: 'ww1234567890abcdef',
corpsecret: 'your-secret-here'
});
async function manageDepartments() {
// 创建顶级部门
const itDept = await client.department.create({
name: '技术部',
parentid: 1,
order: 1
});
console.log('创建技术部 ID:', itDept.id);
// 在技术部下创建子部门
const backendDept = await client.department.create({
name: '后端组',
parentid: itDept.id,
order: 1
});
console.log('创建后端组 ID:', backendDept.id);
// 获取所有部门
const allDepts = await client.department.list();
console.log('所有部门:', allDepts.department);
// 更新部门信息
await client.department.update({
id: backendDept.id,
name: '后端开发组'
});
// 获取部门成员
const members = await client.user.simpleList(itDept.id, 1); // 递归获取
console.log('技术部成员数:', members.userlist.length);
}
manageDepartments();更新日志
v0.1.0 (2026-03-24)
- 初始版本发布
- 完成所有测试用例 (44/44 通过)
- 支持 CommonJS 和 ES Module 引用
- 修复加密解密中文支持问题
- 完善错误处理和中文错误信息
- 优化 Token 缓存机制
- 增加多企业多应用支持
许可证
MIT License
联系方式
如有问题,请提交 Issue。
⚠️ 免责声明
- 本 SDK 尚未在实际企业微信项目中验证使用
- API 参数和返回值可能与企业微信官方文档存在差异
- 使用前请务必阅读企业微信官方 API 文档
- 生产环境使用前建议进行充分测试
