node-easywechat 3.5.7 → 3.5.9
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 +14 -0
- package/dist/Core/HttpClient/HttpClientResponse.d.ts +5 -0
- package/dist/Core/HttpClient/HttpClientResponse.js +7 -0
- package/dist/Core/Support/AES.js +2 -2
- package/dist/Core/Support/PublicKey.d.ts +8 -1
- package/dist/Core/Support/PublicKey.js +25 -7
- package/dist/OpenPlatform/Authorizer/MiniApp/Utils.d.ts +1 -1
- package/dist/OpenPlatform/Authorizer/MiniApp/Utils.js +1 -1
- package/dist/Pay/Application.d.ts +5 -0
- package/dist/Pay/Application.js +33 -0
- package/dist/Pay/Contracts/MerchantInterface.d.ts +5 -0
- package/dist/Pay/Contracts/MerchantInterface.js +5 -0
- package/dist/Pay/Contracts/ValidatorInterface.d.ts +5 -0
- package/dist/Pay/Contracts/ValidatorInterface.js +4 -0
- package/dist/Pay/Merchant.d.ts +1 -0
- package/dist/Pay/Merchant.js +3 -0
- package/dist/Pay/Validator.d.ts +4 -2
- package/dist/Pay/Validator.js +13 -0
- package/dist/Types/global.d.ts +2 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v3.5.9 (2023-12-18)
|
|
5
|
+
|
|
6
|
+
- Feat: 微信支付增加读取平台证书的方法loadPlatformCerts,并自动写入商户配置 (#57)
|
|
7
|
+
- Feat: 微信支付增加v2版本的消息验证方法validateV2 (#56)
|
|
8
|
+
|
|
9
|
+
## v3.5.8 (2023-12-18)
|
|
10
|
+
|
|
11
|
+
- Feat: thirdpartyCode2Session方法重命名为code2Session (#54)
|
|
12
|
+
- Feat: 新增将请求响应类转换为标准http响应类的方法toHttpResponse
|
|
13
|
+
|
|
14
|
+
- Fix: 修复验证器类型错误 (#58)
|
|
15
|
+
- Fix: 修复验证器类型错误的问题 (#56)
|
|
16
|
+
- Fix: 修复ts类型错误
|
|
17
|
+
|
|
4
18
|
## v3.5.7 (2023-12-18)
|
|
5
19
|
|
|
6
20
|
- Feat: 企业微信工具类增加encrypt、decrypt加解密方法 (#58)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AxiosResponse } from "axios";
|
|
2
2
|
import { HttpClientFailureJudgeClosure, WeixinResponse } from "../../Types/global";
|
|
3
3
|
import HttpClientResponseInterface from "./Contracts/HttpClientResponseInterface";
|
|
4
|
+
import Response from "../Http/Response";
|
|
4
5
|
declare class HttpClientResponse implements HttpClientResponseInterface {
|
|
5
6
|
protected response: AxiosResponse;
|
|
6
7
|
protected failureJudge: HttpClientFailureJudgeClosure;
|
|
@@ -89,5 +90,9 @@ declare class HttpClientResponse implements HttpClientResponseInterface {
|
|
|
89
90
|
getInfo(type?: string): import("axios").InternalAxiosRequestConfig<any>;
|
|
90
91
|
offsetExists(key: any): Promise<boolean>;
|
|
91
92
|
offsetGet(key: any): Promise<any>;
|
|
93
|
+
/**
|
|
94
|
+
* 转换为标准的 http 响应类
|
|
95
|
+
*/
|
|
96
|
+
toHttpResponse(): Response;
|
|
92
97
|
}
|
|
93
98
|
export = HttpClientResponse;
|
|
@@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
const fs_1 = __importDefault(require("fs"));
|
|
15
15
|
const Utils_1 = require("../Support/Utils");
|
|
16
|
+
const Response_1 = __importDefault(require("../Http/Response"));
|
|
16
17
|
class HttpClientResponse {
|
|
17
18
|
constructor(response, failureJudge = null, throwError = false) {
|
|
18
19
|
this.response = response;
|
|
@@ -241,5 +242,11 @@ class HttpClientResponse {
|
|
|
241
242
|
return (yield this.toObject())[key] || null;
|
|
242
243
|
});
|
|
243
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* 转换为标准的 http 响应类
|
|
247
|
+
*/
|
|
248
|
+
toHttpResponse() {
|
|
249
|
+
return new Response_1.default(this.response.status, this.getHeaders(), this.toString());
|
|
250
|
+
}
|
|
244
251
|
}
|
|
245
252
|
module.exports = HttpClientResponse;
|
package/dist/Core/Support/AES.js
CHANGED
|
@@ -82,8 +82,8 @@ class AES_GCM {
|
|
|
82
82
|
else {
|
|
83
83
|
buf = Buffer.from(ciphertext);
|
|
84
84
|
}
|
|
85
|
-
let tag = buf.
|
|
86
|
-
let payload = buf.
|
|
85
|
+
let tag = buf.subarray(-16);
|
|
86
|
+
let payload = buf.subarray(0, -16);
|
|
87
87
|
let decipher = (0, crypto_1.createDecipheriv)(method, key, iv).setAuthTag(tag).setAAD(Buffer.from(aad));
|
|
88
88
|
return Buffer.concat([
|
|
89
89
|
decipher.update(payload),
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
export declare class PublicKey {
|
|
3
3
|
protected certificate: Buffer;
|
|
4
|
-
|
|
4
|
+
protected serialNo: string;
|
|
5
|
+
constructor(certificate: string, serialNo?: string);
|
|
5
6
|
/**
|
|
6
7
|
* 获取公钥的序列号
|
|
7
8
|
* @returns
|
|
@@ -17,4 +18,10 @@ export declare class PublicKey {
|
|
|
17
18
|
* @returns
|
|
18
19
|
*/
|
|
19
20
|
toString(): string;
|
|
21
|
+
/**
|
|
22
|
+
* 通过内容创建实例
|
|
23
|
+
* @param content 证书内容
|
|
24
|
+
* @param serialNo 证书序列号
|
|
25
|
+
*/
|
|
26
|
+
static createByCertificateContent(content: string, serialNo: string): PublicKey;
|
|
20
27
|
}
|
|
@@ -7,8 +7,15 @@ exports.PublicKey = void 0;
|
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const crypto_1 = require("crypto");
|
|
9
9
|
class PublicKey {
|
|
10
|
-
constructor(certificate) {
|
|
11
|
-
if (
|
|
10
|
+
constructor(certificate, serialNo = '') {
|
|
11
|
+
if (serialNo) {
|
|
12
|
+
if (!certificate) {
|
|
13
|
+
throw new Error('Invalid PublicKey content');
|
|
14
|
+
}
|
|
15
|
+
this.certificate = Buffer.from(certificate);
|
|
16
|
+
this.serialNo = serialNo;
|
|
17
|
+
}
|
|
18
|
+
else if (fs_1.default.existsSync(certificate)) {
|
|
12
19
|
this.certificate = fs_1.default.readFileSync(certificate) || Buffer.from('');
|
|
13
20
|
}
|
|
14
21
|
else {
|
|
@@ -20,12 +27,15 @@ class PublicKey {
|
|
|
20
27
|
* @returns
|
|
21
28
|
*/
|
|
22
29
|
getSerialNo() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
if (!this.serialNo) {
|
|
31
|
+
try {
|
|
32
|
+
this.serialNo = new crypto_1.X509Certificate(this.certificate).serialNumber;
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
throw new Error('Read the $certificate failed, please check it whether or nor correct');
|
|
36
|
+
}
|
|
28
37
|
}
|
|
38
|
+
return this.serialNo;
|
|
29
39
|
}
|
|
30
40
|
/**
|
|
31
41
|
* 获取证书内容
|
|
@@ -41,5 +51,13 @@ class PublicKey {
|
|
|
41
51
|
toString() {
|
|
42
52
|
return this.certificate.toString();
|
|
43
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* 通过内容创建实例
|
|
56
|
+
* @param content 证书内容
|
|
57
|
+
* @param serialNo 证书序列号
|
|
58
|
+
*/
|
|
59
|
+
static createByCertificateContent(content, serialNo) {
|
|
60
|
+
return new PublicKey(content, serialNo);
|
|
61
|
+
}
|
|
44
62
|
}
|
|
45
63
|
exports.PublicKey = PublicKey;
|
|
@@ -9,6 +9,6 @@ declare class Utils extends BaseUtils {
|
|
|
9
9
|
* @param code
|
|
10
10
|
* @returns
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
code2Session(code: string): Promise<import("../../../Types/global").WeixinResponse>;
|
|
13
13
|
}
|
|
14
14
|
export = Utils;
|
|
@@ -24,7 +24,7 @@ class Utils extends Utils_1.default {
|
|
|
24
24
|
* @param code
|
|
25
25
|
* @returns
|
|
26
26
|
*/
|
|
27
|
-
|
|
27
|
+
code2Session(code) {
|
|
28
28
|
return __awaiter(this, void 0, void 0, function* () {
|
|
29
29
|
let client = this.app.getHttpClient();
|
|
30
30
|
let response = yield client.request('GET', '/sns/component/jscode2session', {
|
|
@@ -60,6 +60,11 @@ 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>;
|
|
63
68
|
}
|
|
64
69
|
interface Application extends ConfigMixin, CacheMixin, ServerRequestMixin, HttpClientMixin {
|
|
65
70
|
}
|
package/dist/Pay/Application.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
|
};
|
|
@@ -15,6 +24,8 @@ const Utils_2 = __importDefault(require("./Utils"));
|
|
|
15
24
|
const Config_1 = __importDefault(require("../OfficialAccount/Config"));
|
|
16
25
|
const Client_1 = __importDefault(require("./Client"));
|
|
17
26
|
const Validator_1 = __importDefault(require("./Validator"));
|
|
27
|
+
const PublicKey_1 = require("../Core/Support/PublicKey");
|
|
28
|
+
const AES_1 = require("../Core/Support/AES");
|
|
18
29
|
/**
|
|
19
30
|
* 微信支付应用
|
|
20
31
|
*/
|
|
@@ -117,6 +128,28 @@ class Application {
|
|
|
117
128
|
baseURL: 'https://api.mch.weixin.qq.com',
|
|
118
129
|
}, this.getConfig().get('http'));
|
|
119
130
|
}
|
|
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
|
+
}
|
|
120
153
|
}
|
|
121
154
|
;
|
|
122
155
|
;
|
|
@@ -31,5 +31,10 @@ declare abstract class MerchantInterface {
|
|
|
31
31
|
* @returns
|
|
32
32
|
*/
|
|
33
33
|
getPlatformCert(serial: string): PublicKey;
|
|
34
|
+
/**
|
|
35
|
+
* 设置平台证书
|
|
36
|
+
* @param certs 键名:序列号,键值:PublicKey实例
|
|
37
|
+
*/
|
|
38
|
+
setPlatformCerts(certs: Record<string, PublicKey>): void;
|
|
34
39
|
}
|
|
35
40
|
export = MerchantInterface;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import Request from "../../Core/Http/Request";
|
|
2
|
+
import Message from "../Message";
|
|
2
3
|
declare abstract class ValidatorInterface {
|
|
3
4
|
/**
|
|
4
5
|
* 验证请求是否正确
|
|
5
6
|
*/
|
|
6
7
|
validate(request: Request): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* 验证请求是否正确(v2)
|
|
10
|
+
*/
|
|
11
|
+
validateV2(message: Message): boolean;
|
|
7
12
|
}
|
|
8
13
|
export = ValidatorInterface;
|
package/dist/Pay/Merchant.d.ts
CHANGED
package/dist/Pay/Merchant.js
CHANGED
package/dist/Pay/Validator.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ValidatorInterface from "./Contracts/ValidatorInterface";
|
|
2
|
-
import
|
|
2
|
+
import MessageInterface from "../Core/Http/Contracts/MessageInterface";
|
|
3
3
|
import MerchantInterface from "./Contracts/MerchantInterface";
|
|
4
|
+
import Message from "./Message";
|
|
4
5
|
declare class Validator implements ValidatorInterface {
|
|
5
6
|
protected merchant: MerchantInterface;
|
|
6
7
|
static MAX_ALLOWED_CLOCK_OFFSET: number;
|
|
@@ -9,6 +10,7 @@ declare class Validator implements ValidatorInterface {
|
|
|
9
10
|
static HEADER_SERIAL: string;
|
|
10
11
|
static HEADER_SIGNATURE: string;
|
|
11
12
|
constructor(merchant: MerchantInterface);
|
|
12
|
-
validate(request:
|
|
13
|
+
validate(request: MessageInterface): boolean;
|
|
14
|
+
validateV2(message: Message): boolean;
|
|
13
15
|
}
|
|
14
16
|
export = Validator;
|
package/dist/Pay/Validator.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
const Utils_1 = require("../Core/Support/Utils");
|
|
6
6
|
const RSA_1 = __importDefault(require("../Core/Support/RSA"));
|
|
7
|
+
const Utils_2 = __importDefault(require("./Utils"));
|
|
7
8
|
class Validator {
|
|
8
9
|
constructor(merchant) {
|
|
9
10
|
this.merchant = merchant;
|
|
@@ -39,6 +40,18 @@ class Validator {
|
|
|
39
40
|
}
|
|
40
41
|
return true;
|
|
41
42
|
}
|
|
43
|
+
validateV2(message) {
|
|
44
|
+
let messageSign = (message.get('sign') + '' || '').toUpperCase();
|
|
45
|
+
if (!messageSign) {
|
|
46
|
+
throw new Error('Missing Signature');
|
|
47
|
+
}
|
|
48
|
+
const utils = new Utils_2.default(this.merchant);
|
|
49
|
+
let calculateSign = utils.createV2Signature(message.toObject());
|
|
50
|
+
if (messageSign !== calculateSign) {
|
|
51
|
+
throw new Error('Invalid Signature');
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
42
55
|
}
|
|
43
56
|
Validator.MAX_ALLOWED_CLOCK_OFFSET = 300;
|
|
44
57
|
Validator.HEADER_TIMESTAMP = 'Wechatpay-Timestamp';
|
package/dist/Types/global.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import OpenPlatformMessage from '../OpenPlatform/Message';
|
|
|
10
10
|
import OpenWorkMessage from '../OpenWork/Message';
|
|
11
11
|
import HttpClientResponseInterface from '../Core/HttpClient/Contracts/HttpClientResponseInterface';
|
|
12
12
|
import { PublicKey } from "../Core/Support/PublicKey";
|
|
13
|
+
import { IAxiosRetryConfig } from 'axios-retry';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* 微信接口响应数据格式
|
|
@@ -75,7 +76,7 @@ export interface HttpConfig extends AxiosRequestConfig {
|
|
|
75
76
|
* 是否抛出异常
|
|
76
77
|
* @see https://github.com/softonic/axios-retry#options
|
|
77
78
|
*/
|
|
78
|
-
retry?:
|
|
79
|
+
retry?: IAxiosRetryConfig;
|
|
79
80
|
// retry?: {
|
|
80
81
|
// /**
|
|
81
82
|
// * 仅以下状态码重试
|