@yunzhanghu/sdk-nodejs 1.0.2 → 1.0.4

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 (66) hide show
  1. package/.editorconfig +8 -0
  2. package/.eslintrc.js +16 -0
  3. package/.prettierrc.js +3 -0
  4. package/README.md +23 -6
  5. package/example/apiUserSign.js +66 -12
  6. package/example/authentication.js +136 -25
  7. package/example/bizlicXjjH5.js +33 -7
  8. package/example/bizlicXjjH5Api.js +50 -10
  9. package/example/conf/config.js +2 -0
  10. package/example/dataService.js +105 -8
  11. package/example/h5UserSign.js +65 -10
  12. package/example/invoice.js +111 -14
  13. package/example/notify.js +0 -1
  14. package/example/payment.js +208 -26
  15. package/example/tax.js +31 -3
  16. package/example/uploadusersign.js +66 -0
  17. package/package.json +50 -45
  18. package/src/common/client.ts +364 -355
  19. package/src/common/exception/yzhSDKHttpException.ts +29 -26
  20. package/src/common/http/index.ts +62 -53
  21. package/src/common/utils/index.ts +16 -14
  22. package/src/index.ts +1 -1
  23. package/src/services/apiusersign/index.ts +107 -105
  24. package/src/services/authentication/index.ts +162 -196
  25. package/src/services/bizlicxjjh5/index.ts +77 -107
  26. package/src/services/bizlicxjjh5api/index.ts +108 -156
  27. package/src/services/dataservice/index.ts +246 -268
  28. package/src/services/h5usersign/index.ts +93 -105
  29. package/src/services/index.ts +11 -10
  30. package/src/services/invoice/index.ts +184 -244
  31. package/src/services/payment/index.ts +501 -435
  32. package/src/services/tax/index.ts +53 -51
  33. package/src/services/uploadusersign/index.ts +88 -0
  34. package/src/typings.d.ts +1 -1
  35. package/tdsformat.js +22 -0
  36. package/tsconfig.json +2 -1
  37. package/yzh/common/client.d.ts +3 -0
  38. package/yzh/common/client.js +9 -3
  39. package/yzh/common/http/index.d.ts +1 -0
  40. package/yzh/common/http/index.js +18 -8
  41. package/yzh/common/utils/index.d.ts +1 -0
  42. package/yzh/common/utils/index.js +1 -0
  43. package/yzh/services/apiusersign/index.d.ts +34 -7
  44. package/yzh/services/apiusersign/index.js +9 -8
  45. package/yzh/services/authentication/index.d.ts +57 -19
  46. package/yzh/services/authentication/index.js +12 -11
  47. package/yzh/services/bizlicxjjh5/index.d.ts +16 -4
  48. package/yzh/services/bizlicxjjh5/index.js +6 -5
  49. package/yzh/services/bizlicxjjh5api/index.d.ts +22 -5
  50. package/yzh/services/bizlicxjjh5api/index.js +7 -6
  51. package/yzh/services/dataservice/index.d.ts +52 -11
  52. package/yzh/services/dataservice/index.js +23 -10
  53. package/yzh/services/h5usersign/index.d.ts +28 -6
  54. package/yzh/services/h5usersign/index.js +8 -7
  55. package/yzh/services/index.d.ts +3 -2
  56. package/yzh/services/index.js +7 -5
  57. package/yzh/services/invoice/index.d.ts +51 -12
  58. package/yzh/services/invoice/index.js +11 -10
  59. package/yzh/services/payment/index.d.ts +194 -18
  60. package/yzh/services/payment/index.js +28 -13
  61. package/yzh/services/tax/index.d.ts +17 -4
  62. package/yzh/services/tax/index.js +6 -5
  63. package/yzh/services/uploadusersign/index.d.ts +78 -0
  64. package/yzh/services/uploadusersign/index.js +19 -0
  65. package/.eslintrc.json +0 -19
  66. package/prettier.config.js +0 -32
