node-easywechat 3.0.0-beta.3 → 3.0.0

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +36 -1
  3. package/dist/Core/Contracts/RefreshableAccessTokenInterface.d.ts +2 -2
  4. package/dist/Core/Contracts/RefreshableAccessTokenInterface.js +2 -2
  5. package/dist/Core/Http/Minxins/MessageMixin.js +1 -2
  6. package/dist/Core/Http/ServerRequest.d.ts +1 -1
  7. package/dist/Core/Http/ServerRequest.js +16 -6
  8. package/dist/Core/HttpClient/HttpClient.d.ts +7 -0
  9. package/dist/Core/HttpClient/HttpClient.js +43 -7
  10. package/dist/Core/HttpClient/HttpClientResponse.d.ts +16 -5
  11. package/dist/Core/HttpClient/HttpClientResponse.js +64 -22
  12. package/dist/Core/HttpClient/Mixins/PresetMixin.d.ts +20 -1
  13. package/dist/Core/HttpClient/Mixins/PresetMixin.js +41 -2
  14. package/dist/Core/Message.d.ts +0 -127
  15. package/dist/Core/Message.js +5 -1
  16. package/dist/Core/Mixins/DecryptXmlMessageMixin.js +1 -1
  17. package/dist/Core/Mixins/ResponseXmlMessageMixin.js +2 -2
  18. package/dist/Core/Support/PrivateKey.d.ts +20 -0
  19. package/dist/Core/Support/PrivateKey.js +38 -0
  20. package/dist/Core/Support/PublicKey.d.ts +14 -0
  21. package/dist/Core/Support/PublicKey.js +36 -0
  22. package/dist/Core/Support/RSA.d.ts +2 -2
  23. package/dist/Core/Support/RSA.js +4 -4
  24. package/dist/Core/Support/Utils.d.ts +6 -0
  25. package/dist/Core/Support/Utils.js +15 -1
  26. package/dist/MiniApp/Application.d.ts +4 -4
  27. package/dist/MiniApp/Contracts/ApplicationInterface.d.ts +2 -2
  28. package/dist/OfficialAccount/AccessToken.d.ts +2 -2
  29. package/dist/OfficialAccount/AccessToken.js +2 -2
  30. package/dist/OfficialAccount/Application.d.ts +4 -4
  31. package/dist/OfficialAccount/Application.js +0 -5
  32. package/dist/OfficialAccount/Contracts/ApplicationInterface.d.ts +2 -2
  33. package/dist/OfficialAccount/JsApiTicket.js +2 -2
  34. package/dist/OfficialAccount/Message.d.ts +139 -0
  35. package/dist/OfficialAccount/Message.js +1 -0
  36. package/dist/OfficialAccount/Server.js +1 -1
  37. package/dist/Pay/Application.d.ts +52 -0
  38. package/dist/Pay/Application.js +96 -0
  39. package/dist/Pay/Client.d.ts +42 -0
  40. package/dist/Pay/Client.js +125 -0
  41. package/dist/Pay/Config.d.ts +5 -0
  42. package/dist/Pay/Config.js +17 -0
  43. package/dist/Pay/Contracts/ApplicationInterface.d.ts +50 -0
  44. package/dist/Pay/Contracts/ApplicationInterface.js +45 -0
  45. package/dist/Pay/Contracts/MerchantInterface.d.ts +35 -0
  46. package/dist/Pay/Contracts/MerchantInterface.js +35 -0
  47. package/dist/Pay/Contracts/ResponseValidatorInterface.d.ts +9 -0
  48. package/dist/Pay/Contracts/ResponseValidatorInterface.js +10 -0
  49. package/dist/Pay/LegacySignature.d.ts +12 -0
  50. package/dist/Pay/LegacySignature.js +59 -0
  51. package/dist/Pay/Merchant.d.ts +25 -0
  52. package/dist/Pay/Merchant.js +53 -0
  53. package/dist/Pay/Message.d.ts +175 -0
  54. package/dist/Pay/Message.js +24 -0
  55. package/dist/Pay/Server.d.ts +41 -0
  56. package/dist/Pay/Server.js +122 -0
  57. package/dist/Pay/Signature.d.ts +15 -0
  58. package/dist/Pay/Signature.js +44 -0
  59. package/dist/Pay/Utils.d.ts +54 -0
  60. package/dist/Pay/Utils.js +142 -0
  61. package/dist/Types/global.d.ts +114 -1
  62. package/dist/index.d.ts +3 -3
  63. package/dist/index.js +3 -3
  64. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,6 +1,35 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
