85 lines
2.7 KiB
TypeScript
85 lines
2.7 KiB
TypeScript
import { SimpleRouter } from '@kevisual/router/simple';
|
||
import CryptoJS from 'crypto-js';
|
||
import { useContextKey } from '@kevisual/context';
|
||
import { Redis } from 'ioredis';
|
||
import http from 'node:http';
|
||
import { Wx, WxMsgEvent, parseWxMessage } from './wx/index.ts';
|
||
import { contextConfig as config } from './modules/config.ts';
|
||
import { loginByTicket } from './wx/login-by-ticket.ts';
|
||
import { Queue } from 'bullmq';
|
||
import { parseXml } from './utils/get-json-from-xml.ts';
|
||
export const simpleRouter: SimpleRouter = await useContextKey('router');
|
||
export const redis: Redis = await useContextKey('redis');
|
||
export const wxmsgQueue = useContextKey<Queue>('wxmsgQueue', () => {
|
||
return new Queue('wxmsg', {
|
||
connection: redis
|
||
});
|
||
});
|
||
simpleRouter.get('/api/wxmsg', async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||
console.log('微信检测服务是否可用');
|
||
const query = simpleRouter.getSearch(req);
|
||
const body = await simpleRouter.getBody(req);
|
||
const {
|
||
signature, // 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
|
||
timestamp, // 时间戳
|
||
nonce, // 随机数
|
||
echostr, // 随机字符串
|
||
} = query;
|
||
const token = 'xiongabc123';
|
||
let str = [token, timestamp, nonce].sort().join('');
|
||
let strSha1 = CryptoJS.SHA1(str).toString();
|
||
// 签名对比,相同则按照微信要求返回echostr参数值
|
||
if (signature == strSha1) {
|
||
res.end(echostr);
|
||
} else {
|
||
res.end('send fail');
|
||
}
|
||
});
|
||
|
||
simpleRouter.post('/api/wxmsg', async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||
try {
|
||
const xml = await parseXml(req);
|
||
const msgOrigin = xml?.xml;
|
||
if (!msgOrigin) {
|
||
console.error('No message received');
|
||
res.end('');
|
||
return
|
||
}
|
||
const msg = parseWxMessage(msgOrigin);
|
||
const { fromusername, msgtype } = msg;
|
||
res.end('')
|
||
if (msgtype === 'event') {
|
||
const wxMsgEvent = msg as WxMsgEvent;
|
||
if (wxMsgEvent.eventkey?.includes?.('login')) {
|
||
await loginByTicket({
|
||
ticket: wxMsgEvent.ticket!,
|
||
openid: wxMsgEvent.fromusername,
|
||
});
|
||
}
|
||
return
|
||
}
|
||
if (fromusername) {
|
||
// 代理分析返回
|
||
const wx = new Wx({ appId: config.WX_MP_APP_ID, appSecret: config.WX_MP_APP_SECRET, redis });
|
||
wx.analyzeUserMsg(msg);
|
||
}
|
||
return
|
||
|
||
|
||
// 直接返回
|
||
// const builder = new xml2js.Builder();
|
||
// const result = builder.buildObject({
|
||
// xml: {
|
||
// ToUserName: fromusername,
|
||
// FromUserName: tousername,
|
||
// CreateTime: Date.now(),
|
||
// MsgType: msgtype,
|
||
// Content: 'Hello ' + content,
|
||
// },
|
||
// });
|
||
// res.end(result);
|
||
} catch (e) {
|
||
console.error('Error processing message:', e);
|
||
}
|
||
});
|