From 2b7c7a86424668d81b61f07b6ed04207313f23d6 Mon Sep 17 00:00:00 2001 From: abearxiong Date: Sat, 1 Mar 2025 13:50:00 +0800 Subject: [PATCH] temp: add wx-minimp --- app/package.json | 4 +- app/pnpm-lock.yaml | 28 +++++++++++ app/src/routes-simple/wx-mp-login.ts | 74 ++++++++++++++++++++++++++++ app/src/wx/routes/access.ts | 6 +++ app/src/wx/routes/kefu.ts | 31 ++++++++++++ 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 app/src/routes-simple/wx-mp-login.ts create mode 100644 app/src/wx/routes/access.ts create mode 100644 app/src/wx/routes/kefu.ts diff --git a/app/package.json b/app/package.json index e57bda6..65e8cce 100644 --- a/app/package.json +++ b/app/package.json @@ -40,7 +40,8 @@ "lodash-es": "^4.17.21", "nanoid": "^5.1.2", "pg": "^8.13.3", - "sequelize": "^6.37.5" + "sequelize": "^6.37.5", + "xml2js": "^0.6.2" }, "devDependencies": { "@kevisual/types": "^0.0.6", @@ -55,6 +56,7 @@ "@types/formidable": "^3.4.5", "@types/lodash-es": "^4.17.12", "@types/node": "^22.13.5", + "@types/xml2js": "^0.4.14", "concurrently": "^9.1.2", "cross-env": "^7.0.3", "nodemon": "^3.1.9", diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml index 0a733ae..33d90a3 100644 --- a/app/pnpm-lock.yaml +++ b/app/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: sequelize: specifier: ^6.37.5 version: 6.37.5(pg@8.13.3) + xml2js: + specifier: ^0.6.2 + version: 0.6.2 devDependencies: '@kevisual/types': specifier: ^0.0.6 @@ -75,6 +78,9 @@ importers: '@types/node': specifier: ^22.13.5 version: 22.13.5 + '@types/xml2js': + specifier: ^0.4.14 + version: 0.4.14 concurrently: specifier: ^9.1.2 version: 9.1.2 @@ -544,6 +550,9 @@ packages: '@types/validator@13.12.2': resolution: {integrity: sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==} + '@types/xml2js@0.4.14': + resolution: {integrity: sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==} + accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -2084,6 +2093,14 @@ packages: utf-8-validate: optional: true + xml2js@0.6.2: + resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} + engines: {node: '>=4.0.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -2482,6 +2499,10 @@ snapshots: '@types/validator@13.12.2': {} + '@types/xml2js@0.4.14': + dependencies: + '@types/node': 22.13.5 + accepts@1.3.8: dependencies: mime-types: 2.1.35 @@ -4274,6 +4295,13 @@ snapshots: ws@8.18.0: {} + xml2js@0.6.2: + dependencies: + sax: 1.4.1 + xmlbuilder: 11.0.1 + + xmlbuilder@11.0.1: {} + xtend@4.0.2: {} y18n@5.0.8: {} diff --git a/app/src/routes-simple/wx-mp-login.ts b/app/src/routes-simple/wx-mp-login.ts new file mode 100644 index 0000000..c16a550 --- /dev/null +++ b/app/src/routes-simple/wx-mp-login.ts @@ -0,0 +1,74 @@ +import { SimpleRouter } from '@kevisual/router/simple'; +import crypto from 'crypto'; +import xml2js from 'xml2js'; +export const simpleRouter = new SimpleRouter(); + +simpleRouter.get('/api/wxmsg', async (req, res) => { + 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 = crypto.createHash('sha1').update(str).digest('hex'); + // 签名对比,相同则按照微信要求返回echostr参数值 + if (signature == strSha1) { + res.end(echostr); + } else { + res.end('send fail'); + } +}); + +export const getJsonFromXml = async (req: any): Promise => { + return await new Promise((resolve) => { + // 读取请求数据 + let data = ''; + req.setEncoding('utf8'); + // 监听data事件,接收数据片段 + req.on('data', (chunk) => { + data += chunk; + }); + // 当请求结束时处理数据 + req.on('end', () => { + try { + // 使用xml2js解析XML + xml2js.parseString(data, function (err, result) { + if (err) { + console.error('XML解析错误:', err); + resolve(null); + } else { + const jsonString = JSON.stringify(result); + resolve(jsonString); + } + }); + } catch (error) { + console.error('处理请求时出错:', error); + resolve(null); + } + }); + }); +}; + +simpleRouter.post('/api/wxmsg', async (req, res) => { + console.log('tuisong'); + const msg = await getJsonFromXml(req); + console.log('Receive:', msg); + const builder = new xml2js.Builder(); + const result = builder.buildObject({ + xml: { + ToUserName: msg.FromUserName, + FromUserName: msg.ToUserName, + CreateTime: Date.now(), + MsgType: msg.MsgType, + Content: 'Hello ' + msg.Content, + }, + }); + res.end(result); +}); +export const listen = async (req, res) => { + return await simpleRouter.parse(req, res); +}; diff --git a/app/src/wx/routes/access.ts b/app/src/wx/routes/access.ts new file mode 100644 index 0000000..cbf0730 --- /dev/null +++ b/app/src/wx/routes/access.ts @@ -0,0 +1,6 @@ +// const accessURL = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET' +const accessURL = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential'; + +export const getAccessURL = (appId: string, appSecret: string) => { + return `${accessURL}&appid=${appId}&secret=${appSecret}`; +}; diff --git a/app/src/wx/routes/kefu.ts b/app/src/wx/routes/kefu.ts new file mode 100644 index 0000000..100793b --- /dev/null +++ b/app/src/wx/routes/kefu.ts @@ -0,0 +1,31 @@ +// { +// "touser":"OPENID", +// "msgtype":"text", +// "text": +// { +// "content":"Hello World" +// } +// } + +// 正常执行是errorcode为0 + +// res { +// errcode: 45047, +// errmsg: 'out of response count limit rid: 67c26b8d-3d22149f-5031a93c' +// } +export const sendUser = async (accessToken: string) => { + const data = { + touser: 'omcvy7AHC6bAA0QM4x9_bE0fGD1g', + msgtype: 'text', + text: { + content: 'Hello World', + }, + }; + const url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN'; + const link = url.replace('ACCESS_TOKEN', accessToken); + const res = await fetch(link, { + method: 'POST', + body: JSON.stringify(data), + }).then((res) => res.json()); + console.log('res', res); +};