/
utils.ts
129 lines (120 loc) · 2.8 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import * as buffer from "buffer";
import * as crypto from "crypto";
import * as getRawBody from "raw-body";
import * as stream from "stream";
import * as xml2js from "xml2js";
import * as types from "./types";
/**
* 生成随机字符串
*/
export function nonceStr(length: number = 32): string {
const chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
const len = chars.length;
let result = "";
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * len));
}
return result;
}
/**
* 转换成 XML 格式
*/
export function toXML(data: any): string {
const builder = new xml2js.Builder({
rootName: "xml",
headless: true
});
return builder.buildObject(data);
}
/**
* 从 XML 格式字符串生成对象
*/
export function fromXML<T>(data: string) {
const parser = new xml2js.Parser({
trim: true,
explicitArray: false,
explicitRoot: false
});
return new Promise<T>((resolve, reject) => {
parser.parseString(data, (err, ret) => {
if (err) {
return reject(err);
}
resolve(<T> ret);
});
});
}
/**
* 签名
*/
export function sign(signType: types.SignType, data: object, secret: string) {
const combined =
Object.keys(data)
.filter(
key =>
key !== "sign" &&
data.hasOwnProperty(key) &&
data[key] !== undefined &&
data[key] !== null &&
data[key] !== ""
)
.sort()
.map(key => key + "=" + data[key])
.join("&") +
"&key=" +
secret;
if (signType === types.SignType.MD5) {
return md5(combined).toUpperCase();
} else {
return hmacSha256(secret, combined).toUpperCase();
}
}
/**
* md5 加密
*/
export function md5(data: string): string {
return crypto
.createHash("md5")
.update(data)
.digest("hex");
}
/**
* HMAC-SHA256 加密
*/
export function hmacSha256(secret: string, data: string): string {
return crypto
.createHmac("sha256", secret)
.update(data)
.digest("hex");
}
/**
* RSA 加密
*/
export function rsa(pemKey: string, data: string) {
return crypto
.publicEncrypt(pemKey, buffer.Buffer.from(data))
.toString("base64");
}
/**
* 解密
*/
export function decode(key: string, data: string) {
const secret = md5(key).toLowerCase();
const decipher = crypto.createDecipheriv("aes-256-ecb", secret, "");
decipher.setAutoPadding(true);
const decipherChunks = [];
decipherChunks.push(decipher.update(data, "base64", "utf8"));
decipherChunks.push(decipher.final("utf8"));
return decipherChunks.join("");
}
/**
* 从请求中获取 xml 数据并解析
*/
export async function getXMLBody(
req: stream.Readable,
options: getRawBody.Options
) {
const rawData = await getRawBody(req, options);
return fromXML(rawData.toString("utf8"));
}