Express.js集成whatsapp-web.js遇404错误:接口无法访问求助
问题排查:Express + whatsapp-web.js 接口返回404错误
问题现象
使用Express.js结合whatsapp-web.js开发,手机扫码后控制台打印"READY",但向/sendmessage发送JSON请求、访问/getqr均返回404错误,已按官方文档使用LocalAuth适配多设备,无法定位问题。
核心错误原因
- Express实例创建顺序错误:原代码中
const app = express()定义在client事件监听之后,导致client.on('qr')回调里挂载/getqr路由时,app变量尚未初始化,路由根本无法挂载成功。 - 路由挂载时机错误:将
/getqr路由放在qr事件回调内,只有当触发QR码生成事件时才会尝试挂载路由,且即使触发,此时app可能已经启动监听,Express不会自动识别后续动态添加的路由。
修复方案
步骤1:调整代码结构,提前创建Express实例
将const app = express()移到代码最前面,确保所有路由挂载和中间件配置都基于已初始化的app实例。
步骤2:用变量存储QR码,统一挂载路由
定义全局变量存储QR码内容,在qr事件中更新该变量,提前在app上挂载/getqr路由,直接返回存储的QR码。
步骤3:清理冗余代码
原代码中保留的SESSION_FILE_PATH相关逻辑属于旧的文件认证方式,使用LocalAuth时无需保留,可直接删除。
修复后的完整代码
const express = require('express'); const createError = require('http-errors'); const morgan = require('morgan'); const { Client, LocalAuth } = require('whatsapp-web.js'); const qrcode = require('qrcode-terminal'); require('dotenv').config(); // 提前创建Express实例 const app = express(); // 全局变量存储QR码 let currentQrCode = null; // 配置Express中间件 app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(morgan('dev')); // 初始化whatsapp-web.js客户端 const client = new Client({ authStrategy: new LocalAuth({ clientId: "client-one" }), puppeteer: { headless: false, } }); client.initialize(); client.on('qr', qr => { console.log('QR RECEIVED', qr); qrcode.generate(qr, { small: true }); // 更新全局QR码变量 currentQrCode = qr; }); client.on('authenticated', () => { console.log('WHATSAPP WEB => Authenticated'); }); client.on('auth_failure', msg => { console.error('AUTHENTICATION FAILURE', msg); }); client.on('ready', () => { console.log('READY'); }); // 挂载/getqr路由 app.get('/getqr', (req, res) => { if (!currentQrCode) { return res.status(404).send({ message: '当前无可用QR码' }); } res.send({ qr: currentQrCode }); }); // 挂载/sendmessage路由 app.post('/sendmessage', async (req, res, next) => { try { // 检查客户端是否已就绪 if (!client.info) { return res.status(400).send({ message: 'WhatsApp客户端尚未就绪,请扫码后重试' }); } const { number, message } = req.body; const msg = await client.sendMessage(`${number}@c.us`, message); res.send({ msg }); } catch (error) { next(error); } }); // 404处理中间件 app.use((req, res, next) => { next(createError.NotFound()); }); // 全局错误处理中间件 app.use((err, req, res) => { res.status(err.status || 500); res.send({ status: err.status || 500, message: err.message, }); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`🚀 服务启动于 http://localhost:${PORT}`));
额外注意事项
- 使用LocalAuth时,会话数据会自动存储在项目根目录的
.wwebjs_auth文件夹下,无需手动处理session文件。 - 在
/sendmessage接口中增加了客户端就绪检查,避免未扫码就发送消息导致的错误。 - Express路由和中间件的挂载顺序很重要:中间件(如
express.json())必须在路由之前挂载,否则无法解析请求体。
内容的提问来源于stack exchange,提问作者E.MRZ
相关产品推荐
相关产品推荐

