/**
|
* Node.js + Express 企业微信 OAuth 后端示例
|
*
|
* 安装依赖:
|
* npm install express axios cors dotenv morgan
|
*
|
* 启动服务:
|
* node server.js
|
*/
|
|
require('dotenv').config();
|
const express = require('express');
|
const cors = require('cors');
|
const morgan = require('morgan');
|
const axios = require('axios');
|
const path = require('path');
|
|
const app = express();
|
|
// 中间件
|
app.use(cors());
|
app.use(morgan('combined'));
|
app.use(express.json());
|
app.use(express.static(path.join(__dirname, '../dist')));
|
|
// 企业微信配置
|
const WECOM_CONFIG = {
|
corpId: process.env.WECOM_CORP_ID,
|
appSecret: process.env.WECOM_APP_SECRET,
|
agentId: process.env.WECOM_AGENT_ID
|
};
|
|
// 缓存 access_token
|
let accessTokenCache = {
|
token: null,
|
expireTime: 0
|
};
|
|
/**
|
* 获取企业微信访问令牌
|
*/
|
async function getAccessToken() {
|
const now = Date.now();
|
|
// 如果 token 未过期,直接返回缓存
|
if (accessTokenCache.token && accessTokenCache.expireTime > now) {
|
return accessTokenCache.token;
|
}
|
|
try {
|
const response = await axios.get('https://qyapi.weixin.qq.com/cgi-bin/gettoken', {
|
params: {
|
corpid: WECOM_CONFIG.corpId,
|
corpsecret: WECOM_CONFIG.appSecret
|
}
|
});
|
|
if (response.data.errcode === 0) {
|
const token = response.data.access_token;
|
const expiresIn = response.data.expires_in || 7200;
|
|
accessTokenCache = {
|
token: token,
|
expireTime: now + (expiresIn - 300) * 1000 // 提前5分钟刷新
|
};
|
|
return token;
|
} else {
|
throw new Error(`获取 token 失败: ${response.data.errmsg}`);
|
}
|
} catch (error) {
|
console.error('获取 access_token 错误:', error.message);
|
throw error;
|
}
|
}
|
|
/**
|
* API: 使用授权码获取用户信息
|
*/
|
app.post('/api/wecom/getUserInfo', async (req, res) => {
|
const { code } = req.body;
|
|
if (!code) {
|
return res.status(400).json({
|
code: -1,
|
message: '缺少授权码'
|
});
|
}
|
|
try {
|
const accessToken = await getAccessToken();
|
|
// 获取用户信息
|
const response = await axios.get('https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail', {
|
params: {
|
access_token: accessToken,
|
code: code
|
}
|
});
|
|
if (response.data.errcode === 0) {
|
const userData = {
|
userid: response.data.userid,
|
name: response.data.name,
|
mobile: response.data.mobile || '',
|
email: response.data.email || '',
|
department: (response.data.department && response.data.department[0]) || '',
|
position: response.data.position || '',
|
gender: response.data.gender || 0,
|
avatar: response.data.avatar || '',
|
extattr: response.data.extattr || {}
|
};
|
|
// 可选: 将用户信息存储到数据库
|
// await saveUserToDatabase(userData);
|
|
res.json({
|
code: 0,
|
message: 'success',
|
data: userData
|
});
|
} else {
|
res.status(401).json({
|
code: response.data.errcode,
|
message: response.data.errmsg || '获取用户信息失败'
|
});
|
}
|
} catch (error) {
|
console.error('获取用户信息错误:', error.message);
|
res.status(500).json({
|
code: -1,
|
message: '获取用户信息失败: ' + error.message
|
});
|
}
|
});
|
|
/**
|
* API: 获取用户详情
|
*/
|
app.get('/api/wecom/userDetail/:userId', async (req, res) => {
|
const { userId } = req.params;
|
|
try {
|
const accessToken = await getAccessToken();
|
|
const response = await axios.get('https://qyapi.weixin.qq.com/cgi-bin/user/get', {
|
params: {
|
access_token: accessToken,
|
userid: userId
|
}
|
});
|
|
if (response.data.errcode === 0) {
|
res.json({
|
code: 0,
|
message: 'success',
|
data: response.data
|
});
|
} else {
|
res.status(404).json({
|
code: response.data.errcode,
|
message: response.data.errmsg
|
});
|
}
|
} catch (error) {
|
console.error('获取用户详情错误:', error.message);
|
res.status(500).json({
|
code: -1,
|
message: '获取用户详情失败'
|
});
|
}
|
});
|
|
/**
|
* API: 验证用户权限
|
*/
|
app.get('/api/wecom/verify/:userId', async (req, res) => {
|
const { userId } = req.params;
|
|
try {
|
// 实现自己的权限验证逻辑
|
// 例如: 检查用户是否在允许的部门列表中
|
const authorized = await checkUserPermission(userId);
|
|
res.json({
|
code: 0,
|
message: 'success',
|
data: {
|
authorized: authorized
|
}
|
});
|
} catch (error) {
|
console.error('验证用户权限错误:', error.message);
|
res.status(500).json({
|
code: -1,
|
message: '验证失败'
|
});
|
}
|
});
|
|
/**
|
* API: 同步用户到本地系统
|
*/
|
app.post('/api/user/sync', async (req, res) => {
|
const { userid, name, mobile } = req.body;
|
|
try {
|
// 实现自己的用户同步逻辑
|
// 例如: 保存到数据库、更新缓存等
|
|
console.log(`同步用户: ${userid}, ${name}, ${mobile}`);
|
|
res.json({
|
code: 0,
|
message: 'success',
|
data: {
|
synced: true
|
}
|
});
|
} catch (error) {
|
console.error('同步用户错误:', error.message);
|
res.status(500).json({
|
code: -1,
|
message: '同步用户失败'
|
});
|
}
|
});
|
|
/**
|
* 健康检查
|
*/
|
app.get('/api/health', (req, res) => {
|
res.json({
|
code: 0,
|
message: 'OK',
|
timestamp: new Date().toISOString()
|
});
|
});
|
|
/**
|
* SPA 路由处理
|
*/
|
app.get('*', (req, res) => {
|
res.sendFile(path.join(__dirname, '../dist/index.html'));
|
});
|
|
/**
|
* 错误处理中间件
|
*/
|
app.use((error, req, res, next) => {
|
console.error('未捕获的错误:', error);
|
res.status(500).json({
|
code: -1,
|
message: '服务器内部错误'
|
});
|
});
|
|
/**
|
* 权限检查辅助函数 (示例)
|
*/
|
async function checkUserPermission(userId) {
|
// 实现你的权限验证逻辑
|
// 例如:
|
// 1. 检查用户是否在允许列表中
|
// 2. 检查用户的部门是否被授权
|
// 3. 查询数据库的权限配置
|
|
// 这里返回 true 作为示例
|
return true;
|
}
|
|
/**
|
* 数据库保存函数 (示例)
|
*/
|
async function saveUserToDatabase(userData) {
|
// 实现保存到数据库的逻辑
|
// 例如使用 MongoDB:
|
// const user = new User(userData);
|
// await user.save();
|
console.log('保存用户到数据库:', userData);
|
}
|
|
// 启动服务器
|
const PORT = process.env.PORT || 3000;
|
app.listen(PORT, () => {
|
console.log(`服务器运行在 http://localhost:${PORT}`);
|
console.log(`企业微信配置:`);
|
console.log(` CorpID: ${WECOM_CONFIG.corpId}`);
|
console.log(` AgentID: ${WECOM_CONFIG.agentId}`);
|
});
|
|
module.exports = app;
|