1.登录
developers.weixin.qq.com/console/pro…
2.公众号-域名与消息推送配置
1.JS接口安全域名 80 443端口被占用可以使用nginx进行转发到其他的端口
server {
listen 80;
server_name www.xxx.com xxx.com; # 替换为你的域名
location / {
proxy_pass http://localhost:3333;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
#新增:将 /wechat 路径代理到本地 Node.js 服务
location /wechat {
proxy_pass http://127.0.0.1:7777; # 注意:结尾不要加 /
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
2.消息推送 启动对应端口的服务进行接收消息推送
const express = require('express');
const xml2js = require('xml2js');
const crypto = require('crypto');
const app = express();
// ========== 配置区域 ==========
const CONFIG = {
// 微信 Token
token: '你的token',
// 默认回复
defaultReply: '感谢您的消息!'
};
// ========== 工具函数 ==========
// 验证微信签名
function checkSignature(signature, timestamp, nonce) {
const tmpArr = [CONFIG.token, timestamp, nonce].sort();
const tmpStr = tmpArr.join('');
const shasum = crypto.createHash('sha1');
shasum.update(tmpStr);
const hash = shasum.digest('hex');
return hash === signature;
}
// 解析 XML
function parseXML(xml) {
return new Promise((resolve, reject) => {
xml2js.parseString(xml, { explicitArray: false }, (err, result) => {
if (err) reject(err);
else resolve(result.xml || result);
});
});
}
// 生成 XML 回复
function generateXML(data) {
const builder = new xml2js.Builder({ rootName: 'xml', headless: true });
return builder.buildObject(data);
}
// 处理文本消息
function handleTextMessage(message) {
const content = message.Content;
const fromUser = message.FromUserName;
const toUser = message.ToUserName;
console.log('收到消息:', content);
let replyContent = CONFIG.defaultReply;
// 创建回复消息
return {
ToUserName: fromUser,
FromUserName: toUser,
CreateTime: Math.floor(Date.now() / 1000),
MsgType: 'text',
Content: replyContent
};
}
// ========== 路由处理 ==========
// 解析 XML 请求体
app.use('/wechat', express.text({ type: 'text/xml' }));
// GET: 验证服务器地址
app.get('/wechat', (req, res) => {
const { signature, timestamp, nonce, echostr } = req.query;
if (!signature || !timestamp || !nonce || !echostr) {
return res.status(400).send('Missing parameters');
}
if (checkSignature(signature, timestamp, nonce)) {
console.log('URL验证成功');
return res.send(echostr);
} else {
console.log('签名验证失败');
return res.status(403).send('Invalid signature');
}
});
// POST: 接收消息
app.post('/wechat', async (req, res) => {
const { signature, timestamp, nonce } = req.query;
const xmlData = req.body;
// 验证签名
if (!checkSignature(signature, timestamp, nonce)) {
console.log('消息签名验证失败');
return res.status(403).send('Invalid signature');
}
try {
// 解析消息
const message = await parseXML(xmlData);
const msgType = message.MsgType;
// 只处理文本消息
if (msgType === 'text') {
const reply = handleTextMessage(message);
const replyXML = generateXML(reply);
console.log('发送回复:', reply.Content);
res.set('Content-Type', 'text/xml');
return res.send(replyXML);
}
// 其他消息类型不回复
res.send('success');
} catch (error) {
console.error('处理消息时出错:', error);
res.send('success');
}
});
// 启动服务
app.listen(7777, '127.0.0.1', () => {
console.log('微信服务运行在 http://127.0.0.1:7777');
console.log('配置说明:');
console.log('- Token:', CONFIG.token);
console.log('- 只处理文本消息');
});