Commit 3080232bfb492d79a9c1ccce315d014681b35c20
0 parents
Exists in
master
initial comit
Showing 9 changed files with 472 additions and 0 deletions Side-by-side Diff
.gitignore
aaa.js
... | ... | @@ -0,0 +1,159 @@ |
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; |
config.sample.ini
... | ... | @@ -0,0 +1,18 @@ |
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 | + |
httpserver.js
... | ... | @@ -0,0 +1,90 @@ |
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; |
index.js
... | ... | @@ -0,0 +1,13 @@ |
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 partner = require('./partner-scrappingkisel.js'); | |
11 | + | |
12 | +partner.start(config, aaa.callbackReport); | |
13 | +aaa.start(config, partner); |
logs/empty
package.json
... | ... | @@ -0,0 +1,35 @@ |
1 | +{ | |
2 | + "name": "sate24-to-sc", | |
3 | + "version": "0.0.1", | |
4 | + "description": "ST24 to SimpleConnect 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-sc.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 | + "xml2js": "~0.4.9", | |
31 | + "redis": "~0.12.1", | |
32 | + "hiredis": "~0.4.0", | |
33 | + "node-simple-router": "~0.9.4-2" | |
34 | + } | |
35 | +} |
partner-scrappingkisel.js
... | ... | @@ -0,0 +1,104 @@ |
1 | +var fs = require('fs'); | |
2 | +var https = require('https'); | |
3 | +var http = require('http'); | |
4 | +var url = require('url'); | |
5 | +var request = require('request'); | |
6 | +var xml2js = require('xml2js').parseString; | |
7 | +var strftime = require('strftime'); | |
8 | +var math = require('mathjs'); | |
9 | + | |
10 | +var config; | |
11 | +var httpServer; | |
12 | + | |
13 | +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; | |
14 | + | |
15 | +var logTag = __filename.split('/').reverse()[0]; | |
16 | + | |
17 | +function topupRequest(task) { | |
18 | + if (config.globals.requests_count == undefined) { | |
19 | + config.globals.requests_count = 1; | |
20 | + } else { | |
21 | + config.globals.requests_count++; | |
22 | + } | |
23 | + | |
24 | + if (config.globals.active_requests_count == undefined) { | |
25 | + config.globals.active_requests_count = 1; | |
26 | + } else { | |
27 | + config.globals.active_requests_count++; | |
28 | + } | |
29 | + | |
30 | + if (config.globals.max_active_requests_count == undefined) { | |
31 | + config.globals.max_active_requests_count = config.globals.active_requests_count; | |
32 | + } else { | |
33 | + config.globals.max_active_requests_count = math.max(config.globals.max_active_requests_count, config.globals.active_requests_count); | |
34 | + } | |
35 | + | |
36 | + var options = { | |
37 | + url: config.h2h_out.partner, | |
38 | + qs: { | |
39 | + reqid: task['requestId'], | |
40 | + msisdn: task['destination'], | |
41 | + product: task['product'] | |
42 | + } | |
43 | + }; | |
44 | + console.log(options); | |
45 | + | |
46 | + request(options, function (error, response, body) { | |
47 | + if (config.globals.active_requests_count == undefined) { | |
48 | + config.globals.active_requests_count = 0; | |
49 | + } else { | |
50 | + config.globals.active_requests_count--; | |
51 | + } | |
52 | + | |
53 | + if (error || response.statusCode != 200) { | |
54 | + console.log(logTag + ': Gateway Error'); | |
55 | + callbackReport(task['requestId'], '40', 'Gateway Error'); | |
56 | + return; | |
57 | + } | |
58 | + | |
59 | + console.log(logTag + ': Supplier response:'); | |
60 | + console.log(body); | |
61 | + | |
62 | + xml2js(body, function (err, result) { | |
63 | + if (err) { | |
64 | + callbackReport(task['requestId'], '40', body); | |
65 | + return; | |
66 | + } | |
67 | + | |
68 | + console.log(result); | |
69 | + | |
70 | + var response_code = '68'; | |
71 | + var message = result.trx_response.info[0].trim(); | |
72 | + | |
73 | + if (message == 'Error Parsing') { | |
74 | + | |
75 | + response_code = '40'; | |
76 | + | |
77 | + } else if (message == "Phone number's not found") { | |
78 | + | |
79 | + response_code = '14'; | |
80 | + | |
81 | + } else if (message == "TRANSAKSI SUKSES !!!") { | |
82 | + var destination = result.trx_response.msisdn.join(' ').trim(); | |
83 | + var product = result.trx_response.product.join(' ').trim(); | |
84 | + var ref_num = result.trx_response.ref_num.join(' ').trim(); | |
85 | + var harga = result.trx_response.harga.join(' ').trim(); | |
86 | + var kode_voucher = result.trx_response.kode_voucher.join(' ').trim(); | |
87 | + | |
88 | + response_code = '00'; | |
89 | + | |
90 | + message = 'SN=' + ref_num + '; ' + product + ' ' + msisdn + ' ' + harga + ' ref_num: ' + ref_num + ' kode_voucher: ' + kode_voucher; | |
91 | + } | |
92 | + | |
93 | + callbackReport(task['requestId'], response_code, message); | |
94 | + }); | |
95 | + }); | |
96 | +} | |
97 | + | |
98 | +function start(_config, _callbackReport) { | |
99 | + config = _config; | |
100 | + callbackReport = _callbackReport | |
101 | +} | |
102 | + | |
103 | +exports.start = start; | |
104 | +exports.topupRequest = topupRequest; |
test.js
... | ... | @@ -0,0 +1,49 @@ |
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 | + | |
35 | +describe('aaa', function() { | |
36 | + var partner = require('./httppulsakita'); | |
37 | + | |
38 | + describe("#parseResult()", function() { | |
39 | + message = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><respon><tanggal>2015/6/16 15:43:35</tanggal><idagen>P0039</idagen><refid>AEE15B32987941D89FFF4BC7EF676C13</refid><produk>PLN20</produk><tujuan>14204279369</tujuan><rc>0000</rc><data> </data><token> </token><pesan>#14836 PLN20 ke:14204279369 SUKSES. SN:3520-2887-6627-6699-4826/TestDummyPanjang6955555/P1/7000VA/32,4. \ | |
40 | +Sisa saldo Rp. 5,000,000 - Rp. 18,700 = Rp. 4,981,300</pesan></respon>'; | |
41 | + | |
42 | + data = partner.parseResult(message); | |
43 | + console.log(data); | |
44 | + | |
45 | + it('should return 2015/6/16 15:43:35', function() { | |
46 | + assert.equal('2015/6/16 15:43:35', data.respon.tanggal); | |
47 | + }); | |
48 | + }); | |
49 | +}); |