gamerpc 8.0.8 → 9.0.1

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/src/index.js CHANGED
@@ -1,679 +1,140 @@
1
- //const {encrypt, decrypt, createHmac} = require('./utils/util');
2
- const {stringify, NotifyType, extendObj, CommStatus, clone, ReturnCodeName, ReturnCode, CommMode, io} = require('./utils/util');
3
- const EventEmitter = require('events').EventEmitter;
4
- const Indicator = require('./utils/Indicator');
5
- // const assert = require('./utils/assert')
6
- // let {sha1, hash160, hash256, verifyData, generateKey, signObj, verifyObj, verifyAddress} = require('./utils/verifyData');
7
- // const Secret = require('./utils/secret')
8
-
9
1
  /**
10
- * RPC控件
11
- * @note
12
- * 1、根据创建参数,可分别支持WS、Socket、Http三种常用通讯模式,支持Notify、JSONP、Watching等报文通讯模式
13
- * 2、支持LBS重定向功能
14
- * 3、内部封装了一定的断言功能
2
+ * gamerpc V9.0.0 - 游戏云/区块链统一工具包
3
+ *
4
+ * 合并 V7.1.3 (auth3.0 分支) 和 V9.0.0 (V8.0.8 继承)。
5
+ *
6
+ * 提供两大核心连接器:
7
+ * 1. gameConn - 游戏云服务器连接器 (连接 Gamecloud,发起RPC调用,订阅推送)
8
+ * 2. conn/authConn - 区块链全节点连接器 (连接 Gamegold Core 对等网络,钱包操作)
9
+ *
10
+ * 同时提供区块链密码学工具函数和通用工具函数。
15
11
  */
