Commit 7663b06b6597003abac328272ac2cd7c60e5d81a
1 parent
e79945d73f
Exists in
master
ready to pretest
Showing 2 changed files with 166 additions and 1 deletions Inline Diff
package.json
1 | { | 1 | { |
2 | "name": "sate24-to-trustlink", | 2 | "name": "sate24-to-trustlink", |
3 | "version": "1.0.0", | 3 | "version": "1.0.0", |
4 | "description": "ST24 to TrustLink", | 4 | "description": "ST24 to TrustLink", |
5 | "main": "index.js", | 5 | "main": "index.js", |
6 | "scripts": { | 6 | "scripts": { |
7 | "test": "mocha" | 7 | "test": "mocha" |
8 | }, | 8 | }, |
9 | "repository": { | 9 | "repository": { |
10 | "type": "git", | 10 | "type": "git", |
11 | "url": "git@gitlab.kodesumber.com:reload97/sate24-to-trustlink.git" | 11 | "url": "git@gitlab.kodesumber.com:reload97/sate24-to-trustlink.git" |
12 | }, | 12 | }, |
13 | "keywords": [ | 13 | "keywords": [ |
14 | "st24", | 14 | "st24", |
15 | "ppob", | 15 | "ppob", |
16 | "r97", | 16 | "r97", |
17 | "trust" | 17 | "trust" |
18 | ], | 18 | ], |
19 | "author": "Adhidarma Hadiwinoto <adhisimon@host2host.id>", | 19 | "author": "Adhidarma Hadiwinoto <adhisimon@host2host.id>", |
20 | "license": "ISC", | 20 | "license": "ISC", |
21 | "dependencies": { | 21 | "dependencies": { |
22 | "ini": "^1.3.4", | 22 | "ini": "^1.3.4", |
23 | "request": "^2.72.0", | 23 | "request": "^2.72.0", |
24 | "sate24": "git+http://gitlab.kodesumber.com/reload97/node-sate24.git", | 24 | "sate24": "git+http://gitlab.kodesumber.com/reload97/node-sate24.git", |
25 | "sate24-expresso": "git+http://gitlab.kodesumber.com/reload97/sate24-expresso.git", | 25 | "sate24-expresso": "git+http://gitlab.kodesumber.com/reload97/sate24-expresso.git", |
26 | "strftime": "^0.9.2", | 26 | "strftime": "^0.9.2", |
27 | "winston": "^2.2.0" | 27 | "winston": "^2.2.0", |
28 | "xml2js": "^0.4.16" | ||
28 | } | 29 | } |
29 | } | 30 | } |
30 | 31 |
partner-trustlink.js
File was created | 1 | var winston = require('winston'); | |
2 | var request = require('request'); | ||
3 | var strftime = require('strftime'); | ||
4 | var url = require('url'); | ||
5 | var xor = require('base64-xor'); | ||
6 | var http = require('http'); | ||
7 | var xml2js = require('xml2js').parseString; | ||
8 | |||
9 | var max_retry = 3; | ||
10 | var sleep_before_retry = 2000; | ||
11 | |||
12 | var config; | ||
13 | var callbackReport; | ||
14 | var aaa; | ||
15 | var logger; | ||
16 | var options; | ||
17 | |||
18 | function start(_config, _callbackReport, options) { | ||
19 | config = _config; | ||
20 | callbackReport = _callbackReport | ||
21 | |||
22 | if (options && options.aaa) { | ||
23 | aaa = options.aaa; | ||
24 | } | ||
25 | |||
26 | if (options && options.logger) { | ||
27 | logger = options.logger; | ||
28 | } else { | ||
29 | logger = new winston.Logger({ | ||
30 | transports: [ | ||
31 | new (winston.transports.Console)() | ||
32 | ] | ||
33 | }); | ||
34 | } | ||
35 | |||
36 | createReverseReportServer(); | ||
37 | } | ||
38 | |||
39 | function createReverseReportServer() { | ||
40 | var httpServer = http.createServer(onReverseReport).listen(config.h2h_out.listen_port, function() { | ||
41 | logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port); | ||
42 | }); | ||
43 | } | ||
44 | |||
45 | function onReverseReport(req, res) { | ||
46 | res.end('OK'); | ||
47 | |||
48 | var qs = url.parse(req.url, true).query; | ||
49 | logger.info('Reverse Report', {qs: qs}); | ||
50 | } | ||
51 | |||
52 | function calculateSignature(ts, destination, password) { | ||
53 | var a = ts + destination.substr(destination.length - 4); | ||
54 | var b = destination.substr(destination.length - 4).split('').reverse().join('') + password; | ||
55 | |||
56 | return xor.encode(a,b); | ||
57 | } | ||
58 | |||
59 | function createXmlPayload(task, userid, password) { | ||
60 | var ts = strftime('%H%M%S', new Date()); | ||
61 | |||
62 | var signature = calculateSignature(ts, task.destination, password); | ||
63 | |||
64 | var payload = { | ||
65 | evoucher: [ | ||
66 | {command: 'TOPUP'}, | ||
67 | {product: task.remoteProduct}, | ||
68 | {userid: userid}, | ||
69 | {time: ts}, | ||
70 | {msisdn: task.destination}, | ||
71 | {partner_trxid: task.requestId}, | ||
72 | {signature: signature}, | ||
73 | {trxke: 1}, | ||
74 | ] | ||
75 | }; | ||
76 | |||
77 | if (logger) { | ||
78 | logger.verbose('Generate xml payload', {payload: payload}); | ||
79 | } | ||
80 | |||
81 | return "<?xml version=\"1.0\" ?>\n" + xml(payload); | ||
82 | } | ||
83 | |||
84 | function topupRequest(task, retry) { | ||
85 | if (retry === undefined) { | ||
86 | retry = max_retry; | ||
87 | } | ||
88 | |||
89 | var payload = createXmlPayload(task, config.globals.userid, config.globals.password); | ||
90 | |||
91 | var partner = url.parse(config.h2h_out.partner); | ||
92 | |||
93 | var request_options = { | ||
94 | host: partner.hostname, | ||
95 | path: partner.path, | ||
96 | port: partner.port, | ||
97 | method: "POST", | ||
98 | headers: { | ||
99 | 'Content-Type': 'text/xml', | ||
100 | 'Content-Length': Buffer.byteLength(payload) | ||
101 | } | ||
102 | }; | ||
103 | |||
104 | var buffer = ""; | ||
105 | |||
106 | logger.info('Requesting to partner', {request_options: request_options}); | ||
107 | |||
108 | var req = http.request(request_options, function( res ) { | ||
109 | |||
110 | logger.info('Status code: ' + res.statusCode ); | ||
111 | var buffer = ""; | ||
112 | res.on( "data", function( data ) { buffer = buffer + data; } ); | ||
113 | res.on( "end", function( data ) { | ||
114 | //directResponseHandler(buffer, task); | ||
115 | logger.info('Got direct response from partner', {resp: buffer}); | ||
116 | }); | ||
117 | |||
118 | }); | ||
119 | |||
120 | req.on('error', function(e) { | ||
121 | logger.warn('problem with request: ' + e.message); | ||
122 | callbackReport(task.requestId, '68', e.message); | ||
123 | return; | ||
124 | }); | ||
125 | |||
126 | logger.verbose('Sending payload to partner', {payload: payload}); | ||
127 | req.write( payload ); | ||
128 | req.end(); | ||
129 | } | ||
130 | |||
131 | function directResponseHandler(body, task) { | ||
132 | |||
133 | logger.info('Got direct response'); | ||
134 | |||
135 | xml2js(body, function (err, result) { | ||
136 | if (err) { | ||
137 | logger.warn('Error parsing xml', {body: body}); | ||
138 | callbackReport(request_id, '68', buffer); | ||
139 | return; | ||
140 | } | ||
141 | |||
142 | logger.info('Direct response parsed', {result: result}); | ||
143 | |||
144 | var response_code = '68'; | ||
145 | |||
146 | var request_id = result.evoucher.partner_trxid[0].trim(); | ||
147 | var message = result.evoucher.message[0].trim(); | ||
148 | var status = result.evoucher.result[0].trim(); | ||
149 | |||
150 | if (status === 'failed') { | ||
151 | response_code = '40'; | ||
152 | |||
153 | var new_response_code = responseCodeFromMessage(message); | ||
154 | if (new_response_code) { | ||
155 | response_code = new_response_code; | ||
156 | } | ||
157 | |||
158 | } | ||
159 | |||
160 | callbackReport(request_id, response_code, message); | ||
161 | }); | ||
162 | } | ||
163 | |||
164 | export.start = start; | ||
165 |