Commit 05158bd37278cc8f8405d3f03158f091ce635e1d

Authored by Adhidarma Hadiwinoto
0 parents
Exists in master

initial commit

Showing 9 changed files with 570 additions and 0 deletions Inline Diff

File was created 1 node_modules/
2 config.ini
3 log.txt
4 logs/log*
5
File was created 1 var request = require('request');
2 var strftime = require('strftime');
3
4 var max_retry = 10;
5 var sleep_before_retry = 3000;
6
7 var config;
8 var partner;
9
10 var available_products = [];
11
12 function unaliasResponseCode(response_code, config_responsecode_alias) {
13 if (config_responsecode_alias == undefined && config && config.h2h_out && config.h2h_out.responsecode_alias) {
14 config_responsecode_alias = config.h2h_out.responsecode_alias;
15 }
16
17 if (!config_responsecode_alias) {
18 return response_code;
19 }
20
21 items = config_responsecode_alias.split(',');
22 items_count = items.length;
23
24 for (var i=0; i < items_count; i++) {
25 codes = items[i].split(':');
26
27 if (codes.length <= 0) { continue; }
28
29 if (response_code == codes[0]) {
30 console.log('Change response code from ' + codes[0] + ' to ' + codes[1]);
31 return codes[1];
32 }
33 }
34
35 return response_code;
36 }
37
38 function pullCity() {
39 var url = config.globals.aaa_host + '/pull_city';
40 console.log('Pull cities from AAA - ' + url);
41 request(url, function (error, response, body) {
42 if (!error && response.statusCode == 200) {
43 //console.log('city=' + body);
44 } else {
45 console.log('Error in pull city');
46 }
47 });
48 }
49
50 function pullProduct() {
51 var url = config.globals.aaa_host + '/pull_product?opr_name=' + config.globals.operators;
52 console.log('Pull products from AAA - ' + url);
53
54 request(url, function (error, response, body) {
55 if (error || response.statusCode != 200) {
56 console.log('Error in pull products');
57 return;
58 }
59
60 var productsAndOperators = body.split(';');
61 var productsCount = productsAndOperators.length;
62
63 for (var i=0; i < productsCount; i++) {
64 var product = productsAndOperators[i].split(',', 1)[0];
65 available_products.push(product);
66 }
67 //console.log(available_products);
68 });
69 }
70
71 function pull() {
72 var url = config.globals.aaa_host
73 + '/pull?city=ALL&nom=' + config.globals.products
74 + '&chip_info=' + config.globals.gateway_name;
75
76 //console.log('AAA PULL - ' + url);
77 request(url, function (error, response, body) {
78 if (!error && response.statusCode == 200) {
79 if (body == 'NONE') {
80 return;
81 }
82 console.log(body);
83
84 var result = body.split(';');
85 if (result[0] != 'OK') {
86 return;
87 }
88
89 var task = [];
90 task['requestId'] = result[1];
91 task['timestamp'] = result[3];
92 task['destination'] = result[4];
93 task['product'] = result[7];
94
95 if (config.products[task['product']] !== undefined) {
96 task['remoteProduct'] = config.products[task['product']];
97 } else {
98 task['remoteProduct'] = task['product'];
99 }
100
101 partner.topupRequest(task);
102
103 } else {
104 console.log('Error in pull task');
105 return;
106 }
107 });
108 }
109
110 function pullLoop() {
111 if (!config.globals.pause) {
112 pull();
113 }
114
115 setTimeout(pullLoop, config.globals.interval);
116 }
117
118 function callbackReport(requestId, responseCode, message, retry) {
119 if (retry === undefined) {
120 retry = max_retry;
121 }
122
123 responseCode = unaliasResponseCode(responseCode);
124
125 timestamp = strftime('%Y%m%d%H%M%S');
126 var url = config.globals.aaa_host
127 + '/topup?trans_id=' + requestId
128 + '&trans_date' + timestamp
129 + '&trans_date=' + timestamp
130 + '&resp_code=' + responseCode
131 + '&ussd_msg=' + config.globals.gateway_name
132 + '$' + encodeURIComponent(message);
133
134 console.log('Report to AAA - ' + url);
135 request(url, function (error, response, body) {
136 if (error || response.statusCode != 200) {
137 console.log('Error report to AAA');
138
139 if (retry) {
140 console.log('Retrying to report to AAA (' + retry + ')');
141 callbackReport(requestId, responseCode, message, retry - 1);
142 }
143 }
144 });
145 }
146
147 function start(_config, _partner) {
148 config = _config;
149 partner = _partner;
150
151 pullCity();
152 pullProduct();
153
154 setTimeout(pullLoop, 10 * 1000);
155 }
156
157 exports.start = start;
158 exports.callbackReport = callbackReport;
159 exports.unaliasResponseCode = unaliasResponseCode;
160
File was created 1 [globals]
2 operators=TEST,XL_ALTERNATIF
3 products=TST1
4 gateway_name=NODEJS-DEV
5 aaa_host=http://172.23.0.12:4250
6 interval=1000
7 admin_port=17456
8
9 [h2h_out]
10 partner=https://172.23.0.12:6789
11 userid=R97DEV
12 password=czcb
13 listen_port=13522
14 check_interval=2000
15
16 [products]
17 TST1=TR1
18
19
File was created 1 var http = require('http');
2 var nsr = require('node-simple-router');
3 var router = nsr();
4
5 var config;
6 var httpServer;
7
8 function start(_config) {
9 if (_config != undefined) {
10 config = _config;
11 }
12 listenPort = config.globals.admin_port;
13
14 router.get("/info", function(request, response) {
15 response.setHeader("Content-Type", "text/plain");
16 response.write('CHIPINFO / GATEWAY NAME: ' + config.globals.gateway_name + "\n");
17 response.write('PRODUCTS: ' + config.globals.products + "\n");
18 response.write('AAA HOST: ' + config.globals.aaa_host + "\n");
19 response.write('PARTNER: ' + config.h2h_out.partner + "\n");
20 response.write('PAUSED: ' + config.globals.pause + "\n");
21 response.write('UPTIME: ' + process.uptime() + "\n");
22 response.write('REQUESTS COUNT: ' + config.globals.requests_count + "\n");
23 response.write('ACTIVE REQUESTS COUNT: ' + config.globals.active_requests_count + "\n");
24 response.write('MAX ACTIVE REQUESTS COUNT: ' + config.globals.max_active_requests_count + "\n");
25
26 response.end();
27 });
28
29 router.get("/pause/:apikey", function(request, response) {
30 if (!config.globals.apikey) {
31 response.end('Undefined APIKEY on config');
32 return;
33 }
34
35 if (request.params.apikey != config.globals.apikey) {
36 response.end('Invalid APIKEY');
37 return;
38 }
39
40 config.globals.pause = 1;
41 response.end('Paused');
42 });
43
44 router.get("/resume/:apikey", function(request, response) {
45 if (!config.globals.apikey) {
46 response.end('Undefined APIKEY on config');
47 return;
48 }
49
50 if (request.params.apikey != config.globals.apikey) {
51 response.end('Invalid APIKEY');
52 return;
53 }
54
55 delete config.globals.pause;
56 response.end('Resume');
57 });
58
59 router.get("/reset-stats/:apikey", function(request, response) {
60 if (!config.globals.apikey) {
61 response.end('Undefined APIKEY on config');
62 return;
63 }
64
65 if (request.params.apikey != config.globals.apikey) {
66 response.end('Invalid APIKEY');
67 return;
68 }
69
70 config.globals.max_active_requests_count = 0;
71
72 response.writeHead(307, {
73 'Location': '/info'
74 });
75
76 response.end();
77 });
78
79 httpServer = http.createServer(router).listen(listenPort);
80 console.log('HTTP server listens on port ' + listenPort);
81
82 return httpServer;
83 }
84
85 function setConfig(_config) {
86 config = _config;
87 }
88
89 exports.start = start;
90 exports.setConfig = setConfig;
91
File was created 1 var iniparser = require('iniparser');
2 var config = iniparser.parseSync('./config.ini');
3
4 var aaaHost = config.globals.aaa_host;
5
6 HttpServer = require('./httpserver.js');
7 var httpServer = HttpServer.start(config);
8
9 var aaa = require('./aaa.js');
10 var xmlout = require('./xmlout.js');
11
12 xmlout.start(config, aaa.callbackReport);
13 aaa.start(config, xmlout);
14
File was created 1 {
2 "name": "sate24-to-sate24",
3 "version": "0.0.1",
4 "description": "ST24 to ST24 H2H OUT",
5 "main": "index.js",
6 "scripts": {
7 "test": "mocha"
8 },
9 "repository": {
10 "type": "git",
11 "url": "git@gitlab.kodesumber.com:reload97/sate24-to-sate24.git"
12 },
13 "keywords": [
14 "st24",
15 "reload97",
16 "ppob",
17 "h2h",
18 "m2m",
19 "xmlrpc"
20 ],
21 "author": "Adhidarma Hadiwinoto <gua@adhisimon.org>",
22 "license": "BSD",
23 "dependencies": {
24 "mocha": "~2.2.5",
25 "request": "~2.57.0",
26 "strftime": "~0.9.2",
27 "iniparser": "~1.0.5",
28 "mathjs": "~1.7.0",
29 "xmlrpc": "~1.3.1"
30 }
31 }
32
File was created 1 var assert = require("assert");
2
3
4 describe('aaa', function() {
5 var aaa = require('./aaa');
6
7 describe("#unaliasResponseCode()", function() {
8 it('should return 68', function() {
9 assert.equal('68', aaa.unaliasResponseCode('01', '01:68'));
10 });
11
12 it('should return 68', function() {
13 assert.equal('68', aaa.unaliasResponseCode('68', '01:68'));
14 });
15
16 it('should return 00', function() {
17 assert.equal('00', aaa.unaliasResponseCode('00', '01:68'));
18 });
19
20 it('should return 40', function() {
21 assert.equal('40', aaa.unaliasResponseCode('40', ''));
22 });
23
24 it('should return 40', function() {
25 assert.equal('40', aaa.unaliasResponseCode('40', ''));
26 });
27
28 it('should return 40', function() {
29 assert.equal('40', aaa.unaliasResponseCode('40'));
30 });
31
32 });
33 });
34
File was created 1 var xmlrpc = require('xmlrpc');
2 var url = require('url');
3 var math = require('mathjs');
4
5 var config;
6 var callbackReport;
7
8 var max_retry = 2;
9 var sleep_before_retry = 2000;
10
11 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
12
13 function topupRequest(task, retry) {
14 if (config.globals.requests_count == undefined) {
15 config.globals.requests_count = 1;
16 } else {
17 config.globals.requests_count++;
18 }
19
20 if (config.globals.active_requests_count == undefined) {
21 config.globals.active_requests_count = 1;
22 } else {
23 config.globals.active_requests_count++;
24 }
25
26 if (config.globals.max_active_requests_count == undefined) {
27 config.globals.max_active_requests_count = config.globals.active_requests_count;
28 } else {
29 config.globals.max_active_requests_count = math.max(config.globals.max_active_requests_count, config.globals.active_requests_count);
30 }
31
32
33 if (retry === undefined) {
34 retry = max_retry;
35 }
36
37 var partnerUrl = url.parse(config.h2h_out.partner);
38 var clientOptions = {
39 host: partnerUrl.hostname
40 , port: partnerUrl.port
41 , path: partnerUrl.pathname
42 };
43 console.log('XMLRPC client options:');
44 console.log(clientOptions);
45
46 var client;
47 if (partnerUrl.protocol == 'https:') {
48 console.log('Use SSL');
49 client = xmlrpc.createSecureClient(clientOptions);
50 } else {
51 console.log('Not using SSL');
52 client = xmlrpc.createClient(clientOptions);
53 }
54
55 var methodName = 'topUpRequest';
56 console.log('methodName: ' + methodName);
57
58 var params = {
59 MSISDN: config.h2h_out.userid,
60 REQUESTID: task['requestId'],
61 PIN: config.h2h_out.password,
62 NOHP: task['destination'],
63 NOM: task['remoteProduct']
64 };
65 console.log('PARAMS:');
66 console.log(params);
67
68
69 client.methodCall(methodName, [ params ], function (error, value) {
70
71 if (config.globals.active_requests_count == undefined) {
72 config.globals.active_requests_count = 0;
73 } else {
74 config.globals.active_requests_count--;
75 }
76
77 // Results of the method response
78 if (error) {
79 console.log('XMLRPC Client Error (' + task['requestId'] + '): ');
80 console.log(error);
81
82 if (retry) {
83
84 console.log('Retrying topUpRequest (' + retry + ')');
85 setTimeout(function() {
86 topupRequest(task, retry - 1);
87 }, sleep_before_retry);
88
89 } else {
90 callbackReport(task['requestId'], '40', 'Gangguan koneksi ke suplier');
91 }
92 return;
93 }
94
95 console.log('Method response for \'' + methodName + '\': ')
96 console.log(value);
97
98 if (value['RESPONSECODE'] == '00' && config.h2h_out.parse_sn == 'YES') {
99 value['MESSAGE'] = 'SN=' + parseSN(value['MESSAGE']) + '; ' + value['MESSAGE'];
100 //console.log('Message with SN: ' + value['MESSAGE']);
101 }
102
103 callbackReport(value['REQUESTID'], value['RESPONSECODE'], value['MESSAGE']);
104 });
105 }
106
107 function createServer() {
108
109 console.log('Creating XML-RPC server on port ' + config.h2h_out.listen_port);
110 var serverOptions = {
111 port: config.h2h_out.listen_port
112 };
113
114 var server = xmlrpc.createServer(serverOptions);
115
116 server.on('NotFound', function (method, params) {
117 console.log(method + ' is not found on our XML-RPC server');
118 console.log('params:');
119 console.log(params);
120 });
121
122 server.on('topUpReport', function (err, params, callback) {
123 console.log('RECEIVE topUpReport, params:');
124 console.log(params);
125
126 var paramscount = params.length;
127 for (var i = 0; i < paramscount; i++) {
128 var value = params[i];
129
130 if (value['RESPONSECODE'] == '00' && config.h2h_out.parse_sn == 'YES') {
131 value['MESSAGE'] = 'SN=' + parseSN(value['MESSAGE']) + '; ' + value['MESSAGE'];
132 //console.log('Message with SN: ' + value['MESSAGE']);
133 }
134
135 callbackReport(value['REQUESTID'], value['RESPONSECODE'], value['MESSAGE']);
136 }
137
138 callback(null, 'ACK REPORT OK');
139 })
140
141 }
142
143 function checkStatus(task) {
144 var partnerUrl = url.parse(config.h2h_out.partner);
145 var clientOptions = {
146 host: partnerUrl.hostname
147 , port: partnerUrl.port
148 , path: partnerUrl.pathname
149 };
150 console.log('XMLRPC client options:');
151 console.log(clientOptions);
152
153 var client;
154 if (partnerUrl.protocol == 'https:') {
155 console.log('Use SSL');
156 client = xmlrpc.createSecureClient(clientOptions);
157 } else {
158 console.log('Not using SSL');
159 client = xmlrpc.createClient(clientOptions);
160 }
161
162 var methodName = 'topUpInquiry';
163 console.log('methodName: ' + methodName);
164
165 var params = {
166 MSISDN: config.h2h_out.userid,
167 REQUESTID: task['requestId'],
168 PIN: config.h2h_out.password,
169 NOHP: task['destination']
170 };
171 console.log('PARAMS:');
172 console.log(params);
173
174 client.methodCall(methodName, [ params ], function (error, value) {
175 // Results of the method response
176 if (error) {
177 console.log('Error: ');
178 console.log(error);
179 return;
180 }
181 console.log('Method response for \'' + methodName + '\': ')
182 console.log(value);
183
184 callbackReport(value['REQUESTID'], value['RESPONSECODE'], value['MESSAGE']);
185 });
186 }
187
188 function start(_config, _callbackReport) {
189 config = _config;
190 callbackReport = _callbackReport
191
192 createServer();
193 }
194
195 function parseSN(message) {
196 var sn_regex = new RegExp(config.h2h_out.sn_pattern);
197 var sn_match = message.match(sn_regex);
198
199 //console.log('SN MATCH:');
200 //console.log(sn_match);
201
202 if (sn_match <= 0) {
203 console.log('SN Not found: ' + message);
204 return '';
205 }
206
207 var sn = sn_match[0];
208 var sn_remove_patterns = config.h2h_out.sn_remove_patterns.split(config.h2h_out.sn_remove_patterns_separator);
209 //console.log('SN REMOVE PATTERNS:');
210 //console.log (sn_remove_patterns);
211
212 var count = sn_remove_patterns.length;
213
214 for(var i = 0; i < count; i++) {
215 sn = sn.replace(sn_remove_patterns[i], '');
216 }
217
218 return sn.trim();
219 }
220
221 exports.start = start;
222 exports.topupRequest = topupRequest;
223