16
- class Remote {
17
- constructor(options) {
18
- this.rpcMode = CommMode.post;
19
- this.loginMode = Indicator.inst();
20
- this.configOri = options; //读取并保存初始配置,不会修改
21
- this.config = clone(this.configOri); //复制一份配置信息,有可能修改
22
- this.notifyHandles = {};
23
- this.userInfo = {};
24
- //事件管理器
25
- this.events = new EventEmitter();
26
- //状态管理器
27
- this.status = Indicator.inst(options.status);
28
-
29
- //两阶段登录时,用户输入验证码时提交此事件
30
- this.events.on('authcode', async code => {
31
- console.log('gameconn: commit authcode', code);
32
- await this.setSign(code).login();
33
- })
34
- }
35
-
36
- /**
37
- * 修改通讯模式
38
- * @param {*} $mode 通讯模式
39
- * @param {*} cb 建立连接时的回调
40
- */
41
- setmode($mode) {
42
- this.rpcMode = $mode;
43
- return this;
44
- }
45
-
46
- /**
47
- * 创建通讯连接组件
48
- * @param {*} ip
49
- * @param {*} port
50
- */
51
- async createSocket() {
52
- let port = this.config.webserver.port;
53
- let host = this.config.webserver.host;
54
- let url = this.config.webserver.url;
55
-
56
- this.close();
57
-
58
- if(!url) {
59
- this.socket = io(`${this.config.UrlHead}://${host}:${port}`, {'force new connection': true});
60
- } else {
61
- this.socket = io(`${this.config.UrlHead}://${url}`, {'force new connection': true});
62
- }
63
- this.socket.on('notify', ret => {//监听推送消息
64
- if(this.notifyHandles[ret.type]) {
65
- this.notifyHandles[ret.type](ret.info);
66
- }
67
- else if(!!this.notifyHandles['0']){
68
- this.notifyHandles['0'](ret.info);
69
- }
70
- })
71
- .on('disconnect', ()=>{//断线重连
72
- console.log('gameconn: socket disconnected');
73
- this.events.emit('comm', {status: 'disconnect'});
74
- this.socket.needConnect = true;
75
- setTimeout(()=>{
76
- if(!!this.socket.needConnect) {
77
- this.socket.needConnect = false;
78
- this.socket.connect();
79
- }
80
- }, 1500);
81
- }).on('connect', () => { //连接消息
82
- console.log('gameconn: socket connected');
83
- this.events.emit('comm', {status: 'connect'});
84
- }).on('error', () => {
85
- this.events.emit('comm', {status: 'error'});
86
- });
87
-
88
- let self = this;
89
- let prom = new Promise(resolve => {
90
- self.events.on('comm', async msg => {
91
- if(msg.status == 'connect') {
92
- resolve();
93
- }
94
- })
95
- });
96
- return prom;
97
- }
98
-
99
- /**
100
- * 获取签名数据集
101
- */
102
- async getSign() {
103
- console.log('gameconn: getSign');
104
- //此处根据实际需要,发起了基于HTTP请求的认证访问,和本身创建时指定的通讯模式无关。
105
- let router = this.userInfo.openid.split('.')[0]; //openid一般由代表验证模式的前缀,加上代表节点类型的后缀组成, 获取签名接口的路由路径默认等于其前缀
106
- let msg = await this.getRequest({}, router);
107
-
108
- //客户端从模拟网关取得了签名集
109
- if(!msg) {
110
- return false;
111
- }
112
-
113
- this.userInfo.auth = msg;
114
-
115
- console.log('gameconn: getSign', msg);
116
-
117
- return true;
118
- }
119
-
120
- /**
121
- * 设置验证码
122
- * @param {*} code
123
- */
124
- setSign(code) {
125
- if(!!this.userInfo) {
126
- if(this.loginMode.check(CommStatus.reqSign)) {
127
- this.status.set(CommStatus.signCode);
128
- this.userInfo.auth = this.userInfo.auth || {};
129
- this.userInfo.auth.captcha = code;
130
- }
131
- }
132
- return this;
133
- }
134
-
135
- /**
136
- * 登录并获得令牌
137
- */
138
- async getToken() {
139
- if(!this.userInfo
140
- || (this.loginMode.check(CommStatus.reqLb) && !this.status.check(CommStatus.lb))
141
- || (this.loginMode.check(CommStatus.reqSign) && !this.status.check(CommStatus.signCode)
142
- || this.status.check(CommStatus.logined))
143
- ) {
144
- //不满足登录的前置条件或已经登录
145
- return false;
146
- }
147
-
148
- //将签证发送到服务端进行验证
149
- console.log('gameconn: getToken');
150
- let msg = await this.fetching({
151
- 'func': 'login.UserLogin',
152
- "oemInfo": this.userInfo,
153
- });
154
-
155
- if(!!msg) {
156
- console.log('gameconn: getToken', msg.code);
157
- if(msg.code == ReturnCode.Success && !!msg.data) {
158
- if(typeof msg.data == 'object') {
159
- extendObj(this.userInfo, msg.data);
160
- }
161
- this.status.set(CommStatus.logined);
162
- this.events.emit('logined', {code:0, data:{currentAuthority: this.userInfo.currentAuthority}});
163
-
164
- return true;
165
- } else {
166
- this.events.emit('logined', {code: msg.code});
167
- }
168
- } else {
169
- console.log('gameconn: getToken failed');
170
- this.events.emit('logined', {code:-1});
171
- }
172
- return false;
173
- }
174
-
175
- /**
176
- * 清空先前的缓存状态
177
- */
178
- clearCache() {
179
- if(this.userInfo) {
180
- this.userInfo.token = null;
181
- }
182
- }
183
-
184
- /**
185
- * 执行负载均衡流程
186
- * @param {*} ui
187
- */
188
- async setLB(force) {
189
- if(!this.userInfo) {
190
- //尚未设置有效的用户数据,无法执行
191
- return false;
192
- }
193
-
194
- if(!force && this.status.check(CommStatus.lb)) {
195
- //已经执行过LB操作,且非强制执行模式
196
- return true;
197
- }
198
-
199
- this.clearCache();
200
- this.status.init();
201
-
202
- console.log('gameconn: lb');
203
- let msg = await this.locate(this.configOri.webserver.host, this.configOri.webserver.port, this.configOri.webserver.url).getRequest({"func": "lb.getServerInfo", "oemInfo":{"domain": this.userInfo.domain, "openid": this.userInfo.openid}});
204
-
205
- if(!!msg && msg.code == ReturnCode.Success) {
206
- console.log('gameconn: lb', msg.data);
207
- this.status.set(CommStatus.lb);
208
- this.locate(msg.data.ip, msg.data.port, msg.data.url);
209
- return true;
210
- }
211
-
212
- console.log('gameconn: lb failed');
213
- return false;
214
- }
215
-
216
- /**
217
- * 登录流程
218
- * @param {Object} options
219
- * @param {Boolean} options.force 强制登录
220
- */
221
- async login(options) {
222
- options = options || {};
223
- if(options.force) {
224
- this.clearCache();
225
- this.status.init();
226
- }
227
-
228
- if(options.domain) {
229
- let authmode = options.openid.split('.')[0];
230
- switch(authmode) {
231
- case 'bxs': { //新增一种验证模式
232
- this.setUserInfo({
233
- domain: options.domain, //认证模式
234
- openid: options.openid, //用户证书
235
- openkey: options.openkey, //中间证书,经由Auth服务器转换成 openid 下发给客户端
236
- auth: options.auth, //验证信息
237
- }, CommStatus.reqLb);
238
-
239
- break;
240
- }
241
-
242
- case 'authwx': {
243
- this.setUserInfo({
244
- domain: options.domain, //认证模式
245
- openkey: options.openkey, //中间证书,经由Auth服务器转换成 openid 下发给客户端
246
- }, CommStatus.reqLb | CommStatus.reqOpenId);
247
-
248
- break;
249
- }
250
-
251
- case 'auth2step': {
252
- this.setUserInfo({
253
- domain: options.domain, //验证模式
254
- openid: options.openid, //用户证书
255
- openkey: options.openkey, //用户证书
256
- addrType: options.addrType, //验证方式
257
- address: options.address, //验证地址
258
- }, CommStatus.reqLb | CommStatus.reqSign);
259
-
260
- break;
261
- }
262
-
263
- case 'authpwd': {
264
- this.setUserInfo({
265
- domain: options.domain, //验证模式
266
- openid: options.openid, //用户证书
267
- openkey: options.openkey, //用户密码
268
- }, CommStatus.reqLb);
269
-
270
- break;
271
- }
272
-
273
- default: {
274
- this.setUserInfo({
275
- domain: options.domain || 'official', //验证模式
276
- openid: options.openid, //登录名称
277
- openkey: options.openkey, //登录密码
278
- });
279
- break;
280
- }
281
- }
282
- }
283
-
284
- if(this.status.check(CommStatus.logined)) {
285
- return false;
286
- }
287
12
 
288
- if(!this.userInfo) {
289
- return false;
290
- }
291
-
292
- //检测执行负载均衡
293
- if(this.loginMode.check(CommStatus.reqLb)) {
294
- if(!this.status.check(CommStatus.lb)) {
295
- //如果需要负载均衡且尚未执行,执行如下语句
296
- if(!(await this.setLB())) {
297
- //如果负载均衡失败,抛出异常,外围程序负责重新调用
298
- throw(new Error('lb error'));
299
- } else {
300
- this.status.set(CommStatus.lb);
301
- }
302
- }
303
- }
304
-
305
- //检测执行两阶段验证
306
- //两阶段验证模式(例如浏览器直接登录):执行此操作,访问控制器方法 authmode.auth 获取签名对象,并赋值到 userInfo.auth 字段,服务端同时会将关联验证码通过邮件或短信下发
307
- //第三方授权登录模式(例如微信或QQ登录)跳过此步
308
- if(this.loginMode.check(CommStatus.reqSign)) {
309
- if(!this.status.check(CommStatus.sign)) {
310
- //如果需要两阶段验证且尚未执行,执行如下语句
311
- if(!(await this.getSign())) {
312
- //如果负载均衡失败,抛出异常,外围程序负责重新调用
313
- throw(new Error('get sign error'));
314
- } else {
315
- this.status.set(CommStatus.sign);
316
- return true;
317
- }
318
- } else {
319
- return await this.getToken();
320
- }
321
- } else {
322
- return await this.getToken();
323
- }
324
- }
325
-
326
- /**
327
- * 设置用户信息
328
- * 1. 支持局部设定模式
329
- * 2. 每次设置,状态类缓存会被清除,通讯状态被复原
330
- * @param {Object} ui {openid}
331
- * @param {Number} st 登录流程描述符
332
- */
333
- setUserInfo(ui, st) {
334
- this.userInfo = this.userInfo || {};
335
-
336
- this.clearCache();
337
-
338
- //设置登录模式
339
- if(!!st) {
340
- this.loginMode.init(st);
341
- }
342
-
343
- //合并对象数据
344
- extendObj(this.userInfo, ui);
345
-
346
- return this;
347
- }
348
-
349
- /**
350
- * 设置服务端推送报文的监控句柄,支持链式调用
351
- * @param cb 回调
352
- * @param etype
353
- * @returns {Remote}
354
- */
355
- watch(cb, etype = '0') {
356
- this.notifyHandles[etype] = cb;
357
- return this;
358
- }
359
- /**
360
- * 移除监控句柄
361
- * @param {*} etype
362
- */
363
- unWatch(etype) {
364
- if(!!this.notifyHandles[etype]) {
365
- delete this.notifyHandles[etype];
366
- }
367
- return this;
13
+ // V7.1.3: 为数组添加工具方法
14
+ Array.prototype.randObj = function() {
15
+ if (this.length == 0) {
16
+ return null;
17
+ } else if (this.length == 1) {
18
+ return this[0];
19
+ } else {
20
+ return this[(Math.random() * this.length) | 0];
368
21
  }
22
+ };
369
23
 
370
- /**
371
- * 判断返回值是否成功
372
- * @param msg 网络报文
373
- * @param out 强制打印日志
374
- * @returns {*}
375
- */
376
- isSuccess(msg, out=false) {
377
- if(!msg) {
378
- return false;
379
- }
380
-
381
- msg.msg = ReturnCodeName[msg.code];
382
-
383
- if((msg.code != ReturnCode.Success) || out){
384
- this.log(msg);
385
- }
386
-
387
- return msg.code == ReturnCode.Success;
388
- }
389
-
390
- /**
391
- * 直接打印各种对象
392
- * @param val
393
- */
394
- log(val){
395
- if(!val){
396
- console.log('undefined');
397
- return;
398
- }
399
-
400
- if(!!val.code){
401
- val.msg = ReturnCodeName[val.code];
402
- }
403
-
404
- switch(typeof val){
405
- case 'number':
406
- case 'string':
407
- case 'boolean':
408
- console.log(val);
409
- break;
410
- case 'function':
411
- console.log(val());
412
- break;
413
- case 'undefined':
414
- console.log('err: undefined');
415
- break;
416
- default:
417
- console.log(JSON.stringify(val));
418
- break;
419
- }
420
- }
421
-
422
- get newone(){
423
- return new Remote(this.configOri).setmode(this.rpcMode);
424
- }
24
+ const toolkit = exports;
425
25
 
426
- /**
427
- * 获取新的远程对象
428
- * @returns {Remote}
429
- */
430
- get new(){
431
- return new Remote(this.configOri).setmode(this.rpcMode);
432
- }
26
+ // ==================== 核心连接器 ====================
433
27
 
434
- /**
435
- * 等待指定时长
436
- * @param {Number} time 等待时长(毫秒)
437
- */
438
- async wait (time) {
439
- await (async (time) => {return new Promise(resolve => {setTimeout(resolve, time);});})(time);
440
- }
28
+ /** 游戏云连接器 - 用于连接游戏云服务器 */
29
+ toolkit.gameconn = require('./gameConn');
30
+ toolkit.gameConn = toolkit.gameconn; // 别名
441
31
 
442
- /**
443
- * 为了提供node下的兼容性而添加的属性设定函数
444
- * @param {*} fn
445
- */
446
- setFetch(fn) {
447
- this.fetch = fn;
448
- return this;
449
- }
32
+ /** 区块链授权式连接器 - 用于连接 Gamegold Core 全节点 */
33
+ const AuthConn = require('./authConn');
34
+ toolkit.conn = AuthConn;
35
+ toolkit.authConn = AuthConn; // 别名
450
36
 
451
- /**
452
- * 向服务端提交请求,默认JSONP模式
453
- * @param params 命令参数,JSON对象
454
- * .command 命令名称,格式: obj.func, 可以缩写为 func,此时obj为默认值'index',例如 index.setNewbie 等价于 setNewbie
455
- * .url 附加url地址
456
- * @param callback 回调函数
457
- * @returns {*}
458
- */
459
- async fetching(params) {
460
- this.parseParams(params);
37
+ // ==================== 区块链密码学工具 ====================
461
38
 
462
- if(this.loginMode.check(CommStatus.reqLb) && !this.status.check(CommStatus.lb)) {
463
- await this.setLB();
464
- }
39
+ const verifyData = require('./utils/verifyData');
40
+ const Secret = require('./utils/secret');
41
+ const sha256 = require('./utils/sha256');
465
42
 
466
- switch(this.rpcMode) {
467
- case CommMode.ws:
468
- if(!this.socket) {
469
- await this.createSocket();
470
- }
471
- return new Promise((resolve, reject) => {
472
- this.socket.emit('req', params, msg => {
473
- resolve(msg);
474
- });
475
- });
43
+ // 签名与验证
44
+ toolkit.generateKey = verifyData.generateKey;
45
+ toolkit.signObj = verifyData.signObj;
46
+ toolkit.verifyObj = verifyData.verifyObj;
47
+ toolkit.verifyData = verifyData.verifyData;
48
+ toolkit.verifyAddress = verifyData.verifyAddress;
476
49
 
477
- case CommMode.get:
478
- return this.getRequest(params);
50
+ // 哈希函数
51
+ toolkit.hash256 = verifyData.hash256;
52
+ toolkit.hash160 = verifyData.hash160;
53
+ toolkit.sha1 = verifyData.sha1;
54
+ toolkit.sha256 = sha256.digest;
479
55
 
480
- case CommMode.post:
481
- return this.postRequest(params);
482
- }
56
+ // BIP151 加密流
57
+ toolkit.Secret = Secret;
483
58
 
484
- return Promise.reject();
485
- }
59
+ // ==================== AES 加解密 ====================
486
60
 
487
- /**
488
- * 设定远程服务器地址
489
- * @param host
490
- * @param port
491
- * @returns {Remote}
492
- */
493
- locate(host, port, url) {
494
- this.config.webserver.host = host;
495
- this.config.webserver.port = port;
496
- this.config.webserver.url = url;
61
+ const aes = require('./utils/aes');
497
62
 
498
- return this;
499
- }
63
+ /**
64
+ * AES-CBC 字符串加密(兼容 V7.x API)
65
+ * 编码规则:每字节拆分为高4位和低4位,加97偏移映射到 a-p 字符
66
+ */
67
+ toolkit.encrypt = function encrypt(key, iv, data) {
68
+ if (!Buffer.isBuffer(key)) key = Buffer.from(key, 'binary');
69
+ if (!Buffer.isBuffer(iv)) iv = Buffer.from(iv, 'binary');
70
+ if (!Buffer.isBuffer(data)) data = Buffer.from(data, 'binary');
500
71
 
501
- /**
502
- * 关闭长连接
503
- */
504
- close() {
505
- if(this.socket){
506
- this.socket.removeAllListeners();
507
- this.socket.disconnect();
508
- this.socket = null;
509
- }
72
+ var crypted = aes.encipher(data, key, iv);
73
+ crypted = Buffer.from(crypted, 'binary');
510
74
 
511
- return this;
75
+ let ret = Buffer.alloc(crypted.length * 2);
76
+ for (let i = 0; i < crypted.length; i++) {
77
+ ret[2 * i] = (crypted[i] >> 4) + 97;
78
+ ret[2 * i + 1] = (crypted[i] & 0x0F) + 97;
512
79
  }
80
+ return ret.toString('binary');
81
+ };
513
82
 
514
- /**
515
- * 彻底清除连接器历史数据,包括通讯状态、运行数据缓存,只保留最原始的配置信息
516
- */
517
- init() {
518
- this.close();
83
+ /**
84
+ * AES-CBC 字符串解密(兼容 V7.x API)
85
+ */
86
+ toolkit.decrypt = function decrypt(key, iv, data) {
87
+ if (!Buffer.isBuffer(key)) key = Buffer.from(key, 'binary');
88
+ if (!Buffer.isBuffer(iv)) iv = Buffer.from(iv, 'binary');
89
+ if (!Buffer.isBuffer(data)) data = Buffer.from(data, 'binary');
519
90
 
520
- this.config = clone(this.configOri); //复制一份配置信息,有可能修改
521
- this.userInfo = {};
522
- this.status.init();
523
- this.loginMode.init();
524
-
525
- return this;
91
+ let ret = Buffer.alloc(data.length / 2);
92
+ for (let i = 0; i < ret.length; i++) {
93
+ ret[i] = ((data[i * 2] - 97) << 4) | (data[i * 2 + 1] - 97);
526
94
  }
527
95
 
528
- /**
529
- * 参数调整
530
- * @param params
531
- */
532
- parseParams(params) {
533
- params.func = !!params.func ? params.func : 'index.login';
534
- //填充自动登录参数
535
- let arr = params.func.split('.');
536
- if(arr.length > 1) {
537
- params.control = arr[0];
538
- params.func = arr[1];
539
- } else {
540
- params.func = arr[0];
541
- }
96
+ var decoded = aes.decipher(ret, key, iv);
97
+ return decoded.toString('binary');
98
+ };
542
99
 
543
- params.oemInfo = {
544
- domain: this.userInfo.domain,
545
- openid: this.userInfo.openid,
546
- };
547
-
548
- if(this.userInfo.openkey) {
549
- params.oemInfo.openkey = this.userInfo.openkey;
550
- }
551
- if(this.userInfo.token) {
552
- params.oemInfo.token = this.userInfo.token;
553
- }
554
- if(this.userInfo.addrType) {
555
- params.oemInfo.addrType = this.userInfo.addrType;
556
- }
557
- if(this.userInfo.address) {
558
- params.oemInfo.address = this.userInfo.address;
559
- }
560
- if(this.userInfo.auth) {
561
- params.oemInfo.auth = this.userInfo.auth;
562
- }
563
- }
100
+ // ==================== HMAC 工具 ====================
564
101
 
565
- /**
566
- * 以 GET 方式访问远程API
567
- * @param {*} url 远程地址
568
- */
569
- async get(url) {
570
- const newOptions = { json: true, method: 'GET', mode: 'cors', };
571
-
572
- newOptions.headers = {
573
- Accept: 'application/json',
574
- 'Content-Type': 'application/json; charset=utf-8',
575
- };
102
+ const createHmac = require('create-hmac/browser');
576
103
 
577
- if(this.fetch) {
578
- let ret = await this.fetch(url, newOptions);
579
- return await ret.json();
580
- }
581
- else {
582
- let ret = await fetch(url, newOptions);
583
- return await ret.json();
584
- }
585
- }
586
-
587
- /**
588
- * 以 POST 方式访问远程API
589
- * @param {*} url 远程地址
590
- * @param {*} options body
591
- */
592
- async post(url, options) {
593
- const newOptions = { json: true, method: 'POST', mode: 'cors', body: JSON.stringify(options) };
594
-
595
- newOptions.headers = {
596
- Accept: 'application/json',
597
- 'Content-Type': 'application/json; charset=utf-8',
598
- };
104
+ /**
105
+ * 利用 HMAC-SHA256 计算访问令牌
106
+ */
107
+ function signHMAC(token, random) {
108
+ var hmac = createHmac('sha256', random);
109
+ return hmac.update(token).digest('hex');
110
+ }
599
111
 
600
- try {
601
- if(this.fetch) {
602
- let ret = await this.fetch(url, newOptions);
603
- return await ret.json();
604
- }
605
- else {
606
- let ret = await fetch(url, newOptions);
607
- return await ret.json();
608
- }
609
- }
610
- catch(e) {
611
- console.error(e);
612
- }
613
- }
614
-
615
- /**
616
- * (内部函数)发起基于Http协议的RPC请求
617
- * @param params
618
- */
619
- async getRequest(params, authControl) {
620
- this.parseParams(params);
112
+ toolkit.createHmac = createHmac;
113
+ toolkit.signHMAC = signHMAC;
621
114
 
622
- let url = null;
623
- if(!this.config.webserver.url) {
624
- let port = !!params.port ? params.port : this.config.webserver.port;
625
- url = !!authControl ? `${this.config.UrlHead}://${this.config.webserver.host}:${port}/${authControl}` : `${this.config.UrlHead}://${this.config.webserver.host}:${port}/index.html`;
626
- } else {
627
- url = !!authControl ? `${this.config.UrlHead}://${this.config.webserver.url}/${authControl}` : `${this.config.UrlHead}://${this.config.webserver.url}/index.html`;
628
- }
115
+ // ==================== 通用工具 ====================
629
116
 
630
- url += "?" + Object.keys(params).reduce((ret, next)=>{
631
- if(ret != '') {
632
- ret += '&';
633
- }
634
- //增加了字段编译,避免特殊字符如汉字对URL拼接造成干扰
635
- return ret + next + "=" + ((typeof params[next]) == "object" ? encodeURIComponent(JSON.stringify(params[next])) : encodeURIComponent(params[next]));
636
- }, '');
117
+ const util = require('./utils/util');
637
118
 
638
- return this.get(url);
639
- }
119
+ toolkit.assert = require('./utils/assert');
120
+ toolkit.stringify = util.stringify;
121
+ toolkit.extendObj = util.extendObj;
122
+ toolkit.clone = util.clone;
123
+ toolkit.Base64 = util.Base64;
124
+ toolkit.CommMode = util.CommMode;
125
+ toolkit.CommStatus = util.CommStatus;
126
+ toolkit.ReturnCode = util.ReturnCode;
127
+ toolkit.ReturnCodeName = util.ReturnCodeName;
128
+ toolkit.NotifyType = util.NotifyType;
129
+ toolkit.sprintf = util.sprintf;
130
+ toolkit.isHex = util.isHex;
640
131
 
641
- /**
642
- * (内部函数)发起基于Http协议的RPC请求
643
- * @param params
644
- */
645
- async postRequest(params, authControl) {
646
- this.parseParams(params);
132
+ // ==================== 全局对象挂载 ====================
647
133
 
648
- let url = null;
649
- if(!this.config.webserver.url) {
650
- let port = !!params.port ? params.port : this.config.webserver.port;
651
- url = !!authControl ? `${this.config.UrlHead}://${this.config.webserver.host}:${port}/${authControl}` : `${this.config.UrlHead}://${this.config.webserver.host}:${port}/index.html`;
652
- } else {
653
- url = !!authControl ? `${this.config.UrlHead}://${this.config.webserver.url}/${authControl}` : `${this.config.UrlHead}://${this.config.webserver.url}/index.html`;
654
- }
134
+ // V7.1.3: Node.js 环境的 global.toolkit
135
+ global.toolkit = toolkit;
655
136
 
656
- return this.post(url, params);
657
- }
137
+ // V9.0.0: 浏览器 <script> 标签引入时的 window.toolkit
138
+ if (typeof window !== 'undefined') {
139
+ window.toolkit = toolkit;
658
140
  }
659
-
660
- Remote.prototype.CommMode = CommMode;
661
- // Remote.prototype.createHmac = createHmac;
662
- // Remote.prototype.assert = assert;
663
- Remote.prototype.stringify = stringify;
664
- // Remote.prototype.encrypt = encrypt;
665
- // Remote.prototype.decrypt = decrypt;
666
- // Remote.prototype.verifyData = verifyData;
667
- // Remote.prototype.generateKey = generateKey;
668
- // Remote.prototype.signObj = signObj;
669
- // Remote.prototype.verifyObj = verifyObj;
670
- // Remote.prototype.verifyAddress = verifyAddress;
671
- Remote.prototype.CommStatus = CommStatus;
672
- Remote.prototype.ReturnCode = ReturnCode;
673
- Remote.prototype.NotifyType = NotifyType;
674
- // Remote.prototype.Secret = Secret;
675
- // Remote.prototype.hash256 = hash256;
676
- // Remote.prototype.hash160 = hash160;
677
- // Remote.prototype.sha1 = sha1;
678
-
679
- module.exports = Remote;