自动回复文本功能实现
功能概述
自动回复文本功能是微信公众号开发中最基础也是最常用的功能之一。当用户发送消息给公众号时,系统会根据预设的规则自动回复相应的文本内容。
基础实现
1. 简单的关键词回复
function handleTextMessage(message, fromUserName, toUserName) {
const content = message.Content[0];
// 关键词匹配
if (content.includes('你好') || content.includes('hello')) {
return createTextReply(fromUserName, toUserName, '你好!欢迎关注我们的公众号!');
} else if (content.includes('帮助') || content.includes('help')) {
return createTextReply(fromUserName, toUserName,
'您可以发送以下关键词:\n- 你好\n- 帮助\n- 天气\n- 时间');
} else if (content.includes('天气')) {
return createTextReply(fromUserName, toUserName, '抱歉,天气功能正在开发中...');
} else if (content.includes('时间')) {
const now = new Date();
return createTextReply(fromUserName, toUserName, `当前时间:${now.toLocaleString()}`);
} else {
return createTextReply(fromUserName, toUserName,
`您发送的是:${content}\n\n如需帮助,请发送"帮助"`);
}
}
function createTextReply(fromUserName, toUserName, content) {
return `
<xml>
<ToUserName><![CDATA[${fromUserName}]]></ToUserName>
<FromUserName><![CDATA[${toUserName}]]></FromUserName>
<CreateTime>${Date.now()}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${content}]]></Content>
</xml>
`;
}
2. 正则表达式匹配
function handleTextMessageWithRegex(message, fromUserName, toUserName) {
const content = message.Content[0];
// 问候语匹配
if (/^(你好|hello|hi|您好)$/i.test(content)) {
return createTextReply(fromUserName, toUserName, '你好!很高兴为您服务!');
}
// 帮助请求匹配
if (/^(帮助|help|?|?)$/i.test(content)) {
return createTextReply(fromUserName, toUserName,
'📋 帮助菜单:\n\n' +
'🔍 查询功能:\n' +
'- 天气 [城市名]\n' +
'- 时间\n' +
'- 日期\n\n' +
'💬 互动功能:\n' +
'- 你好\n' +
'- 笑话\n' +
'- 新闻');
}
// 天气查询
const weatherMatch = content.match(/^天气\s*(.+)$/);
if (weatherMatch) {
const city = weatherMatch[1];
return createTextReply(fromUserName, toUserName,
`正在查询 ${city} 的天气信息...\n\n(天气功能正在开发中)`);
}
// 时间查询
if (/^(时间|几点|现在几点)$/i.test(content)) {
const now = new Date();
const timeString = now.toLocaleString('zh-CN');
return createTextReply(fromUserName, toUserName, `🕐 当前时间:${timeString}`);
}
// 默认回复
return createTextReply(fromUserName, toUserName,
`收到您的消息:${content}\n\n💡 发送"帮助"查看所有可用功能`);
}
高级功能
1. 智能回复系统
class SmartReplySystem {
constructor() {
this.userContext = new Map();
}
handleMessage(message, fromUserName, toUserName) {
const content = message.Content[0];
const userContext = this.getUserContext(fromUserName);
// 更新用户上下文
userContext.lastMessage = content;
userContext.messageCount = (userContext.messageCount || 0) + 1;
userContext.lastActiveTime = Date.now();
// 根据消息内容生成回复
if (/^(你好|hello|hi|您好)$/i.test(content)) {
return this.generateGreeting(userContext);
} else if (/^(帮助|help|?|?)$/i.test(content)) {
return this.generateHelpMenu(userContext);
} else if (content.includes('天气')) {
return this.generateWeatherReply(content);
} else if (/^(时间|几点|现在几点)$/i.test(content)) {
return this.generateTimeReply();
} else {
return this.generateDefaultReply(content, userContext);
}
}
getUserContext(userId) {
if (!this.userContext.has(userId)) {
this.userContext.set(userId, {
firstMessageTime: Date.now(),
messageCount: 0
});
}
return this.userContext.get(userId);
}
generateGreeting(context) {
const hour = new Date().getHours();
let greeting = '';
if (hour < 12) greeting = '早上好!祝您一天愉快!';
else if (hour < 18) greeting = '下午好!工作顺利!';
else greeting = '晚上好!今天过得怎么样?';
return createTextReply(fromUserName, toUserName, greeting);
}
generateHelpMenu(context) {
const isNewUser = context.messageCount <= 3;
if (isNewUser) {
return createTextReply(fromUserName, toUserName,
`🎉 欢迎新朋友!\n\n` +
`📋 快速开始:\n` +
`• 发送"你好"打个招呼\n` +
`• 发送"时间"查看当前时间\n` +
`• 发送"笑话"听个笑话\n\n` +
`💡 更多功能请发送"帮助"`);
} else {
return createTextReply(fromUserName, toUserName,
`📋 功能菜单:\n\n` +
`🔍 查询功能:\n` +
`• 天气 [城市名] - 查询天气\n` +
`• 时间 - 查看当前时间\n` +
`• 日期 - 查看当前日期\n\n` +
`💬 互动功能:\n` +
`• 你好 - 打招呼\n` +
`• 笑话 - 听笑话\n` +
`• 新闻 - 查看新闻\n\n` +
`💡 您已发送 ${context.messageCount} 条消息`);
}
}
generateWeatherReply(content) {
const cityMatch = content.match(/天气\s*(.+)/);
const city = cityMatch ? cityMatch[1] : '未知城市';
return createTextReply(fromUserName, toUserName,
`🌤️ ${city} 天气信息:\n\n` +
`温度:22°C\n` +
`天气:多云\n` +
`湿 度:65%\n` +
`风力:3级\n\n` +
`(此为模拟数据,实际功能需要接入天气API)`);
}
generateTimeReply() {
const now = new Date();
const timeString = now.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
weekday: 'long'
});
return createTextReply(fromUserName, toUserName, `🕐 当前时间:${timeString}`);
}
generateDefaultReply(content, context) {
if (context.messageCount === 1) {
return createTextReply(fromUserName, toUserName,
`👋 欢迎您!\n\n` +
`收到您的第一条消息:${content}\n\n` +
`💡 发送"帮助"查看所有可用功能`);
} else {
return createTextReply(fromUserName, toUserName,
`收到您的消息:${content}\n\n` +
`💡 发送"帮助"查看所有功能`);
}
}
}
2. 完整服务器实现
const express = require('express');
const crypto = require('crypto');
const xml2js = require('xml2js');
const bodyParser = require('body-parser');
const app = express();
const PORT = 3000;
const TOKEN = 'your_token_here';
// 中间件配置
app.use(bodyParser.text({ type: 'application/xml' }));
// 智能回复系统实例
const smartReply = new SmartReplySystem();
// 验证签名函数
function verifySignature(signature, timestamp, nonce, token) {
const arr = [token, timestamp, nonce].sort();
const str = arr.join('');
const sha1 = crypto.createHash('sha1');
sha1.update(str);
return sha1.digest('hex') === signature;
}
// 处理微信验证请求
app.get('/wechat', (req, res) => {
const { signature, timestamp, nonce, echostr } = req.query;
if (verifySignature(signature, timestamp, nonce, TOKEN)) {
res.send(echostr);
} else {
res.status(403).send('Forbidden');
}
});
// 处理微信消息
app.post('/wechat', async (req, res) => {
try {
// 解析XML消息
const parser = new xml2js.Parser();
const result = await parser.parseStringPromise(req.body);
const message = result.xml;
// 获取消息基本信息
const toUserName = message.ToUserName[0];
const fromUserName = message.FromUserName[0];
const msgType = message.MsgType[0];
console.log('收到消息:', {
from: fromUserName,
type: msgType,
content: message.Content ? message.Content[0] : 'N/A'
});
// 根据消息类型处理
let reply = '';
switch (msgType) {
case 'text':
reply = smartReply.handleMessage(message, fromUserName, toUserName);
break;
case 'event':
reply = handleEventMessage(message, fromUserName, toUserName);
break;
default:
reply = createTextReply(fromUserName, toUserName, '暂不支持此类型消息');
}
res.type('application/xml');
res.send(reply);
} catch (error) {
console.error('处理消息错误:', error);
res.status(500).send('Internal Server Error');
}
});
// 处理事件消息
function handleEventMessage(message, fromUserName, toUserName) {
const event = message.Event[0];
switch (event) {
case 'subscribe':
return createTextReply(fromUserName, toUserName,
'🎉 感谢关注我们的公众号!\n\n' +
'💡 发送"帮助"查看所有可用功能\n' +
'💡 发送"你好"打个招呼');
case 'unsubscribe':
return ''; // 用户取消关注,不需要回复
default:
return createTextReply(fromUserName, toUserName, `收到事件:${event}`);
}
}
// 创建文本回复
function createTextReply(fromUserName, toUserName, content) {
return `
<xml>
<ToUserName><![CDATA[${fromUserName}]]></ToUserName>
<FromUserName><![CDATA[${toUserName}]]></FromUserName>
<CreateTime>${Date.now()}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${content}]]></Content>
</xml>
`;
}
// 启动服务器
app.listen(PORT, () => {
console.log(`服务器运行在端口 ${PORT}`);
console.log(`微信验证地址: http://localhost:${PORT}/wechat`);
});
测试和调试
1. 本地测试
# 安装依赖
npm install express crypto xml2js body-parser
# 启动服务器
node app.js
# 使用ngrok进行外网映射
ngrok http 3000
2. 功能测试
- 发送"你好"测试问候功能
- 发送"帮助"测试帮助菜单
- 发送"时间"测试时间查询
- 发送"天气北京"测试天气查询
最佳实践
1. 回复内容设计
- 简洁明了: 回复内容要简洁易懂
- 功能导向: 引导用户使用其他功能
- 个性化: 根据用户行为提供个性化回复
- 友好性: 保持友好和专业的语调
2. 性能优化
- 缓存机制: 缓存常用的回复内容
- 异步处理: 对于复杂查询使用异步处理
- 错误处理: 完善的错误处理机制
3. 用户体验
- 快速响应: 确保回复速度
- 引导使用: 主动引导用户使用功能
- 反馈机制: 提供用户反馈渠道
总结
自动回复文本功能是微信公众号开发的基础功能,通过合理的规则设计和智能回复系统,可以为用户提供良好的交互体验。
在接下来的学习中,我们将介绍如何实现多媒体回复功能,包括图片、语音、视频等。