const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { getDatabase } = require('../config/database');
const WeChatService = require('../services/WeChatService');
const WebhookService = require('../services/WebhookService');
const SchedulerService = require('../services/SchedulerService');
const logger = require('../utils/logger');
router.get('/docs', (req, res) => {
res.json({
name: '微信AccessToken管理系统 API',
version: '1.0.0',
endpoints: {
'GET /api/config': '获取当前配置',
'POST /api/config': '保存配置',
'POST /api/config/test': '测试配置',
'GET /api/token/current': '获取当前Token',
'POST /api/token/refresh': '手动刷新Token',
'GET /api/service/status': '获取服务状态',
'POST /api/service/start': '启动服务',
'POST /api/service/stop': '停止服务',
'GET /api/logs/operations': '获取操作日志',
'GET /api/logs/webhooks': '获取Webhook日志'
}
});
});
router.get('/config', async (req, res) => {
try {
const db = getDatabase();
db.get('SELECT * FROM configs WHERE is_active = 1 ORDER BY updated_at DESC LIMIT 1', (err, row) => {
if (err) {
logger.error('获取配置失败:', err);
return res.status(500).json({
success: false,
message: '获取配置失败'
});
}
if (row) {
const config = {
id: row.id,
appid: row.appid,
interval_minutes: row.interval_minutes,
webhook_url: row.webhook_url,
is_active: row.is_active,
created_at: row.created_at,
updated_at: row.updated_at
};
res.json({
success: true,
data: config
});
} else {
res.json({
success: true,
data: null
});
}
});
} catch (error) {
logger.error('获取配置失败:', error);
res.status(500).json({
success: false,
message: '服务器错误'
});
}
});
router.post('/config', async (req, res) => {
try {
const { appid, appsecret, interval_minutes, webhook_url } = req.body;
if (!appid || !appsecret) {
return res.status(400).json({
success: false,
message: 'AppID和AppSecret为必填项'
});
}
if (interval_minutes < 10 || interval_minutes > 7200) {
return res.status(400).json({
success: false,
message: '获取间隔必须在10分钟到120小时之间'
});
}
const db = getDatabase();
await new Promise((resolve, reject) => {
db.run('UPDATE configs SET is_active = 0', (err) => {
if (err) reject(err);
else resolve();
});
});
const result = await new Promise((resolve, reject) => {
const sql = `
INSERT INTO configs (appid, appsecret, interval_minutes, webhook_url, is_active)
VALUES (?, ?, ?, ?, 1)
`;
db.run(sql, [appid, appsecret, interval_minutes, webhook_url], function(err) {
if (err) {
reject(err);
} else {
resolve(this.lastID);
}
});
});
logger.info(`配置已保存 - ID: ${result}, AppID: ${appid}`);
res.json({
success: true,
message: '配置保存成功',
data: { id: result }
});
} catch (error) {
logger.error('保存配置失败:', error);
res.status(500).json({
success: false,
message: '保存配置失败'
});
}
});
router.post('/config/test', async (req, res) => {
try {
const { appid, appsecret, webhook_url } = req.body;
if (!appid || !appsecret) {
return res.status(400).json({
success: false,
message: 'AppID和AppSecret为必填项'
});
}
const results = {
wechat: { success: false, message: '' },
webhook: { success: false, message: '' }
};
try {
await WeChatService.getAccessToken(appid, appsecret);
results.wechat = { success: true, message: '微信API连接正常' };
} catch (error) {
results.wechat = { success: false, message: error.message };
}
if (webhook_url) {
try {
const webhookResult = await WebhookService.testWebhook(webhook_url);
results.webhook = webhookResult;
} catch (error) {
results.webhook = { success: false, message: error.message };
}
} else {
results.webhook = { success: true, message: '未配置Webhook URL' };
}
const allSuccess = results.wechat.success && results.webhook.success;
res.json({
success: allSuccess,
message: allSuccess ? '所有测试通过' : '部分测试失败',
data: results
});
} catch (error) {
logger.error('测试配置失败:', error);
res.status(500).json({
success: false,
message: '测试失败'
});
}
});
router.get('/token/current', async (req, res) => {
try {
const token = await WeChatService.getLatestToken();
if (token) {
res.json({
success: true,
data: {
access_token: token.access_token,
expires_in: token.expires_in,
expire_time: token.expire_time,
created_at: token.created_at
}
});
} else {
res.json({
success: true,
data: null,
message: '暂无可用Token'
});
}
} catch (error) {
logger.error('获取Token失败:', error);
res.status(500).json({
success: false,
message: '获取Token失败'
});
}
});
router.post('/token/refresh', async (req, res) => {
try {
const db = getDatabase();
const config = await new Promise((resolve, reject) => {
db.get('SELECT * FROM configs WHERE is_active = 1 ORDER BY updated_at DESC LIMIT 1', (err, row) => {
if (err) reject(err);
else resolve(row);
});
});
if (!config) {
return res.status(400).json({
success: false,
message: '未找到活跃配置'
});
}
const result = await SchedulerService.manualRefresh(config.id);
res.json({
success: true,
message: 'Token刷新成功',
data: result
});
} catch (error) {
logger.error('手动刷新失败:', error);
res.status(500).json({
success: false,
message: '刷新失败: ' + error.message
});
}
});
router.get('/service/status', (req, res) => {
try {
const status = SchedulerService.getStatus();
res.json({
success: true,
data: status
});
} catch (error) {
logger.error('获取服务状态失败:', error);
res.status(500).json({
success: false,
message: '获取服务状态失败'
});
}
});
router.post('/service/start', async (req, res) => {
try {
await SchedulerService.loadActiveConfigs();
res.json({
success: true,
message: '服务启动成功'
});
} catch (error) {
logger.error('启动服务失败:', error);
res.status(500).json({
success: false,
message: '启动服务失败: ' + error.message
});
}
});
router.post('/service/stop', (req, res) => {
try {
SchedulerService.stop();
res.json({
success: true,
message: '服务停止成功'
});
} catch (error) {
logger.error('停止服务失败:', error);
res.status(500).json({
success: false,
message: '停止服务失败: ' + error.message
});
}
});
router.get('/logs/operations', (req, res) => {
try {
const limit = parseInt(req.query.limit) || 50;
const db = getDatabase();
const sql = `
SELECT * FROM operation_logs
ORDER BY created_at DESC
LIMIT ?
`;
db.all(sql, [limit], (err, rows) => {
if (err) {
logger.error('获取操作日志失败:', err);
return res.status(500).json({
success: false,
message: '获取日志失败'
});
}
res.json({
success: true,
data: rows
});
});
} catch (error) {
logger.error('获取操作日志失败:', error);
res.status(500).json({
success: false,
message: '获取日志失败'
});
}
});
router.get('/logs/webhooks', async (req, res) => {
try {
const limit = parseInt(req.query.limit) || 50;
const logs = await WebhookService.getWebhookLogs(limit);
res.json({
success: true,
data: logs
});
} catch (error) {
logger.error('获取Webhook日志失败:', error);
res.status(500).json({
success: false,
message: '获取Webhook日志失败'
});
}
});
module.exports = router;