node-easywechat 3.6.3 → 3.7.1
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 +11 -0
- package/README.md +25 -0
- package/dist/Channel/AccessToken.d.ts +8 -0
- package/dist/Channel/AccessToken.js +15 -0
- package/dist/Channel/Account.d.ts +4 -0
- package/dist/Channel/Account.js +8 -0
- package/dist/Channel/Application.d.ts +60 -0
- package/dist/Channel/Application.js +125 -0
- package/dist/Channel/Contracts/AccountInterface.d.ts +23 -0
- package/dist/Channel/Contracts/AccountInterface.js +25 -0
- package/dist/Channel/Contracts/ApplicationInterface.d.ts +62 -0
- package/dist/Channel/Contracts/ApplicationInterface.js +55 -0
- package/dist/Channel/Message.d.ts +542 -0
- package/dist/Channel/Message.js +9 -0
- package/dist/Channel/Server.d.ts +91 -0
- package/dist/Channel/Server.js +16 -0
- package/dist/Core/Cache/FileCache.js +46 -63
- package/dist/Core/Contracts/AccessTokenInterface.js +2 -15
- package/dist/Core/Contracts/CacheInterface.js +4 -21
- package/dist/Core/Contracts/RefreshableAccessTokenInterface.js +1 -12
- package/dist/Core/Contracts/ServerInterface.d.ts +3 -3
- package/dist/Core/Contracts/ServerInterface.js +4 -15
- package/dist/Core/Http/ServerRequest.js +34 -49
- package/dist/Core/HttpClient/AccessTokenAwareClient.js +6 -17
- package/dist/Core/HttpClient/Contracts/HttpClientInterface.js +1 -12
- package/dist/Core/HttpClient/HttpClient.js +74 -85
- package/dist/Core/HttpClient/HttpClientResponse.js +35 -50
- package/dist/Core/HttpClient/Mixins/HttpClientMethodsMixin.js +34 -59
- package/dist/Core/HttpClient/Mixins/PresetMixin.js +8 -11
- package/dist/Core/Message.js +20 -31
- package/dist/Core/Mixins/{DecryptXmlMessageMixin.d.ts → DecryptMessageMixin.d.ts} +2 -2
- package/dist/Core/Mixins/DecryptMessageMixin.js +34 -0
- package/dist/Core/Mixins/HandlersMixin.d.ts +8 -8
- package/dist/Core/Mixins/HandlersMixin.js +26 -39
- package/dist/Core/Mixins/{ResponseXmlMessageMixin.d.ts → ResponseMessageMixin.d.ts} +4 -3
- package/dist/Core/Mixins/ResponseMessageMixin.js +61 -0
- package/dist/Core/Support/Utils.js +8 -19
- package/dist/MiniApp/Application.js +1 -1
- package/dist/MiniApp/Utils.js +13 -24
- package/dist/OfficialAccount/AccessToken.js +42 -59
- package/dist/OfficialAccount/Application.js +1 -1
- package/dist/OfficialAccount/JsApiTicket.js +31 -44
- package/dist/OfficialAccount/Server.d.ts +24 -0
- package/dist/OfficialAccount/Server.js +25 -37
- package/dist/OfficialAccount/Utils.js +6 -17
- package/dist/OpenPlatform/Application.js +62 -86
- package/dist/OpenPlatform/Authorizer/MiniApp/Utils.js +14 -25
- package/dist/OpenPlatform/AuthorizerAccessToken.js +6 -19
- package/dist/OpenPlatform/ComponentAccessToken.js +27 -42
- package/dist/OpenPlatform/Server.js +31 -54
- package/dist/OpenPlatform/VerifyTicket.js +14 -27
- package/dist/OpenWork/Application.js +61 -84
- package/dist/OpenWork/AuthorizerAccessToken.js +32 -47
- package/dist/OpenWork/JsApiTicket.js +64 -81
- package/dist/OpenWork/ProviderAccessToken.js +26 -41
- package/dist/OpenWork/Server.js +50 -94
- package/dist/OpenWork/SuiteAccessToken.js +27 -42
- package/dist/OpenWork/SuiteTicket.js +14 -27
- package/dist/Pay/Application.js +1 -2
- package/dist/Pay/Client.js +63 -77
- package/dist/Pay/LegacySignature.js +2 -3
- package/dist/Pay/Merchant.js +36 -52
- package/dist/Pay/Server.js +55 -70
- package/dist/Pay/Utils.js +13 -26
- package/dist/Pay/Validator.js +28 -39
- package/dist/Types/global.d.ts +31 -0
- package/dist/Work/AccessToken.js +26 -41
- package/dist/Work/Application.js +21 -32
- package/dist/Work/JsApiTicket.js +60 -77
- package/dist/Work/Server.js +47 -86
- package/dist/Work/Utils.js +12 -25
- package/dist/index.d.ts +14 -2
- package/dist/index.js +19 -1
- package/package.json +1 -1
- package/tsconfig.json +2 -2
- package/dist/Core/Mixins/DecryptXmlMessageMixin.js +0 -38
- package/dist/Core/Mixins/ResponseXmlMessageMixin.js +0 -63
package/dist/Pay/Merchant.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
|
const AES_1 = require("../Core/Support/AES");
|
|
12
3
|
const PrivateKey_1 = require("../Core/Support/PrivateKey");
|
|
13
4
|
const PublicKey_1 = require("../Core/Support/PublicKey");
|
|
@@ -71,26 +62,21 @@ class Merchant {
|
|
|
71
62
|
getCertificate() {
|
|
72
63
|
return this.certificate;
|
|
73
64
|
}
|
|
74
|
-
getPlatformCert(serial) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
return (_a = this.platformCerts[serial]) !== null && _a !== void 0 ? _a : null;
|
|
83
|
-
});
|
|
65
|
+
async getPlatformCert(serial) {
|
|
66
|
+
if (!this.isConfigPlatformCerts) {
|
|
67
|
+
// 如果不是通过配置文件设置的平台证书,则每次都从缓存或者接口获取证书
|
|
68
|
+
let certs = await this.loadPlatformCerts();
|
|
69
|
+
this.setPlatformCerts(certs);
|
|
70
|
+
}
|
|
71
|
+
return this.platformCerts[serial] ?? null;
|
|
84
72
|
}
|
|
85
|
-
getPlatformCerts() {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return this.platformCerts;
|
|
93
|
-
});
|
|
73
|
+
async getPlatformCerts() {
|
|
74
|
+
if (!this.isConfigPlatformCerts) {
|
|
75
|
+
// 如果不是通过配置文件设置的平台证书,则每次都从缓存或者接口获取证书
|
|
76
|
+
let certs = await this.loadPlatformCerts();
|
|
77
|
+
this.setPlatformCerts(certs);
|
|
78
|
+
}
|
|
79
|
+
return this.platformCerts;
|
|
94
80
|
}
|
|
95
81
|
setPlatformCerts(certs) {
|
|
96
82
|
let newCerts = {};
|
|
@@ -116,32 +102,30 @@ class Merchant {
|
|
|
116
102
|
this.cacheKeyPlatformCert = key;
|
|
117
103
|
return this;
|
|
118
104
|
}
|
|
119
|
-
loadPlatformCerts() {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
yield cache.set(cacheKey, certs, 36000); // 缓存10小时
|
|
140
|
-
}
|
|
105
|
+
async loadPlatformCerts(force = false) {
|
|
106
|
+
let cacheKey = this.getPlatformCertKey();
|
|
107
|
+
let cache = this.app.getCache();
|
|
108
|
+
let certs = await cache.get(cacheKey);
|
|
109
|
+
if (force || !certs || Object.keys(certs).length === 0) {
|
|
110
|
+
certs = {};
|
|
111
|
+
let response = await this.app.getClient().get('/v3/certificates');
|
|
112
|
+
let data = response.toObject();
|
|
113
|
+
if (data && data.data && data.data.length > 0) {
|
|
114
|
+
let nowTime = Math.round((new Date()).getTime() / 1000);
|
|
115
|
+
data.data.forEach((item) => {
|
|
116
|
+
// 跳过有效期少于1天的证书
|
|
117
|
+
let expireTime = Math.round((new Date(item.expire_time)).getTime() / 1000) - 86400;
|
|
118
|
+
if (expireTime < nowTime)
|
|
119
|
+
return;
|
|
120
|
+
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();
|
|
121
|
+
certs[item.serial_no] = content;
|
|
122
|
+
});
|
|
123
|
+
if (Object.keys(certs).length > 0) {
|
|
124
|
+
await cache.set(cacheKey, certs, 36000); // 缓存10小时
|
|
141
125
|
}
|
|
142
126
|
}
|
|
143
|
-
|
|
144
|
-
|
|
127
|
+
}
|
|
128
|
+
return certs;
|
|
145
129
|
}
|
|
146
130
|
}
|
|
147
131
|
module.exports = Merchant;
|
package/dist/Pay/Server.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
|
};
|
|
@@ -26,73 +17,67 @@ class Server extends ServerInterface_1.default {
|
|
|
26
17
|
* 服务端消息处理
|
|
27
18
|
* @returns
|
|
28
19
|
*/
|
|
29
|
-
serve() {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
}
|
|
41
|
-
let response = yield this.handle(defaultResponse, message);
|
|
42
|
-
if (!(response instanceof Response_1.default)) {
|
|
43
|
-
response = defaultResponse;
|
|
44
|
-
}
|
|
45
|
-
return response;
|
|
20
|
+
async serve() {
|
|
21
|
+
let message = await this.getRequestMessage();
|
|
22
|
+
let isV2Message = message.getOriginalContents().startsWith('<xml');
|
|
23
|
+
try {
|
|
24
|
+
let defaultResponse;
|
|
25
|
+
if (isV2Message) {
|
|
26
|
+
defaultResponse = new Response_1.default(200, {}, (0, Utils_1.buildXml)({ return_code: 'SUCCESS', return_msg: '' }));
|
|
46
27
|
}
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
}
|
|
28
|
+
else {
|
|
29
|
+
defaultResponse = new Response_1.default(200, {}, JSON.stringify({ code: 'SUCCESS', message: '成功' }));
|
|
54
30
|
}
|
|
55
|
-
|
|
31
|
+
let response = await this.handle(defaultResponse, message);
|
|
32
|
+
if (!(response instanceof Response_1.default)) {
|
|
33
|
+
response = defaultResponse;
|
|
34
|
+
}
|
|
35
|
+
return response;
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
if (isV2Message) {
|
|
39
|
+
return new Response_1.default(200, {}, (0, Utils_1.buildXml)({ return_code: 'ERROR', return_msg: e.message }));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
return new Response_1.default(200, {}, JSON.stringify({ code: 'ERROR', message: e.message }));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
56
45
|
}
|
|
57
46
|
/**
|
|
58
47
|
* 获取来自微信服务器的推送消息
|
|
59
48
|
* @param request 未设置该参数时,则从当前服务端收到的请求中获取
|
|
60
49
|
* @returns
|
|
61
50
|
*/
|
|
62
|
-
getRequestMessage() {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return new Message_1.default(attributes, originContent);
|
|
80
|
-
});
|
|
51
|
+
async getRequestMessage(request = null) {
|
|
52
|
+
if (!request) {
|
|
53
|
+
request = this.request;
|
|
54
|
+
}
|
|
55
|
+
let originContent = '';
|
|
56
|
+
let body = request.getBody();
|
|
57
|
+
if (body) {
|
|
58
|
+
originContent = body.toString();
|
|
59
|
+
}
|
|
60
|
+
let attributes = await request.getParsedBody();
|
|
61
|
+
if (originContent.startsWith('<xml')) {
|
|
62
|
+
attributes = await this.decodeXmlMessage(attributes);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
attributes = this.decodeJsonMessage(attributes);
|
|
66
|
+
}
|
|
67
|
+
return new Message_1.default(attributes, originContent);
|
|
81
68
|
}
|
|
82
|
-
decodeXmlMessage(attributes) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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());
|
|
69
|
+
async decodeXmlMessage(attributes) {
|
|
70
|
+
if (attributes['req_info']) {
|
|
71
|
+
let key = this.merchant.getV2SecretKey();
|
|
72
|
+
if (!key) {
|
|
73
|
+
throw new Error('V2 secret key is required');
|
|
90
74
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
75
|
+
attributes = await (0, Utils_1.parseXml)(AES_1.AES.decrypt(attributes['req_info'], (0, Utils_1.createHash)(key, 'md5'), '', true, 'aes-256-ecb').toString());
|
|
76
|
+
}
|
|
77
|
+
if (!attributes || Object.keys(attributes).length === 0) {
|
|
78
|
+
throw new Error('Failed to decrypt request message');
|
|
79
|
+
}
|
|
80
|
+
return attributes;
|
|
96
81
|
}
|
|
97
82
|
decodeJsonMessage(attributes) {
|
|
98
83
|
if (!attributes || Object.keys(attributes).length === 0) {
|
|
@@ -124,14 +109,14 @@ class Server extends ServerInterface_1.default {
|
|
|
124
109
|
* @returns
|
|
125
110
|
*/
|
|
126
111
|
handlePaid(handler) {
|
|
127
|
-
this.with((message, next) =>
|
|
112
|
+
this.with(async (message, next) => {
|
|
128
113
|
let isV2Message = message.getOriginalContents().startsWith('<xml');
|
|
129
114
|
if (isV2Message) {
|
|
130
115
|
return handler(message, next);
|
|
131
116
|
}
|
|
132
117
|
return message.getEventType() === 'TRANSACTION.SUCCESS' && message.trade_state === 'SUCCESS'
|
|
133
118
|
? handler(message, next) : next(message);
|
|
134
|
-
})
|
|
119
|
+
});
|
|
135
120
|
return this;
|
|
136
121
|
}
|
|
137
122
|
/**
|
|
@@ -140,14 +125,14 @@ class Server extends ServerInterface_1.default {
|
|
|
140
125
|
* @returns
|
|
141
126
|
*/
|
|
142
127
|
handleRefunded(handler) {
|
|
143
|
-
this.with((message, next) =>
|
|
128
|
+
this.with(async (message, next) => {
|
|
144
129
|
let eventType = message.getEventType();
|
|
145
130
|
return [
|
|
146
131
|
'REFUND.SUCCESS',
|
|
147
132
|
'REFUND.ABNORMAL',
|
|
148
133
|
'REFUND.CLOSED',
|
|
149
134
|
].findIndex(o => o === eventType) > -1 ? handler(message, next) : next(message);
|
|
150
|
-
})
|
|
135
|
+
});
|
|
151
136
|
return this;
|
|
152
137
|
}
|
|
153
138
|
}
|
package/dist/Pay/Utils.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
|
};
|
|
@@ -23,14 +14,12 @@ class Utils {
|
|
|
23
14
|
* 获取加密所用的平台证书
|
|
24
15
|
* @returns
|
|
25
16
|
*/
|
|
26
|
-
getPlatformCert() {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return certs[Object.keys(certs)[0]];
|
|
33
|
-
});
|
|
17
|
+
async getPlatformCert() {
|
|
18
|
+
let certs = await this.merchant.getPlatformCerts();
|
|
19
|
+
if (!certs || Object.keys(certs).length === 0) {
|
|
20
|
+
throw new Error('Fail to get platform certs');
|
|
21
|
+
}
|
|
22
|
+
return certs[Object.keys(certs)[0]];
|
|
34
23
|
}
|
|
35
24
|
/**
|
|
36
25
|
* 获取敏感信息加密机
|
|
@@ -38,15 +27,13 @@ class Utils {
|
|
|
38
27
|
* @param platformCert PublicKey封装过的平台证书
|
|
39
28
|
* @returns
|
|
40
29
|
*/
|
|
41
|
-
getEncryptor() {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return encryptor;
|
|
49
|
-
});
|
|
30
|
+
async getEncryptor(platformCert = null) {
|
|
31
|
+
if (!platformCert || !(platformCert instanceof PublicKey_1.PublicKey)) {
|
|
32
|
+
platformCert = await this.getPlatformCert();
|
|
33
|
+
}
|
|
34
|
+
let encryptor = new Encryptor_1.default;
|
|
35
|
+
encryptor.setCerts(platformCert, this.merchant.getPrivateKey());
|
|
36
|
+
return encryptor;
|
|
50
37
|
}
|
|
51
38
|
/**
|
|
52
39
|
* 创建签名(V3),并返回签名字符串
|
package/dist/Pay/Validator.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
|
};
|
|
@@ -18,38 +9,36 @@ class Validator {
|
|
|
18
9
|
constructor(merchant) {
|
|
19
10
|
this.merchant = merchant;
|
|
20
11
|
}
|
|
21
|
-
validate(request) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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\`.`);
|
|
12
|
+
async validate(request) {
|
|
13
|
+
[
|
|
14
|
+
Validator.HEADER_TIMESTAMP,
|
|
15
|
+
Validator.HEADER_NONCE,
|
|
16
|
+
Validator.HEADER_SERIAL,
|
|
17
|
+
Validator.HEADER_SIGNATURE,
|
|
18
|
+
].forEach(key => {
|
|
19
|
+
if (!request.hasHeader(key)) {
|
|
20
|
+
throw new Error(`Missing Header: ${key}`);
|
|
45
21
|
}
|
|
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;
|
|
52
22
|
});
|
|
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 = await 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;
|
|
53
42
|
}
|
|
54
43
|
validateV2(message) {
|
|
55
44
|
let messageSign = (message.get('sign') + '' || '').toUpperCase();
|
package/dist/Types/global.d.ts
CHANGED
|
@@ -481,3 +481,34 @@ export interface PayAppConfig {
|
|
|
481
481
|
*/
|
|
482
482
|
sign: string;
|
|
483
483
|
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* 视频号配置
|
|
487
|
+
*/
|
|
488
|
+
export interface ChannelConfig extends BaseConfig {
|
|
489
|
+
/**
|
|
490
|
+
* 视频号 app_id
|
|
491
|
+
*/
|
|
492
|
+
app_id?: string;
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* 视频号 secret
|
|
496
|
+
*/
|
|
497
|
+
secret?: string;
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* 服务端接口验证 token
|
|
501
|
+
*/
|
|
502
|
+
token?: string;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* 服务端消息加解密密钥 aes_key
|
|
506
|
+
*/
|
|
507
|
+
aes_key?: string;
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* 是否使用稳定版接口调用凭据,默认:false
|
|
511
|
+
* @see https://developers.weixin.qq.com/doc/channels/API/basics/getStableAccessToken.html
|
|
512
|
+
*/
|
|
513
|
+
use_stable_access_token?: boolean;
|
|
514
|
+
}
|
package/dist/Work/AccessToken.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
|
};
|
|
@@ -44,41 +35,35 @@ class AccessToken {
|
|
|
44
35
|
this.key = key;
|
|
45
36
|
return this;
|
|
46
37
|
}
|
|
47
|
-
getToken() {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return this.refresh();
|
|
57
|
-
});
|
|
38
|
+
async getToken() {
|
|
39
|
+
let token = '';
|
|
40
|
+
if (this.cache) {
|
|
41
|
+
token = await this.cache.get(this.getKey());
|
|
42
|
+
}
|
|
43
|
+
if (!!token && typeof token === 'string') {
|
|
44
|
+
return token;
|
|
45
|
+
}
|
|
46
|
+
return this.refresh();
|
|
58
47
|
}
|
|
59
|
-
toQuery() {
|
|
60
|
-
return
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
};
|
|
64
|
-
});
|
|
48
|
+
async toQuery() {
|
|
49
|
+
return {
|
|
50
|
+
access_token: await this.getToken(),
|
|
51
|
+
};
|
|
65
52
|
}
|
|
66
|
-
refresh() {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
corpsecret: this.secret,
|
|
72
|
-
}
|
|
73
|
-
})).toObject();
|
|
74
|
-
if (!response['access_token']) {
|
|
75
|
-
throw new Error('Failed to get access_token: ' + JSON.stringify(response));
|
|
76
|
-
}
|
|
77
|
-
if (this.cache) {
|
|
78
|
-
yield this.cache.set(this.getKey(), response['access_token'], parseInt(response['expires_in']));
|
|
53
|
+
async refresh() {
|
|
54
|
+
let response = (await this.httpClient.request('get', 'cgi-bin/gettoken', {
|
|
55
|
+
params: {
|
|
56
|
+
corpid: this.corpId,
|
|
57
|
+
corpsecret: this.secret,
|
|
79
58
|
}
|
|
80
|
-
|
|
81
|
-
|
|
59
|
+
})).toObject();
|
|
60
|
+
if (!response['access_token']) {
|
|
61
|
+
throw new Error('Failed to get access_token: ' + JSON.stringify(response));
|
|
62
|
+
}
|
|
63
|
+
if (this.cache) {
|
|
64
|
+
await this.cache.set(this.getKey(), response['access_token'], parseInt(response['expires_in']));
|
|
65
|
+
}
|
|
66
|
+
return response['access_token'];
|
|
82
67
|
}
|
|
83
68
|
}
|
|
84
69
|
module.exports = AccessToken;
|
package/dist/Work/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
|
};
|
|
@@ -119,29 +110,27 @@ class Application {
|
|
|
119
110
|
this.oauthFactory = oauthFactory;
|
|
120
111
|
return this;
|
|
121
112
|
}
|
|
122
|
-
getOAuth() {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
redirect: app.getConfig().get('oauth.redirect_url'),
|
|
130
|
-
});
|
|
113
|
+
async getOAuth() {
|
|
114
|
+
if (!this.oauthFactory) {
|
|
115
|
+
this.oauthFactory = ((app) => {
|
|
116
|
+
return new WeWork_1.default({
|
|
117
|
+
client_id: app.getAccount().getCorpId(),
|
|
118
|
+
client_secret: app.getAccount().getSecret(),
|
|
119
|
+
redirect: app.getConfig().get('oauth.redirect_url'),
|
|
131
120
|
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
let provider = this.oauthFactory.call(null, this);
|
|
124
|
+
if (!(provider instanceof WeWork_1.default)) {
|
|
125
|
+
throw new Error(`The factory must return a \`ProviderInterface\` instance.`);
|
|
126
|
+
}
|
|
127
|
+
provider.withApiAccessToken(await this.getAccessToken().getToken());
|
|
128
|
+
provider.scopes(this.getConfig().get('oauth.scopes', 'snsapi_userinfo'));
|
|
129
|
+
let agent_id = parseInt(this.config.get('agent_id')) || null;
|
|
130
|
+
if (agent_id) {
|
|
131
|
+
provider.setAgentId(agent_id);
|
|
132
|
+
}
|
|
133
|
+
return provider;
|
|
145
134
|
}
|
|
146
135
|
getTicket() {
|
|
147
136
|
if (!this.ticket) {
|
|
@@ -172,7 +161,7 @@ class Application {
|
|
|
172
161
|
return this.utils;
|
|
173
162
|
}
|
|
174
163
|
createClient() {
|
|
175
|
-
return (new AccessTokenAwareClient_1.default(this.getHttpClient(), this.getAccessToken(), (response) =>
|
|
164
|
+
return (new AccessTokenAwareClient_1.default(this.getHttpClient(), this.getAccessToken(), (response) => response.toObject()['errcode'] ?? 0, this.getConfig().get('http.throw', true)))
|
|
176
165
|
.setPresets(this.getConfig().all());
|
|
177
166
|
}
|
|
178
167
|
/**
|