import { Router, Request, Response } from 'express'; import { wechatService } from '../services/wechat.service'; import { getIO } from '../socket'; import { logger } from '../utils/logger'; const router = Router(); /** * GET /api/wechat/login * Generate WeChat login QR code URL */ router.get('/login', async (req: Request, res: Response) => { const { pcSocketId } = req.query; if (!pcSocketId || typeof pcSocketId !== 'string') { return res.status(400).json({ success: false, error: 'pcSocketId is required', }); } const result = await wechatService.createLoginState(pcSocketId); if (!result.success) { return res.status(500).json(result); } res.json(result); }); /** * GET /api/wechat/callback * WeChat OAuth2 callback handler */ router.get('/callback', async (req: Request, res: Response) => { const { code, state } = req.query; if (!code || !state || typeof code !== 'string' || typeof state !== 'string') { logger.warn({ code, state }, 'Invalid WeChat callback parameters'); return res.status(400).send(renderCallbackPage(false, 'Invalid parameters')); } const result = await wechatService.handleCallback(code, state); if (!result.success || !result.data) { logger.error({ error: result.error }, 'WeChat callback failed'); return res.status(400).send(renderCallbackPage(false, result.error || 'Login failed')); } const { openid, pcSocketId, sessionToken, userId, userInfo } = result.data; // Notify PC client via WebSocket try { const io = getIO(); io.to(pcSocketId).emit('wechat:login_success' as any, { openid, sessionToken, userId, userName: userInfo?.nickname || `微信用户_${openid.slice(-6)}`, userInfo, }); logger.info({ pcSocketId, userId }, 'WeChat login success notification sent'); } catch (error) { logger.error({ error, pcSocketId }, 'Failed to notify PC client'); } // Return success page res.send(renderCallbackPage(true, 'Login successful')); }); /** * GET /api/wechat/status * Check WeChat configuration status */ router.get('/status', (_req: Request, res: Response) => { res.json({ configured: wechatService.isConfigured(), }); }); /** * Render callback result page */ function renderCallbackPage(success: boolean, message: string): string { const color = success ? '#52c41a' : '#ff4d4f'; const icon = success ? '✓' : '✗'; return `