+ ## v3.0.0 (2022-07-28)
5
+
6
+ - Feat: 请求后自动解析响应结果,简化获取数据的方式
7
+ - Feat: 新增微信支付模块的公共调用方法
8
+ - Feat: 新增支付模块
9
+
10
+ - Fix: 响应内容解析时排除buffer对象
11
+ - Fix: 修复获取框架版本异常的问题
12
+ - Fix: 修复获取响应对象的字符串数据时异常的问题
13
+ - Fix: 修复测试用例中post等方式模拟请求时异常的问题
14
+ - Fix: 调整微信支付配置项
15
+ - Fix: 修复消息参数提示缺失问题
16
+ - Fix: 调整默认的RSA加密算法中的哈希方式为sha256
17
+ - Fix: 调整默认Message提示的作用域为公众号和小程序
18
+ - Fix: 修复AccessToken对象声明错误的问题
19
+
20
+ - Docs: 增加微信支付相关说明文档
21
+
22
+ ## v3.0.0-beta.5 (2022-06-29)
23
+
24
+ - Fix: 修复服务端获取消息异常的问题
25
+
26
+ ## v3.0.0-beta.4 (2022-06-24)
27
+
28
+ - Feat: 增加链式添加上传文件的方法
29
+ - Feat: 请求接口数据增加 FormData 实例的支持
30
+
31
+ - Fix: 修复接受微信回调接口验证请求时,返回对象无文件内容的问题
32
+
4
33
  ## v3.0.0-beta.3 (2022-06-22)
5
34
 
6
35
  - Fix: 修复获取js ticket时无法自动获取access_token的问题
package/README.md CHANGED
@@ -37,16 +37,31 @@ let app = new MiniApp({
37
37
  // 配置项
38
38
  });
39
39
 
40
+ // 微信支付
41
+ const { Pay } = require('node-easywechat');
42
+ // 实例化应用
43
+ let app = new Pay({
44
+ // 配置项
45
+ });
46
+
40
47
  // ----- 以下为通用的 api 调用方法 -----
41
48
 
42
49
  // 获取 api 调用客户端
43
50
  let client = app.getClient();
44
51
 
45
52
  // 请求 api
53
+ // 注意,这里返回的是 HttpClientResponse 对象
46
54
  let response = await client.post('/cgi-bin/user/info/updateremark', {
47
55
  openid: 'xxxx',
48
56
  remark: 'xxxx',
49
57
  });
58
+ // 获取具体数据
59
+ let data = response.toObject();
60
+ // 另外还有以下方法:
61
+ // toJson() 转json字符串
62
+ // toString() 转字符串
63
+ // saveAs(filename) 保存为文件
64
+ // toDataUrl() 转base64字符串
50
65
  ```
51
66
 
52
67
  ### 配置项示例
@@ -103,6 +118,26 @@ let response = await client.post('/cgi-bin/user/info/updateremark', {
103
118
  }
104
119
  ```
105
120
 
121
+ ``` js
122
+ // 微信支付配置
123
+ {
124
+ // 商户号
125
+ mch_id: '',
126
+ // 商户证书路径
127
+ certificate: '',
128
+ // 商户证书私钥路径
129
+ private_key: '',
130
+ // 平台证书(v3接口需要)
131
+ // 持路径列表或者PublicKey对象列表或者,以serial_no为key,证书内容或PublicKey对象为value的对象
132
+ // 下载工具:https://github.com/wechatpay-apiv3/CertificateDownloader
133
+ platform_certs: '',
134
+ // v3 API密钥
135
+ secret_key: '',
136
+ // v2 API密钥
137
+ v2_secret_key: '',
138
+ }
139
+ ```
140
+
106
141
  ### 自定义模块(模块替换)使用方法
