abler-api 0.1.9 → 0.1.12
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/dist/cjs/pp-util.js +6 -8
- package/package.json +2 -2
- package/dist/es/pp-util.js +0 -1259
package/dist/cjs/pp-util.js
CHANGED
|
@@ -424,7 +424,7 @@ class apiUtil$1 {
|
|
|
424
424
|
// Object.defineProperty(options, "identifyLimit", {
|
|
425
425
|
// get: function () {
|
|
426
426
|
// if (!this._identifyLimit) {
|
|
427
|
-
// // this._identifyLimit =
|
|
427
|
+
// // this._identifyLimit = ppUtil.waitPromise(_getIdentifyLimit(this.companyId));
|
|
428
428
|
// throw "options._identifyLimit 没有赋值";
|
|
429
429
|
// }
|
|
430
430
|
//
|
|
@@ -451,7 +451,7 @@ class apiUtil$1 {
|
|
|
451
451
|
*/
|
|
452
452
|
|
|
453
453
|
|
|
454
|
-
static
|
|
454
|
+
static extractToken(req, res, noErr) {
|
|
455
455
|
configNeeded();
|
|
456
456
|
|
|
457
457
|
if (!req.accessToken) {
|
|
@@ -732,7 +732,7 @@ class apiUtil$1 {
|
|
|
732
732
|
};
|
|
733
733
|
|
|
734
734
|
if (rec.secret !== "") {
|
|
735
|
-
rec.secret =
|
|
735
|
+
rec.secret = ppUtil$1.getEncAse192(rec.secret);
|
|
736
736
|
}
|
|
737
737
|
|
|
738
738
|
req.apiCallRec = rec;
|
|
@@ -1197,18 +1197,16 @@ class apiUtil$1 {
|
|
|
1197
1197
|
if (req.isMobile) {
|
|
1198
1198
|
// GET 请求的应该都是H5页面,由手机前端发起,需要把headers中的请求方ip换成服务端的
|
|
1199
1199
|
// todo: 如何在API访问记录中记住请求者(手机端)的真实IP
|
|
1200
|
-
req.headers['x-phone-ip'] =
|
|
1200
|
+
req.headers['x-phone-ip'] = apiUtil$1.getClientIp(req);
|
|
1201
1201
|
req.headers['x-real-ip'] = p.clientIp;
|
|
1202
1202
|
} else {
|
|
1203
|
-
p.clientIp =
|
|
1203
|
+
p.clientIp = apiUtil$1.getClientIp(req);
|
|
1204
1204
|
}
|
|
1205
1205
|
|
|
1206
1206
|
req.isApiCall = true;
|
|
1207
1207
|
req.tokenData = p;
|
|
1208
1208
|
apiUtil$1.$checkApiKeyOld(req, res, next);
|
|
1209
1209
|
}).catch(e => {
|
|
1210
|
-
// res.send(hb.showError("授权令牌不存在或已过期"));
|
|
1211
|
-
// res.send(spoApiFail(err.TOKEN_INVALID, req));
|
|
1212
1210
|
apiUtil$1.sendOrRedirect(req, res, apiUtil$1.spoApiFail(err.TOKEN_INVALID, req));
|
|
1213
1211
|
});
|
|
1214
1212
|
}
|
|
@@ -1228,7 +1226,7 @@ class apiUtil$1 {
|
|
|
1228
1226
|
let tokenExist = await apiUtil$1.tokenDataExist(apiUtil$1.userTokenStoreKey(accessToken));
|
|
1229
1227
|
|
|
1230
1228
|
if (tokenExist) {
|
|
1231
|
-
return apiUtil$1.$checkToken(req, res, next);
|
|
1229
|
+
return await apiUtil$1.$checkToken(req, res, next);
|
|
1232
1230
|
}
|
|
1233
1231
|
|
|
1234
1232
|
tokenExist = await apiUtil$1.tokenDataExist(apiUtil$1.apiTokenStoreKey(accessToken));
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abler-api",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "API服务相关工具",
|
|
5
5
|
"main": "./dist/cjs/pp-util.js",
|
|
6
|
-
"module": "./dist/es/pp-util.js",
|
|
6
|
+
"-module": "./dist/es/pp-util.js",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "npx rollup -c rollup.config.js",
|
|
9
9
|
"test": "echo \"Error: no test specified\" && exit 1"
|
package/dist/es/pp-util.js
DELETED
|
@@ -1,1259 +0,0 @@
|
|
|
1
|
-
import require$$0 from 'crypto';
|
|
2
|
-
import require$$1 from 'abler-util';
|
|
3
|
-
import require$$2 from 'abler-db';
|
|
4
|
-
|
|
5
|
-
const crypto = require$$0;
|
|
6
|
-
const ppUtil$1 = require$$1.ppUtil;
|
|
7
|
-
const {
|
|
8
|
-
dbUtil,
|
|
9
|
-
kvStorage
|
|
10
|
-
} = require$$2;
|
|
11
|
-
let conf, appSetting, err, dbSql;
|
|
12
|
-
const pnToken = "access_token",
|
|
13
|
-
hnToken = pnToken,
|
|
14
|
-
pnApiKey = "apiKey",
|
|
15
|
-
hnApiKey = pnApiKey.toLowerCase(),
|
|
16
|
-
// 我们接收到的 headers 中的字段名总是全小写的
|
|
17
|
-
pnApiSecret = "apiSecret",
|
|
18
|
-
hnApiSecret = pnApiSecret.toLowerCase();
|
|
19
|
-
const MD5 = ppUtil$1.MD5,
|
|
20
|
-
moveProperty = ppUtil$1.moveProperty;
|
|
21
|
-
|
|
22
|
-
class apiUtil$1 {
|
|
23
|
-
static debugFlag = ppUtil$1.newGuid(); //应用必须设置,否则谁也不知道是啥
|
|
24
|
-
|
|
25
|
-
static testFlag = ppUtil$1.newGuid();
|
|
26
|
-
static envId_dev = "?"; // static apiCallRecSaver;
|
|
27
|
-
|
|
28
|
-
static config(appConfig, appErrCfg, appDbSql) {
|
|
29
|
-
ppUtil$1.config(appConfig, appErrCfg);
|
|
30
|
-
conf = appConfig;
|
|
31
|
-
appSetting = conf?.appSetting;
|
|
32
|
-
err = appErrCfg, dbSql = appDbSql;
|
|
33
|
-
apiUtil$1.debugFlag = appSetting?.debugFlag || apiUtil$1.debugFlag;
|
|
34
|
-
apiUtil$1.testFlag = appSetting?.testFlag || apiUtil$1.testFlag; // apiUtil.apiCallRecSaver = apiCallRecSaver;
|
|
35
|
-
} //#region ===== 需要应用系统重写的方法
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* 根据机构标识获取机构的 ApiSecret
|
|
39
|
-
* @param companyId
|
|
40
|
-
* @returns {*}
|
|
41
|
-
*/
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
static _getApiSecret(companyId) {
|
|
45
|
-
return ppUtil$1.newGuid();
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* 保存 API 调用记录,应用系统必须重写此方法
|
|
49
|
-
* @param rec
|
|
50
|
-
* @param responseData
|
|
51
|
-
* @returns {Promise<unknown>}
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
static async _saveApiCallRec(rec, responseData) {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* 检查API调用签名是否已经完成了验证
|
|
60
|
-
* @param req
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
static signatureVerified(req) {
|
|
65
|
-
return req.signatureVerified;
|
|
66
|
-
} //#endregion
|
|
67
|
-
//#region ===== API服务相关工具
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* 获取客户端IP地址
|
|
71
|
-
* @param req
|
|
72
|
-
* @returns {*|string|string}
|
|
73
|
-
*/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
static getClientIp(req) {
|
|
77
|
-
let ip = req.headers["x-real-ip"] || req.headers["x-true-ip"] || req.headers['x-forwarded-for'] || req.headers['x-forward-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.headers['host'] || ""; // console.log("Request IP:", ip, "req: ", req);
|
|
78
|
-
|
|
79
|
-
if (ip.indexOf(",") >= 0) {
|
|
80
|
-
ip = ip.split(',')[0];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (ip.indexOf(":") >= 0) {
|
|
84
|
-
ip = ip.substring(ip.lastIndexOf(':') + 1);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return ip;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* 从请求中解出数据,包括路径参数、查询参数和Body
|
|
91
|
-
* @param req
|
|
92
|
-
* @returns {*}
|
|
93
|
-
*/
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
static extractParams(req) {
|
|
97
|
-
if (!req._requestParams) {
|
|
98
|
-
if (req.method === "POST" || req.method === "PUT") {
|
|
99
|
-
let contentType = req.headers["content-type"] || "application/json";
|
|
100
|
-
|
|
101
|
-
if (contentType.startsWith("multipart/form-data")) {
|
|
102
|
-
req._requestParams = new Object();
|
|
103
|
-
|
|
104
|
-
for (let k in req.body) {
|
|
105
|
-
req._requestParams[k] = req.body[k];
|
|
106
|
-
}
|
|
107
|
-
} else {
|
|
108
|
-
req._requestParams = req.body;
|
|
109
|
-
}
|
|
110
|
-
} else {
|
|
111
|
-
req._requestParams = req.query;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (req.headers["content-type"] !== "application/json") {
|
|
115
|
-
const obj = req._requestParams;
|
|
116
|
-
|
|
117
|
-
for (let key in obj) {
|
|
118
|
-
if (!obj.hasOwnProperty(key)) continue;
|
|
119
|
-
let value = obj[key];
|
|
120
|
-
|
|
121
|
-
if (typeof value === "string" && value.length > 0) {
|
|
122
|
-
if (value[0] === "{" || value[0] === "[") {
|
|
123
|
-
try {
|
|
124
|
-
obj[key] = JSON.parse(value);
|
|
125
|
-
continue;
|
|
126
|
-
} catch (e) {}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
let x = JSON.hbDateConv(key, value);
|
|
130
|
-
|
|
131
|
-
if (x !== value) {
|
|
132
|
-
obj[key] = x;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (req.params) {
|
|
139
|
-
req._requestParams = Object.assign(req.params, req._requestParams);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
apiUtil$1.setParamsFunctions(req._requestParams);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return req._requestParams;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
static extractTokenData(req) {
|
|
149
|
-
if (req.tokenData) {
|
|
150
|
-
return req.tokenData;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
let params = apiUtil$1.extractParams(req);
|
|
154
|
-
let tokenData = {
|
|
155
|
-
apiKey: req.headers[hnApiKey] || params[pnApiKey],
|
|
156
|
-
apiSecret: req.headers[hnApiSecret] || params[pnApiSecret],
|
|
157
|
-
clientIp: apiUtil$1.getClientIp(req)
|
|
158
|
-
};
|
|
159
|
-
return tokenData;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* 为从传入请求中解出的参数对象设置一些函数属性,包括 asNumber, asBool
|
|
163
|
-
* @param params
|
|
164
|
-
*/
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
static setParamsFunctions(params) {
|
|
168
|
-
ppUtil$1.defUnenumProp(params, "asNumber", function (name, minValue, maxValue, defaultValue) {
|
|
169
|
-
// if (!this.hasOwnProperty(name)) // {} 定义的对象没有 hasOwnProperty 函数
|
|
170
|
-
if (this[name] === undefined) return defaultValue;
|
|
171
|
-
let result = +this[name];
|
|
172
|
-
|
|
173
|
-
if (typeof result !== "number" || result < minValue || result > maxValue) {
|
|
174
|
-
throw [err.INVALID_PARAM, `参数 ${name} 必须是 ${minValue} ~ ${maxValue} 之间的数字`];
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return result;
|
|
178
|
-
});
|
|
179
|
-
ppUtil$1.defUnenumProp(params, "asBool", function (name, defaultValue) {
|
|
180
|
-
if (this[name] === undefined) return defaultValue;
|
|
181
|
-
let result = JSON.parse(this[name]);
|
|
182
|
-
return !!result;
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* 将返回结果转向到指定地址或者通过response发送返回结果
|
|
187
|
-
* @param res
|
|
188
|
-
* @param redirectUrl
|
|
189
|
-
* @param data
|
|
190
|
-
*/
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
static sendOrRedirect(res, redirectUrl, data) {
|
|
194
|
-
if (redirectUrl) {
|
|
195
|
-
redirectUrl = urlAppendParams(redirectUrl, data, true);
|
|
196
|
-
res.redirect(redirectUrl);
|
|
197
|
-
} else {
|
|
198
|
-
res.send(data);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* 生成 API 成功返回结果
|
|
203
|
-
* @param data
|
|
204
|
-
* @param req
|
|
205
|
-
* @returns {{datetime: Date, success: boolean, stateCode: number, message: string}}
|
|
206
|
-
*/
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
static apiSuccess(data, req) {
|
|
210
|
-
let response = {
|
|
211
|
-
success: true,
|
|
212
|
-
stateCode: 0,
|
|
213
|
-
message: '',
|
|
214
|
-
datetime: new Date()
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
if (req && req.headers) {
|
|
218
|
-
let userAgent = req.headers["user-agent"];
|
|
219
|
-
|
|
220
|
-
if (userAgent && userAgent.startsWith("Postman")) {
|
|
221
|
-
response._elapse = (new Date().valueOf() - req.headers.timestamp) / 1000;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (data && data._message_) {
|
|
226
|
-
response.message = data._message_;
|
|
227
|
-
delete data._message_;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
response.data = data;
|
|
231
|
-
if (Array.isArray(data) && typeof data.recordCount != 'undefined') response.recordCount = data.recordCount;
|
|
232
|
-
return response;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* 生成 API 失败返回结果
|
|
236
|
-
* @param error
|
|
237
|
-
* @param req
|
|
238
|
-
* @returns {*}
|
|
239
|
-
*/
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
static apiFail(error, req) {
|
|
243
|
-
configNeeded();
|
|
244
|
-
let response = err.ERROR(error, err.errorLangParamFlag + ppUtil$1.getMsgLang(req));
|
|
245
|
-
response.datetime = new Date();
|
|
246
|
-
|
|
247
|
-
if (req && req.headers) {
|
|
248
|
-
let userAgent = req.headers["user-agent"];
|
|
249
|
-
|
|
250
|
-
if (userAgent && userAgent.startsWith("Postman")) {
|
|
251
|
-
response._elapse = (new Date().valueOf() - req.headers.timestamp) / 1000;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return response;
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* 生成面向服务商的API成功返回结果
|
|
259
|
-
* @param data
|
|
260
|
-
* @param req
|
|
261
|
-
* @returns {*}
|
|
262
|
-
*/
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
static spoApiSucc(data, req) {
|
|
266
|
-
let params = apiUtil$1.extractParams(req);
|
|
267
|
-
return apiUtil$1.apiSuccess(data, req, params.spOrderNum);
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* 生成面向服务商的API失败返回结果
|
|
271
|
-
* @param error
|
|
272
|
-
* @param req
|
|
273
|
-
* @returns {*}
|
|
274
|
-
*/
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
static spoApiFail(error, req) {
|
|
278
|
-
let params = apiUtil$1.extractParams(req);
|
|
279
|
-
return apiUtil$1.apiFail(error, req, params.spOrderNum);
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* API 服务结束,发送响应
|
|
283
|
-
* @param response
|
|
284
|
-
* @param promise
|
|
285
|
-
*/
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
static sendResponse(response, promise) {
|
|
289
|
-
promise.then(function (data) {
|
|
290
|
-
if (!response.finished) {
|
|
291
|
-
try {
|
|
292
|
-
response.send(data);
|
|
293
|
-
} catch (e) {
|
|
294
|
-
console.log(`response.send 出错了,req.url: ${response.req.url}, response:`, response);
|
|
295
|
-
console.log("异常信息", e);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}, function (error) {
|
|
299
|
-
console.log('ERROR:', error);
|
|
300
|
-
|
|
301
|
-
if (!response.finished) {
|
|
302
|
-
response.send(error);
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* API 服务结束,包装数据并发送响应
|
|
308
|
-
* @param response
|
|
309
|
-
* @param promise
|
|
310
|
-
*/
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
static async responseOf(response, promise) {
|
|
314
|
-
promise.then(function (data) {
|
|
315
|
-
// console.log('RES:', apiSuccess(data));
|
|
316
|
-
if (!response.finished) response.send(apiUtil$1.apiSuccess(data, response.req));
|
|
317
|
-
}, function (error) {
|
|
318
|
-
console.log('ERROR:', error);
|
|
319
|
-
if (!response.finished) response.send(apiUtil$1.apiFail(error, response.req));
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* 面向服务商的API结束,发送响应
|
|
324
|
-
* @param response
|
|
325
|
-
* @param promise
|
|
326
|
-
*/
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
static async spoApiResponse(response, promise) {
|
|
330
|
-
promise.then(function (result) {
|
|
331
|
-
let responseData = apiUtil$1.spoApiSucc(result, response.req);
|
|
332
|
-
|
|
333
|
-
apiUtil$1._saveApiCallRec(response.req.apiCallRec, responseData);
|
|
334
|
-
|
|
335
|
-
if (!response.finished) response.send(responseData);
|
|
336
|
-
}, function (error) {
|
|
337
|
-
console.log('ERROR:', error);
|
|
338
|
-
let responseData = apiUtil$1.spoApiFail(error, response.req);
|
|
339
|
-
|
|
340
|
-
apiUtil$1._saveApiCallRec(response.req.apiCallRec, responseData);
|
|
341
|
-
|
|
342
|
-
if (!response.finished) response.send(responseData);
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* 从请求参数中获取查询参数
|
|
347
|
-
* @param req
|
|
348
|
-
* @param res
|
|
349
|
-
* @returns {*}
|
|
350
|
-
*/
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
static getQueryOptions(req, res) {
|
|
354
|
-
req.headers.timestamp = new Date().valueOf(); // let options = {replacements: {}};
|
|
355
|
-
|
|
356
|
-
let options = {};
|
|
357
|
-
let parameters = apiUtil$1.extractParams(req);
|
|
358
|
-
|
|
359
|
-
for (let qryParam in parameters) {
|
|
360
|
-
if (qryParam !== 'token') {
|
|
361
|
-
if (['start', 'limit', 'orderby', 'orderBy'].indexOf(qryParam) >= 0) {
|
|
362
|
-
options[qryParam] = parameters[qryParam];
|
|
363
|
-
delete parameters[qryParam];
|
|
364
|
-
} // else
|
|
365
|
-
// options.replacements[qryParam] = parameters[qryParam];
|
|
366
|
-
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
if (options.limit && !options.start) {
|
|
371
|
-
options.start = 0;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
if (options.orderby) {
|
|
375
|
-
options.orderBy = options.orderby;
|
|
376
|
-
} // options.__debug__ = req.headers['__debug__'] && req.headers['__debug__'] == "true";
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
options.replacements = parameters; // if (arguments.length > 1) //其后的每个参数是要求必须存在的参数名称
|
|
380
|
-
// {
|
|
381
|
-
// for(i=1; i<arguments.length; i++){
|
|
382
|
-
// var paramName = arguments[i];
|
|
383
|
-
// if (!qryOptions.replacements[paramName])
|
|
384
|
-
// error();
|
|
385
|
-
// }
|
|
386
|
-
// }
|
|
387
|
-
|
|
388
|
-
options.userInfo = req.userInfo;
|
|
389
|
-
return apiUtil$1.setOptionsPropFuncions(options, res);
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* 为API请求 options 设置属性
|
|
393
|
-
* @param options
|
|
394
|
-
* @param res
|
|
395
|
-
* @returns {{identifyLimit}|*}
|
|
396
|
-
*/
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
static setOptionsPropFuncions(options, res) {
|
|
400
|
-
// if (!options.identifyLimit) {
|
|
401
|
-
// // 根据企业标识获取身份认证限制相关设置,如果没有传递企业标识,
|
|
402
|
-
// // 则尝试从options.companyInfo或options.contractOrder中获取
|
|
403
|
-
// Object.defineProperty(options, "companyId", {
|
|
404
|
-
// get: function () {
|
|
405
|
-
// var result;
|
|
406
|
-
// if (this.companyInfo) {
|
|
407
|
-
// result = this.companyInfo.companyId;
|
|
408
|
-
// } else if (this.contractOrder) {
|
|
409
|
-
// result = this.contractOrder.companyId;
|
|
410
|
-
// } else if (this._companyId) {
|
|
411
|
-
// result = this._companyId;
|
|
412
|
-
// }
|
|
413
|
-
// return result;
|
|
414
|
-
// }
|
|
415
|
-
// });
|
|
416
|
-
// Object.defineProperty(options, "identifyLimit", {
|
|
417
|
-
// get: function () {
|
|
418
|
-
// if (!this._identifyLimit) {
|
|
419
|
-
// // this._identifyLimit = hb.waitPromise(_getIdentifyLimit(this.companyId));
|
|
420
|
-
// throw "options._identifyLimit 没有赋值";
|
|
421
|
-
// }
|
|
422
|
-
//
|
|
423
|
-
// return this._identifyLimit;
|
|
424
|
-
// },
|
|
425
|
-
// // configurable : true
|
|
426
|
-
// });
|
|
427
|
-
// }
|
|
428
|
-
if (res) {
|
|
429
|
-
Object.defineProperty(options, '_res', {
|
|
430
|
-
value: res,
|
|
431
|
-
enumerable: false
|
|
432
|
-
});
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
return options;
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* 从请求头获取token
|
|
439
|
-
* @param req
|
|
440
|
-
* @param res
|
|
441
|
-
* @param noErr
|
|
442
|
-
* @returns {Promise<*>}
|
|
443
|
-
*/
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
static async extractToken(req, res, noErr) {
|
|
447
|
-
configNeeded();
|
|
448
|
-
|
|
449
|
-
if (!req.accessToken) {
|
|
450
|
-
//检查post的信息或者url查询参数或者头信息
|
|
451
|
-
let token = req.headers[hnToken] || req.headers['x-access-token']; //向后兼容
|
|
452
|
-
|
|
453
|
-
if (!token) {
|
|
454
|
-
let params = apiUtil$1.extractParams(req);
|
|
455
|
-
token = params[pnToken];
|
|
456
|
-
|
|
457
|
-
if (token) {
|
|
458
|
-
delete params[pnToken];
|
|
459
|
-
} else if (params.token) {
|
|
460
|
-
token = params.token; //向后兼容
|
|
461
|
-
|
|
462
|
-
delete params.token;
|
|
463
|
-
} else {
|
|
464
|
-
// 如果没有token,则返回错误
|
|
465
|
-
console.log(err.TOKEN_NEEDED);
|
|
466
|
-
|
|
467
|
-
if (res) {
|
|
468
|
-
res.send(err.ERROR(err.TOKEN_NEEDED));
|
|
469
|
-
} else if (!noErr) {
|
|
470
|
-
throw err.TOKEN_NEEDED;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
req.accessToken = token;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
return req.accessToken;
|
|
479
|
-
}
|
|
480
|
-
/**
|
|
481
|
-
* 检查是不是内部调用,应用系统可替换此函数实施更隐秘的检查
|
|
482
|
-
* @param req
|
|
483
|
-
* @returns {Promise<boolean|undefined>}
|
|
484
|
-
*/
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
static async checkInternalToken(req) {
|
|
488
|
-
// return await checkInternalToken(req);
|
|
489
|
-
const params = apiUtil$1.extractParams(req);
|
|
490
|
-
req.accessToken = req.accessToken || apiUtil$1.extractToken(req);
|
|
491
|
-
|
|
492
|
-
if (req.accessToken === MD5(ppUtil$1.idNumDisturbing)) {
|
|
493
|
-
//todo: 检查IP
|
|
494
|
-
params.__internal__ = true;
|
|
495
|
-
req.ignoreToken = true; // if (params.idNum || params.personId) {
|
|
496
|
-
// return queryPersonUser(params.idNum, params.personId)
|
|
497
|
-
// .then(async userInfo => {
|
|
498
|
-
// if (!userInfo) {
|
|
499
|
-
// // console.log('queryPersonUser error.', e);
|
|
500
|
-
// throw err.TOKEN_INVALID;
|
|
501
|
-
// }
|
|
502
|
-
// if (req.tokenValidater) await req.tokenValidater(userInfo, req)
|
|
503
|
-
// req.userInfo = userInfo;
|
|
504
|
-
// return true
|
|
505
|
-
// })
|
|
506
|
-
// } else {
|
|
507
|
-
// return true
|
|
508
|
-
// }
|
|
509
|
-
|
|
510
|
-
return true;
|
|
511
|
-
} else {
|
|
512
|
-
// console.log('token error.', req.accessToken);
|
|
513
|
-
throw err.TOKEN_INVALID;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
/**
|
|
517
|
-
* 检查请求是否存在合法的token,若不存在则抛出异常
|
|
518
|
-
* @param req
|
|
519
|
-
* @returns {Promise<void>}
|
|
520
|
-
*/
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
static async checkRequestToken(req) {
|
|
524
|
-
req.accessToken = req.accessToken || apiUtil$1.extractToken(req);
|
|
525
|
-
await apiUtil$1.restoreTokenData(apiUtil$1.userTokenStoreKey(req.accessToken), apiUtil$1.tokenExpireTime(req)).then(async function (data) {
|
|
526
|
-
req.userInfo = apiUtil$1.setUserIdNo(data, data._idNo);
|
|
527
|
-
if (req.tokenValidater) await req.tokenValidater(req.userInfo, req);
|
|
528
|
-
return true;
|
|
529
|
-
}, async function (e) {
|
|
530
|
-
// 如果给定的token不存在,看看是不是平台内部调用
|
|
531
|
-
return await apiUtil$1.checkInternalToken(req);
|
|
532
|
-
});
|
|
533
|
-
}
|
|
534
|
-
/**
|
|
535
|
-
* 检查是不是调试模式
|
|
536
|
-
* @param req
|
|
537
|
-
* @returns {*|boolean|boolean}
|
|
538
|
-
*/
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
static isDebugMode(req) {
|
|
542
|
-
if (req.__debug__ === undefined) {
|
|
543
|
-
let dbgToken = req.headers['__debug__'] || req.headers[apiUtil$1.debugFlag];
|
|
544
|
-
|
|
545
|
-
if (dbgToken) {
|
|
546
|
-
let envId = process.env.ECS_DEPLOY_ID;
|
|
547
|
-
req.__debug__ = dbgToken && dbgToken === MD5(req.headers.timestamp, ppUtil$1.commonHashDisturbing) && (envId === "florist_longdan" || envId === "shuzi");
|
|
548
|
-
} else {
|
|
549
|
-
req.__debug__ = false;
|
|
550
|
-
} // console.log("__debug__:", req.__debug__, "dbgToken:", dbgToken);
|
|
551
|
-
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
return req.__debug__; // return req.headers["postman-token"] || req.headers['__debug__'] && req.headers['__debug__'] == "true";
|
|
555
|
-
}
|
|
556
|
-
/**
|
|
557
|
-
* 检查是不是测试模式
|
|
558
|
-
* @param req
|
|
559
|
-
* @returns {*|boolean}
|
|
560
|
-
*/
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
static isTestMode(req) {
|
|
564
|
-
if (req.__postman__ === undefined) {
|
|
565
|
-
let dbgToken = req.headers["__postman__"] || req.headers[apiUtil$1.testFlag];
|
|
566
|
-
|
|
567
|
-
if (dbgToken) {
|
|
568
|
-
let envId = process.env.ECS_DEPLOY_ID;
|
|
569
|
-
let testToken = MD5(req.headers.timestamp, apiUtil$1.extractToken(req, null, true) || req.headers.apikey);
|
|
570
|
-
req.__postman__ = dbgToken === testToken && (envId.indexOf("myfacesign.com") < 0 || envId.indexOf(".dev.") > 0);
|
|
571
|
-
} else {
|
|
572
|
-
req.__postman__ = false;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
return req.__postman__;
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* 获取令牌过期时长
|
|
580
|
-
* @param req
|
|
581
|
-
* @returns {any}
|
|
582
|
-
*/
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
static tokenExpireTime(req) {
|
|
586
|
-
return apiUtil$1.isDebugMode(req) ? 30 * 24 * 60 * 60 : apiUtil$1.isTestMode(req) ? 4 * 60 * 60 : appSetting.tokenExpireTime;
|
|
587
|
-
}
|
|
588
|
-
/**
|
|
589
|
-
* 获取用户令牌保存键
|
|
590
|
-
* @param token
|
|
591
|
-
* @returns {string}
|
|
592
|
-
*/
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
static userTokenStoreKey(token) {
|
|
596
|
-
return "ut_" + token;
|
|
597
|
-
}
|
|
598
|
-
/**
|
|
599
|
-
* 获取机构令牌保存键
|
|
600
|
-
* @param token
|
|
601
|
-
* @returns {string}
|
|
602
|
-
*/
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
static apiTokenStoreKey(token) {
|
|
606
|
-
return "api_" + token;
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* 判断是不是香港身份证
|
|
610
|
-
* @param idNum
|
|
611
|
-
* @returns {boolean}
|
|
612
|
-
*/
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
static checkIsHKIC(idNum) {
|
|
616
|
-
return idNum.length === 8;
|
|
617
|
-
}
|
|
618
|
-
/**
|
|
619
|
-
* 将身份证号码暂存到用户信息中
|
|
620
|
-
* @param userInfo
|
|
621
|
-
* @param idNum
|
|
622
|
-
* @returns {*}
|
|
623
|
-
*/
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
static setUserIdNo(userInfo, idNum) {
|
|
627
|
-
if (userInfo && idNum) {
|
|
628
|
-
userInfo._idNo = idNum;
|
|
629
|
-
userInfo.isHKIC = apiUtil$1.checkIsHKIC(idNum);
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
return userInfo;
|
|
633
|
-
}
|
|
634
|
-
/**
|
|
635
|
-
* 暂存令牌
|
|
636
|
-
* @param token
|
|
637
|
-
* @param tokenData
|
|
638
|
-
* @param dataId
|
|
639
|
-
* @param req
|
|
640
|
-
* @returns {Promise<void>}
|
|
641
|
-
*/
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
static async storeToken(token, tokenData, dataId, req) {
|
|
645
|
-
// let timeout = tokenData.clientIp.substring(0, 8) == "192.168." ? 90 * 24 : 1;
|
|
646
|
-
let timeout = apiUtil$1.tokenExpireTime(req);
|
|
647
|
-
|
|
648
|
-
if (req.certPublicKey) {
|
|
649
|
-
tokenData.certPublicKey = req.certPublicKey;
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
kvStorage.storeObj(token, tokenData, timeout);
|
|
653
|
-
|
|
654
|
-
if (dataId) {
|
|
655
|
-
kvStorage.restoreValue("token_" + dataId).then(function (oldToken) {
|
|
656
|
-
if (oldToken !== token) {
|
|
657
|
-
kvStorage.unstoreValue(oldToken);
|
|
658
|
-
} else {
|
|
659
|
-
dataId = "";
|
|
660
|
-
}
|
|
661
|
-
}, function (e) {}).then(() => {
|
|
662
|
-
if (dataId !== "") kvStorage.storeValue("token_" + dataId, token, timeout);
|
|
663
|
-
});
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* 恢复令牌数据
|
|
668
|
-
* @param accessToken
|
|
669
|
-
* @param expireTime
|
|
670
|
-
* @returns {Promise<any>}
|
|
671
|
-
*/
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
static async restoreTokenData(accessToken, expireTime) {
|
|
675
|
-
return await kvStorage.restoreObj(accessToken, expireTime);
|
|
676
|
-
}
|
|
677
|
-
/**
|
|
678
|
-
* 创建 API 调用记录
|
|
679
|
-
* @param tokenData
|
|
680
|
-
* @param req
|
|
681
|
-
* @returns {any}
|
|
682
|
-
*/
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
static createApiCallRec(tokenData, req) {
|
|
686
|
-
if (!req.apiCallRec) {
|
|
687
|
-
if (req.apiCallRecId) {
|
|
688
|
-
return dbQueryOne(dbSql.loadApiUsage, {
|
|
689
|
-
replacements: {
|
|
690
|
-
id: req.apiCallRecId
|
|
691
|
-
}
|
|
692
|
-
}).then(rec => {
|
|
693
|
-
req.apiCallRec = rec;
|
|
694
|
-
return req.apiCallRec;
|
|
695
|
-
});
|
|
696
|
-
} else {
|
|
697
|
-
let params = extractParams(req); // let contentLength = parseInt(req.headers["content-length"]) || 0;
|
|
698
|
-
|
|
699
|
-
let rec = {
|
|
700
|
-
id: newGuid(),
|
|
701
|
-
companyId: tokenData.apiKey || '',
|
|
702
|
-
orderId: params.orderId || '',
|
|
703
|
-
signerId: params.signerId || '',
|
|
704
|
-
userId: params.userId || '',
|
|
705
|
-
contractName: params.contractName || '',
|
|
706
|
-
spOrderNum: params.spOrderNum || '',
|
|
707
|
-
notifyUri: params.notifyUri || '',
|
|
708
|
-
fileName: params.fileName || '',
|
|
709
|
-
fileHash: params.fileHash || '',
|
|
710
|
-
fileKeyHash: params.fileKeyHash || '',
|
|
711
|
-
fileSignedHash: params.fileSignedHash || '',
|
|
712
|
-
createTime: new Date(),
|
|
713
|
-
secret: tokenData.apiSecret || '',
|
|
714
|
-
fromIp: tokenData.clientIp || '',
|
|
715
|
-
method: req.method,
|
|
716
|
-
uri: req.route.path,
|
|
717
|
-
urlParams: req.url.split("?")[1] || "",
|
|
718
|
-
contentType: (req.headers["content-type"] || '').substring(0, 45),
|
|
719
|
-
// body: contentLength < 500 ? req.rawBody || '' : 'lob data, size:' + contentLength,
|
|
720
|
-
body: _getBodyLogStr(req),
|
|
721
|
-
resultCode: params.resultCode || '0',
|
|
722
|
-
resultInfo: params.resultInfo || '',
|
|
723
|
-
resultData: params.resultData || ''
|
|
724
|
-
};
|
|
725
|
-
|
|
726
|
-
if (rec.secret !== "") {
|
|
727
|
-
rec.secret = hb.getEncAse192(rec.secret);
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
req.apiCallRec = rec;
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
return req.apiCallRec;
|
|
735
|
-
}
|
|
736
|
-
/**
|
|
737
|
-
* 查询机构信息
|
|
738
|
-
* @param companyId
|
|
739
|
-
* @param nullable
|
|
740
|
-
* @returns {Promise<null|*>}
|
|
741
|
-
*/
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
static async queryCompanyInfo(companyId, nullable) {
|
|
745
|
-
return await dbUtil.dbQueryOne(dbSql.queryCompanyInfo, {
|
|
746
|
-
companyId
|
|
747
|
-
}, nullable);
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
* 获取企业有效证书
|
|
751
|
-
* @param companyId: 企业标识
|
|
752
|
-
*/
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
static async getCompanyCertificate(companyId) {
|
|
756
|
-
let certInfo = {
|
|
757
|
-
// 正式启用的证书
|
|
758
|
-
certLiving: null,
|
|
759
|
-
certLivingId: '',
|
|
760
|
-
// 备用证书
|
|
761
|
-
certSpare: null,
|
|
762
|
-
certSpareId: ''
|
|
763
|
-
};
|
|
764
|
-
return await dbUtil.dbQueryOne(dbSql.queryCertDataByOwner, {
|
|
765
|
-
ownerId: companyId,
|
|
766
|
-
applyId: "company"
|
|
767
|
-
}, false).then(certRec => {
|
|
768
|
-
// console.log('当前证书:\n', certRec);
|
|
769
|
-
// checkCertStatus(certRec);
|
|
770
|
-
let certData = JSON.parse(certRec.certBody);
|
|
771
|
-
let pubKeyData = Buffer.from(certData.cert, "base64").toString(); // 公司正式证书
|
|
772
|
-
|
|
773
|
-
certInfo.certLiving = pubKeyData;
|
|
774
|
-
certInfo.certLivingId = certRec.id;
|
|
775
|
-
return dbUtil.dbQueryOne(dbSql.queryCertDataByOwner, {
|
|
776
|
-
ownerId: companyId,
|
|
777
|
-
applyId: "company_spare"
|
|
778
|
-
}, false).then(certRec1 => {
|
|
779
|
-
// console.log('备用证书:\n', certRec1);
|
|
780
|
-
// checkCertStatus(certRec1);
|
|
781
|
-
let certData1 = JSON.parse(certRec1.certBody);
|
|
782
|
-
let pubKeyData1 = Buffer.from(certData1.cert, "base64").toString(); // 公司备用证书
|
|
783
|
-
|
|
784
|
-
certInfo.certSpare = pubKeyData1;
|
|
785
|
-
certInfo.certSpareId = certRec1.id;
|
|
786
|
-
}).catch(e => {
|
|
787
|
-
// console.log('获取备用证书失败。', e);
|
|
788
|
-
certInfo.certSpare = null;
|
|
789
|
-
});
|
|
790
|
-
}).then(() => {
|
|
791
|
-
return certInfo;
|
|
792
|
-
}).catch(e => {
|
|
793
|
-
console.log('获取企业证书失败:\n', e);
|
|
794
|
-
throw [err.ACCESS_REFUSED, `获取企业证书失败:${err.ERROR(e).message}`];
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
-
/**
|
|
798
|
-
* 验证API调用签名
|
|
799
|
-
* @param tokenData
|
|
800
|
-
* @param req
|
|
801
|
-
* @returns {Promise<*|boolean>}
|
|
802
|
-
*/
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
static async verifyApiSignature(tokenData, req) {
|
|
806
|
-
try {
|
|
807
|
-
if (!req.headers.timestamp) {
|
|
808
|
-
throw [err.ACCESS_REFUSED, `必须在请求头中设置时戳`];
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
let timestamp = parseInt(req.headers.timestamp);
|
|
812
|
-
let currentTime = new Date().valueOf();
|
|
813
|
-
let maxTimeDiff = apiUtil$1.isDebugMode(req) ? 7 * 24 * 3600 : apiUtil$1.isTestMode(req) ? 4 * 3600 : 100; // 100
|
|
814
|
-
|
|
815
|
-
if (timestamp.toString() == "NaN" || currentTime < timestamp - 5000 || currentTime - timestamp > maxTimeDiff * 1000) {
|
|
816
|
-
throw [err.ACCESS_REFUSED, `时戳(${timestamp})无效,当前时戳:${currentTime},时差 ${(currentTime - timestamp) / 1000}秒`];
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
let signature = req.headers.signature;
|
|
820
|
-
|
|
821
|
-
if (!signature) {
|
|
822
|
-
throw [err.ACCESS_REFUSED, `必须在请求头中提供签名`];
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
let signData = apiUtil$1.extractToken(req, null, true) || tokenData.apiKey;
|
|
826
|
-
signData += timestamp;
|
|
827
|
-
|
|
828
|
-
if (apiUtil$1.isDebugMode(req) || apiUtil$1.isTestMode(req)) {
|
|
829
|
-
let publicKey = req.headers.publickey || req.body.publicKey || req.query.publicKey;
|
|
830
|
-
|
|
831
|
-
if (publicKey) {
|
|
832
|
-
publicKey = decodeURIComponent(publicKey);
|
|
833
|
-
tokenData.certPublicKey = publicKey;
|
|
834
|
-
req.certPublicKey = publicKey;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
if (tokenData.certPublicKey) {
|
|
839
|
-
let verifyResult = doVerify(signData, signature, tokenData.certPublicKey);
|
|
840
|
-
return await verifyResult;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
return apiUtil$1.getCompanyCertificate(tokenData.apiKey).then(info => {
|
|
844
|
-
tokenData.certPublicKey = info.certLiving;
|
|
845
|
-
tokenData.certPublicKeySpare = info.certSpare;
|
|
846
|
-
tokenData.certLivingId = info.certLivingId;
|
|
847
|
-
tokenData.certSpareId = info.certSpareId;
|
|
848
|
-
req.certPublicKey = info.certLiving;
|
|
849
|
-
let token = apiUtil$1.extractToken(req, null, true);
|
|
850
|
-
|
|
851
|
-
if (token) {
|
|
852
|
-
apiUtil$1.storeToken(apiUtil$1.apiTokenStoreKey(token), tokenData, tokenData.apiKey, req);
|
|
853
|
-
}
|
|
854
|
-
}).then(() => {
|
|
855
|
-
return doVerify(signData, signature, tokenData.certPublicKey);
|
|
856
|
-
});
|
|
857
|
-
} catch (e) {
|
|
858
|
-
// return Promise.reject(e);
|
|
859
|
-
throw e;
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
function doVerify(signData, signature) {
|
|
863
|
-
let verify = crypto.createVerify('SHA256');
|
|
864
|
-
verify.write(signData);
|
|
865
|
-
verify.end();
|
|
866
|
-
let verifyOK = false;
|
|
867
|
-
|
|
868
|
-
try {
|
|
869
|
-
// 先用正式证书验证
|
|
870
|
-
verifyOK = verify.verify(tokenData.certPublicKey, signature, 'base64');
|
|
871
|
-
} catch (e) {
|
|
872
|
-
console.log("SPO服务签名验证异常(正式证书), ", e);
|
|
873
|
-
verifyOK = false;
|
|
874
|
-
|
|
875
|
-
if (!tokenData.certPublicKeySpare) {
|
|
876
|
-
throw {
|
|
877
|
-
eo: err.ACCESS_REFUSED,
|
|
878
|
-
msgArgv: "签名验证异常",
|
|
879
|
-
data: e
|
|
880
|
-
};
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
if (!verifyOK && tokenData.certPublicKeySpare) {
|
|
885
|
-
try {
|
|
886
|
-
// 再用备用证书验证
|
|
887
|
-
let verifySpare = crypto.createVerify('SHA256');
|
|
888
|
-
verifySpare.write(signData);
|
|
889
|
-
verifySpare.end();
|
|
890
|
-
verifyOK = verifySpare.verify(tokenData.certPublicKeySpare, signature, 'base64');
|
|
891
|
-
|
|
892
|
-
if (verifyOK) {
|
|
893
|
-
// 备用证书验证成功了,则将备用证书替换为正式证书
|
|
894
|
-
console.log(`公司(${tokenData.apiKey})备用证书验签成功,正式启用...`);
|
|
895
|
-
return dbUtil.dbTrans(trans => {
|
|
896
|
-
let p1 = dbUtil.dbExec(dbSql.deleteCertRecById, {
|
|
897
|
-
replacements: {
|
|
898
|
-
id: tokenData.certLivingId
|
|
899
|
-
},
|
|
900
|
-
transaction: trans
|
|
901
|
-
});
|
|
902
|
-
let p2 = dbUtil.dbExec(dbSql.spareCertToLiving, {
|
|
903
|
-
replacements: {
|
|
904
|
-
id: tokenData.certSpareId
|
|
905
|
-
},
|
|
906
|
-
transaction: trans
|
|
907
|
-
});
|
|
908
|
-
return Promise.all([p1, p2]);
|
|
909
|
-
}).then(() => {
|
|
910
|
-
tokenData.certPublicKey = tokenData.certPublicKeySpare;
|
|
911
|
-
delete tokenData.certLivingId;
|
|
912
|
-
delete tokenData.certSpareId;
|
|
913
|
-
delete tokenData.certPublicKeySpare;
|
|
914
|
-
let token = apiUtil$1.extractToken(req);
|
|
915
|
-
|
|
916
|
-
if (token) {
|
|
917
|
-
apiUtil$1.storeToken(apiTokenStoreKey(token), tokenData, tokenData.apiKey, req);
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
console.log(`公司(${tokenData.apiKey})备用证书成功转换为正式证书`);
|
|
921
|
-
});
|
|
922
|
-
}
|
|
923
|
-
} catch (e) {
|
|
924
|
-
console.log("SPO服务签名验证异常(备用证书), ", e);
|
|
925
|
-
throw {
|
|
926
|
-
eo: err.ACCESS_REFUSED,
|
|
927
|
-
msgArgv: "签名验证异常(spare)",
|
|
928
|
-
data: e
|
|
929
|
-
};
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
if (!verifyOK) {
|
|
934
|
-
console.log("SPO服务签名验证失败, tokenData: ", tokenData);
|
|
935
|
-
throw [err.ACCESS_REFUSED, "签名验证未通过"];
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
return verifyOK;
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
/**
|
|
942
|
-
* 检查API调用之合法性
|
|
943
|
-
* @param tokenData
|
|
944
|
-
* @param req
|
|
945
|
-
* @returns {Promise<any>}
|
|
946
|
-
*/
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
static async checkApiCallValid(tokenData, req) {
|
|
950
|
-
if (!tokenData.companyInfo) {
|
|
951
|
-
tokenData.companyInfo = await apiUtil$1.queryCompanyInfo(tokenData.apiKey, true).catch(e => {
|
|
952
|
-
console.log("执行企业信息查询发生异常", e);
|
|
953
|
-
throw [err.API_KEY_INVALID, "执行企业信息查询发生异常:" + e.message || ""];
|
|
954
|
-
});
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
const companyInfo = tokenData.companyInfo;
|
|
958
|
-
|
|
959
|
-
if (companyInfo != null) {
|
|
960
|
-
let secret = apiUtil$1._getApiSecret(tokenData.apiKey);
|
|
961
|
-
|
|
962
|
-
if (secret !== tokenData.apiSecret) throw err.API_SCREPT_INVALID; // 不再检查 IP 白名单,改为验证证书签名
|
|
963
|
-
// console.log("fromIp:", tokenData.clientIp, "ipWhiteList:", companyInfo.ipWhiteList);
|
|
964
|
-
// let whiteList = companyInfo.ipWhiteList || "";
|
|
965
|
-
// // 没有设置ip白名单的就不检查了
|
|
966
|
-
// if (whiteList == "" || ipMatched(tokenData.clientIp, whiteList + ",127.0.0.1,1"))
|
|
967
|
-
|
|
968
|
-
if (apiUtil$1.signatureVerified()) return companyInfo;
|
|
969
|
-
return apiUtil$1.verifyApiSignature(tokenData, req).then(x => {
|
|
970
|
-
return companyInfo;
|
|
971
|
-
}, e => {
|
|
972
|
-
throw e;
|
|
973
|
-
});
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
throw [err.API_KEY_INVALID, tokenData.apiKey];
|
|
977
|
-
}
|
|
978
|
-
/**
|
|
979
|
-
* 检查令牌数据是否存在
|
|
980
|
-
* @param token
|
|
981
|
-
* @returns {*}
|
|
982
|
-
*/
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
static tokenDataExist(token) {
|
|
986
|
-
return kvStorage.stored(token);
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
static parametersOK(params) {
|
|
990
|
-
configNeeded();
|
|
991
|
-
let paramSufix = params._param_sufix || "";
|
|
992
|
-
|
|
993
|
-
for (let i = 1; i < arguments.length; i++) {
|
|
994
|
-
let paramName = arguments[i];
|
|
995
|
-
let paramExists = false;
|
|
996
|
-
|
|
997
|
-
if (paramName.includes("/")) {
|
|
998
|
-
let names = paramName.split("/"); // if (params[names[0]]) {
|
|
999
|
-
// paramExists = true;
|
|
1000
|
-
// } else {
|
|
1001
|
-
// if (params[names[1]]) {
|
|
1002
|
-
// paramExists = true;
|
|
1003
|
-
// params[names[0]] = params[names[1]];
|
|
1004
|
-
// delete params[names[1]];
|
|
1005
|
-
// }
|
|
1006
|
-
// }
|
|
1007
|
-
|
|
1008
|
-
for (let ind in names) {
|
|
1009
|
-
let name = names[ind];
|
|
1010
|
-
|
|
1011
|
-
if (typeof params[name] != 'undefined') {
|
|
1012
|
-
paramExists = true;
|
|
1013
|
-
break;
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
if (paramSufix != "" && typeof params[name + paramSufix] != 'undefined') {
|
|
1017
|
-
paramExists = true;
|
|
1018
|
-
break;
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
paramName = `${paramName} 之一`;
|
|
1023
|
-
} else {
|
|
1024
|
-
paramExists = typeof params[paramName] != 'undefined' || typeof params[paramName + paramSufix] != 'undefined';
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
if (!paramExists) return ppUtil$1.errorPormise(err.ERROR(err.PARAMETER_NEEDED, paramName));
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
return Promise.resolve(paramSufix);
|
|
1031
|
-
} //#endregion
|
|
1032
|
-
//region ====中间件
|
|
1033
|
-
|
|
1034
|
-
/**
|
|
1035
|
-
* 检查令牌,若存在则将其的用户信息置入req,否则返回错误信息
|
|
1036
|
-
*/
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
static async $checkToken(req, res, next) {
|
|
1040
|
-
try {
|
|
1041
|
-
await apiUtil$1.checkRequestToken(req);
|
|
1042
|
-
return true;
|
|
1043
|
-
} catch (e) {
|
|
1044
|
-
res.send(err.ERROR(e));
|
|
1045
|
-
return false;
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
/**
|
|
1049
|
-
* 检查令牌,若存在则将其用户信息置入req
|
|
1050
|
-
*/
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
static async $getToken(req, res, next) {
|
|
1054
|
-
function extractToken(req, res) {
|
|
1055
|
-
if (!req.accessToken) {
|
|
1056
|
-
//检查post的信息或者url查询参数或者头信息
|
|
1057
|
-
let token = req.headers["access_token"] || req.headers['x-access-token']; //向后兼容
|
|
1058
|
-
|
|
1059
|
-
if (!token) {
|
|
1060
|
-
let params = apiUtil$1.extractParams(req);
|
|
1061
|
-
token = params["access_token"];
|
|
1062
|
-
|
|
1063
|
-
if (token) {
|
|
1064
|
-
delete params["access_token"];
|
|
1065
|
-
} else if (params.token) {
|
|
1066
|
-
token = params.token; //向后兼容
|
|
1067
|
-
|
|
1068
|
-
delete params.token; // } else if (res) {
|
|
1069
|
-
// // 如果没有token,则返回错误
|
|
1070
|
-
// console.log(err.TOKEN_NEEDED);
|
|
1071
|
-
// res.send(err.ERROR(err.TOKEN_NEEDED));
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
req.accessToken = token;
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
return req.accessToken;
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
try {
|
|
1082
|
-
if (extractToken(req, res)) {
|
|
1083
|
-
await apiUtil$1.restoreTokenData(apiUtil$1.userTokenStoreKey(req.accessToken), apiUtil$1.tokenExpireTime(req)).then(function (data) {
|
|
1084
|
-
req.userInfo = apiUtil$1.setUserIdNo(data, data._idNo);
|
|
1085
|
-
}, function (e) {//no token
|
|
1086
|
-
});
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
return true;
|
|
1090
|
-
} catch (e) {
|
|
1091
|
-
res.send(err.ERROR(e));
|
|
1092
|
-
return false;
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
/**
|
|
1096
|
-
* 标识此请求已经完成了签名验证或者无需进行签名验证
|
|
1097
|
-
*/
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
static $signatureVerified(req, res, next) {
|
|
1101
|
-
req.signatureVerified = true;
|
|
1102
|
-
return true;
|
|
1103
|
-
}
|
|
1104
|
-
/**
|
|
1105
|
-
* 标识此请求是从前端发过来的,比如移动端、PC浏览器等,区别于SPO一般的服务端后台请求。
|
|
1106
|
-
* 如果在请求参数中包含有签名参数,则将其移到请求头中
|
|
1107
|
-
*/
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
static $isMobile(req, res, next) {
|
|
1111
|
-
req.isMobile = true;
|
|
1112
|
-
|
|
1113
|
-
if (!req.signatureVerified) {
|
|
1114
|
-
let params = apiUtil$1.extractParams(req);
|
|
1115
|
-
moveProperty(params, req.headers, "access_token");
|
|
1116
|
-
moveProperty(params, req.headers, "timestamp");
|
|
1117
|
-
|
|
1118
|
-
if (moveProperty(params, req.headers, "signature")) {
|
|
1119
|
-
req.headers.signature = decodeURIComponent(req.headers.signature);
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
next();
|
|
1124
|
-
}
|
|
1125
|
-
/**
|
|
1126
|
-
* 检查企业 API 调用合法性 (apiKey, apiSecret)
|
|
1127
|
-
* @param req
|
|
1128
|
-
* @param res
|
|
1129
|
-
* @param next
|
|
1130
|
-
*/
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
static $checkApiKeyOld(req, res, next) {
|
|
1134
|
-
//检查post的信息或者url查询参数或者头信息
|
|
1135
|
-
let tokenData = apiUtil$1.extractTokenData(req);
|
|
1136
|
-
let params = apiUtil$1.extractParams(req);
|
|
1137
|
-
apiUtil$1.createApiCallRec(tokenData, req);
|
|
1138
|
-
let errResponse = null;
|
|
1139
|
-
|
|
1140
|
-
if (!tokenData.clientIp) {
|
|
1141
|
-
errResponse = apiUtil$1.spoApiFail(err.GET_CLIENTIP_FAIL, req);
|
|
1142
|
-
} else if (!tokenData.apiKey) {
|
|
1143
|
-
errResponse = apiUtil$1.spoApiFail([err.PARAMETER_NEEDED, "apiKey"], req);
|
|
1144
|
-
} else if (!tokenData.apiSecret) {
|
|
1145
|
-
errResponse = apiUtil$1.spoApiFail([err.PARAMETER_NEEDED, "apiSecret"], req);
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
if (errResponse != null) {
|
|
1149
|
-
apiUtil$1._saveApiCallRec(req.apiCallRec, errResponse);
|
|
1150
|
-
|
|
1151
|
-
apiUtil$1.sendOrRedirect(req, res, errResponse);
|
|
1152
|
-
} else {
|
|
1153
|
-
apiUtil$1.checkApiCallValid(tokenData, req).then(companyInfo => {
|
|
1154
|
-
params.companyId = params.companyId || companyInfo.companyId;
|
|
1155
|
-
req.companyInfo = companyInfo;
|
|
1156
|
-
next();
|
|
1157
|
-
}, e => {
|
|
1158
|
-
console.log('apiCallInvalid:', e);
|
|
1159
|
-
let errResponse = spoApiFail(e, req);
|
|
1160
|
-
|
|
1161
|
-
apiUtil$1._saveApiCallRec(req.apiCallRec, errResponse);
|
|
1162
|
-
|
|
1163
|
-
apiUtil$1.sendOrRedirect(req, res, errResponse);
|
|
1164
|
-
});
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
/**
|
|
1168
|
-
* 检查机构令牌
|
|
1169
|
-
*/
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
static $checkApiKey(req, res, next) {
|
|
1173
|
-
if (req.ignoreToken) {
|
|
1174
|
-
next();
|
|
1175
|
-
return;
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
|
-
let accessToken = apiUtil$1.extractToken(req);
|
|
1179
|
-
|
|
1180
|
-
if (!accessToken) {
|
|
1181
|
-
res.send(apiUtil$1.spoApiFail(err.TOKEN_NEEDED, req)); // apiUtil.sendOrRedirect(req, res, spoApiFail(err.TOKEN_NEEDED, req));
|
|
1182
|
-
|
|
1183
|
-
return;
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
apiUtil$1.restoreTokenData(apiUtil$1.apiTokenStoreKey(accessToken)).then(p => {
|
|
1187
|
-
// req.headers[hnApiKey] = p.apiKey || '';
|
|
1188
|
-
// req.headers[hnApiSecret] = p.apiSecret || '';
|
|
1189
|
-
if (req.isMobile) {
|
|
1190
|
-
// GET 请求的应该都是H5页面,由手机前端发起,需要把headers中的请求方ip换成服务端的
|
|
1191
|
-
// todo: 如何在API访问记录中记住请求者(手机端)的真实IP
|
|
1192
|
-
req.headers['x-phone-ip'] = hb.getClientIp(req);
|
|
1193
|
-
req.headers['x-real-ip'] = p.clientIp;
|
|
1194
|
-
} else {
|
|
1195
|
-
p.clientIp = hb.getClientIp(req);
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
req.isApiCall = true;
|
|
1199
|
-
req.tokenData = p;
|
|
1200
|
-
apiUtil$1.$checkApiKeyOld(req, res, next);
|
|
1201
|
-
}).catch(e => {
|
|
1202
|
-
// res.send(hb.showError("授权令牌不存在或已过期"));
|
|
1203
|
-
// res.send(spoApiFail(err.TOKEN_INVALID, req));
|
|
1204
|
-
apiUtil$1.sendOrRedirect(req, res, apiUtil$1.spoApiFail(err.TOKEN_INVALID, req));
|
|
1205
|
-
});
|
|
1206
|
-
}
|
|
1207
|
-
/**
|
|
1208
|
-
* 检查请求令牌,允许个人用户令牌和机构令牌,若不存在或不合法,则返回错误信息
|
|
1209
|
-
* @param req
|
|
1210
|
-
* @param res
|
|
1211
|
-
* @param next
|
|
1212
|
-
* @returns {Promise<void|boolean|boolean|undefined>}
|
|
1213
|
-
*/
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
static async $checkTokenOrApiKey(req, res, next) {
|
|
1217
|
-
let accessToken = apiUtil$1.extractToken(req, res);
|
|
1218
|
-
|
|
1219
|
-
if (accessToken) {
|
|
1220
|
-
let tokenExist = await apiUtil$1.tokenDataExist(apiUtil$1.userTokenStoreKey(accessToken));
|
|
1221
|
-
|
|
1222
|
-
if (tokenExist) {
|
|
1223
|
-
return apiUtil$1.$checkToken(req, res, next);
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
tokenExist = await apiUtil$1.tokenDataExist(apiUtil$1.apiTokenStoreKey(accessToken));
|
|
1227
|
-
|
|
1228
|
-
if (tokenExist) {
|
|
1229
|
-
return apiUtil$1.$checkApiKey(req, res, next);
|
|
1230
|
-
} // 如果给定的token不存在,看看是不是平台内部调用
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
return await apiUtil$1.checkInternalToken(req).catch(e => {
|
|
1234
|
-
res.send(apiUtil$1.apiFail(e, req));
|
|
1235
|
-
return false;
|
|
1236
|
-
});
|
|
1237
|
-
}
|
|
1238
|
-
} //#endregion
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
function configNeeded() {
|
|
1244
|
-
if (!conf || !err) {
|
|
1245
|
-
ppUtil$1.configNeeded();
|
|
1246
|
-
conf = ppUtil$1.appConfig;
|
|
1247
|
-
appSetting = conf.appSetting;
|
|
1248
|
-
err = ppUtil$1.appErrCfg;
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
var ppUtilApi = apiUtil$1;
|
|
1253
|
-
|
|
1254
|
-
const apiUtil = ppUtilApi;
|
|
1255
|
-
var ppUtil = {
|
|
1256
|
-
apiUtil
|
|
1257
|
-
};
|
|
1258
|
-
|
|
1259
|
-
export { ppUtil as default };
|