Commit 795261f4233f87d8b9310a079a2ef76255ba5d33
1 parent
8004247ae9
Exists in
master
Add requester ip on incoming callback log
Showing 1 changed file with 5 additions and 1 deletions Inline Diff
lib/partner.js
1 | const HTTP = require('http'); | 1 | const HTTP = require('http'); |
2 | const URL = require('url'); | 2 | const URL = require('url'); |
3 | const request = require('request'); | 3 | const request = require('request'); |
4 | const uuidv4 = require('uuid/v4'); | 4 | const uuidv4 = require('uuid/v4'); |
5 | const stringify = require('json-stringify-pretty-compact'); | 5 | const stringify = require('json-stringify-pretty-compact'); |
6 | 6 | ||
7 | const config = require('komodo-sdk/config'); | 7 | const config = require('komodo-sdk/config'); |
8 | const logger = require('komodo-sdk/logger'); | 8 | const logger = require('komodo-sdk/logger'); |
9 | const matrix = require('komodo-sdk/matrix'); | 9 | const matrix = require('komodo-sdk/matrix'); |
10 | const pull = require('komodo-sdk/gateway/pull'); | 10 | const pull = require('komodo-sdk/gateway/pull'); |
11 | 11 | ||
12 | const komodoClient = require('./komodo-client'); | 12 | const komodoClient = require('./komodo-client'); |
13 | const partnerRc = require('./komodo-rc'); | 13 | const partnerRc = require('./komodo-rc'); |
14 | 14 | ||
15 | if (!matrix.pending_tasks) { | 15 | if (!matrix.pending_tasks) { |
16 | matrix.pending_tasks = {}; | 16 | matrix.pending_tasks = {}; |
17 | } | 17 | } |
18 | 18 | ||
19 | function deleteFromPendingTasks(trx_id) { | 19 | function deleteFromPendingTasks(trx_id) { |
20 | if (matrix.pending_tasks && matrix.pending_tasks[trx_id]) { | 20 | if (matrix.pending_tasks && matrix.pending_tasks[trx_id]) { |
21 | delete matrix.pending_tasks[trx_id]; | 21 | delete matrix.pending_tasks[trx_id]; |
22 | } | 22 | } |
23 | } | 23 | } |
24 | 24 | ||
25 | function report(data) { | 25 | function report(data) { |
26 | pull.report(data); | 26 | pull.report(data); |
27 | 27 | ||
28 | if (data.rc !== '68' && data.rc !== '96') { | 28 | if (data.rc !== '68' && data.rc !== '96') { |
29 | deleteFromPendingTasks(data.trx_id); | 29 | deleteFromPendingTasks(data.trx_id); |
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | function _hit(task, is_advice) { | 33 | function _hit(task, is_advice) { |
34 | 34 | ||
35 | if (matrix.pending_tasks && !matrix.pending_tasks[task.trx_id]) { | 35 | if (matrix.pending_tasks && !matrix.pending_tasks[task.trx_id]) { |
36 | matrix.pending_tasks[task.trx_id] = task; | 36 | matrix.pending_tasks[task.trx_id] = task; |
37 | } | 37 | } |
38 | 38 | ||
39 | const request_options = { | 39 | const request_options = { |
40 | url: config.partner.url, | 40 | url: config.partner.url, |
41 | qs: { | 41 | qs: { |
42 | request_id: task.trx_id, | 42 | request_id: task.trx_id, |
43 | terminal_name: config.partner.terminal_name || config.partner.username, | 43 | terminal_name: config.partner.terminal_name || config.partner.username, |
44 | password: config.partner.password, | 44 | password: config.partner.password, |
45 | reverse_url: config.reverse_report_url, | 45 | reverse_url: config.reverse_report_url, |
46 | product_name: task.remote_product, | 46 | product_name: task.remote_product, |
47 | destination: task.destination | 47 | destination: task.destination |
48 | } | 48 | } |
49 | } | 49 | } |
50 | 50 | ||
51 | if (!request_options.qs.request_id || !request_options.qs.terminal_name || !request_options.qs.password || !request_options.qs.reverse_url || !request_options.qs.product_name || !request_options.qs.destination) { | 51 | if (!request_options.qs.request_id || !request_options.qs.terminal_name || !request_options.qs.password || !request_options.qs.reverse_url || !request_options.qs.product_name || !request_options.qs.destination) { |
52 | logger.verbose('Missing parameter on request', request_options.qs); | 52 | logger.verbose('Missing parameter on request', request_options.qs); |
53 | return; | 53 | return; |
54 | } | 54 | } |
55 | 55 | ||
56 | logger.info('Requesting to partner', {is_advice: is_advice, trx_id: task.trx_id, destination: task.destination, product: task.product, remote_product: task.remote_product}); | 56 | logger.info('Requesting to partner', {is_advice: is_advice, trx_id: task.trx_id, destination: task.destination, product: task.product, remote_product: task.remote_product}); |
57 | request(request_options, function(err, res, body) { | 57 | request(request_options, function(err, res, body) { |
58 | if (err) { | 58 | if (err) { |
59 | logger.warn('Error requesting to partner', {err: err, trx_id: task.trx_id, destination: task.destination, is_advice: is_advice}); | 59 | logger.warn('Error requesting to partner', {err: err, trx_id: task.trx_id, destination: task.destination, is_advice: is_advice}); |
60 | report({ | 60 | report({ |
61 | trx_id: task.trx_id, | 61 | trx_id: task.trx_id, |
62 | rc: (!is_advice && (err.syscall === 'connect')) ? '91' : '68', | 62 | rc: (!is_advice && (err.syscall === 'connect')) ? '91' : '68', |
63 | message: 'INTERNAL: REQUEST ERROR: ' + err.toString(), | 63 | message: 'INTERNAL: REQUEST ERROR: ' + err.toString(), |
64 | misc: { | 64 | misc: { |
65 | task: task | 65 | task: task |
66 | } | 66 | } |
67 | }); | 67 | }); |
68 | return; | 68 | return; |
69 | } | 69 | } |
70 | 70 | ||
71 | if (res.statusCode != 200) { | 71 | if (res.statusCode != 200) { |
72 | logger.warn('Partner returning non 200 HTTP status code', {trx_id: task.trx_id, destination: task.destination, is_advice: is_advice, http_status_code: res.statusCode, response_body: body}); | 72 | logger.warn('Partner returning non 200 HTTP status code', {trx_id: task.trx_id, destination: task.destination, is_advice: is_advice, http_status_code: res.statusCode, response_body: body}); |
73 | report({ | 73 | report({ |
74 | trx_id: task.trx_id, | 74 | trx_id: task.trx_id, |
75 | rc: '68', | 75 | rc: '68', |
76 | message: ('INTERNAL: Got non 200 HTTP status code: ' + res.statusCode + '\n\n' + body).trim(), | 76 | message: ('INTERNAL: Got non 200 HTTP status code: ' + res.statusCode + '\n\n' + body).trim(), |
77 | raw: body, | 77 | raw: body, |
78 | misc: { | 78 | misc: { |
79 | task: task | 79 | task: task |
80 | } | 80 | } |
81 | }); | 81 | }); |
82 | return; | 82 | return; |
83 | } | 83 | } |
84 | 84 | ||
85 | logger.verbose('Got response from partner', {trx_id: task.trx_id, destination: task.destination, is_advice: is_advice, response_body: body}); | 85 | logger.verbose('Got response from partner', {trx_id: task.trx_id, destination: task.destination, is_advice: is_advice, response_body: body}); |
86 | 86 | ||
87 | const result = komodoClient.parseResponse(body); | 87 | const result = komodoClient.parseResponse(body); |
88 | if (!result) { | 88 | if (!result) { |
89 | logger.warn('Partner returning invalid JSON', {trx_id: task.trx_id, destination: task.destination, is_advice: is_advice, response_body: body}); | 89 | logger.warn('Partner returning invalid JSON', {trx_id: task.trx_id, destination: task.destination, is_advice: is_advice, response_body: body}); |
90 | report({ | 90 | report({ |
91 | trx_id: task.trx_id, | 91 | trx_id: task.trx_id, |
92 | rc: is_advice ? '68' : '90', | 92 | rc: is_advice ? '68' : '90', |
93 | message: 'INTERNAL: Partner return invalid JSON:\n' + body, | 93 | message: 'INTERNAL: Partner return invalid JSON:\n' + body, |
94 | raw: body, | 94 | raw: body, |
95 | misc: { | 95 | misc: { |
96 | task: task | 96 | task: task |
97 | } | 97 | } |
98 | }); | 98 | }); |
99 | return; | 99 | return; |
100 | } | 100 | } |
101 | 101 | ||
102 | const reportMessage = config.report_as_json | 102 | const reportMessage = config.report_as_json |
103 | ? stringify({ DIRECTRESPONSE: result }) | 103 | ? stringify({ DIRECTRESPONSE: result }) |
104 | : stringify({ DIRECTRESPONSE: result.message }); | 104 | : stringify({ DIRECTRESPONSE: result.message }); |
105 | 105 | ||
106 | report({ | 106 | report({ |
107 | trx_id: task.trx_id, | 107 | trx_id: task.trx_id, |
108 | rc: result.rc ? partnerRc[result.rc] || '40' : '68', | 108 | rc: result.rc ? partnerRc[result.rc] || '40' : '68', |
109 | sn: result.sn, | 109 | sn: result.sn, |
110 | amount: Number(result.amount) || null, | 110 | amount: Number(result.amount) || null, |
111 | balance: Number(result.ending_balance) || null, | 111 | balance: Number(result.ending_balance) || null, |
112 | message: reportMessage, | 112 | message: reportMessage, |
113 | raw: body, | 113 | raw: body, |
114 | misc: { | 114 | misc: { |
115 | task: task | 115 | task: task |
116 | } | 116 | } |
117 | }); | 117 | }); |
118 | }) | 118 | }) |
119 | } | 119 | } |
120 | 120 | ||
121 | function buy(task) { | 121 | function buy(task) { |
122 | _hit(task, false); | 122 | _hit(task, false); |
123 | } | 123 | } |
124 | 124 | ||
125 | function advice(task) { | 125 | function advice(task) { |
126 | _hit(task, true); | 126 | _hit(task, true); |
127 | } | 127 | } |
128 | 128 | ||
129 | function reverseReportHandler(req, res) { | 129 | function reverseReportHandler(req, res) { |
130 | const report_id = uuidv4(); | 130 | const report_id = uuidv4(); |
131 | 131 | ||
132 | logger.verbose('Incoming reverse report', {report_id: report_id, url: req.url}); | 132 | logger.verbose('Incoming reverse report', { |
133 | report_id: report_id, | ||
134 | requester_ip: req.socket && req.socket.localAddress, | ||
135 | url: req.url | ||
136 | }); | ||
133 | res.end('OK'); | 137 | res.end('OK'); |
134 | 138 | ||
135 | const qs = URL.parse(req.url, true).query; | 139 | const qs = URL.parse(req.url, true).query; |
136 | 140 | ||
137 | if (!qs.request_id || !qs.rc) { | 141 | if (!qs.request_id || !qs.rc) { |
138 | logger.verbose('No request_id and rc on reverse report message', {report_id: report_id, url: req.url, qs: qs}); | 142 | logger.verbose('No request_id and rc on reverse report message', {report_id: report_id, url: req.url, qs: qs}); |
139 | return; | 143 | return; |
140 | } | 144 | } |
141 | 145 | ||
142 | const task = { | 146 | const task = { |
143 | trx_id: qs.request_id, | 147 | trx_id: qs.request_id, |
144 | destination: qs.destination, | 148 | destination: qs.destination, |
145 | remote_product: qs.product_name | 149 | remote_product: qs.product_name |
146 | } | 150 | } |
147 | 151 | ||
148 | const reportMessage = config.report_as_json | 152 | const reportMessage = config.report_as_json |
149 | ? stringify({ CALLBACK: qs }) | 153 | ? stringify({ CALLBACK: qs }) |
150 | : stringify({ CALLBACK: qs.message }); | 154 | : stringify({ CALLBACK: qs.message }); |
151 | 155 | ||
152 | report({ | 156 | report({ |
153 | trx_id: qs.request_id, | 157 | trx_id: qs.request_id, |
154 | rc: partnerRc[qs.rc] || '40', | 158 | rc: partnerRc[qs.rc] || '40', |
155 | sn: qs.sn, | 159 | sn: qs.sn, |
156 | amount: qs.amount || null, | 160 | amount: qs.amount || null, |
157 | balance: Number(qs.ending_balance) || null, | 161 | balance: Number(qs.ending_balance) || null, |
158 | message: reportMessage, | 162 | message: reportMessage, |
159 | raw: req.url, | 163 | raw: req.url, |
160 | misc: { | 164 | misc: { |
161 | task: task | 165 | task: task |
162 | } | 166 | } |
163 | }); | 167 | }); |
164 | } | 168 | } |
165 | 169 | ||
166 | function createReverseReportHttpServer() { | 170 | function createReverseReportHttpServer() { |
167 | const http_server = HTTP.createServer(reverseReportHandler); | 171 | const http_server = HTTP.createServer(reverseReportHandler); |
168 | http_server.listen(config.reverse_report_port, function(err) { | 172 | http_server.listen(config.reverse_report_port, function(err) { |
169 | if (err) { | 173 | if (err) { |
170 | logger.warn('Error creating reverse report HTTP server: ' + err.toString()); | 174 | logger.warn('Error creating reverse report HTTP server: ' + err.toString()); |
171 | process.exit(1); | 175 | process.exit(1); |
172 | return; | 176 | return; |
173 | } | 177 | } |
174 | 178 | ||
175 | logger.info('Reverse report HTTP server listening on port ' + config.reverse_report_port); | 179 | logger.info('Reverse report HTTP server listening on port ' + config.reverse_report_port); |
176 | }) | 180 | }) |
177 | } | 181 | } |
178 | 182 | ||
179 | createReverseReportHttpServer(); | 183 | createReverseReportHttpServer(); |
180 | 184 | ||
181 | exports.buy = buy; | 185 | exports.buy = buy; |
182 | exports.advice = advice; | 186 | exports.advice = advice; |
183 | 187 |