107
142
 
108
143
  #### 日志模块
@@ -214,7 +249,7 @@ app.setRequest(request);
214
249
  ### 模块支持情况
215
250
 
216
251
  - [x] 公众号模块
217
- - [ ] 微信支付
252
+ - [x] 微信支付
218
253
  - [x] 小程序
219
254
  - [ ] 开放平台
220
255
  - [ ] 企业微信
@@ -1,9 +1,9 @@
1
1
  import AccessTokenInterface from "./AccessTokenInterface";
2
- declare abstract class RefreshableAccessToken extends AccessTokenInterface {
2
+ declare abstract class RefreshableAccessTokenInterface extends AccessTokenInterface {
3
3
  /**
4
4
  * 刷新token
5
5
  * @returns
6
6
  */
7
7
  refresh(): Promise<string>;
8
8
  }
9
- export = RefreshableAccessToken;
9
+ export = RefreshableAccessTokenInterface;
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  const AccessTokenInterface_1 = __importDefault(require("./AccessTokenInterface"));
15
- class RefreshableAccessToken extends AccessTokenInterface_1.default {
15
+ class RefreshableAccessTokenInterface extends AccessTokenInterface_1.default {
16
16
  /**
17
17
  * 刷新token
18
18
  * @returns
@@ -22,4 +22,4 @@ class RefreshableAccessToken extends AccessTokenInterface_1.default {
22
22
  }
23
23
  }
24
24
  ;
25
- module.exports = RefreshableAccessToken;
25
+ module.exports = RefreshableAccessTokenInterface;
@@ -63,8 +63,7 @@ class MessageMixin {
63
63
  }
64
64
  withBody(body) {
65
65
  if (Buffer.isBuffer(body)) {
66
- this.content = Buffer.from('');
67
- this.content.copy(body);
66
+ this.content = body;
68
67
  }
69
68
  else if (typeof body === 'string') {
70
69
  this.content = Buffer.from(body);
@@ -43,7 +43,7 @@ declare class ServerRequest implements ServerRequestInterface {
43
43
  * @param body 支持 Buffer、object对象、JSON字符串、XML字符串、QueryString格式的 body 内容字符串
44
44
  * @returns
45
45
  */
46
- static createFromIncomingMessage(req: IncomingMessage, body?: Buffer | Record<string, any> | string): ServerRequest;
46
+ static createFromIncomingMessage(req: IncomingMessage, body?: Buffer | Record<string, any> | string): Promise<ServerRequest>;
47
47
  }
48
48
  interface ServerRequest extends MessageMixin, RequestMixin {
49
49
  }
@@ -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
  };
@@ -124,13 +133,14 @@ class ServerRequest {
124
133
  * @returns
125
134
  */
126
135
  static createFromIncomingMessage(req, body = null) {
127
- let request = new ServerRequest(req.method, req.url, req.headers || {}, body, req.httpVersion, (0, url_1.parse)(req.url, true).query || {});
128
- if (!body) {
129
- (0, raw_body_1.default)(req).then(res => {
136
+ return __awaiter(this, void 0, void 0, function* () {
137
+ let request = new ServerRequest(req.method, req.url, req.headers || {}, body, req.httpVersion);
138
+ if (!body) {
139
+ let res = yield (0, raw_body_1.default)(req);
130
140
  request.withBody(res);
131
- });
132
- }
133
- return request;
141
+ }
142
+ return request;
143
+ });
134
144
  }
135
145
  }
136
146
  ;
@@ -2,6 +2,7 @@ import { AxiosInstance, AxiosRequestConfig, Method } from 'axios';
2
2
  import HttpClientInterface from './Contracts/HttpClientInterface';
3
3
  import HttpClientResponse from './HttpClientResponse';
4
4
  import { HttpClientFailureJudgeClosure, LogHandler } from '../../Types/global';
5
+ import FormData from 'form-data';
5
6
  declare class HttpClient implements HttpClientInterface {
6
7
  protected axios: AxiosInstance;
7
8
  protected failureJudge: HttpClientFailureJudgeClosure;
@@ -19,6 +20,12 @@ declare class HttpClient implements HttpClientInterface {
19
20
  request(method: Method, url: string, payload?: AxiosRequestConfig<any>): Promise<HttpClientResponse>;
20
21
  getInstance(): AxiosInstance;
21
22
  setInstance(instance: AxiosInstance): this;
23
+ /**
24
+ * 获取 FormData 对象的 headers
25
+ * @param formData
26
+ * @returns
27
+ */
28
+ protected getFormDataHeaders(formData: FormData): Promise<Record<string, string | number>>;
22
29
  /**
23
30
  * 创建http客户端
24
31
  * @param config
@@ -11,10 +11,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
- const merge_1 = __importDefault(require("merge"));
15
14
  const axios_1 = __importDefault(require("axios"));
16
15
  const HttpClientResponse_1 = __importDefault(require("./HttpClientResponse"));
17
16
  const Utils_1 = require("../Support/Utils");
17
+ const form_data_1 = __importDefault(require("form-data"));
18
18
  class HttpClient {
19
19
  constructor(axios, failureJudge = null, throwError = false) {
20
20
  this.axios = axios;
@@ -35,7 +35,9 @@ class HttpClient {
35
35
  }
36
36
  request(method, url, payload = {}) {
37
37
  return __awaiter(this, void 0, void 0, function* () {
38
- let options = merge_1.default.recursive(true, payload);
38
+ let options = Object.assign({}, payload);
39
+ if (!options.headers)
40
+ options.headers = {};
39
41
  options.method = method;
40
42
  options.url = url;
41
43
  if (options['xml'] !== undefined) {
@@ -49,8 +51,6 @@ class HttpClient {
49
51
  else {
50
52
  throw new Error('The type of `xml` must be string or object.');
51
53
  }
52
- if (!options.headers)
53
- options.headers = {};
54
54
  if (!options.headers['Content-Type'] && !options.headers['content-type']) {
55
55
  options.headers['content-type'] = 'text/xml';
56
56
  }
@@ -69,8 +69,6 @@ class HttpClient {
69
69
  else {
70
70
  throw new Error('The type of `json` must be string or object.');
71
71
  }
72
- if (!options.headers)
73
- options.headers = {};
74
72
  if (!options.headers['Content-Type'] && !options.headers['content-type']) {
75
73
  options.headers['content-type'] = 'application/json';
76
74
  }
@@ -78,6 +76,23 @@ class HttpClient {
78
76
  options['json'] = undefined;
79
77
  delete options['json'];
80
78
  }
79
+ if (options['formData'] && Object.keys(options['formData']).length > 0) {
80
+ let formData = new form_data_1.default();
81
+ for (let key in options['formData']) {
82
+ formData.append(key, options['formData'][key]);
83
+ }
84
+ if (options.data)
85
+ for (let key in options.data) {
86
+ formData.append(key, options.data[key]);
87
+ }
88
+ options.data = formData;
89
+ options['formData'] = undefined;
90
+ delete options['formData'];
91
+ }
92
+ // 如果 data 是 FormData 对象,则从中提取 headers
93
+ if (options.data && options.data instanceof form_data_1.default) {
94
+ options.headers = Object.assign(Object.assign({}, (yield this.getFormDataHeaders(options.data))), options.headers);
95
+ }
81
96
  let starttime = Date.now();
82
97
  if (typeof this.logger === 'function') {
83
98
  yield this.logger('before', options);
@@ -87,7 +102,9 @@ class HttpClient {
87
102
  let usedTime = Date.now() - starttime;
88
103
  yield this.logger('after', options, usedTime, response);
89
104
  }
90
- return new HttpClientResponse_1.default(response, this.failureJudge, this.throwError);
105
+ let resp = new HttpClientResponse_1.default(response, this.failureJudge, this.throwError);
106
+ yield resp.parseContent(this.throwError);
107
+ return resp;
91
108
  });
92
109
  }
93
110
  getInstance() {
@@ -97,6 +114,25 @@ class HttpClient {
97
114
  this.axios = instance;
98
115
  return this;
99
116
  }
117
+ /**
118
+ * 获取 FormData 对象的 headers
119
+ * @param formData
120
+ * @returns
121
+ */
122
+ getFormDataHeaders(formData) {
123
+ return new Promise((resolve, reject) => {
124
+ let headers = formData.getHeaders();
125
+ formData.getLength(function (err, length) {
126
+ if (err) {
127
+ headers['content-length'] = 0;
128
+ }
129
+ else {
130
+ headers['content-length'] = length;
131
+ }
132
+ resolve(headers);
133
+ });
134
+ });
135
+ }
100
136
  /**
101
137
  * 创建http客户端
102
138
  * @param config
@@ -5,7 +5,20 @@ declare class HttpClientResponse implements HttpClientResponseInterface {
5
5
  protected response: AxiosResponse;
6
6
  protected failureJudge: HttpClientFailureJudgeClosure;
7
7
  protected throwError: boolean;
8
+ protected parsedContent: Record<string, any>;
8
9
  constructor(response: AxiosResponse, failureJudge?: HttpClientFailureJudgeClosure, throwError?: boolean);
10
+ /**
11
+ * 设置解析后的body内容
12
+ * @param content
13
+ * @returns
14
+ */
15
+ setParsedContent(content: Record<string, any>): this;
16
+ /**
17
+ * 解析body内容
18
+ * @param throwError
19
+ * @returns
20
+ */
21
+ parseContent(throwError?: boolean): Promise<void>;
9
22
  withThrowError(throwError: boolean): this;
10
23
  throwOnFailure(): this;
11
24
  quietly(): this;
@@ -27,21 +40,19 @@ declare class HttpClientResponse implements HttpClientResponseInterface {
27
40
  isSuccessful(): boolean;
28
41
  /**
29
42
  * 返回对象格式
30
- * @param throwError
31
43
  * @returns
32
44
  */
33
- toObject<T = WeixinResponse>(throwError?: boolean): Promise<T>;
45
+ toObject<T = WeixinResponse>(): T;
34
46
  /**
35
47
  * 返回json字符串
36
- * @param throwError
37
48
  * @returns
38
49
  */
39
- toJson(throwError?: boolean): Promise<string>;
50
+ toJson(): string;
40
51
  /**
41
52
  * 返回字符串
42
53
  * @returns
43
54
  */
44
- toString(): Promise<string>;
55
+ toString(): string;
45
56
  /**
46
57
  * 另存为文件
47
58
  * @param filename 完整的文件名(含路径)
@@ -15,10 +15,65 @@ const fs_1 = __importDefault(require("fs"));
15
15
  const merge_1 = __importDefault(require("merge"));
16
16
  const Utils_1 = require("../Support/Utils");
17
17
  class HttpClientResponse {
18
- constructor(response, failureJudge = null, throwError = true) {
18
+ constructor(response, failureJudge = null, throwError = false) {
19
19
  this.response = response;
20
20
  this.failureJudge = failureJudge;
21
21
  this.throwError = throwError;
22
+ this.parsedContent = null;
23
+ }
24
+ /**
25
+ * 设置解析后的body内容
26
+ * @param content
27
+ * @returns
28
+ */
29
+ setParsedContent(content) {
30
+ this.parsedContent = content;
31
+ return this;
32
+ }
33
+ /**
34
+ * 解析body内容
35
+ * @param throwError
36
+ * @returns
37
+ */
38
+ parseContent(throwError = false) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ throwError = throwError !== null && throwError !== void 0 ? throwError : this.throwError;
41
+ let content = this.response.data;
42
+ if (!content) {
43
+ if (throwError) {
44
+ throw new Error('Response body is empty.');
45
+ }
46
+ return;
47
+ }
48
+ if (typeof content === 'string') {
49
+ if (this.is('xml') && content.indexOf('<xml>') > -1) {
50
+ this.parsedContent = yield (0, Utils_1.parseXml)(content);
51
+ }
52
+ else if (this.is('json')) {
53
+ try {
54
+ this.parsedContent = JSON.parse(content);
55
+ }
56
+ catch (e) {
57
+ if (throwError) {
58
+ throw new Error('Fail to parse JSON content.');
59
+ }
60
+ }
61
+ }
62
+ else if (this.is('text')) {
63
+ try {
64
+ this.parsedContent = (0, Utils_1.parseQueryString)(content);
65
+ }
66
+ catch (e) {
67
+ if (throwError) {
68
+ throw new Error('Fail to parse QueryString content.');
69
+ }
70
+ }
71
+ }
72
+ }
73
+ else if (!Buffer.isBuffer(content)) {
74
+ this.parsedContent = content;
75
+ }
76
+ });
22
77
  }
23
78
  withThrowError(throwError) {
24
79
  this.throwError = throwError;
@@ -63,40 +118,25 @@ class HttpClientResponse {
63
118
  }
64
119
  /**
65
120
  * 返回对象格式
66
- * @param throwError
67
121
  * @returns
68
122
  */
69
- toObject(throwError = null) {
70
- return __awaiter(this, void 0, void 0, function* () {
71
- throwError = throwError === null ? this.throwError : throwError;
72
- let content = this.response.data;
73
- if (!content) {
74
- throw new Error('Response body is empty.');
75
- }
76
- if (typeof content === 'string') {
77
- if (this.is('xml') && content.indexOf('<xml>') > -1) {
78
- return (0, Utils_1.parseXml)(content);
79
- }
80
- }
81
- return content;
82
- });
123
+ toObject() {
124
+ return this.parsedContent;
83
125
  }
84
126
  /**
85
127
  * 返回json字符串
86
- * @param throwError
87
128
  * @returns
88
129
  */
89
- toJson(throwError = null) {
90
- return __awaiter(this, void 0, void 0, function* () {
91
- return JSON.stringify(yield this.toObject(throwError));
92
- });
130
+ toJson() {
131
+ return JSON.stringify(this.toObject());
93
132
  }
94
133
  /**
95
134
  * 返回字符串
96
135
  * @returns
97
136
  */
98
137
  toString() {
99
- return this.toJson();
138
+ let obj = this.getContent();
139
+ return (typeof obj === 'object' && obj !== null) ? JSON.stringify(obj) : String(obj);
100
140
  }
101
141
  /**
102
142
  * 另存为文件
@@ -126,6 +166,8 @@ class HttpClientResponse {
126
166
  */
127
167
  is(type) {
128
168
  let contentType = this.getHeader('content-type');
169
+ if (!contentType)
170
+ return false;
129
171
  let res = false;
130
172
  switch (type.toLowerCase()) {
131
173
  case 'json':
@@ -1,4 +1,6 @@
1
+ /// <reference types="node" />
1
2
  import { AxiosRequestConfig, Method } from "axios";
3
+ import fs from "fs";
2
4
  declare class PresetMixin {
3
5
  /**
4
6
  * 存储预置参数
@@ -12,6 +14,10 @@ declare class PresetMixin {
12
14
  * 存储预置数据
13
15
  */
14
16
  protected prependData: Record<string, any>;
17
+ /**
18
+ * 存储预置文件数据
19
+ */
20
+ protected prependFiles: Record<string, fs.ReadStream>;
15
21
  /**
16
22
  * 设置预置参数
17
23
  * @param presets
@@ -68,12 +74,25 @@ declare class PresetMixin {
68
74
  * @returns
69
75
  */
70
76
  withMchIdAs(new_alias?: string): this;
77
+ /**
78
+ * 预设置文件
79
+ * @param file 文件路径或可读文件流
80
+ * @param key 参数名,默认:'file'
81
+ * @returns
82
+ */
83
+ withFile(file: string | fs.ReadStream, key?: string): this;
84
+ /**
85
+ * 预设置多个文件
86
+ * @param files 键名:文件名,键值:文件路径或可读文件流
87
+ * @returns
88
+ */
89
+ withFiles(files: Record<string, string | fs.ReadStream>): this;
71
90
  /**
72
91
  * 合并预置参数并清空预置数据
73
92
  * @param payload
74
93
  * @param method
75
94
  * @returns
76
95
  */
77
- mergeThenResetPrepends(payload: AxiosRequestConfig, method?: Method): any;
96
+ mergeThenResetPrepends(payload: AxiosRequestConfig, method?: Method): AxiosRequestConfig<any>;
78
97
  }
79
98
  export = PresetMixin;
@@ -2,7 +2,7 @@
2
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
- const merge_1 = __importDefault(require("merge"));
5
+ const fs_1 = __importDefault(require("fs"));
6
6
  class PresetMixin {
7
7
  constructor() {
8
8
  /**
@@ -17,6 +17,10 @@ class PresetMixin {
17
17
  * 存储预置数据
18
18
  */
19
19
  this.prependData = {};
20
+ /**
21
+ * 存储预置文件数据
22
+ */
23
+ this.prependFiles = {};
20
24
  }
21
25
  /**
22
26
  * 设置预置参数
@@ -123,6 +127,35 @@ class PresetMixin {
123
127
  this.with(new_alias, this.presets['mch_id']);
124
128
  return this;
125
129
  }
130
+ /**
131
+ * 预设置文件
132
+ * @param file 文件路径或可读文件流
133
+ * @param key 参数名,默认:'file'
134
+ * @returns
135
+ */
136
+ withFile(file, key = 'file') {
137
+ if (typeof this.prependFiles !== 'object') {
138
+ this.prependFiles = {};
139
+ }
140
+ if (file instanceof fs_1.default.ReadStream) {
141
+ this.prependFiles[key] = file;
142
+ }
143
+ else if (typeof file === 'string') {
144
+ this.prependFiles[key] = fs_1.default.createReadStream(file);
145
+ }
146
+ return this;
147
+ }
148
+ /**
149
+ * 预设置多个文件
150
+ * @param files 键名:文件名,键值:文件路径或可读文件流
151
+ * @returns
152
+ */
153
+ withFiles(files) {
154
+ for (const key in files) {
155
+ this.withFile(files[key], key);
156
+ }
157
+ return this;
158
+ }
126
159
  /**
127
160
  * 合并预置参数并清空预置数据
128
161
  * @param payload
@@ -132,9 +165,11 @@ class PresetMixin {
132
165
  mergeThenResetPrepends(payload, method = 'get') {
133
166
  var _a, _b, _c, _d;
134
167
  let field = method.toLowerCase() === 'get' ? 'params' : 'data';
135
- let options = merge_1.default.recursive(true, payload);
168
+ let options = Object.assign({}, payload);
136
169
  if (!options.headers)
137
170
  options.headers = {};
171
+ if (!options.formData)
172
+ options.formData = {};
138
173
  if (((_b = (_a = options.headers['Content-Type']) !== null && _a !== void 0 ? _a : options.headers['content-type']) !== null && _b !== void 0 ? _b : null) === 'application/json' || !!options.json) {
139
174
  field = 'json';
140
175
  }
@@ -147,8 +182,12 @@ class PresetMixin {
147
182
  if (this.prependHeaders && Object.keys(this.prependHeaders).length > 0) {
148
183
  options.headers = Object.assign(Object.assign({}, this.prependHeaders), options.headers);
149
184
  }
185
+ if (this.prependFiles && Object.keys(this.prependFiles).length > 0) {
186
+ options.formData = Object.assign(Object.assign({}, this.prependFiles), options.formData);
187
+ }
150
188
  this.prependData = {};
151
189
  this.prependHeaders = {};
190
+ this.prependFiles = {};
152
191
  return options;
153
192
  }
154
193
  }