Commit 60fa6ddb465ae83e3d3c1895b449f0dcb392ac66
1 parent
2fbb21dc08
Exists in
master
coba ditest
Showing 5 changed files with 273 additions and 0 deletions Side-by-side Diff
.gitignore
index.js
... | ... | @@ -0,0 +1,29 @@ |
1 | +var fs = require('fs'); | |
2 | +var ini = require('ini'); | |
3 | +var expresso = require('sate24-expresso'); | |
4 | +var config = ini.parse(fs.readFileSync(__dirname + '/config.ini', 'utf-8')); | |
5 | + | |
6 | +process.chdir(__dirname); | |
7 | + | |
8 | +var logDirectory = __dirname + '/logs'; | |
9 | +fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory); | |
10 | + | |
11 | +var logger = require('sate24/logger.js').start(); | |
12 | +var HttpServer = require('sate24/httpserver.js'); | |
13 | +var aaa = require('sate24/aaa.js'); | |
14 | +var partner = require('./partner-fm.js'); | |
15 | + | |
16 | +var matrix = aaa.prepareMatrix(); | |
17 | + | |
18 | +var options = { | |
19 | + 'aaa': aaa, | |
20 | + 'logger': logger, | |
21 | + 'config': config, | |
22 | + 'matrix': matrix, | |
23 | +} | |
24 | + | |
25 | +var httpServer = HttpServer.start(config, options); | |
26 | + | |
27 | +partner.start(config, aaa.callbackReport, options); | |
28 | +aaa.start(config, partner, options); | |
29 | +expresso.start(options); |
package.json
... | ... | @@ -0,0 +1,32 @@ |
1 | +{ | |
2 | + "name": "sate24-to-fm-bp", | |
3 | + "version": "1.0.0", | |
4 | + "description": "ST24 H2H-OUT to FM based on belanjapulsa.com", | |
5 | + "main": "index.js", | |
6 | + "scripts": { | |
7 | + "test": "mocha" | |
8 | + }, | |
9 | + "repository": { | |
10 | + "type": "git", | |
11 | + "url": "git@gitlab.kodesumber.com:reload97/sate24-to-fm-bp.git" | |
12 | + }, | |
13 | + "keywords": [ | |
14 | + "st24", | |
15 | + "reload97", | |
16 | + "r97", | |
17 | + "ppob", | |
18 | + "fm", | |
19 | + "flashmachine" | |
20 | + ], | |
21 | + "author": "Adhidarma Hadiwinoto <me@adhisimon.org>", | |
22 | + "license": "ISC", | |
23 | + "dependencies": { | |
24 | + "request": "^2.74.0", | |
25 | + "sate24": "git+http://gitlab.kodesumber.com/reload97/node-sate24.git", | |
26 | + "sate24-expresso": "git+http://gitlab.kodesumber.com/reload97/sate24-expresso.git", | |
27 | + "xml2js": "^0.4.17" | |
28 | + }, | |
29 | + "devDependencies": { | |
30 | + "should": "^11.1.0" | |
31 | + } | |
32 | +} |
partner-fm.js
... | ... | @@ -0,0 +1,178 @@ |
1 | +var xml2js = require('xml2js'); | |
2 | + | |
3 | +var aaa; | |
4 | +var _callbackReport; | |
5 | +var config; | |
6 | +var logger; | |
7 | + | |
8 | +var xmlBuilder = new xml2js.Builder(); | |
9 | + | |
10 | +function start(options) { | |
11 | + if (!options) { | |
12 | + console.log('Undefined options, terminating....'); | |
13 | + process.exit(1); | |
14 | + } | |
15 | + | |
16 | + if (options.config) { | |
17 | + config = options.config; | |
18 | + } else { | |
19 | + console.log('Undefined options.config, terminating....') | |
20 | + process.exit(1); | |
21 | + } | |
22 | + | |
23 | + if (options.aaa) { | |
24 | + aaa = options.aaa; | |
25 | + _callbackReport = options.aaa.callbackReportWithPushToMongoDb; | |
26 | + } else { | |
27 | + console.log('Undefined options.aaa, terminating....') | |
28 | + process.exit(1); | |
29 | + } | |
30 | + | |
31 | + if (options && options.logger) { | |
32 | + logger = options.logger; | |
33 | + } else { | |
34 | + console.log('Undefined options.logger, terminating....') | |
35 | + process.exit(1); | |
36 | + } | |
37 | + | |
38 | + createServer(); | |
39 | + | |
40 | + /* | |
41 | + resendDelay.init({ | |
42 | + config: config, | |
43 | + topupRequest: topupRequest, | |
44 | + logger: logger | |
45 | + }); | |
46 | + */ | |
47 | +} | |
48 | + | |
49 | +function topupRequest(task) { | |
50 | + aaa.insertTaskToMongoDb(task); | |
51 | + | |
52 | + var payload = composeTopupStatusMessage( | |
53 | + config.h2h_out.pin, | |
54 | + task.remoteProduct, | |
55 | + task.destination, | |
56 | + task.requestId | |
57 | + ); | |
58 | + | |
59 | + var reqOpts = { | |
60 | + url: config.h2h_out.partner_url, | |
61 | + method: "POST", | |
62 | + headers: { | |
63 | + 'Content-Type': 'text/xml', | |
64 | + 'Content-Length': Buffer.byteLength(payload) | |
65 | + } | |
66 | + } | |
67 | + | |
68 | + logger.verbose('Requesting to partner', {reqOpts: reqOpts, payload: payload}); | |
69 | + var buffer = ""; | |
70 | + var req = http.request(reqOpts, function( res ) { | |
71 | + | |
72 | + logger.info('Status code: ' + res.statusCode ); | |
73 | + var buffer = ""; | |
74 | + res.on( "data", function( data ) { buffer = buffer + data; } ); | |
75 | + res.on( "end", function( data ) { | |
76 | + logger.verbose('Got a direct response from partner', {response: buffer, task: task}); | |
77 | + topupResponseHandler(buffer, task.requestId); | |
78 | + }); | |
79 | + }); | |
80 | +} | |
81 | + | |
82 | +function topupResponseHandler(xmlResponse, _requestId, cb) { | |
83 | + var xmlParser = xml2js.parseString; | |
84 | + xmlParser(xmlResponse, function(err, data) { | |
85 | + var msg; | |
86 | + var requestId; | |
87 | + var rc = '68'; | |
88 | + | |
89 | + if (_requestId) { | |
90 | + requestId = _requestId; | |
91 | + } | |
92 | + | |
93 | + if (err) { | |
94 | + msg = 'Error parsing xml response: ' + err; | |
95 | + | |
96 | + if (logger) { | |
97 | + logger.warn(msg, {err: err, response: xmlResponse, task: task}); | |
98 | + } else { | |
99 | + console.log(msg); | |
100 | + } | |
101 | + } else { | |
102 | + | |
103 | + try { | |
104 | + msg = data.fm.message | |
105 | + } | |
106 | + catch(e) { | |
107 | + msg = 'Unknown message' | |
108 | + } | |
109 | + | |
110 | + if (data.fm.status == '0') { | |
111 | + | |
112 | + rc = '00'; | |
113 | + msg = modifyMessageWithSn(msg); | |
114 | + | |
115 | + } else if (data.fm.status == '1') { | |
116 | + rc = '68'; | |
117 | + } else if (data.fm.status == '2') { | |
118 | + rc = '40'; | |
119 | + } else if (data.fm.status == '3') { | |
120 | + rc = '40'; | |
121 | + } else { | |
122 | + rc = '68'; | |
123 | + } | |
124 | + | |
125 | + if (data.fm.refTrxid) { | |
126 | + requestId = data.fm.refTrxid; | |
127 | + } | |
128 | + | |
129 | + } | |
130 | + | |
131 | + cb(requestId, rc, msg, xmlResponse) | |
132 | + }); | |
133 | +} | |
134 | + | |
135 | +function callbackReport(requestId, responseCode, msg, rawResponse) { | |
136 | + if (requestId) { | |
137 | + _callbackReport(requestId, responseCode, msg, null, rawResponse); | |
138 | + } else { | |
139 | + logger.warn('Undefined requestId, not sending callbackReport', {rc: responseCode, msg: msg, rawResponse: rawResponse}); | |
140 | + } | |
141 | + | |
142 | +} | |
143 | + | |
144 | +function getSnFromMessage(msg) { | |
145 | + try { | |
146 | + var matches = msg.match(/SN:(\w+)/); | |
147 | + return matches[1]; | |
148 | + } | |
149 | + catch(e) { | |
150 | + return; | |
151 | + } | |
152 | +} | |
153 | + | |
154 | +function modifyMessageWithSn(msg) { | |
155 | + var sn = getSnFromMessage(msg); | |
156 | + if (sn) { | |
157 | + msg = 'SN=' + sn + '; ' + msg; | |
158 | + } | |
159 | + return msg; | |
160 | +} | |
161 | + | |
162 | +function composeTopupStatusMessage(pin, product, destination, requestId) { | |
163 | + var data = {fm: { | |
164 | + command: 'TOPUP', | |
165 | + pin: pin, | |
166 | + product: product, | |
167 | + msisdn: destination, | |
168 | + refTrxid: requestId | |
169 | + }} | |
170 | + | |
171 | + return xmlBuilder.buildObject(data); | |
172 | +} | |
173 | + | |
174 | +exports.start = start; | |
175 | +exports.topupRequest = topupRequest; | |
176 | +exports.composeTopupStatusMessage = composeTopupStatusMessage; | |
177 | +exports.getSnFromMessage = getSnFromMessage; | |
178 | +exports.modifyMessageWithSn = modifyMessageWithSn; |
test.js
... | ... | @@ -0,0 +1,28 @@ |
1 | +var should = require('should'); | |
2 | +var crypto = require('crypto'); | |
3 | + | |
4 | +describe('#partner', function () { | |
5 | + var partner = require('./partner-fm') | |
6 | + | |
7 | + describe('#composeTopupStatusMessage', function() { | |
8 | + it('should return correct xml message', function() { | |
9 | + var msg = partner.composeTopupStatusMessage('1234', 'S10', '08120812', '2345'); | |
10 | + crypto.createHash('sha256').update(msg, 'utf8').digest().toString('hex').should.equal('1b926cb9101d9b172ae12206d0c10d4800b553f3d9f2e320fe526c7effb11985'); | |
11 | + }) | |
12 | + }); | |
13 | + | |
14 | + describe('#getSnFromMessage', function() { | |
15 | + it('should return correct sn', function() { | |
16 | + partner.getSnFromMessage('S10.081300000000 berhasil, SN:123456789').should.equal('123456789'); | |
17 | + }); | |
18 | + }) | |
19 | + | |
20 | + describe('#modifyMessageWithSn', function() { | |
21 | + it('should return correct sn', function() { | |
22 | + partner.modifyMessageWithSn('S10.081300000000 berhasil.').should.equal('S10.081300000000 berhasil.'); | |
23 | + partner.modifyMessageWithSn('S10.081300000000 berhasil, SN:').should.equal('S10.081300000000 berhasil, SN:'); | |
24 | + partner.modifyMessageWithSn('S10.081300000000 berhasil, SN:123456789').should.equal('SN=123456789; S10.081300000000 berhasil, SN:123456789'); | |
25 | + partner.modifyMessageWithSn('S10.081300000000 berhasil, SN:123456789. Berita tambahan').should.equal('SN=123456789; S10.081300000000 berhasil, SN:123456789. Berita tambahan'); | |
26 | + }); | |
27 | + }); | |
28 | +}) |