顺晟科技
2021-06-16 10:59:24
586
之前写了一个解密json格式加密。我认为xml和json很相似。那是上周五。我同事也在微信微信官方账号里做消息推送解密,发现好像只能用xml加密格式发送到服务器。去年还做了企业微信的消息推送解密。真的,虽然感觉差不多,但是如果用同样的代码,三个完全不能复用,但是你做了一个之后,再做别的,就明白他的原理了。我正在github上逐节点完善微信各种API的配置和使用。所有的源代码都在https://github.com/zzz111111/wx_app的地址里,并且使用了express框架。
事实上,xml格式的解密类似于json格式,只是express框架的一些问题影响了我们。在使用body-parser中间件后,json格式的数据将被添加到req.body中,但是在xml格式中,我们一般不使用其他中间件将xml格式的数据添加到req.body中.在这里,我使用express-xml-bodyparser中间件来解析出xml,或者我可以不使用这些中间件,直接使用本机代码来获取数据。
使用中间件的代码。
1 const XML parser=require(' express-XML-body parser ');
2
3 app . use(xmlparser());/*添加用于解析微信的xml格式文件*/
四
五
6 router.post('/your address ',(req,res)={
7 console.log('在请求url中收到');
8 console . log(req . query);
9 console.log('收到请求,在请求正文中');
10 console . log(req . body);
11 });
不用中间件就可以得到。之所以写这个,是因为同事用koa2框架,找不到解析xml格式的中间件,所以后来在网上找了一些资料,自己写了一个。
刚才,在测试过程中,我找到了所请求的内容在本机req对象上的位置。我也是天才。Koa2框架。
1 router.post('/xml ',async ctx={
2 console.log('请求xml接口');
三
4 console . log(CTX . req . readablestate . buffer);
5 console.log('其他内容-head ');
6 var buf 1=CTX . req . _ readablestate . buffer . head . data;
7 console . log(buf 1);
8控制台. log(新缓冲区(buf1)。toString());
9 console.log('其他内容-tail ');
10 var buf 2=CTX . req . _ readablestate . buffer . tail . data;
11 console . log(buf 2);
12 console.log(新缓冲区(buf2)。toString());
13 ctx.body=' xml
14 })
Buffer对象转换的两个对象都是xml格式的对象。
这里,xml格式的内容仍然是一个字符串,所以我们首先以正常的方式获取请求体中的内容,然后解析它。
以上纯属扯淡。一般在我们属性的名字前面加一个_(也就是下划线),表示这个东西不想被外界访问,所以由正常人操作。正常得到。
1路由器. post('/xmlTest ',async ctx={
2 console.log('请求xml接口');
3 var数据=' ';
4 ctx.req.on('data ',(chunk)={
5 data=chunk
6 });
7 ctx.req.on('end ',()={
8 console.log('数据传输结束');
9 console.log(数据);
10 });
11 ctx.body=' xml
12 });
这是我向他要的。
只有这样才能正常得到请求的xml格式,然后我们用xml2js模块解析,转换成json格式对象。
npm i -S xml2js
xml到json和json到xml的方法
1 const xml={
2 xmlToJson(str){
3返回新承诺((解决,拒绝)={
4 const ParseString=xml2js . ParseString
5 parseString(str,(err,result)={
6 if (err) {
7拒绝(错误)
8 }其他{
9解决(结果)
10 }
11 })
12 })
13 },
14 JSontXMl(){
15 const builder=new xml2js。建设者()
16 return builder . BuildObject(obj)
17 }
18
19 }
我们可以使用koa2,洋葱模型,在前面的方法中解析xml文件,并把它放在ctx.req.body之上来访问它。
1路由器. post('/xml2 ',async (ctx,next)={
2 if(CTX . method==' POST ' CTX . is(' text/XML '){
3让承诺=新承诺(功能(解决,拒绝){
4让buf=' '
5 ctx.req.setEncoding('utf8 ')
6 ctx.req.on('data ',(chunk)={
7 console.log('接收数据');
八
9 console . log(chunk);
10 buf=chunk
11
12 })
13 ctx.req.on('end ',()={
14 xml.xmlToJson(buf)
15 .然后(解决)
16 .捕捉(拒绝)
17 })
18 })
19
20等待承诺
21 ctx.req.body=结果
22 })
23 .catch((e)={
24 e.status=400
25 })
26
27下一个()
28 }其他{
29等待下一个()
30 }
31 },异步ctx={
32 console . log(CTX . req . body);
33
34 console . log(CTX . req . body . XML . TouseName[0])
35 ctx.body='第二次返回信息';
36 });
以上可以解析,xml格式转换成json对象。
本文的主题是解析微信推送的xml消息。不能跑题。以上都是铺垫和基础。当时,因为我们无法获得xml数据,我们搜索了很长时间。express将直接安装上面提到的中间件。koa2可以自己写,也可以得到。
八卦就不多说了,拿到手后和json格式没什么区别,可以看看json格式的解析。
因为我用的是express框架,把方法列表分开,所以可以把代码发出去,去我的github上看看详细情况,地址也给了。
1 /**
2 *这里的方法解析微信消息加密的XML格式
3 *
4 *流程介绍如下
5 * 1.首先获取消息网址中的字符串,然后获取消息正文中的秘密样式
6 * 2.验证微信对URL和密式提供的加密方式是否等于消息体签名,验证消息是否由微信转发
7 * 3.步骤2验证成功后,对微信消息进行解密,解密功能在工具功能中
8 *
9 *网址中的内容
10 *
11 * @params {String}签名字符串
12 * @params {String}时间戳时间戳
13 * @params {String}随机数随机字符串
14 * @params {String} encrypt_type加密类型(aes)
15 * @params {String} openid
16 * @ params { string } msg _ signature消息正文签名。用于验证消息正文的正确性
17 *
18 *请求正文中的内容-解析后
用户名小程序的原始id的19 * @ params {string}
20 * @params {String}加密加密的消息字符串
21 *
22 */
23 exports . handlecustomerserverxML=(req,res)={
24 console.log('在请求url中收到');
25 console . log(req . query);
26 console.log('收到请求,在请求正文中');
27 console . log(req . body);
28 const {signature,timestamp,nonce,encrypt_type,openid,msg _ signature }=req.query
29 const msg _ encrypt=req . body . XML . encrypt[0];
30
31 //验证消息的正确性
32 const dev _ msg _ signature=sha1(config . PushToken,timestamp,nonce,msg _ encrypt);
33 if(dev _ msg _ signature==msg _ signature){
34 //签名消息正确,从微信服务器解密
35 const LastData=utils . DecryptXMl({
36 AES key : config . server . encoding AES key,
37文本:消息_加密,
38 corpid: config.app.appId
39 });
40 console . log(' msg函数中接收的数据内容');
41
42 console . log(LastData);
43 console.log('收到的消息是-' last data . msg . XML . content[0]);
四十四
45 var msgArr={
46 '新年快乐' : '祝你新年快乐',
47 '值班' : '我今天不上班,你值得你m ',
48' Hello' :' Hello ',
49 '什么' : '你在说什么'
50 };
51 var replyMsg=MsGarr[LastData . msg . XML . content[0]];
52 if(replyMsg){
53 ZY.msg.textMsg(openid,openid,replyMsg)
54 .然后(res={
55控制台. log('消息发送成功!');
56 console . log(RES);
57 })
58 .catch(err={
59 console.log('消息发送失败');
60 console . log(err);
61 })
62 }else{
63 ZY.msg.textMsg(openid,openid,'看你在说什么?')
64 .然后(res={
65控制台. log('消息发送成功!');
66 console . log(RES);
67 })
68 .catch(err={
69 console.log('消息发送失败');
70控制台。log(err);
71 })
72 }
73 res.send('成功');
74 }其他{
75 console.log('非微信服务器试图发送消息给我!');
76 res.send('你在玩啥呢?');
77 }
78 }
sha1方法
1 /*
2 @解释sh1加密
3 @ 1 .0 .一版
四
5 @作者: Z
6 @data : 2019-2-13
七
8 @params {String,String.} a、b、c……
9 @return {String}加密完成后的字符串
10 */
11出口. sha1=函数(.arr) {
12返回crypto.createHash('sha1 ').update(arr.sort().join(').摘要(' hex ');
13 };
只针对于可扩展标记语言格式的解析方法。
1 /**
2 * 解析微信上传消息此方法只解析可扩展置标语言格式
3 * @ 1 .0 .0版
4 * @数据2019-3-21
5 *
6 * @参数{对象}
7 * obj .AESKey:解密的aesKey值
8 * obj.text:需要解密的密文
9 * obj.corpid:企业的id /微信小程序的应用编号
10 *
11 * @返回{对象}
12 * obj.noncestr随机数
13 * obj.msg_len微信密文的低输入联网(低入门网络的缩写)
14 * obj.msg解密后的明文数据格式
15 * obj.corpid错乱的应用编号尾部填充了些东西,可以舍弃,因为我们知道自己的应用编号是多少,不需要这里告诉我们
16 *
17 */
18出口。decryptXMl=函数(obj){
19让aesKey=Buffer.from(obj .AESKey '=',' base64 ');
20 const CircuIt编码=' base64
21 const clearEncoding=' utf8
22常量密码=加密。createdecidepheriv(' AES-256-CBC ',aesKey,aesKey.slice(0,16));
23密码。setautopadding(false);//是否取消自动填充不取消
24让this _ text=密码。更新(obj。文本、密码编码、明文编码)。final(clearEncoding);
25让xmlText=
26 xml2js。ParseString(this _ text。substring(20,this _ text。'(1)的最后一个索引,函数(错误,结果){
27 if(err)throw err;
28 xmlText=结果;
29 });
30返回{
31 noncrest : thi _ text。子串(0,16),
32 msg _ len : this _ text。子串(16,20),
33 msg:xmlText,
34 corpid : this _ text。substring(this _ text。'(1)的最后一个索引
35 }
36 }
放到服务器上面的打印是这样的。
那些看不到的信息,可以在加密的函数中打印看到到底返回来什么。
回复的消息图。
11
2022-05
28
2021-08
16
2021-06
16
2021-06
16
2021-06
16
2021-06