node-easywechat 3.5.9 → 3.5.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/Core/Http/Contracts/ServerRequestInterface.d.ts +1 -1
- package/dist/Core/Http/Minxins/MessageMixin.js +2 -1
- package/dist/Core/Http/ServerRequest.d.ts +3 -3
- package/dist/Core/Http/ServerRequest.js +29 -26
- package/dist/Core/Mixins/HandlersMixin.d.ts +10 -10
- package/dist/OfficialAccount/Server.d.ts +11 -3
- package/dist/OpenPlatform/Server.d.ts +15 -7
- package/dist/OpenWork/Server.d.ts +25 -17
- package/dist/Pay/Application.d.ts +0 -5
- package/dist/Pay/Application.js +1 -34
- package/dist/Pay/Contracts/MerchantInterface.d.ts +18 -4
- package/dist/Pay/Contracts/MerchantInterface.js +16 -2
- package/dist/Pay/Contracts/ValidatorInterface.d.ts +1 -1
- package/dist/Pay/Contracts/ValidatorInterface.js +1 -1
- package/dist/Pay/Merchant.d.ts +9 -3
- package/dist/Pay/Merchant.js +59 -3
- package/dist/Pay/Server.d.ts +12 -2
- package/dist/Pay/Server.js +50 -21
- package/dist/Pay/Signature.d.ts +3 -1
- package/dist/Pay/Signature.js +21 -3
- package/dist/Pay/Validator.d.ts +1 -1
- package/dist/Pay/Validator.js +38 -27
- package/dist/Work/Server.d.ts +8 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v3.5.11 (2023-12-19)
|
|
5
|
+
|
|
6
|
+
- Fix: 微信支付获取平台证书优化为随用随获取的方式,并增加缓存 (#57)
|
|
7
|
+
- Fix: 修复微信支付请求无参数时,签名计算异常的问题 (#60)
|
|
8
|
+
|
|
9
|
+
## v3.5.10 (2023-12-19)
|
|
10
|
+
|
|
11
|
+
- Feat: 微信支付通知处理增加v2接口xml格式的消息处理 (#56)
|
|
12
|
+
|
|
13
|
+
- Fix: 修复计算v3签名时请求的querystring参数丢失导致签名错误的问题 (#60)
|
|
14
|
+
- Fix: 修复回调方法的消息类型推到错误的问题
|
|
15
|
+
- Fix: 修复获取平台证书时,响应数据解析异常的问题 (#57)
|
|
16
|
+
|
|
4
17
|
## v3.5.9 (2023-12-18)
|
|
5
18
|
|
|
6
19
|
- Feat: 微信支付增加读取平台证书的方法loadPlatformCerts,并自动写入商户配置 (#57)
|
|
@@ -17,9 +17,9 @@ declare class ServerRequest implements ServerRequestInterface {
|
|
|
17
17
|
constructor(method: string, url: string, headers?: Record<string, any>, body?: Buffer | Record<string, any> | string, version?: string, serverParams?: Record<string, any>);
|
|
18
18
|
/**
|
|
19
19
|
* 解析 body 内容
|
|
20
|
-
*
|
|
20
|
+
* 支持 JSON字符串、XML字符串、QueryString等格式
|
|
21
21
|
*/
|
|
22
|
-
protected parseBody(
|
|
22
|
+
protected parseBody(): Promise<void>;
|
|
23
23
|
getServerParams(): Record<string, any>;
|
|
24
24
|
getCookieParams(): Record<string, any>;
|
|
25
25
|
withCookieParams(cookies: Record<string, any>): this;
|
|
@@ -27,7 +27,7 @@ declare class ServerRequest implements ServerRequestInterface {
|
|
|
27
27
|
withQueryParams(query: Record<string, any>): this;
|
|
28
28
|
getUploadedFiles(): Record<string, any>;
|
|
29
29
|
withUploadedFiles(files: Record<string, any>): this;
|
|
30
|
-
getParsedBody(): Record<string, any
|
|
30
|
+
getParsedBody(): Promise<Record<string, any>>;
|
|
31
31
|
withParsedBody(data: Record<string, any>): this;
|
|
32
32
|
getAttributes(): Record<string, any>;
|
|
33
33
|
getAttribute(name: string, defaultValue?: any): any;
|
|
@@ -35,42 +35,40 @@ class ServerRequest {
|
|
|
35
35
|
.withProtocolVersion(version)
|
|
36
36
|
.withQueryParams((0, url_1.parse)(url, true).query || {});
|
|
37
37
|
if (body) {
|
|
38
|
-
this.
|
|
38
|
+
this.withBody(body);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* 解析 body 内容
|
|
43
|
-
*
|
|
43
|
+
* 支持 JSON字符串、XML字符串、QueryString等格式
|
|
44
44
|
*/
|
|
45
|
-
parseBody(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
this.content = Buffer.from(JSON.stringify(body));
|
|
53
|
-
this.headers['content-type'] = 'application/json';
|
|
54
|
-
}
|
|
55
|
-
else if (typeof body === 'string') {
|
|
56
|
-
try {
|
|
57
|
-
this.parsedBody = JSON.parse(body);
|
|
58
|
-
this.headers['content-type'] = 'application/json';
|
|
45
|
+
parseBody() {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
let body = this.content.toString();
|
|
48
|
+
if (body.startsWith('<xml')) {
|
|
49
|
+
let res = yield (0, Utils_1.parseXml)(body);
|
|
50
|
+
this.parsedBody = res;
|
|
51
|
+
this.headers['content-type'] = 'text/xml';
|
|
59
52
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.headers['content-type'] = 'text/xml';
|
|
65
|
-
});
|
|
53
|
+
else if (body.startsWith('{') || body.startsWith('[')) {
|
|
54
|
+
try {
|
|
55
|
+
this.parsedBody = JSON.parse(body);
|
|
56
|
+
this.headers['content-type'] = 'application/json';
|
|
66
57
|
}
|
|
67
|
-
|
|
58
|
+
catch (e) {
|
|
59
|
+
this.parsedBody = {};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
try {
|
|
68
64
|
this.parsedBody = (0, Utils_1.parseQueryString)(body);
|
|
69
65
|
this.headers['content-type'] = 'application/x-www-form-urlencoded';
|
|
70
66
|
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
this.parsedBody = {};
|
|
69
|
+
}
|
|
71
70
|
}
|
|
72
|
-
|
|
73
|
-
}
|
|
71
|
+
});
|
|
74
72
|
}
|
|
75
73
|
getServerParams() {
|
|
76
74
|
return this.serverParams;
|
|
@@ -97,7 +95,12 @@ class ServerRequest {
|
|
|
97
95
|
return this;
|
|
98
96
|
}
|
|
99
97
|
getParsedBody() {
|
|
100
|
-
return this
|
|
98
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
if (!this.parsedBody || Object.keys(this.parsedBody).length === 0) {
|
|
100
|
+
yield this.parseBody();
|
|
101
|
+
}
|
|
102
|
+
return this.parsedBody;
|
|
103
|
+
});
|
|
101
104
|
}
|
|
102
105
|
withParsedBody(data) {
|
|
103
106
|
this.parsedBody = merge_1.default.recursive(true, data);
|
|
@@ -12,56 +12,56 @@ declare class HandlersMixin {
|
|
|
12
12
|
* @param handler
|
|
13
13
|
* @returns
|
|
14
14
|
*/
|
|
15
|
-
createHandlerItem(handler: ServerHandlerClosure): ServerHandlerItem;
|
|
15
|
+
createHandlerItem(handler: ServerHandlerClosure<Message>): ServerHandlerItem;
|
|
16
16
|
/**
|
|
17
17
|
* 计算处理器hash
|
|
18
18
|
* @param handler
|
|
19
19
|
* @returns
|
|
20
20
|
*/
|
|
21
|
-
protected getHandlerHash(handler: ServerHandlerClosure): string;
|
|
21
|
+
protected getHandlerHash(handler: ServerHandlerClosure<Message>): string;
|
|
22
22
|
/**
|
|
23
23
|
* @alias withHandler()
|
|
24
24
|
*/
|
|
25
|
-
with(handler: ServerHandlerClosure): this;
|
|
25
|
+
with(handler: ServerHandlerClosure<Message>): this;
|
|
26
26
|
/**
|
|
27
27
|
* 从最后添加处理器
|
|
28
28
|
* @param handler
|
|
29
29
|
* @returns
|
|
30
30
|
*/
|
|
31
|
-
withHandler(handler: ServerHandlerClosure): this;
|
|
31
|
+
withHandler(handler: ServerHandlerClosure<Message>): this;
|
|
32
32
|
/**
|
|
33
33
|
* @alias prependHandler()
|
|
34
34
|
*/
|
|
35
|
-
prepend(handler: ServerHandlerClosure): this;
|
|
35
|
+
prepend(handler: ServerHandlerClosure<Message>): this;
|
|
36
36
|
/**
|
|
37
37
|
* 从最前添加处理器
|
|
38
38
|
* @param handler
|
|
39
39
|
* @returns
|
|
40
40
|
*/
|
|
41
|
-
prependHandler(handler: ServerHandlerClosure): this;
|
|
41
|
+
prependHandler(handler: ServerHandlerClosure<Message>): this;
|
|
42
42
|
/**
|
|
43
43
|
* @alias withoutHandler()
|
|
44
44
|
*/
|
|
45
|
-
without(handler: ServerHandlerClosure): this;
|
|
45
|
+
without(handler: ServerHandlerClosure<Message>): this;
|
|
46
46
|
/**
|
|
47
47
|
* 删除处理器
|
|
48
48
|
* @param handler
|
|
49
49
|
* @returns
|
|
50
50
|
*/
|
|
51
|
-
withoutHandler(handler: ServerHandlerClosure): this;
|
|
51
|
+
withoutHandler(handler: ServerHandlerClosure<Message>): this;
|
|
52
52
|
/**
|
|
53
53
|
* 获取处理器的索引
|
|
54
54
|
* @param handler
|
|
55
55
|
* @returns
|
|
56
56
|
*/
|
|
57
|
-
indexOf(handler: ServerHandlerClosure): number;
|
|
57
|
+
indexOf(handler: ServerHandlerClosure<Message>): number;
|
|
58
58
|
/**
|
|
59
59
|
* 当 value 为true或者返回true时,添加处理器
|
|
60
60
|
* @param value
|
|
61
61
|
* @param handler
|
|
62
62
|
* @returns
|
|
63
63
|
*/
|
|
64
|
-
when(value: boolean | Function | Promise<boolean>, handler: ServerHandlerClosure): this;
|
|
64
|
+
when(value: boolean | Function | Promise<boolean>, handler: ServerHandlerClosure<Message>): this;
|
|
65
65
|
/**
|
|
66
66
|
* 执行处理器
|
|
67
67
|
* @param result
|
|
@@ -19,20 +19,28 @@ declare class Server extends ServerInterface {
|
|
|
19
19
|
* @param handler
|
|
20
20
|
* @returns
|
|
21
21
|
*/
|
|
22
|
-
addMessageListener(type: ServerMessageType, handler: ServerHandlerClosure): this;
|
|
22
|
+
addMessageListener(type: ServerMessageType, handler: ServerHandlerClosure<Message>): this;
|
|
23
23
|
/**
|
|
24
24
|
* 添加事件消息处理器
|
|
25
25
|
* @param event
|
|
26
26
|
* @param handler
|
|
27
27
|
* @returns
|
|
28
28
|
*/
|
|
29
|
-
addEventListener(event: ServerEventType, handler: ServerHandlerClosure): this;
|
|
29
|
+
addEventListener(event: ServerEventType, handler: ServerHandlerClosure<Message>): this;
|
|
30
30
|
/**
|
|
31
31
|
* 获取来自微信服务器的推送消息
|
|
32
32
|
* @param request 未设置该参数时,则从当前服务端收到的请求中获取
|
|
33
33
|
* @returns
|
|
34
34
|
*/
|
|
35
35
|
getRequestMessage(request?: ServerRequestInterface): Promise<Message>;
|
|
36
|
-
protected decryptRequestMessage(query: Record<string, any>): ServerHandlerClosure
|
|
36
|
+
protected decryptRequestMessage(query: Record<string, any>): ServerHandlerClosure<Message>;
|
|
37
|
+
}
|
|
38
|
+
interface Server {
|
|
39
|
+
with(next: ServerHandlerClosure<Message>): this;
|
|
40
|
+
withHandler(next: ServerHandlerClosure<Message>): this;
|
|
41
|
+
prepend(next: ServerHandlerClosure<Message>): this;
|
|
42
|
+
prependHandler(next: ServerHandlerClosure<Message>): this;
|
|
43
|
+
without(next: ServerHandlerClosure<Message>): this;
|
|
44
|
+
withoutHandler(next: ServerHandlerClosure<Message>): this;
|
|
37
45
|
}
|
|
38
46
|
export = Server;
|
|
@@ -7,7 +7,7 @@ import { ServerHandlerClosure } from '../Types/global';
|
|
|
7
7
|
declare class Server extends ServerInterface {
|
|
8
8
|
protected encryptor: Encryptor;
|
|
9
9
|
protected request: ServerRequestInterface;
|
|
10
|
-
protected defaultVerifyTicketHandler: ServerHandlerClosure
|
|
10
|
+
protected defaultVerifyTicketHandler: ServerHandlerClosure<Message>;
|
|
11
11
|
constructor(encryptor: Encryptor, request?: ServerRequestInterface);
|
|
12
12
|
/**
|
|
13
13
|
* 服务端消息处理
|
|
@@ -19,32 +19,32 @@ declare class Server extends ServerInterface {
|
|
|
19
19
|
* @param handler
|
|
20
20
|
* @returns
|
|
21
21
|
*/
|
|
22
|
-
handleAuthorized(handler: ServerHandlerClosure): this;
|
|
22
|
+
handleAuthorized(handler: ServerHandlerClosure<Message>): this;
|
|
23
23
|
/**
|
|
24
24
|
* 处理取消授权通知
|
|
25
25
|
* @param handler
|
|
26
26
|
* @returns
|
|
27
27
|
*/
|
|
28
|
-
handleUnauthorized(handler: ServerHandlerClosure): this;
|
|
28
|
+
handleUnauthorized(handler: ServerHandlerClosure<Message>): this;
|
|
29
29
|
/**
|
|
30
30
|
* 处理授权更新通知
|
|
31
31
|
* @param handler
|
|
32
32
|
* @returns
|
|
33
33
|
*/
|
|
34
|
-
handleAuthorizeUpdated(handler: ServerHandlerClosure): this;
|
|
34
|
+
handleAuthorizeUpdated(handler: ServerHandlerClosure<Message>): this;
|
|
35
35
|
/**
|
|
36
36
|
* 设置默认的验证票据通知处理回调
|
|
37
37
|
* @param handler
|
|
38
38
|
* @returns
|
|
39
39
|
*/
|
|
40
|
-
withDefaultVerifyTicketHandler(handler: ServerHandlerClosure): void;
|
|
40
|
+
withDefaultVerifyTicketHandler(handler: ServerHandlerClosure<Message>): void;
|
|
41
41
|
/**
|
|
42
42
|
* 处理验证票据通知
|
|
43
43
|
* @param handler
|
|
44
44
|
* @returns
|
|
45
45
|
*/
|
|
46
|
-
handleVerifyTicketRefreshed(handler: ServerHandlerClosure): this;
|
|
47
|
-
protected decryptRequestMessage(): ServerHandlerClosure
|
|
46
|
+
handleVerifyTicketRefreshed(handler: ServerHandlerClosure<Message>): this;
|
|
47
|
+
protected decryptRequestMessage(): ServerHandlerClosure<Message>;
|
|
48
48
|
/**
|
|
49
49
|
* 获取来自微信服务器的推送消息
|
|
50
50
|
* @param request 未设置该参数时,则从当前服务端收到的请求中获取
|
|
@@ -58,4 +58,12 @@ declare class Server extends ServerInterface {
|
|
|
58
58
|
*/
|
|
59
59
|
getDecryptedMessage(request?: ServerRequestInterface): Promise<Message>;
|
|
60
60
|
}
|
|
61
|
+
interface Server {
|
|
62
|
+
with(next: ServerHandlerClosure<Message>): this;
|
|
63
|
+
withHandler(next: ServerHandlerClosure<Message>): this;
|
|
64
|
+
prepend(next: ServerHandlerClosure<Message>): this;
|
|
65
|
+
prependHandler(next: ServerHandlerClosure<Message>): this;
|
|
66
|
+
without(next: ServerHandlerClosure<Message>): this;
|
|
67
|
+
withoutHandler(next: ServerHandlerClosure<Message>): this;
|
|
68
|
+
}
|
|
61
69
|
export = Server;
|
|
@@ -8,91 +8,91 @@ declare class Server extends ServerInterface {
|
|
|
8
8
|
protected encryptor: Encryptor;
|
|
9
9
|
protected providerEncryptor: Encryptor;
|
|
10
10
|
protected request: ServerRequestInterface;
|
|
11
|
-
protected defaultSuiteTicketHandler: ServerHandlerClosure
|
|
11
|
+
protected defaultSuiteTicketHandler: ServerHandlerClosure<Message>;
|
|
12
12
|
constructor(encryptor: Encryptor, providerEncryptor: Encryptor, request?: ServerRequestInterface);
|
|
13
13
|
/**
|
|
14
14
|
* 服务端消息处理
|
|
15
15
|
* @returns
|
|
16
16
|
*/
|
|
17
17
|
serve(): Promise<Response>;
|
|
18
|
-
withDefaultSuiteTicketHandler(handler: ServerHandlerClosure): this;
|
|
18
|
+
withDefaultSuiteTicketHandler(handler: ServerHandlerClosure<Message>): this;
|
|
19
19
|
/**
|
|
20
20
|
* 设置联系人变化的消息处理器
|
|
21
21
|
* @param handler
|
|
22
22
|
*/
|
|
23
|
-
handleSuiteTicketRefreshed(handler: ServerHandlerClosure): this;
|
|
23
|
+
handleSuiteTicketRefreshed(handler: ServerHandlerClosure<Message>): this;
|
|
24
24
|
/**
|
|
25
25
|
* 设置授权成功的消息处理器
|
|
26
26
|
* @param handler
|
|
27
27
|
*/
|
|
28
|
-
handleAuthCreated(handler: ServerHandlerClosure): this;
|
|
28
|
+
handleAuthCreated(handler: ServerHandlerClosure<Message>): this;
|
|
29
29
|
/**
|
|
30
30
|
* 设置变更授权的消息处理器
|
|
31
31
|
* @param handler
|
|
32
32
|
*/
|
|
33
|
-
handleAuthUpdated(handler: ServerHandlerClosure): this;
|
|
33
|
+
handleAuthUpdated(handler: ServerHandlerClosure<Message>): this;
|
|
34
34
|
/**
|
|
35
35
|
* 设置取消授权的消息处理器
|
|
36
36
|
* @param handler
|
|
37
37
|
*/
|
|
38
|
-
handleAuthCancelled(handler: ServerHandlerClosure): this;
|
|
38
|
+
handleAuthCancelled(handler: ServerHandlerClosure<Message>): this;
|
|
39
39
|
/**
|
|
40
40
|
* 设置用户创建的消息处理器
|
|
41
41
|
* @param handler
|
|
42
42
|
*/
|
|
43
|
-
handleUserCreated(handler: ServerHandlerClosure): this;
|
|
43
|
+
handleUserCreated(handler: ServerHandlerClosure<Message>): this;
|
|
44
44
|
/**
|
|
45
45
|
* 设置用户更新的消息处理器
|
|
46
46
|
* @param handler
|
|
47
47
|
*/
|
|
48
|
-
handleUserUpdated(handler: ServerHandlerClosure): this;
|
|
48
|
+
handleUserUpdated(handler: ServerHandlerClosure<Message>): this;
|
|
49
49
|
/**
|
|
50
50
|
* 设置用户删除的消息处理器
|
|
51
51
|
* @param handler
|
|
52
52
|
*/
|
|
53
|
-
handleUserDeleted(handler: ServerHandlerClosure): this;
|
|
53
|
+
handleUserDeleted(handler: ServerHandlerClosure<Message>): this;
|
|
54
54
|
/**
|
|
55
55
|
* 设置部门创建的消息处理器
|
|
56
56
|
* @param handler
|
|
57
57
|
*/
|
|
58
|
-
handlePartyCreated(handler: ServerHandlerClosure): this;
|
|
58
|
+
handlePartyCreated(handler: ServerHandlerClosure<Message>): this;
|
|
59
59
|
/**
|
|
60
60
|
* 设置部门更新的消息处理器
|
|
61
61
|
* @param handler
|
|
62
62
|
*/
|
|
63
|
-
handlePartyUpdated(handler: ServerHandlerClosure): this;
|
|
63
|
+
handlePartyUpdated(handler: ServerHandlerClosure<Message>): this;
|
|
64
64
|
/**
|
|
65
65
|
* 设置部门删除的消息处理器
|
|
66
66
|
* @param handler
|
|
67
67
|
*/
|
|
68
|
-
handlePartyDeleted(handler: ServerHandlerClosure): this;
|
|
68
|
+
handlePartyDeleted(handler: ServerHandlerClosure<Message>): this;
|
|
69
69
|
/**
|
|
70
70
|
* 设置用户标签变化的消息处理器
|
|
71
71
|
* @param handler
|
|
72
72
|
*/
|
|
73
|
-
handleUserTagUpdated(handler: ServerHandlerClosure): this;
|
|
73
|
+
handleUserTagUpdated(handler: ServerHandlerClosure<Message>): this;
|
|
74
74
|
/**
|
|
75
75
|
* 设置共享应用事件的消息处理器
|
|
76
76
|
* @param handler
|
|
77
77
|
*/
|
|
78
|
-
handleShareAgentChanged(handler: ServerHandlerClosure): this;
|
|
78
|
+
handleShareAgentChanged(handler: ServerHandlerClosure<Message>): this;
|
|
79
79
|
/**
|
|
80
80
|
* 设置重置永久授权码的消息处理器
|
|
81
81
|
* @param handler
|
|
82
82
|
*/
|
|
83
|
-
handleResetPermanentCode(handler: ServerHandlerClosure): this;
|
|
83
|
+
handleResetPermanentCode(handler: ServerHandlerClosure<Message>): this;
|
|
84
84
|
/**
|
|
85
85
|
* 设置应用管理员变更的消息处理器
|
|
86
86
|
* @param handler
|
|
87
87
|
*/
|
|
88
|
-
handleChangeAppAdmin(handler: ServerHandlerClosure): this;
|
|
88
|
+
handleChangeAppAdmin(handler: ServerHandlerClosure<Message>): this;
|
|
89
89
|
/**
|
|
90
90
|
* 获取来自微信服务器的推送消息
|
|
91
91
|
* @param request 未设置该参数时,则从当前服务端收到的请求中获取
|
|
92
92
|
* @returns
|
|
93
93
|
*/
|
|
94
94
|
getRequestMessage(request?: ServerRequestInterface): Promise<Message>;
|
|
95
|
-
protected decryptRequestMessage(query: Record<string, any>): ServerHandlerClosure
|
|
95
|
+
protected decryptRequestMessage(query: Record<string, any>): ServerHandlerClosure<Message>;
|
|
96
96
|
/**
|
|
97
97
|
* 获取解密后的消息
|
|
98
98
|
* @param request 未设置该参数时,则从当前服务端收到的请求中获取
|
|
@@ -100,4 +100,12 @@ declare class Server extends ServerInterface {
|
|
|
100
100
|
*/
|
|
101
101
|
getDecryptedMessage(request?: ServerRequestInterface): Promise<import("../Core/Message")>;
|
|
102
102
|
}
|
|
103
|
+
interface Server {
|
|
104
|
+
with(next: ServerHandlerClosure<Message>): this;
|
|
105
|
+
withHandler(next: ServerHandlerClosure<Message>): this;
|
|
106
|
+
prepend(next: ServerHandlerClosure<Message>): this;
|
|
107
|
+
prependHandler(next: ServerHandlerClosure<Message>): this;
|
|
108
|
+
without(next: ServerHandlerClosure<Message>): this;
|
|
109
|
+
withoutHandler(next: ServerHandlerClosure<Message>): this;
|
|
110
|
+
}
|
|
103
111
|
export = Server;
|
|
@@ -60,11 +60,6 @@ declare class Application implements ApplicationInterface {
|
|
|
60
60
|
* @returns
|
|
61
61
|
*/
|
|
62
62
|
protected getHttpClientDefaultOptions(): Record<string, any>;
|
|
63
|
-
/**
|
|
64
|
-
* 如果未配置平台证书,则尝试从接口读取
|
|
65
|
-
* @param force 是否强制读取,默认:false
|
|
66
|
-
*/
|
|
67
|
-
loadPlatformCerts(force?: boolean): Promise<void>;
|
|
68
63
|
}
|
|
69
64
|
interface Application extends ConfigMixin, CacheMixin, ServerRequestMixin, HttpClientMixin {
|
|
70
65
|
}
|
package/dist/Pay/Application.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -24,8 +15,6 @@ const Utils_2 = __importDefault(require("./Utils"));
|
|
|
24
15
|
const Config_1 = __importDefault(require("../OfficialAccount/Config"));
|
|
25
16
|
const Client_1 = __importDefault(require("./Client"));
|
|
26
17
|
const Validator_1 = __importDefault(require("./Validator"));
|
|
27
|
-
const PublicKey_1 = require("../Core/Support/PublicKey");
|
|
28
|
-
const AES_1 = require("../Core/Support/AES");
|
|
29
18
|
/**
|
|
30
19
|
* 微信支付应用
|
|
31
20
|
*/
|
|
@@ -47,7 +36,7 @@ class Application {
|
|
|
47
36
|
getMerchant() {
|
|
48
37
|
var _a;
|
|
49
38
|
if (!this.merchant) {
|
|
50
|
-
this.merchant = new Merchant_1.default(this.config.get('mch_id'), this.config.get('private_key'), this.config.get('certificate'), this.config.get('secret_key'), this.config.get('v2_secret_key'), (_a = this.config.get('platform_certs')) !== null && _a !== void 0 ? _a : []);
|
|
39
|
+
this.merchant = new Merchant_1.default(this.config.get('mch_id'), this.config.get('private_key'), this.config.get('certificate'), this.config.get('secret_key'), this.config.get('v2_secret_key'), (_a = this.config.get('platform_certs')) !== null && _a !== void 0 ? _a : [], this);
|
|
51
40
|
}
|
|
52
41
|
return this.merchant;
|
|
53
42
|
}
|
|
@@ -128,28 +117,6 @@ class Application {
|
|
|
128
117
|
baseURL: 'https://api.mch.weixin.qq.com',
|
|
129
118
|
}, this.getConfig().get('http'));
|
|
130
119
|
}
|
|
131
|
-
/**
|
|
132
|
-
* 如果未配置平台证书,则尝试从接口读取
|
|
133
|
-
* @param force 是否强制读取,默认:false
|
|
134
|
-
*/
|
|
135
|
-
loadPlatformCerts(force = false) {
|
|
136
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
137
|
-
let exists_certs = this.config.get('platform_certs', []);
|
|
138
|
-
if (force || !exists_certs || exists_certs.length === 0) {
|
|
139
|
-
let response = yield this.getClient().get('/v3/certificates');
|
|
140
|
-
let data = response.toObject();
|
|
141
|
-
if (data && data.length > 0) {
|
|
142
|
-
let certs = {};
|
|
143
|
-
let key = this.config.get('secret_key');
|
|
144
|
-
data.forEach((item) => {
|
|
145
|
-
let content = AES_1.AES_GCM.decrypt(item.encrypt_certificate.ciphertext, key, item.encrypt_certificate.nonce, item.encrypt_certificate.associated_data).toString();
|
|
146
|
-
certs[item.serial_no] = PublicKey_1.PublicKey.createByCertificateContent(content, item.serial_no);
|
|
147
|
-
});
|
|
148
|
-
this.getMerchant().setPlatformCerts(certs);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
120
|
}
|
|
154
121
|
;
|
|
155
122
|
;
|
|
@@ -26,15 +26,29 @@ declare abstract class MerchantInterface {
|
|
|
26
26
|
*/
|
|
27
27
|
getCertificate(): PublicKey;
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* 获取平台证书缓存名称
|
|
30
|
+
*/
|
|
31
|
+
getPlatformCertKey(): string;
|
|
32
|
+
/**
|
|
33
|
+
* 设置平台证书缓存名称
|
|
34
|
+
* @param key
|
|
35
|
+
*/
|
|
36
|
+
setPlatformCertKey(key: string): this;
|
|
37
|
+
/**
|
|
38
|
+
* 更具证书序列号获取平台证书
|
|
30
39
|
* @param serial
|
|
31
40
|
* @returns
|
|
32
41
|
*/
|
|
33
|
-
getPlatformCert(serial: string): PublicKey
|
|
42
|
+
getPlatformCert(serial: string): Promise<PublicKey>;
|
|
43
|
+
/**
|
|
44
|
+
* 获取平台证书
|
|
45
|
+
* @param force 是否强制刷新缓存
|
|
46
|
+
*/
|
|
47
|
+
loadPlatformCerts(force: boolean): void;
|
|
34
48
|
/**
|
|
35
49
|
* 设置平台证书
|
|
36
|
-
* @param certs 键名:序列号,键值:PublicKey
|
|
50
|
+
* @param certs 键名:序列号,键值:PublicKey实例或者文件内容字符串
|
|
37
51
|
*/
|
|
38
|
-
setPlatformCerts(certs: Record<string, PublicKey>): void;
|
|
52
|
+
setPlatformCerts(certs: Record<string, PublicKey | string>): void;
|
|
39
53
|
}
|
|
40
54
|
export = MerchantInterface;
|
|
@@ -25,14 +25,28 @@ class MerchantInterface {
|
|
|
25
25
|
*/
|
|
26
26
|
getCertificate() { return null; }
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* 获取平台证书缓存名称
|
|
29
|
+
*/
|
|
30
|
+
getPlatformCertKey() { return null; }
|
|
31
|
+
/**
|
|
32
|
+
* 设置平台证书缓存名称
|
|
33
|
+
* @param key
|
|
34
|
+
*/
|
|
35
|
+
setPlatformCertKey(key) { return this; }
|
|
36
|
+
/**
|
|
37
|
+
* 更具证书序列号获取平台证书
|
|
29
38
|
* @param serial
|
|
30
39
|
* @returns
|
|
31
40
|
*/
|
|
32
41
|
getPlatformCert(serial) { return null; }
|
|
42
|
+
/**
|
|
43
|
+
* 获取平台证书
|
|
44
|
+
* @param force 是否强制刷新缓存
|
|
45
|
+
*/
|
|
46
|
+
loadPlatformCerts(force) { }
|
|
33
47
|
/**
|
|
34
48
|
* 设置平台证书
|
|
35
|
-
* @param certs 键名:序列号,键值:PublicKey
|
|
49
|
+
* @param certs 键名:序列号,键值:PublicKey实例或者文件内容字符串
|
|
36
50
|
*/
|
|
37
51
|
setPlatformCerts(certs) { }
|
|
38
52
|
}
|
package/dist/Pay/Merchant.d.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { PrivateKey } from "../Core/Support/PrivateKey";
|
|
2
2
|
import { PublicKey } from "../Core/Support/PublicKey";
|
|
3
|
+
import Application from "./Application";
|
|
3
4
|
import MerchantInterface from "./Contracts/MerchantInterface";
|
|
4
5
|
declare class Merchant implements MerchantInterface {
|
|
5
6
|
protected mchId: string;
|
|
6
7
|
protected secretKey: string;
|
|
7
8
|
protected v2SecretKey: string;
|
|
9
|
+
protected app: Application;
|
|
8
10
|
protected platformCerts: Record<string, PublicKey>;
|
|
9
11
|
protected privateKey: PrivateKey;
|
|
10
12
|
protected certificate: PublicKey;
|
|
11
|
-
|
|
13
|
+
protected cacheKeyPlatformCert: string;
|
|
14
|
+
constructor(mchId: string, privateKey: string | PrivateKey, certificate: string | PublicKey, secretKey: string, v2SecretKey: string, platformCerts?: Record<string, string | PublicKey> | string[] | PublicKey[], app?: Application);
|
|
12
15
|
/**
|
|
13
16
|
* 统一规范化平台证书
|
|
14
17
|
* @param platformCerts 平台证书列表
|
|
@@ -20,7 +23,10 @@ declare class Merchant implements MerchantInterface {
|
|
|
20
23
|
getSecretKey(): string;
|
|
21
24
|
getV2SecretKey(): string;
|
|
22
25
|
getCertificate(): PublicKey;
|
|
23
|
-
getPlatformCert(serial: string): PublicKey
|
|
24
|
-
setPlatformCerts(certs: Record<string, PublicKey>): void;
|
|
26
|
+
getPlatformCert(serial: string): Promise<PublicKey>;
|
|
27
|
+
setPlatformCerts(certs: Record<string, PublicKey | string>): void;
|
|
28
|
+
getPlatformCertKey(): string;
|
|
29
|
+
setPlatformCertKey(key: string): this;
|
|
30
|
+
loadPlatformCerts(force?: boolean): Promise<Record<string, string>>;
|
|
25
31
|
}
|
|
26
32
|
export = Merchant;
|
package/dist/Pay/Merchant.js
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
const AES_1 = require("../Core/Support/AES");
|
|
2
12
|
const PrivateKey_1 = require("../Core/Support/PrivateKey");
|
|
3
13
|
const PublicKey_1 = require("../Core/Support/PublicKey");
|
|
4
14
|
class Merchant {
|
|
5
|
-
constructor(mchId, privateKey, certificate, secretKey, v2SecretKey =
|
|
15
|
+
constructor(mchId, privateKey, certificate, secretKey, v2SecretKey, platformCerts = [], app = null) {
|
|
6
16
|
this.mchId = mchId;
|
|
7
17
|
this.secretKey = secretKey;
|
|
8
18
|
this.v2SecretKey = v2SecretKey;
|
|
19
|
+
this.app = app;
|
|
9
20
|
this.platformCerts = {};
|
|
10
21
|
if (!(privateKey instanceof PrivateKey_1.PrivateKey)) {
|
|
11
22
|
this.privateKey = new PrivateKey_1.PrivateKey(privateKey);
|
|
@@ -58,10 +69,55 @@ class Merchant {
|
|
|
58
69
|
}
|
|
59
70
|
getPlatformCert(serial) {
|
|
60
71
|
var _a;
|
|
61
|
-
return (
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
if (!this.platformCerts || Object.keys(this.platformCerts).length === 0) {
|
|
74
|
+
yield this.loadPlatformCerts();
|
|
75
|
+
}
|
|
76
|
+
return (_a = this.platformCerts[serial]) !== null && _a !== void 0 ? _a : null;
|
|
77
|
+
});
|
|
62
78
|
}
|
|
63
79
|
setPlatformCerts(certs) {
|
|
64
|
-
|
|
80
|
+
let newCerts = {};
|
|
81
|
+
for (let key of Object.keys(certs)) {
|
|
82
|
+
let cert = certs[key];
|
|
83
|
+
if (typeof cert === 'string') {
|
|
84
|
+
newCerts[key] = PublicKey_1.PublicKey.createByCertificateContent(cert, key);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
newCerts[key] = cert;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
this.platformCerts = newCerts;
|
|
91
|
+
}
|
|
92
|
+
getPlatformCertKey() {
|
|
93
|
+
if (!this.cacheKeyPlatformCert) {
|
|
94
|
+
this.cacheKeyPlatformCert = `pay.platform_certs.${this.mchId}`;
|
|
95
|
+
}
|
|
96
|
+
return this.cacheKeyPlatformCert;
|
|
97
|
+
}
|
|
98
|
+
setPlatformCertKey(key) {
|
|
99
|
+
this.cacheKeyPlatformCert = key;
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
loadPlatformCerts(force = false) {
|
|
103
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
let cacheKey = this.getPlatformCertKey();
|
|
105
|
+
let cache = this.app.getCache();
|
|
106
|
+
let certs = yield cache.get(cacheKey);
|
|
107
|
+
if (force || !certs || Object.keys(certs).length === 0) {
|
|
108
|
+
certs = {};
|
|
109
|
+
let response = yield this.app.getClient().get('/v3/certificates');
|
|
110
|
+
let data = response.toObject();
|
|
111
|
+
if (!data || !data.data || data.data.length === 0)
|
|
112
|
+
return certs;
|
|
113
|
+
data.data.forEach((item) => {
|
|
114
|
+
let content = AES_1.AES_GCM.decrypt(item.encrypt_certificate.ciphertext, this.app.getConfig().get('secret_key'), item.encrypt_certificate.nonce, item.encrypt_certificate.associated_data).toString();
|
|
115
|
+
certs[item.serial_no] = content;
|
|
116
|
+
});
|
|
117
|
+
yield cache.set(cacheKey, certs, 36000); // 缓存10小时
|
|
118
|
+
}
|
|
119
|
+
this.setPlatformCerts(certs);
|
|
120
|
+
});
|
|
65
121
|
}
|
|
66
122
|
}
|
|
67
123
|
module.exports = Merchant;
|
package/dist/Pay/Server.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ declare class Server extends ServerInterface {
|
|
|
19
19
|
* @returns
|
|
20
20
|
*/
|
|
21
21
|
getRequestMessage(request?: ServerRequestInterface): Promise<Message>;
|
|
22
|
+
protected decodeXmlMessage(attributes: Record<string, any>): Promise<Record<string, any>>;
|
|
23
|
+
protected decodeJsonMessage(attributes: Record<string, any>): Record<string, any>;
|
|
22
24
|
/**
|
|
23
25
|
* 获取解密后的消息
|
|
24
26
|
* @param request
|
|
@@ -30,12 +32,20 @@ declare class Server extends ServerInterface {
|
|
|
30
32
|
* @param handler 消息处理器,需要接受两个参数,参数1是消息,参数2是下一个消息处理器
|
|
31
33
|
* @returns
|
|
32
34
|
*/
|
|
33
|
-
handlePaid(handler: ServerHandlerClosure): this;
|
|
35
|
+
handlePaid(handler: ServerHandlerClosure<Message>): this;
|
|
34
36
|
/**
|
|
35
37
|
* 处理退款回调
|
|
36
38
|
* @param handler 消息处理器,需要接受两个参数,参数1是消息,参数2是下一个消息处理器
|
|
37
39
|
* @returns
|
|
38
40
|
*/
|
|
39
|
-
handleRefunded(handler: ServerHandlerClosure): this;
|
|
41
|
+
handleRefunded(handler: ServerHandlerClosure<Message>): this;
|
|
42
|
+
}
|
|
43
|
+
interface Server {
|
|
44
|
+
with(next: ServerHandlerClosure<Message>): this;
|
|
45
|
+
withHandler(next: ServerHandlerClosure<Message>): this;
|
|
46
|
+
prepend(next: ServerHandlerClosure<Message>): this;
|
|
47
|
+
prependHandler(next: ServerHandlerClosure<Message>): this;
|
|
48
|
+
without(next: ServerHandlerClosure<Message>): this;
|
|
49
|
+
withoutHandler(next: ServerHandlerClosure<Message>): this;
|
|
40
50
|
}
|
|
41
51
|
export = Server;
|
package/dist/Pay/Server.js
CHANGED
|
@@ -15,6 +15,7 @@ const ServerInterface_1 = __importDefault(require("../Core/Contracts/ServerInter
|
|
|
15
15
|
const Response_1 = __importDefault(require("../Core/Http/Response"));
|
|
16
16
|
const Message_1 = __importDefault(require("./Message"));
|
|
17
17
|
const AES_1 = require("../Core/Support/AES");
|
|
18
|
+
const Utils_1 = require("../Core/Support/Utils");
|
|
18
19
|
class Server extends ServerInterface_1.default {
|
|
19
20
|
constructor(merchant = null, request = null) {
|
|
20
21
|
super();
|
|
@@ -28,10 +29,15 @@ class Server extends ServerInterface_1.default {
|
|
|
28
29
|
serve() {
|
|
29
30
|
return __awaiter(this, void 0, void 0, function* () {
|
|
30
31
|
let message = yield this.getRequestMessage();
|
|
32
|
+
let isV2Message = message.getOriginalContents().startsWith('<xml');
|
|
31
33
|
try {
|
|
32
|
-
let defaultResponse
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
let defaultResponse;
|
|
35
|
+
if (isV2Message) {
|
|
36
|
+
defaultResponse = new Response_1.default(200, {}, (0, Utils_1.buildXml)({ return_code: 'SUCCESS', return_msg: '' }));
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
defaultResponse = new Response_1.default(200, {}, JSON.stringify({ code: 'SUCCESS', message: '成功' }));
|
|
40
|
+
}
|
|
35
41
|
let response = yield this.handle(defaultResponse, message);
|
|
36
42
|
if (!(response instanceof Response_1.default)) {
|
|
37
43
|
response = defaultResponse;
|
|
@@ -39,9 +45,12 @@ class Server extends ServerInterface_1.default {
|
|
|
39
45
|
return response;
|
|
40
46
|
}
|
|
41
47
|
catch (e) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
48
|
+
if (isV2Message) {
|
|
49
|
+
return new Response_1.default(200, {}, (0, Utils_1.buildXml)({ return_code: 'ERROR', return_msg: e.message }));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
return new Response_1.default(200, {}, JSON.stringify({ code: 'ERROR', message: e.message }));
|
|
53
|
+
}
|
|
45
54
|
}
|
|
46
55
|
});
|
|
47
56
|
}
|
|
@@ -60,27 +69,47 @@ class Server extends ServerInterface_1.default {
|
|
|
60
69
|
if (body) {
|
|
61
70
|
originContent = body.toString();
|
|
62
71
|
}
|
|
63
|
-
let attributes =
|
|
64
|
-
|
|
65
|
-
attributes =
|
|
66
|
-
}
|
|
67
|
-
catch (e) { }
|
|
68
|
-
if (Object.keys(attributes).length === 0) {
|
|
69
|
-
throw new Error('Invalid request body.');
|
|
72
|
+
let attributes = yield request.getParsedBody();
|
|
73
|
+
if (originContent.startsWith('<xml')) {
|
|
74
|
+
attributes = yield this.decodeXmlMessage(attributes);
|
|
70
75
|
}
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
else {
|
|
77
|
+
attributes = this.decodeJsonMessage(attributes);
|
|
73
78
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
return new Message_1.default(attributes, originContent);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
decodeXmlMessage(attributes) {
|
|
83
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
if (attributes['req_info']) {
|
|
85
|
+
let key = this.merchant.getV2SecretKey();
|
|
86
|
+
if (!key) {
|
|
87
|
+
throw new Error('V2 secret key is required');
|
|
88
|
+
}
|
|
89
|
+
attributes = yield (0, Utils_1.parseXml)(AES_1.AES.decrypt(attributes['req_info'], (0, Utils_1.createHash)(key, 'md5'), '', true, 'aes-256-ecb').toString());
|
|
77
90
|
}
|
|
78
|
-
|
|
79
|
-
throw new Error('Failed to decrypt request message
|
|
91
|
+
if (!attributes || Object.keys(attributes).length === 0) {
|
|
92
|
+
throw new Error('Failed to decrypt request message');
|
|
80
93
|
}
|
|
81
|
-
return
|
|
94
|
+
return attributes;
|
|
82
95
|
});
|
|
83
96
|
}
|
|
97
|
+
decodeJsonMessage(attributes) {
|
|
98
|
+
if (!attributes || Object.keys(attributes).length === 0) {
|
|
99
|
+
throw new Error('Invalid request body.');
|
|
100
|
+
}
|
|
101
|
+
if (!attributes['resource']['ciphertext']) {
|
|
102
|
+
throw new Error('Invalid request.');
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
let decryptMessage = AES_1.AES_GCM.decrypt(attributes['resource']['ciphertext'], this.merchant.getSecretKey(), attributes['resource']['nonce'], attributes['resource']['associated_data']);
|
|
106
|
+
attributes = JSON.parse(decryptMessage.toString());
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
throw new Error('Failed to decrypt request message.');
|
|
110
|
+
}
|
|
111
|
+
return attributes;
|
|
112
|
+
}
|
|
84
113
|
/**
|
|
85
114
|
* 获取解密后的消息
|
|
86
115
|
* @param request
|
package/dist/Pay/Signature.d.ts
CHANGED
|
@@ -8,8 +8,10 @@ declare class Signature {
|
|
|
8
8
|
* @param method 请求方式
|
|
9
9
|
* @param url 请求地址
|
|
10
10
|
* @param payload 请求载荷
|
|
11
|
+
* @param nonce 随机串,默认:随机生成
|
|
12
|
+
* @param timestamp 时间戳,默认:当前时间
|
|
11
13
|
* @returns
|
|
12
14
|
*/
|
|
13
|
-
createHeader(method: string, url: string, payload: AxiosRequestConfig<any
|
|
15
|
+
createHeader(method: string, url: string, payload: AxiosRequestConfig<any>, nonce?: string, timestamp?: number): string;
|
|
14
16
|
}
|
|
15
17
|
export = Signature;
|
package/dist/Pay/Signature.js
CHANGED
|
@@ -14,17 +14,35 @@ class Signature {
|
|
|
14
14
|
* @param method 请求方式
|
|
15
15
|
* @param url 请求地址
|
|
16
16
|
* @param payload 请求载荷
|
|
17
|
+
* @param nonce 随机串,默认:随机生成
|
|
18
|
+
* @param timestamp 时间戳,默认:当前时间
|
|
17
19
|
* @returns
|
|
18
20
|
*/
|
|
19
|
-
createHeader(method, url, payload) {
|
|
21
|
+
createHeader(method, url, payload, nonce = null, timestamp = null) {
|
|
20
22
|
let pathname = url;
|
|
21
23
|
if (url.startsWith('https://') || url.startsWith('http://')) {
|
|
22
24
|
let urlObj = new URL(url);
|
|
23
25
|
let search = (0, Utils_1.buildQueryString)((0, merge_1.default)(true, urlObj.searchParams, payload.params));
|
|
24
26
|
pathname = urlObj.pathname + (search ? '?' + search : '');
|
|
25
27
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
else {
|
|
29
|
+
let search = '';
|
|
30
|
+
if (payload.params) {
|
|
31
|
+
if (typeof payload.params === 'string') {
|
|
32
|
+
search = payload.params.replace(/^\?|&/, '');
|
|
33
|
+
}
|
|
34
|
+
else if (Object.keys(payload.params).length > 0) {
|
|
35
|
+
search = (0, Utils_1.buildQueryString)(payload.params);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (search) {
|
|
39
|
+
pathname += (pathname.indexOf('?') > -1 ? '&' : '?') + search;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (!nonce)
|
|
43
|
+
nonce = (0, Utils_1.randomString)();
|
|
44
|
+
if (!timestamp)
|
|
45
|
+
timestamp = (0, Utils_1.getTimestamp)();
|
|
28
46
|
let body = '';
|
|
29
47
|
if (payload.data) {
|
|
30
48
|
if (typeof payload.data === 'object') {
|
package/dist/Pay/Validator.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ declare class Validator implements ValidatorInterface {
|
|
|
10
10
|
static HEADER_SERIAL: string;
|
|
11
11
|
static HEADER_SIGNATURE: string;
|
|
12
12
|
constructor(merchant: MerchantInterface);
|
|
13
|
-
validate(request: MessageInterface): boolean
|
|
13
|
+
validate(request: MessageInterface): Promise<boolean>;
|
|
14
14
|
validateV2(message: Message): boolean;
|
|
15
15
|
}
|
|
16
16
|
export = Validator;
|
package/dist/Pay/Validator.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
13
|
};
|
|
@@ -10,35 +19,37 @@ class Validator {
|
|
|
10
19
|
this.merchant = merchant;
|
|
11
20
|
}
|
|
12
21
|
validate(request) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
[
|
|
24
|
+
Validator.HEADER_TIMESTAMP,
|
|
25
|
+
Validator.HEADER_NONCE,
|
|
26
|
+
Validator.HEADER_SERIAL,
|
|
27
|
+
Validator.HEADER_SIGNATURE,
|
|
28
|
+
].forEach(key => {
|
|
29
|
+
if (!request.hasHeader(key)) {
|
|
30
|
+
throw new Error(`Missing Header: ${key}`);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
let timestamp = request.getHeader(Validator.HEADER_TIMESTAMP) || '';
|
|
34
|
+
let nonce = request.getHeader(Validator.HEADER_NONCE) || '';
|
|
35
|
+
let serial = request.getHeader(Validator.HEADER_SERIAL) || '';
|
|
36
|
+
let signature = request.getHeader(Validator.HEADER_SIGNATURE) || '';
|
|
37
|
+
let body = request.getBody().toString();
|
|
38
|
+
let message = `${timestamp}\n${nonce}\n${body}\n`;
|
|
39
|
+
if ((0, Utils_1.getTimestamp)() - parseInt(timestamp) > Validator.MAX_ALLOWED_CLOCK_OFFSET) {
|
|
40
|
+
throw new Error('Clock Offset Exceeded');
|
|
41
|
+
}
|
|
42
|
+
let publicKey = yield this.merchant.getPlatformCert(serial);
|
|
43
|
+
if (!publicKey) {
|
|
44
|
+
throw new Error(`No platform certs found for serial: ${serial}, please download from wechat pay and set it in merchant config with key \`platform_certs\`.`);
|
|
21
45
|
}
|
|
46
|
+
let rsa = new RSA_1.default;
|
|
47
|
+
rsa.setPublicKey(publicKey.getValue());
|
|
48
|
+
if (false === rsa.verify(signature, message)) {
|
|
49
|
+
throw new Error('Invalid Signature');
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
22
52
|
});
|
|
23
|
-
let timestamp = request.getHeader(Validator.HEADER_TIMESTAMP) || '';
|
|
24
|
-
let nonce = request.getHeader(Validator.HEADER_NONCE) || '';
|
|
25
|
-
let serial = request.getHeader(Validator.HEADER_SERIAL) || '';
|
|
26
|
-
let signature = request.getHeader(Validator.HEADER_SIGNATURE) || '';
|
|
27
|
-
let body = request.getBody().toString();
|
|
28
|
-
let message = `${timestamp}\n${nonce}\n${body}\n`;
|
|
29
|
-
if ((0, Utils_1.getTimestamp)() - parseInt(timestamp) > Validator.MAX_ALLOWED_CLOCK_OFFSET) {
|
|
30
|
-
throw new Error('Clock Offset Exceeded');
|
|
31
|
-
}
|
|
32
|
-
let publicKey = this.merchant.getPlatformCert(serial);
|
|
33
|
-
if (!publicKey) {
|
|
34
|
-
throw new Error(`No platform certs found for serial: ${serial}, please download from wechat pay and set it in merchant config with key \`platform_certs\`.`);
|
|
35
|
-
}
|
|
36
|
-
let rsa = new RSA_1.default;
|
|
37
|
-
rsa.setPublicKey(publicKey.getValue());
|
|
38
|
-
if (false === rsa.verify(signature, message)) {
|
|
39
|
-
throw new Error('Invalid Signature');
|
|
40
|
-
}
|
|
41
|
-
return true;
|
|
42
53
|
}
|
|
43
54
|
validateV2(message) {
|
|
44
55
|
let messageSign = (message.get('sign') + '' || '').toUpperCase();
|
package/dist/Work/Server.d.ts
CHANGED
|
@@ -87,4 +87,12 @@ declare class Server extends ServerInterface {
|
|
|
87
87
|
*/
|
|
88
88
|
getDecryptedMessage(request?: ServerRequestInterface): Promise<import("../Core/Message")>;
|
|
89
89
|
}
|
|
90
|
+
interface Server {
|
|
91
|
+
with(next: ServerHandlerClosure<Message>): this;
|
|
92
|
+
withHandler(next: ServerHandlerClosure<Message>): this;
|
|
93
|
+
prepend(next: ServerHandlerClosure<Message>): this;
|
|
94
|
+
prependHandler(next: ServerHandlerClosure<Message>): this;
|
|
95
|
+
without(next: ServerHandlerClosure<Message>): this;
|
|
96
|
+
withoutHandler(next: ServerHandlerClosure<Message>): this;
|
|
97
|
+
}
|
|
90
98
|
export = Server;
|