95 lines
3.7 KiB
JavaScript
95 lines
3.7 KiB
JavaScript
import { serve } from "@hono/node-server";
|
|
import { Hono } from "hono";
|
|
import { getSignature, decrypt, encrypt } from '@wecom/crypto';
|
|
import { parseStringPromise } from 'xml2js';
|
|
function validateSignature(msgSignature, timestamp, nonce, encrypt) {
|
|
const { WEIXIN_EVENT_TOKEN, } = process.env;
|
|
if (!WEIXIN_EVENT_TOKEN)
|
|
throw new Error('static param error');
|
|
const devMsgSignature = getSignature(WEIXIN_EVENT_TOKEN, timestamp, nonce, encrypt);
|
|
return devMsgSignature === msgSignature;
|
|
}
|
|
export async function handleServer() {
|
|
const app = new Hono();
|
|
app.get('/we-comp/event', ({ req, ...args }) => {
|
|
try {
|
|
const { 'msg_signature': msgSignature, timestamp, nonce, echostr } = req.query();
|
|
const { WEIXIN_EVENT_TOKEN, WEIXIN_EVENT_ENCODING_AES_KEY, } = process.env;
|
|
if (!WEIXIN_EVENT_TOKEN
|
|
|| !WEIXIN_EVENT_ENCODING_AES_KEY
|
|
|| !msgSignature
|
|
|| !timestamp
|
|
|| !nonce
|
|
|| !echostr) {
|
|
throw new Error('static param error');
|
|
}
|
|
if (!validateSignature(msgSignature, timestamp, nonce, echostr)) {
|
|
throw new Error('validate error');
|
|
}
|
|
const { message, id } = decrypt(WEIXIN_EVENT_ENCODING_AES_KEY, echostr);
|
|
console.log('URL验证成功,解密后的消息:', message);
|
|
console.log('接收者ID:', id);
|
|
}
|
|
catch (e) {
|
|
console.error(e);
|
|
}
|
|
return args.text("");
|
|
});
|
|
app.post('/we-comp/event', async ({ req, ...args }) => {
|
|
const { 'msg_signature': msgSignature, timestamp, nonce } = req.query();
|
|
try {
|
|
const result = await parseStringPromise(await req.text());
|
|
const encrypt = result.xml.Encrypt.at(0);
|
|
const { WEIXIN_EVENT_TOKEN, WEIXIN_EVENT_ENCODING_AES_KEY, } = process.env;
|
|
if (!WEIXIN_EVENT_TOKEN
|
|
|| !WEIXIN_EVENT_ENCODING_AES_KEY
|
|
|| !msgSignature
|
|
|| !timestamp
|
|
|| !nonce) {
|
|
throw new Error('static param error');
|
|
}
|
|
// 2. 验证签名
|
|
if (!validateSignature(msgSignature, timestamp, nonce, encrypt)) {
|
|
throw new Error('签名验证失败');
|
|
}
|
|
const { message, id } = decrypt(WEIXIN_EVENT_ENCODING_AES_KEY, encrypt);
|
|
console.log('解密后的消息:', message);
|
|
console.log('接收者ID:', id);
|
|
// 5. 解析明文XML
|
|
const decryptedXml = await parseStringPromise(message);
|
|
const msgData = decryptedXml.xml;
|
|
const msgType = msgData.MsgType?.[0];
|
|
const fromUserName = msgData.FromUserName?.[0];
|
|
const toUserName = msgData.ToUserName?.[0];
|
|
const createTime = msgData.CreateTime?.[0];
|
|
console.log('========== 消息详情 ==========');
|
|
console.log('消息类型:', msgType);
|
|
console.log('发送者:', fromUserName);
|
|
console.log('接收者:', toUserName);
|
|
console.log('创建时间:', createTime);
|
|
console.log('============================');
|
|
}
|
|
catch (e) {
|
|
console.error(e);
|
|
}
|
|
return args.text('');
|
|
});
|
|
const server = serve({
|
|
fetch: app.fetch,
|
|
port: 3080,
|
|
});
|
|
process.on('SIGINT', () => {
|
|
server.close();
|
|
process.exit(0);
|
|
});
|
|
process.on('SIGTERM', () => {
|
|
server.close((err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
process.exit(1);
|
|
}
|
|
process.exit(0);
|
|
});
|
|
});
|
|
}
|
|
//# sourceMappingURL=server.js.map
|