@tmsfe/tms-core 0.0.141 → 0.0.143
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/package.json +1 -1
- package/src/encrypt.js +29 -1
- package/src/index.js +9 -2
- package/src/report/formatV2.ts +3 -1
- package/src/report/helper.ts +3 -0
- package/src/report/types.ts +4 -1
- package/src/request.js +50 -50
package/package.json
CHANGED
package/src/encrypt.js
CHANGED
|
@@ -60,7 +60,7 @@ function _getEccPublicId() {
|
|
|
60
60
|
// 获取私钥
|
|
61
61
|
let privateKeyInfo = null;
|
|
62
62
|
const _getPrivateKeyInfo = (enforceUpdate) => {
|
|
63
|
-
if (!privateKeyInfo || enforceUpdate) {
|
|
63
|
+
if (!privateKeyInfo || enforceUpdate || privateKeyInfo.publicKeyId !== _getEccPublicId()) {
|
|
64
64
|
const aesKey = _generateRandomKey();
|
|
65
65
|
const encryptAesKey = _encryptWithPublicKey(aesKey, _getEccPublicKey());
|
|
66
66
|
privateKeyInfo = {
|
|
@@ -268,11 +268,39 @@ function needsEncryption(url, params) {
|
|
|
268
268
|
return true; // 没有匹配到规则,需要加密
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
+
// 判断是否是加密相关的错误类型(因为rawresponse的配置,需要errcode和errmessage共同来确定加密错误类型)
|
|
272
|
+
const ErrCodeType = {
|
|
273
|
+
pubKeyIdInvalid: '11_Invalid public key!',
|
|
274
|
+
pubKeyExpired: '12_Expired public key!',
|
|
275
|
+
aesCipherInvalid: '13_Invalid AES cipher!',
|
|
276
|
+
decryptError: '14_Decrypt error!',
|
|
277
|
+
cryptoDisabled: '15_Crypto disabled!',
|
|
278
|
+
};
|
|
279
|
+
const reqErrType = {
|
|
280
|
+
pubKeyInvalid: 'pubKeyInvalid',
|
|
281
|
+
decryptError: 'decryptError',
|
|
282
|
+
cryptoDisabled: 'cryptoDisabled',
|
|
283
|
+
};
|
|
284
|
+
const getErrcodeType = (errCode, errMsg) => {
|
|
285
|
+
const errType = `${errCode}_${errMsg}`;
|
|
286
|
+
if (ErrCodeType.decryptError === errType) {
|
|
287
|
+
return reqErrType.decryptError;
|
|
288
|
+
}
|
|
289
|
+
if (ErrCodeType.cryptoDisabled === errType) {
|
|
290
|
+
return reqErrType.cryptoDisabled;
|
|
291
|
+
}
|
|
292
|
+
if ([ErrCodeType.pubKeyIdInvalid, ErrCodeType.pubKeyExpired, ErrCodeType.aesCipherInvalid].indexOf(errType) > -1) {
|
|
293
|
+
return reqErrType.pubKeyInvalid;
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
271
297
|
const encryptObj = {
|
|
272
298
|
reqEncrypt,
|
|
273
299
|
resDecrypt,
|
|
274
300
|
updateDecryptKey,
|
|
275
301
|
needsEncryption,
|
|
302
|
+
getErrcodeType,
|
|
303
|
+
reqErrType,
|
|
276
304
|
};
|
|
277
305
|
|
|
278
306
|
|
package/src/index.js
CHANGED
|
@@ -130,8 +130,15 @@ const init = (options = {}) => {
|
|
|
130
130
|
getLocation: async () => {
|
|
131
131
|
try {
|
|
132
132
|
const res = await getLocationManager().getIpLocation();
|
|
133
|
-
const ad = res
|
|
134
|
-
return {
|
|
133
|
+
const { ad_info: ad, location } = res;
|
|
134
|
+
return {
|
|
135
|
+
province: ad.province,
|
|
136
|
+
cityName: ad.city,
|
|
137
|
+
district: ad.district,
|
|
138
|
+
cityCode: ad.cityCode,
|
|
139
|
+
latitude: location.lat,
|
|
140
|
+
longitude: location.lng,
|
|
141
|
+
};
|
|
135
142
|
} catch {
|
|
136
143
|
return null;
|
|
137
144
|
}
|
package/src/report/formatV2.ts
CHANGED
|
@@ -68,7 +68,9 @@ function getBaseData(page: IPage, deviceData: IDeviceData): { arr: DataItem[], n
|
|
|
68
68
|
arr[27] = helper.getTmsUUID();
|
|
69
69
|
// 28: f28,实际执行页面url
|
|
70
70
|
arr[28] = page.execRoute;
|
|
71
|
-
// 29
|
|
71
|
+
// 29: f29,定位相关信息
|
|
72
|
+
arr[29] = JSON.stringify(location);
|
|
73
|
+
// 30 ~ 30: 预留字段给后续扩展使用
|
|
72
74
|
// 31 ~ 40: 提供给开发自定义
|
|
73
75
|
// --------------------------字段列表--------------------------
|
|
74
76
|
return { arr, nextIndex: 31 };
|
package/src/report/helper.ts
CHANGED
|
@@ -255,6 +255,9 @@ function getDeviceData(): Promise<IDeviceData> {
|
|
|
255
255
|
if (loc) {
|
|
256
256
|
deviceData.location.province = loc.province;
|
|
257
257
|
deviceData.location.cityName = loc.cityName;
|
|
258
|
+
deviceData.location.district = loc.district;
|
|
259
|
+
deviceData.location.latitude = loc.latitude;
|
|
260
|
+
deviceData.location.longitude = loc.longitude;
|
|
258
261
|
}
|
|
259
262
|
resolve();
|
|
260
263
|
})
|
package/src/report/types.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface IInitOptions {
|
|
|
9
9
|
// 小程序版本号
|
|
10
10
|
appVersion: string,
|
|
11
11
|
// 获取定位信息
|
|
12
|
-
getLocation: () => Promise<
|
|
12
|
+
getLocation: () => Promise<ILocation | null>,
|
|
13
13
|
// 允许自定义日志输出
|
|
14
14
|
logger: ILogger,
|
|
15
15
|
// post方法,用于发送埋点
|
|
@@ -53,6 +53,9 @@ export interface ISystemInfo {
|
|
|
53
53
|
export interface ILocation {
|
|
54
54
|
province: string,
|
|
55
55
|
cityName: string,
|
|
56
|
+
district: string
|
|
57
|
+
latitude: number,
|
|
58
|
+
longitude: number,
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
export interface IDeviceData {
|
package/src/request.js
CHANGED
|
@@ -347,17 +347,17 @@ export default class Request {
|
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
// wx请求封装成promise
|
|
350
|
-
async wxRequest(path, method, header = {}, data, needReport
|
|
350
|
+
async wxRequest(path, method, header = {}, data, needReport, seqId) {
|
|
351
351
|
if (needReport && path.indexOf('basic/event/upload') < 0) {
|
|
352
352
|
reporter.reportPerformance(
|
|
353
|
-
'request_encrypt_log', 'main', 'send_unencrypt_request',
|
|
353
|
+
'request_encrypt_log', 'main', 'send_unencrypt_request', seqId,
|
|
354
354
|
!!wx.$_publicKey, Request.requestEncryptOpen, path,
|
|
355
355
|
);
|
|
356
356
|
}
|
|
357
357
|
return new Promise((resolve, reject) => {
|
|
358
358
|
wx.request({
|
|
359
359
|
url: path,
|
|
360
|
-
header: { ...header, 'X-Trace-Id':
|
|
360
|
+
header: { ...header, 'X-Trace-Id': seqId },
|
|
361
361
|
method,
|
|
362
362
|
data,
|
|
363
363
|
enableHttp2: true,
|
|
@@ -373,7 +373,10 @@ export default class Request {
|
|
|
373
373
|
|
|
374
374
|
async refreshEncryptKey() {
|
|
375
375
|
try {
|
|
376
|
-
const
|
|
376
|
+
const requestParam = await composeParam({}, true, {});
|
|
377
|
+
const data = sign(requestParam, this.secretKey);
|
|
378
|
+
const finalUrl = this.makeUrl('basic/crypto/lastkey');
|
|
379
|
+
const res = await this.wxRequest(finalUrl, 'GET', {}, data, true, data.seqId);
|
|
377
380
|
encryptObj.updateDecryptKey(res.data.resData);
|
|
378
381
|
} catch (e) {
|
|
379
382
|
encryptObj.updateDecryptKey(null);
|
|
@@ -389,8 +392,8 @@ export default class Request {
|
|
|
389
392
|
return true;
|
|
390
393
|
}
|
|
391
394
|
|
|
392
|
-
async dealEncryptionSwitch(resHeader) {
|
|
393
|
-
if (!resHeader || this.dealEncryptionSwitching) {
|
|
395
|
+
async dealEncryptionSwitch(resHeader, forceRefresh = false) {
|
|
396
|
+
if (!forceRefresh && (!resHeader || this.dealEncryptionSwitching)) {
|
|
394
397
|
return false;
|
|
395
398
|
}
|
|
396
399
|
this.dealEncryptionSwitching = true;
|
|
@@ -403,7 +406,7 @@ export default class Request {
|
|
|
403
406
|
return false;
|
|
404
407
|
}
|
|
405
408
|
// 打开开关,如果当前是关闭状态,则需要刷新加密key
|
|
406
|
-
if (!wx.$_publicKey) {
|
|
409
|
+
if (forceRefresh || !wx.$_publicKey) {
|
|
407
410
|
await this.refreshEncryptKey();
|
|
408
411
|
}
|
|
409
412
|
this.dealEncryptionSwitching = false;
|
|
@@ -458,58 +461,55 @@ export default class Request {
|
|
|
458
461
|
logger.warn(`接口请求失败:\n${str}`);
|
|
459
462
|
}
|
|
460
463
|
};
|
|
461
|
-
|
|
462
|
-
if (!doEncrypt || !this.checkIfNeedEncrypt(finalUrl, data)) {
|
|
463
|
-
return this.wxRequest(finalUrl, method, header, data, true)
|
|
464
|
-
.then((res) => {
|
|
465
|
-
printLog(true, res.data);
|
|
466
|
-
return res;
|
|
467
|
-
})
|
|
468
|
-
.catch((err) => {
|
|
469
|
-
printLog(false, err);
|
|
470
|
-
throw err;
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
// 1. 加密请求
|
|
474
|
-
const {
|
|
475
|
-
header: encryptHeader, data: encryptData, aesKey,
|
|
476
|
-
} = encryptObj.reqEncrypt(method, data, header, '');
|
|
477
|
-
// 2. 发送请求
|
|
464
|
+
const { seqId } = data;
|
|
478
465
|
try {
|
|
479
|
-
|
|
480
|
-
|
|
466
|
+
// 当前请求不加密 || 不满足加密前提
|
|
467
|
+
if (!doEncrypt || !this.checkIfNeedEncrypt(finalUrl, data)) {
|
|
468
|
+
const result = await this.wxRequest(finalUrl, method, header, data, true, seqId);
|
|
469
|
+
const { header: resHeader, data: resData } = result;
|
|
470
|
+
// 根据返回的响应头来控制接下来运行时的加密开关
|
|
471
|
+
this.dealEncryptionSwitch(resHeader);
|
|
472
|
+
printLog(true, resData);
|
|
473
|
+
return result;
|
|
474
|
+
}
|
|
475
|
+
// 1. 加密请求
|
|
476
|
+
const {
|
|
477
|
+
header: encryptHeader, data: encryptData, aesKey,
|
|
478
|
+
} = encryptObj.reqEncrypt(method, data, header, '');
|
|
479
|
+
// 2. 发送请求
|
|
480
|
+
reporter.reportPerformance('request_encrypt_log', 'main', 'send_encrypt_request', seqId);
|
|
481
|
+
const result = await this.wxRequest(finalUrl, method, encryptHeader, encryptData, false, seqId);
|
|
481
482
|
const { header: resHeader, data: resData } = result;
|
|
482
483
|
// 3. 解密响应
|
|
483
484
|
const { success, header: decryptHeader, data: decryptData } = encryptObj.resDecrypt(aesKey, resHeader, resData);
|
|
484
485
|
if (!success) {
|
|
485
|
-
reporter.reportPerformance('request_encrypt_log', 'main', 'local_response_decrypt_fail',
|
|
486
|
+
reporter.reportPerformance('request_encrypt_log', 'main', 'local_response_decrypt_fail', seqId);
|
|
486
487
|
return this.createRequestTask(path, param, method, header, false);
|
|
487
488
|
}
|
|
488
|
-
reporter.reportPerformance('request_encrypt_log', 'main', 'decrypt_response_success',
|
|
489
|
+
reporter.reportPerformance('request_encrypt_log', 'main', 'decrypt_response_success', seqId);
|
|
489
490
|
// 4. 处理解密失败的响应
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
throw new Error('解密失败,请重试');
|
|
500
|
-
}
|
|
501
|
-
await this.refreshEncryptKey();
|
|
502
|
-
return this.createRequestTask(path, param, method, header, true, retryTimes + 1);
|
|
491
|
+
const errCodeType = encryptObj.getErrcodeType(decryptData.errCode, decryptData.errMsg);
|
|
492
|
+
if (errCodeType === encryptObj.reqErrType.pubKeyInvalid) { // 秘钥失效
|
|
493
|
+
reporter.reportPerformance(
|
|
494
|
+
'request_encrypt_log', 'main', 'remote_response_decrypt_fail',
|
|
495
|
+
seqId, decryptData.errCode, retryTimes,
|
|
496
|
+
);
|
|
497
|
+
const encryptSwitch = await this.dealEncryptionSwitch(resHeader, true);
|
|
498
|
+
if (retryTimes > 2) {
|
|
499
|
+
throw new Error('解密失败,请重试');
|
|
503
500
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
501
|
+
return this.createRequestTask(path, param, method, header, encryptSwitch, retryTimes + 1);
|
|
502
|
+
}
|
|
503
|
+
if (errCodeType === encryptObj.reqErrType.decryptError) { // 解密失败
|
|
504
|
+
reporter.reportPerformance(
|
|
505
|
+
'request_encrypt_log', 'main', 'remote_response_decrypt_fail',
|
|
506
|
+
seqId, decryptData.errCode, retryTimes,
|
|
507
|
+
);
|
|
508
|
+
return this.createRequestTask(path, param, method, header, false);
|
|
509
|
+
}
|
|
510
|
+
if (errCodeType === encryptObj.reqErrType.cryptoDisabled) { // 加密关闭
|
|
511
|
+
wx.$_publicKey = null;
|
|
512
|
+
return this.createRequestTask(path, param, method, header, false);
|
|
513
513
|
}
|
|
514
514
|
result.header = decryptHeader;
|
|
515
515
|
result.data = decryptData;
|