@@ -1,368 +1,377 @@
1
- import getInstance from "../common/http"
2
- import * as crypto from "crypto"
3
- import YZHSDKHttpException from "./exception/yzhSDKHttpException"
4
- const clearEncoding = "utf8"
5
- const cipherEncoding = "base64"
1
+ /* eslint-disable no-param-reassign */
2
+ import * as crypto from 'crypto';
6
3
 
7
- export type ResponseCallback<TReuslt = any> = (error: null | string, rep: TReuslt) => void
4
+ import getInstance from '../common/http';
5
+ import YZHSDKHttpException from './exception/yzhSDKHttpException';
8
6
 
9
- type ResponseData = any
7
+ const clearEncoding = 'utf8';
8
+ const cipherEncoding = 'base64';
9
+
10
+ export type ResponseCallback<TReuslt = any> = (error: null | string, rep: TReuslt) => void;
11
+
12
+ type ResponseData = any;
10
13
 
11
14
  export class YZHClient {
12
- public dealer_id: string
13
- public broker_id: string
14
- public app_key: string
15
- public des3_key: string
16
- public private_key: string
17
- public yzh_public_key: string
18
- public sign_type: "rsa" | "sha256"
19
- public base_url?: string
20
-
21
- /**
22
- * 构造函数参数
23
- * @param {string} dealer_id 平台企业 ID
24
- * @param {string} broker_id 综合服务主体 ID
25
- * @param {string} app_key App Key
26
- * @param {string} des3_key 3DES Key
27
- * @param {string} private_key 平台企业私钥
28
- * @param {string} yzh_public_key 云账户公钥
29
- * @param {string} sign_type 签名算法,支持 RSA、HMAC,枚举分别为 rsa、sha256
30
- * @param {string} base_url 可选,默认为 https://api-service.yunzhanghu.com/
31
- */
32
- constructor(conf: {
33
- dealer_id: string
34
- broker_id: string
35
- app_key: string
36
- des3_key: string
37
- private_key: string
38
- yzh_public_key: string
39
- sign_type: "rsa" | "sha256"
40
- base_url?: string
41
- }) {
42
- const { dealer_id, broker_id, app_key, des3_key, private_key, yzh_public_key, sign_type } =
43
- conf || {}
44
- if (
45
- conf &&
46
- dealer_id &&
47
- broker_id &&
48
- app_key &&
49
- des3_key &&
50
- private_key &&
51
- yzh_public_key &&
52
- sign_type
53
- ) {
54
- this.dealer_id = conf.dealer_id
55
- this.broker_id = conf.broker_id
56
- this.app_key = conf.app_key
57
- this.des3_key = conf.des3_key
58
- this.private_key = conf.private_key
59
- this.yzh_public_key = conf.yzh_public_key
60
- this.sign_type = conf.sign_type
61
- this.base_url = conf?.base_url
62
- } else {
63
- throw new YZHSDKHttpException(
64
- `实例初始化失败,请检查以下配置是否缺失:\ndealer_id、broker_id、app_key、des3_key、private_key、yzh_public_key、sign_type`
65
- )
66
- }
67
- }
68
-
69
- // 基础请求:进行请求实例生成 Header,动态设置、请求体包装等偏底层操作
70
- private doRequest(method: string, action: string, req: any): Promise<ResponseData> {
71
- const { request_id, ...resReq } = req
72
- // 请求参数加密
73
- const encryptParams = this.generatorRequestParams(resReq)
74
- // 生成请求实例,配置 Header
75
- const instance = getInstance({
76
- request_id: request_id ?? this.mess(),
77
- dealer_id: this.dealer_id,
78
- base_url: this.base_url,
79
- })
80
- // 返回请求实例
81
- const baseInstanceConf = { method: method, url: action }
82
- let instanceConf
83
- if (method === "get") {
84
- instanceConf = { ...baseInstanceConf, params: encryptParams }
85
- } else {
86
- instanceConf = { ...baseInstanceConf, data: encryptParams }
87
- }
88
- return instance(instanceConf)
89
- }
90
-
91
- // 公共请求:调用封装好的基础请求方法 doRequest,进行发送请求与响应内容处理
92
- async request(
93
- method: string,
94
- action: string,
95
- req?: any,
96
- options?: { encryption: boolean },
97
- cb?: ResponseCallback
98
- ): Promise<ResponseData> {
99
- if (typeof options === "function") {
100
- cb = options
101
- options = {} as any
102
- }
103
- try {
104
- const result = await this.doRequest(method, action, req ?? {})
105
- // 错误码处理 > 验签 > 解密
106
- const responseData = await this.parseResponse(result, options?.encryption)
107
- cb && cb(null, responseData)
108
-
109
- return responseData
110
- } catch (e) {
111
- if (cb) {
112
- cb(e as any, null)
113
- } else {
114
- throw e
115
- }
116
- }
117
- }
118
-
119
- /**
120
- * 请求参数加密
121
- * @param {object} params
122
- * @returns {*} object
123
- */
124
- private generatorRequestParams(params: string) {
125
- try {
126
- const t = Date.now().toString()
127
- const m = this.mess()
128
-
129
- const plaintext = JSON.stringify(params)
130
-
131
- const data = this.encrypt(plaintext)
132
-
133
- const signStr = this.sign(data, m, t)
134
- return {
135
- data,
136
- mess: m,
137
- timestamp: t,
138
- sign: signStr,
139
- sign_type: this.sign_type,
140
- }
141
- } catch (err) {
142
- throw new YZHSDKHttpException(`${err}`)
143
- }
144
- }
145
-
146
- /**
147
- * 生成签名(RSA 签名算法)
148
- * @param {string} data 经过加密后的具体数据
149
- * @param {string} mess 自定义随机字符串,用于签名
150
- * @param {string} timestamp 时间戳,精确到秒
151
- * @returns {string} 签名内容
152
- */
153
- private signRSASHA256 = (data: string, mess: string, timestamp: string) => {
154
- try {
155
- const plaintext = `data=${data}&mess=${mess}&timestamp=${timestamp}&key=${this.app_key}`
156
- const sign = crypto.createSign("RSA-SHA256")
157
- sign.update(plaintext)
158
- sign.end()
159
- return sign.sign(this.private_key, cipherEncoding)
160
- } catch (err) {
161
- throw new YZHSDKHttpException(`${err}`)
15
+ public dealer_id: string;
16
+
17
+ public broker_id: string;
18
+
19
+ public app_key: string;
20
+
21
+ public des3_key: string;
22
+
23
+ public private_key: string;
24
+
25
+ public yzh_public_key: string;
26
+
27
+ public sign_type: 'rsa' | 'sha256';
28
+
29
+ public base_url?: string;
30
+
31
+ public timeout?: number;
32
+
33
+ /**
34
+ * 构造函数参数
35
+ * @param {string} dealer_id 平台企业 ID
36
+ * @param {string} broker_id 综合服务主体 ID
37
+ * @param {string} app_key App Key
38
+ * @param {string} des3_key 3DES Key
39
+ * @param {string} private_key 平台企业私钥
40
+ * @param {string} yzh_public_key 云账户公钥
41
+ * @param {string} sign_type 签名算法,支持 RSA、HMAC,枚举分别为 rsa、sha256
42
+ * @param {string} base_url 可选,默认为 https://api-service.yunzhanghu.com/
43
+ * @param {number} timeout 请求超时时间。可选,默认30*1000ms。0为永不超时。
44
+ */
45
+ constructor(conf: {
46
+ dealer_id: string;
47
+ broker_id: string;
48
+ app_key: string;
49
+ des3_key: string;
50
+ private_key: string;
51
+ yzh_public_key: string;
52
+ sign_type: 'rsa' | 'sha256';
53
+ base_url?: string;
54
+ timeout?: number;
55
+ }) {
56
+ const { dealer_id, broker_id, app_key, des3_key, private_key, yzh_public_key, sign_type } = conf || {};
57
+ if (conf && dealer_id && broker_id && app_key && des3_key && private_key && yzh_public_key && sign_type) {
58
+ this.dealer_id = conf.dealer_id;
59
+ this.broker_id = conf.broker_id;
60
+ this.app_key = conf.app_key;
61
+ this.des3_key = conf.des3_key;
62
+ this.private_key = conf.private_key;
63
+ this.yzh_public_key = conf.yzh_public_key;
64
+ this.sign_type = conf.sign_type;
65
+ this.base_url = conf?.base_url;
66
+ this.timeout = conf?.timeout;
67
+ } else {
68
+ throw new YZHSDKHttpException(
69
+ `实例初始化失败,请检查以下配置是否缺失:\ndealer_id、broker_id、app_key、des3_key、private_key、yzh_public_key、sign_type`
70
+ );
71
+ }
162
72
  }
163
- }
164
-
165
- /**
166
- * 生成签名(HMAC 签名算法)
167
- * @param {string} data 经过加密后的具体数据
168
- * @param {string} mess 自定义随机字符串,用于签名
169
- * @param {string} timestamp 时间戳,精确到秒
170
- * @returns {string} 签名内容
171
- */
172
- private signHmacSHA256 = (data: string, mess: string, timestamp: string) => {
173
- try {
174
- const plaintext = `data=${data}&mess=${mess}&timestamp=${timestamp}&key=${this.app_key}`
175
- const hmac = crypto.createHmac("sha256", this.app_key)
176
- hmac.update(plaintext)
177
- return hmac.digest("hex")
178
- } catch (err) {
179
- throw new YZHSDKHttpException(`${err}`)
73
+
74
+ // 基础请求:进行请求实例生成 Header,动态设置、请求体包装等偏底层操作
75
+ private doRequest(method: string, action: string, req: any): Promise<ResponseData> {
76
+ const { request_id, ...resReq } = req;
77
+ // 请求参数加密
78
+ const encryptParams = this.generatorRequestParams(resReq);
79
+ // 生成请求实例,配置 Header
80
+ const instance = getInstance({
81
+ request_id: request_id ?? this.mess(),
82
+ dealer_id: this.dealer_id,
83
+ base_url: this.base_url,
84
+ timeout: this.timeout,
85
+ });
86
+
87
+ // 返回请求实例
88
+ const baseInstanceConf = { method, url: action };
89
+ let instanceConf;
90
+ if (method === 'get') {
91
+ instanceConf = { ...baseInstanceConf, params: encryptParams };
92
+ } else {
93
+ instanceConf = { ...baseInstanceConf, data: encryptParams };
94
+ }
95
+ return instance(instanceConf);
180
96
  }
181
- }
182
-
183
- /**
184
- * 生成签名
185
- * @param {string} data 经过加密后的具体数据
186
- * @param {string} mess 自定义随机字符串,用于签名
187
- * @param {string} timestamp 时间戳,精确到秒
188
- * @param {string} sign_type 签名算法,支持 RSA、HMAC,枚举分别为 rsa、sha256
189
- * @returns {string} 签名内容
190
- */
191
- private sign = (data: string, mess: string, timestamp: string) => {
192
- try {
193
- switch (this.sign_type) {
194
- case "rsa": {
195
- return this.signRSASHA256(data, mess, timestamp)
97
+
98
+ // 公共请求:调用封装好的基础请求方法 doRequest,进行发送请求与响应内容处理
99
+ async request(
100
+ method: string,
101
+ action: string,
102
+ req?: any,
103
+ options?: { encryption: boolean },
104
+ cb?: ResponseCallback
105
+ ): Promise<ResponseData> {
106
+ if (typeof options === 'function') {
107
+ cb = options;
108
+ options = {} as any;
196
109
  }
197
- case "sha256": {
198
- return this.signHmacSHA256(data, mess, timestamp)
110
+ try {
111
+ const result = await this.doRequest(method, action, req ?? {});
112
+ // 错误码处理 > 验签 > 解密
113
+ const responseData = await this.parseResponse(result, options?.encryption);
114
+ cb && cb(null, responseData);
115
+
116
+ return responseData;
117
+ } catch (e) {
118
+ if (cb) {
119
+ cb(e as any, null);
120
+ } else {
121
+ throw e;
122
+ }
199
123
  }
200
- default:
201
- throw new YZHSDKHttpException(`sign_type类型不存在`)
202
- }
203
- } catch (err) {
204
- throw new YZHSDKHttpException(`${err}`)
205
- }
206
- }
207
-
208
- // 自定义随机字符串
209
- private mess = () => {
210
- const buf = crypto.randomBytes(16)
211
- const token = buf.toString("hex")
212
- return token.toString()
213
- }
214
-
215
- /**
216
- * 3DES 加密数据
217
- * @param plaintext
218
- * @returns 字符串加密数据
219
- */
220
- private encrypt = (plaintext: string) => {
221
- try {
222
- const iv = this.des3_key.slice(0, 8)
223
- const cipherChunks = []
224
- const cipher = crypto.createCipheriv("des-ede3-cbc", this.des3_key, iv)
225
- cipher.setAutoPadding(true)
226
- cipherChunks.push(cipher.update(plaintext, clearEncoding, cipherEncoding))
227
- cipherChunks.push(cipher.final(cipherEncoding))
228
-
229
- return cipherChunks.join("")
230
- } catch (err) {
231
- throw new YZHSDKHttpException(`${err}`)
232
- }
233
- }
234
-
235
- // 返回处理结果
236
- private async parseResponse(result: ResponseData, encryption?: boolean) {
237
- if (result.status !== 200) {
238
- const yzhError = new YZHSDKHttpException(result.statusText)
239
- yzhError.httpCode = result.status
240
- throw yzhError
241
- } else {
242
- // HTTP Status Code 200
243
- const { data: axiosData } = result
244
- let response = axiosData
245
- // 需解密
246
- if (encryption) {
247
- response = { ...response, data: this.decrypt(response.data) }
248
- }
249
- return response
250
- }
251
- }
252
-
253
- /**
254
- * 3DES 解密数据
255
- * @param ciphertext
256
- * @returns 明文数据
257
- */
258
- decrypt = (ciphertext: string) => {
259
- try {
260
- const iv = this.des3_key.slice(0, 8)
261
- const cipherChunks = []
262
- const decipher = crypto.createDecipheriv("des-ede3-cbc", this.des3_key, iv)
263
- decipher.setAutoPadding(true)
264
- cipherChunks.push(decipher.update(ciphertext, cipherEncoding, clearEncoding))
265
- cipherChunks.push(decipher.final(clearEncoding))
266
- return JSON.parse(cipherChunks.join(""))
267
- } catch (err) {
268
- throw new YZHSDKHttpException(`${err}`)
269
- }
270
- }
271
-
272
- /**
273
- * 验签
274
- * @param {string} data 返回的数据
275
- * @param {string} mess 返回的随机字符串
276
- * @param {string} timestamp 返回的时间戳
277
- * @param {string} sign 返回的签名
278
- * @returns {boolean} true:验签成功;false:验签失败
279
- */
280
- verifyRSASHA256 = (data: string, mess: string, timestamp: string, sign: string) => {
281
- try {
282
- const plaintext = `data=${data}&mess=${mess}&timestamp=${timestamp}&key=${this.app_key}`
283
- const verify = crypto.createVerify("RSA-SHA256")
284
- verify.update(plaintext)
285
- return verify.verify(this.yzh_public_key, sign, cipherEncoding)
286
- } catch (err) {
287
- throw new YZHSDKHttpException(`${err}`)
288
- }
289
- }
290
-
291
- verifyHmacSHA256 = (data: string, mess: string, timestamp: string, sign: string) => {
292
- try {
293
- const plaintext = `data=${data}&mess=${mess}&timestamp=${timestamp}&key=${this.app_key}`
294
- const hmac = crypto.createHmac("sha256", this.app_key)
295
- hmac.update(plaintext)
296
- return hmac.digest("hex") === sign
297
- } catch (err) {
298
- throw new YZHSDKHttpException(`${err}`)
299
- }
300
- }
301
-
302
- /**
303
- * 文件密码解密
304
- * @param ciphertextbase64
305
- * @returns 解密后的密码
306
- */
307
- filePassWordDecryption = (ciphertextbase64: string) => {
308
- try {
309
- const buff = Buffer.from(ciphertextbase64, "base64")
310
-
311
- const decrypted = crypto.privateDecrypt(
312
- {
313
- key: this.private_key,
314
- padding: crypto.constants.RSA_PKCS1_PADDING,
315
- },
316
- buff
317
- )
318
- return decrypted.toString("utf8")
319
- } catch (err) {
320
- throw new YZHSDKHttpException(`${err}`)
321
124
  }
322
- }
323
-
324
- /**
325
- * 验签+解密
326
- * @param responseData 回调返回对象
327
- * @returns
328
- */
329
- notifyDecoder: (params: {
330
- /** 返回的数据 */
331
- data: string
332
- /** 返回的随机字符串 */
333
- mess: string
334
- /** 返回的时间戳 */
335
- timestamp: string
336
- /** 返回的签名 */
337
- sign: string
338
- }) => {
339
- /** 验签结果 */
340
- result: boolean
341
- /** 解密结果 */
342
- plaintext: object
343
- } = (responseData) => {
344
- const notifyDecoderResult = (data: string, mess: string, timestamp: string, sign: string) => {
345
- const verifyMap = {
346
- rsa: this.verifyRSASHA256,
347
- sha256: this.verifyHmacSHA256,
348
- }
349
- // 验签结果 boolean
350
- const verifyResult = verifyMap[this.sign_type](data, mess, timestamp, sign)
351
- let plaintext = {}
352
- if (verifyResult) {
353
- plaintext = this.decrypt(data)
354
- }
355
- return {
356
- result: verifyResult,
357
- plaintext,
358
- }
125
+
126
+ /**
127
+ * 请求参数加密
128
+ * @param {object} params
129
+ * @returns {*} object
130
+ */
131
+ private generatorRequestParams(params: string) {
132
+ try {
133
+ const t = Date.now().toString();
134
+ const m = this.mess();
135
+
136
+ const plaintext = JSON.stringify(params);
137
+
138
+ const data = this.encrypt(plaintext);
139
+
140
+ const signStr = this.sign(data, m, t);
141
+ return {
142
+ data,
143
+ mess: m,
144
+ timestamp: t,
145
+ sign: signStr,
146
+ sign_type: this.sign_type,
147
+ };
148
+ } catch (err) {
149
+ throw new YZHSDKHttpException(`${err}`);
150
+ }
359
151
  }
360
- const { data, mess, timestamp, sign } = responseData ?? {}
361
- if (data && mess && timestamp && sign) {
362
- return notifyDecoderResult(data, mess, timestamp, sign)
152
+
153
+ /**
154
+ * 生成签名(RSA 签名算法)
155
+ * @param {string} data 经过加密后的具体数据
156
+ * @param {string} mess 自定义随机字符串,用于签名
157
+ * @param {string} timestamp 时间戳,精确到秒
158
+ * @returns {string} 签名内容
159
+ */
160
+ private signRSASHA256 = (data: string, mess: string, timestamp: string) => {
161
+ try {
162
+ const plaintext = `data=${data}&mess=${mess}&timestamp=${timestamp}&key=${this.app_key}`;
163
+ const sign = crypto.createSign('RSA-SHA256');
164
+ sign.update(plaintext);
165
+ sign.end();
166
+ return sign.sign(this.private_key, cipherEncoding);
167
+ } catch (err) {
168
+ throw new YZHSDKHttpException(`${err}`);
169
+ }
170
+ };
171
+
172
+ /**
173
+ * 生成签名(HMAC 签名算法)
174
+ * @param {string} data 经过加密后的具体数据
175
+ * @param {string} mess 自定义随机字符串,用于签名
176
+ * @param {string} timestamp 时间戳,精确到秒
177
+ * @returns {string} 签名内容
178
+ */
179
+ private signHmacSHA256 = (data: string, mess: string, timestamp: string) => {
180
+ try {
181
+ const plaintext = `data=${data}&mess=${mess}&timestamp=${timestamp}&key=${this.app_key}`;
182
+ const hmac = crypto.createHmac('sha256', this.app_key);
183
+ hmac.update(plaintext);
184
+ return hmac.digest('hex');
185
+ } catch (err) {
186
+ throw new YZHSDKHttpException(`${err}`);
187
+ }
188
+ };
189
+
190
+ /**
191
+ * 生成签名
192
+ * @param {string} data 经过加密后的具体数据
193
+ * @param {string} mess 自定义随机字符串,用于签名
194
+ * @param {string} timestamp 时间戳,精确到秒
195
+ * @param {string} sign_type 签名算法,支持 RSA、HMAC,枚举分别为 rsa、sha256
196
+ * @returns {string} 签名内容
197
+ */
198
+ private sign = (data: string, mess: string, timestamp: string) => {
199
+ try {
200
+ switch (this.sign_type) {
201
+ case 'rsa': {
202
+ return this.signRSASHA256(data, mess, timestamp);
203
+ }
204
+ case 'sha256': {
205
+ return this.signHmacSHA256(data, mess, timestamp);
206
+ }
207
+ default:
208
+ throw new YZHSDKHttpException(`sign_type 类型不存在`);
209
+ }
210
+ } catch (err) {
211
+ throw new YZHSDKHttpException(`${err}`);
212
+ }
213
+ };
214
+
215
+ // 自定义随机字符串
216
+ // eslint-disable-next-line class-methods-use-this
217
+ private mess = () => {
218
+ const buf = crypto.randomBytes(16);
219
+ const token = buf.toString('hex');
220
+ return token.toString();
221
+ };
222
+
223
+ /**
224
+ * 3DES 加密数据
225
+ * @param plaintext
226
+ * @returns 字符串加密数据
227
+ */
228
+ private encrypt = (plaintext: string) => {
229
+ try {
230
+ const iv = this.des3_key.slice(0, 8);
231
+ const cipherChunks = [];
232
+ const cipher = crypto.createCipheriv('des-ede3-cbc', this.des3_key, iv);
233
+ cipher.setAutoPadding(true);
234
+ cipherChunks.push(cipher.update(plaintext, clearEncoding, cipherEncoding));
235
+ cipherChunks.push(cipher.final(cipherEncoding));
236
+
237
+ return cipherChunks.join('');
238
+ } catch (err) {
239
+ throw new YZHSDKHttpException(`${err}`);
240
+ }
241
+ };
242
+
243
+ // 返回处理结果
244
+ // eslint-disable-next-line @typescript-eslint/require-await
245
+ private async parseResponse(result: ResponseData, encryption?: boolean) {
246
+ if (result.status !== 200) {
247
+ const yzhError = new YZHSDKHttpException(result.statusText);
248
+ yzhError.httpCode = result.status;
249
+ throw yzhError;
250
+ } else {
251
+ // HTTP Status Code 200
252
+ const { data: axiosData } = result;
253
+ let response = axiosData;
254
+ // 需解密
255
+ if (encryption) {
256
+ response = { ...response, data: this.decrypt(response.data) };
257
+ }
258
+ return response;
259
+ }
363
260
  }
364
- return { result: false, plaintext: "" }
365
- }
261
+
262
+ /**
263
+ * 3DES 解密数据
264
+ * @param ciphertext
265
+ * @returns 明文数据
266
+ */
267
+ decrypt = (ciphertext: string) => {
268
+ try {
269
+ const iv = this.des3_key.slice(0, 8);
270
+ const cipherChunks = [];
271
+ const decipher = crypto.createDecipheriv('des-ede3-cbc', this.des3_key, iv);
272
+ decipher.setAutoPadding(true);
273
+ cipherChunks.push(decipher.update(ciphertext, cipherEncoding, clearEncoding));
274
+ cipherChunks.push(decipher.final(clearEncoding));
275
+ return JSON.parse(cipherChunks.join(''));
276
+ } catch (err) {
277
+ throw new YZHSDKHttpException(`${err}`);
278
+ }
279
+ };
280
+
281
+ /**
282
+ * 验签
283
+ * @param {string} data 返回的数据
284
+ * @param {string} mess 返回的随机字符串
285
+ * @param {string} timestamp 返回的时间戳
286
+ * @param {string} sign 返回的签名
287
+ * @returns {boolean} true:验签成功;false:验签失败
288
+ */
289
+ verifyRSASHA256 = (data: string, mess: string, timestamp: string, sign: string) => {
290
+ try {
291
+ const plaintext = `data=${data}&mess=${mess}&timestamp=${timestamp}&key=${this.app_key}`;
292
+ const verify = crypto.createVerify('RSA-SHA256');
293
+ verify.update(plaintext);
294
+ return verify.verify(this.yzh_public_key, sign, cipherEncoding);
295
+ } catch (err) {
296
+ throw new YZHSDKHttpException(`${err}`);
297
+ }
298
+ };
299
+
300
+ verifyHmacSHA256 = (data: string, mess: string, timestamp: string, sign: string) => {
301
+ try {
302
+ const plaintext = `data=${data}&mess=${mess}&timestamp=${timestamp}&key=${this.app_key}`;
303
+ const hmac = crypto.createHmac('sha256', this.app_key);
304
+ hmac.update(plaintext);
305
+ return hmac.digest('hex') === sign;
306
+ } catch (err) {
307
+ throw new YZHSDKHttpException(`${err}`);
308
+ }
309
+ };
310
+
311
+ /**
312
+ * 文件密码解密
313
+ * @param ciphertextbase64
314
+ * @returns 解密后的密码
315
+ */
316
+ filePassWordDecryption = (ciphertextbase64: string) => {
317
+ try {
318
+ const buff = Buffer.from(ciphertextbase64, 'base64');
319
+
320
+ const decrypted = crypto.privateDecrypt(
321
+ {
322
+ key: this.private_key,
323
+ padding: crypto.constants.RSA_PKCS1_PADDING,
324
+ },
325
+ buff
326
+ );
327
+ return decrypted.toString('utf8');
328
+ } catch (err) {
329
+ throw new YZHSDKHttpException(`${err}`);
330
+ }
331
+ };
332
+
333
+ /**
334
+ * 验签+解密
335
+ * @param responseData 回调返回对象
336
+ * @returns
337
+ */
338
+ notifyDecoder: (params: {
339
+ /** 返回的数据 */
340
+ data: string;
341
+ /** 返回的随机字符串 */
342
+ mess: string;
343
+ /** 返回的时间戳 */
344
+ timestamp: string;
345
+ /** 返回的签名 */
346
+ sign: string;
347
+ }) => {
348
+ /** 验签结果 */
349
+ result: boolean;
350
+ /** 解密结果 */
351
+ plaintext: object;
352
+ } = responseData => {
353
+ const notifyDecoderResult = (data: string, mess: string, timestamp: string, sign: string) => {
354
+ const verifyMap = {
355
+ rsa: this.verifyRSASHA256,
356
+ sha256: this.verifyHmacSHA256,
357
+ };
358
+ // 验签结果 boolean
359
+ const verifyResult = verifyMap[this.sign_type](data, mess, timestamp, sign);
360
+ let plaintext = {};
361
+ if (verifyResult) {
362
+ plaintext = this.decrypt(data);
363
+ }
364
+ return {
365
+ result: verifyResult,
366
+ plaintext,
367
+ };
368
+ };
369
+ const { data, mess, timestamp, sign } = responseData ?? {};
370
+ if (data && mess && timestamp && sign) {
371
+ return notifyDecoderResult(data, mess, timestamp, sign);
372
+ }
373
+ return { result: false, plaintext: '' };
374
+ };
366
375
  }
367
376
 
368
- export default YZHClient
377
+ export default YZHClient;