Compare View

switch
from
...
to
 
Commits (8)

Changes

Showing 3 changed files Inline Diff

gateway/advice-push-server.js
1 "use strict"; 1 "use strict";
2 2
3 const express = require('express'); 3 const express = require('express');
4 const bodyParser = require('body-parser'); 4 const bodyParser = require('body-parser');
5 5
6 const pull = require('./pull'); 6 const pull = require('./pull');
7 const config = require('../config'); 7 const config = require('../config');
8 const logger = require('../logger'); 8 const logger = require('../logger');
9 const matrix = require('../matrix'); 9 const matrix = require('../matrix');
10 10
11 const app = express();
12
13 let partner = null; 11 const app = express();
14 12
15 function setPartner(_partner) { 13 let partner = null;
16 partner = _partner; 14
17 15 function setPartner(_partner) {
18 if (!config || !config.push_server || !config.push_server.apikey || !config.push_server.advice || !config.push_server.advice.url || !config.push_server.advice.port) { 16 partner = _partner;
19 return; 17
18 if (!config || !config.push_server || !config.push_server.apikey || !config.push_server.advice || !config.push_server.advice.url || !config.push_server.advice.port) {
19 return;
20 }
21
20 } 22 app.listen(config.push_server.advice.port, function () {
21 23 logger.info('Advice server listening', {port: config.push_server.advice.port});
22 app.listen(config.push_server.advice.port, function () { 24 });
23 logger.info('Advice server listening', {port: config.push_server.advice.port}); 25 }
24 }); 26
25 } 27 function isValidApikey(req, res, next) {
26 28 if (config.push_server && config.push_server.apikey && (req.params.apikey === config.push_server.apikey)) {
27 function isValidApikey(req, res, next) { 29 next();
28 if (config.push_server && config.push_server.apikey && (req.params.apikey === config.push_server.apikey)) { 30 }
29 next(); 31 else {
30 } 32 res.end('INVALID_APIKEY');
31 else { 33 }
32 res.end('INVALID_APIKEY'); 34 }
33 } 35
34 } 36 function adviceHandler(req, res, next) {
35 37
36 function adviceHandler(req, res, next) { 38 if (!partner) {
37 39 logger.warn('PUSH-ADVICE: Undefined partner, skipped');
38 if (!partner) { 40 res.end('UNDEFINED_PARTNER');
39 logger.warn('PUSH-ADVICE: Undefined partner, skipped'); 41 return;
40 res.end('UNDEFINED_PARTNER'); 42 }
41 return; 43
42 } 44 if (!partner.advice) {
43 45 logger.warn('PUSH-ADVICE: Partner does not have ADVICE capabilities');
44 if (!partner.advice) { 46 res.end('UNSUPPORTED');
45 logger.warn('PUSH-ADVICE: Partner does not have ADVICE capabilities'); 47 return;
46 res.end('UNSUPPORTED'); 48 }
47 return; 49
48 } 50 let task = req.body;
49
50 let task = req.body;
51
52 if (!task || !task.trx_id || !task.destination || !task.product) {
53 logger.warn('PUSH-ADVICE: Invalid task');
54 res.end('INVALID_TASK');
55 return;
56 } 51
57 52 if (!task || !task.trx_id || !task.destination || !task.product) {
58 logger.verbose('PUSH-ADVICE: Got advice push', {task: task}); 53 logger.warn('PUSH-ADVICE: Invalid task');
59 54 res.end('INVALID_TASK');
60 task.remote_product = pull.getRemoteProduct(task.product); 55 return;
61 partner.advice(task); 56 }
62 } 57
63 58 logger.verbose('PUSH-ADVICE: Got advice push', {task: task});
64 app.use(bodyParser.json()); 59
65 app.use('/apikey/:apikey', isValidApikey); 60 task.remote_product = pull.getRemoteProduct(task.product);
1 "use strict"; 1 "use strict";
2 2
3 const request = require('request'); 3 const request = require('request');
4 4
5 const config = require('../config'); 5 const config = require('../config');
6 const logger = require('../logger'); 6 const logger = require('../logger');
7 const matrix = require('../matrix'); 7 const matrix = require('../matrix');
8 const controlPanel = require('../control-panel'); 8 const controlPanel = require('../control-panel');
9 const heartbeat = require('../heartbeat'); 9 const heartbeat = require('../heartbeat');
10 10
11 const taskArchive = require('./task-archive'); 11 const taskArchive = require('./task-archive');
12 12
13 const MAX_SLEEP_BEFORE_RESEND_MS = 500; 13 const MAX_SLEEP_BEFORE_RESEND_MS = 500;
14 14
15 if (config.handler_name) { 15 if (config.handler_name) {
16 process.title = "KOMODO-GW@" + config.handler_name; 16 process.title = "KOMODO-GW@" + config.handler_name;
17 } 17 }
18 18
19 heartbeat.setModuleType('gateway'); 19 heartbeat.setModuleType('gateway');
20 20
21 var partner; 21 var partner;
22 22
23 function setPartner(_partner) { 23 function setPartner(_partner) {
24 partner = _partner; 24 partner = _partner;
25 } 25 }
26 26
27 function pullTask() { 27 function pullTask() {
28 if (!partner) { 28 if (!partner) {
29 return; 29 return;
30 } 30 }
31 31
32 let core_pull_task_url; 32 let core_pull_task_url;
33 33
34 if (config.core_url) { 34 if (config.core_url) {
35 core_pull_task_url = config.core_url + '/pull/task'; 35 core_pull_task_url = config.core_url + '/pull/task';
36 } else if (config.pull_url.task) { 36 } else if (config.pull_url.task) {
37 core_pull_task_url = config.pull_url.task.replace('<CORE_APIKEY>', config.core_apikey); 37 core_pull_task_url = config.pull_url.task.replace('<CORE_APIKEY>', config.core_apikey);
38 } 38 }
39 39
40 if (!core_pull_task_url) { 40 if (!core_pull_task_url) {
41 logger.warn('Unknown CORE task url'); 41 logger.warn('Unknown CORE task url');
42 return; 42 return;
43 } 43 }
44 44
45 let options = { 45 let options = {
46 url: core_pull_task_url, 46 url: core_pull_task_url,
47 qs: { 47 qs: {
48 handler: config.handler_name, 48 handler: config.handler_name,
49 products: config.products.join(',') 49 products: config.products.join(',')
50 } 50 }
51 } 51 }
52 52
53 request(options, function(error, response, body) { 53 request(options, function(error, response, body) {
54 if (error) { 54 if (error) {
55 if (matrix.core_is_healthy) { 55 if (matrix.core_is_healthy) {
56 logger.warn('Error pulling task from CORE', {error: error}); 56 logger.warn('Error pulling task from CORE', {error: error});
57 } 57 }
58 matrix.core_is_healthy = false; 58 matrix.core_is_healthy = false;
59 return; 59 return;
60 } 60 }
61 61
62 if (response.statusCode != 200) { 62 if (response.statusCode != 200) {
63 if (matrix.core_is_healthy) { 63 if (matrix.core_is_healthy) {
64 logger.warn('CORE http response status code for pull task is not 200', {http_response_status: response.statusCode}); 64 logger.warn('CORE http response status code for pull task is not 200', {http_response_status: response.statusCode});
65 } 65 }
66 matrix.core_is_healthy = false; 66 matrix.core_is_healthy = false;
67 return; 67 return;
68 } 68 }
69 69
70 if (!matrix.core_is_healthy) { 70 if (!matrix.core_is_healthy) {
71 logger.verbose('CORE is healthy'); 71 logger.verbose('CORE is healthy');
72 } 72 }
73 matrix.core_is_healthy = true; 73 matrix.core_is_healthy = true;
74 74
75 if (body == 'NONE') { 75 if (body == 'NONE') {
76 return; 76 return;
77 } 77 }
78 78
79 forwardCoreTaskToPartner(body); 79 forwardCoreTaskToPartner(body);
80 }); 80 });
81 } 81 }
82 82
83 function forwardCoreTaskToPartner(coreMessage) { 83 function forwardCoreTaskToPartner(coreMessage) {
84 let task; 84 let task;
85 85
86 try { 86 try {
87 task = JSON.parse(coreMessage); 87 task = JSON.parse(coreMessage);
88 } 88 }
89 catch(e) { 89 catch(e) {
90 logger.warn('Exception on parsing CORE pull task response', {coreMessage: coreMessage, error: e}); 90 logger.warn('Exception on parsing CORE pull task response', {coreMessage: coreMessage, error: e});
91 } 91 }
92 92
93 incrementCounterTrx(); 93 incrementCounterTrx();
94 94
95 task.remote_product = getRemoteProduct(task.product); 95 task.remote_product = getRemoteProduct(task.product);
96 96
97 taskArchive.get(task, function(res) { 97 taskArchive.get(task, function(res) {
98 if (res && partner.advice) { 98 if (res && partner.advice) {
99 partner.advice(task); 99 partner.advice(task);
100 } 100 }
101 else { 101 else {
102 partner.buy(task); 102 partner.buy(task);
103 } 103 }
104 }); 104 });
105 105
106 106
107 } 107 }
108 108
109 function replaceRc(original_rc) { 109 function replaceRc(original_rc) {
110 if (!config || !config.replace_rc || !config.replace_rc.length) { 110 if (!config || !config.replace_rc || !config.replace_rc.length) {
111 return original_rc; 111 return original_rc;
112 } 112 }
113 113
114 return config.replace_rc[original_rc] || original_rc; 114 return config.replace_rc[original_rc] || original_rc;
115 } 115 }
116 116
117 function report(data) { 117 function report(data) {
118 118
119 let core_pull_report_url; 119 let core_pull_report_url;
120 120
121 if (config.core_url) { 121 if (config.core_url) {
122 core_pull_report_url = config.core_url + '/pull/report'; 122 core_pull_report_url = config.core_url + '/pull/report';
123 } else if (config.pull_url.report) { 123 } else if (config.pull_url.report) {
124 core_pull_report_url = config.pull_url.report.replace('<CORE_APIKEY>', config.core_apikey); 124 core_pull_report_url = config.pull_url.report.replace('<CORE_APIKEY>', config.core_apikey);
125 } 125 }
126 126
127 if (!core_pull_report_url) { 127 if (!core_pull_report_url) {
128 logger.warn('Unknown CORE report url'); 128 logger.warn('Unknown CORE report url');
129 return; 129 return;
130 } 130 }
131 131
132 if (config && config.push_server && config.push_server.apikey && config.push_server.advice && config.push_server.advice.url && config.push_server.advice.port) { 132 if (config && config.push_server && config.push_server.apikey && config.push_server.advice && config.push_server.advice.url && config.push_server.advice.port) {
133 if (!data.misc) { 133 if (!data.misc) {
134 data.misc = {}; 134 data.misc = {};
135 } 135 }
136 136
137 logger.verbose('Including advice url on report');
138
137 logger.verbose('Including advice url on report'); 139 data.misc.advice_url = config.push_server.advice.url;
138 140 }
139 data.misc.advice_url = config.push_server.advice.url; 141
140 } 142 let options = {
141 143 url: core_pull_report_url,
142 let options = { 144 form: {
143 url: core_pull_report_url, 145 trx_id: data.trx_id,
144 form: { 146 rc: replaceRc(data.rc),
145 trx_id: data.trx_id, 147 message: data.message,
146 rc: replaceRc(data.rc), 148 handler: config.handler_name,
147 message: data.message, 149 sn: data.sn,
148 handler: config.handler_name, 150 amount: data.amount,
149 sn: data.sn, 151 raw: data.raw,
150 amount: data.amount, 152 misc: data.misc
151 raw: data.raw, 153 }
152 misc: data.misc 154 }
153 } 155
154 } 156 if (!config.do_not_verbose_log_report) {
155 157 logger.verbose('Report to CORE using HTTP POST');
156 if (!config.do_not_verbose_log_report) { 158 }
157 logger.verbose('Report to CORE using HTTP POST'); 159
158 } 160 request.post(options, function(error, response, body) {
159 161 if (error) {
160 request.post(options, function(error, response, body) { 162 logger.warn('Error reporting to CORE', {error: error});
161 if (error) { 163 resendReport(data);
162 logger.warn('Error reporting to CORE', {error: error}); 164 }
163 resendReport(data); 165 else if (response.statusCode != 200) {
164 } 166 logger.warn('Error reporting to CORE, http response status is not 200', {requestOptions: options, http_response_status: response.statusCode});
165 else if (response.statusCode != 200) { 167 resendReport(data);
166 logger.warn('Error reporting to CORE, http response status is not 200', {requestOptions: options, http_response_status: response.statusCode}); 168 }
167 resendReport(data); 169 else if (!config.do_not_verbose_log_report) {
168 } 170 logger.verbose('Report has been sent to CORE', {requestOptions: options});
169 else if (!config.do_not_verbose_log_report) { 171 }
170 logger.verbose('Report has been sent to CORE', {requestOptions: options}); 172 });
171 } 173 }
172 }); 174
173 } 175 function resendReport(data) {
174 176 const sleepBeforeResend = Math.round(Math.random() * MAX_SLEEP_BEFORE_RESEND_MS)
175 function resendReport(data) { 177 logger.verbose('Resend report to CORE in ' + sleepBeforeResend + 'ms')
176 const sleepBeforeResend = Math.round(Math.random() * MAX_SLEEP_BEFORE_RESEND_MS) 178
177 logger.verbose('Resend report to CORE in ' + sleepBeforeResend + 'ms') 179 setTimeout(
178 180 function() {
179 setTimeout( 181 report(data);
180 function() { 182 },
181 report(data); 183 sleepBeforeResend
182 }, 184 )
183 sleepBeforeResend 185 }
184 ) 186
185 } 187 function isPaused() {
186 188 return matrix.paused;
187 function isPaused() { 189 }
188 return matrix.paused; 190
189 } 191 function pause() {
190 192 matrix.paused = true;
191 function pause() { 193 }
192 matrix.paused = true; 194
193 } 195 function resume() {
194 196 matrix.pause = false;
195 function resume() { 197 }
196 matrix.pause = false; 198
197 } 199 function initMatrix() {
198 200 if (!matrix) {
199 function initMatrix() { 201 matrix = {};
200 if (!matrix) { 202 }
201 matrix = {}; 203
202 } 204 matrix.counter = {
203 205 trx: 0
204 matrix.counter = { 206 }
205 trx: 0 207 }
206 } 208
207 } 209 function incrementCounterTrx() {
208 210 matrix.counter.trx++;
209 function incrementCounterTrx() { 211 }
210 matrix.counter.trx++; 212
211 } 213 function getRemoteProduct(product) {
212 214 let remoteProduct = config.remote_products[product];
213 function getRemoteProduct(product) { 215 return remoteProduct || product;
214 let remoteProduct = config.remote_products[product]; 216 }
215 return remoteProduct || product; 217
216 } 218 initMatrix();
217 219 setInterval(pullTask, config.pull_interval_ms || 1000);
218 initMatrix(); 220
219 setInterval(pullTask, config.pull_interval_ms || 1000); 221 exports.setPartner = setPartner;
220 222 exports.isPaused = isPaused;
221 exports.setPartner = setPartner; 223 exports.pause = pause;
222 exports.isPaused = isPaused; 224 exports.resume = resume;
223 exports.pause = pause; 225 exports.report = report;
224 exports.resume = resume; 226 exports.getRemoteProduct = getRemoteProduct;
225 exports.report = report; 227
1 { 1 {
2 "name": "komodo-sdk", 2 "name": "komodo-sdk",
3 "version": "1.17.2", 3 "version": "1.18.0",
4 "description": "SDK for Komodo", 4 "description": "SDK for Komodo",
5 "main": "index.js", 5 "main": "index.js",
6 "scripts": { 6 "scripts": {
7 "test": "mocha", 7 "test": "mocha",
8 "postversion": "git push && git push --tags" 8 "postversion": "git push && git push --tags"
9 }, 9 },
10 "repository": { 10 "repository": {
11 "type": "git", 11 "type": "git",
12 "url": "git@gitlab.kodesumber.com:komodo/komodo-sdk.git" 12 "url": "git@gitlab.kodesumber.com:komodo/komodo-sdk.git"
13 }, 13 },
14 "keywords": [ 14 "keywords": [
15 "ppob", 15 "ppob",
16 "payment", 16 "payment",
17 "komodo" 17 "komodo"
18 ], 18 ],
19 "author": "Adhidarma Hadiwinoto <gua@adhisimon.org>", 19 "author": "Adhidarma Hadiwinoto <gua@adhisimon.org>",
20 "license": "ISC", 20 "license": "ISC",
21 "dependencies": { 21 "dependencies": {
22 "basic-auth": "^2.0.0", 22 "basic-auth": "^2.0.0",
23 "body-parser": "^1.18.2", 23 "body-parser": "^1.18.2",
24 "express": "^4.16.3", 24 "express": "^4.16.3",
25 "express-session": "^1.15.6", 25 "express-session": "^1.15.6",
26 "lru-cache": "^4.1.1", 26 "lru-cache": "^4.1.1",
27 "macaddress": "^0.2.8", 27 "macaddress": "^0.2.8",
28 "moment": "^2.19.1", 28 "moment": "^2.19.1",
29 "node-machine-id": "^1.1.10", 29 "node-machine-id": "^1.1.10",
30 "node-natural-sort": "^0.8.6", 30 "node-natural-sort": "^0.8.6",
31 "numeral": "^2.0.6", 31 "numeral": "^2.0.6",
32 "nunjucks": "^3.0.1", 32 "nunjucks": "^3.0.1",
33 "redis": "^2.8.0", 33 "redis": "^2.8.0",
34 "request": "^2.81.0", 34 "request": "^2.81.0",
35 "sha1": "^1.1.1", 35 "sha1": "^1.1.1",
36 "simple-git": "^1.80.1", 36 "simple-git": "^1.80.1",
37 "strftime": "^0.10.0", 37 "strftime": "^0.10.0",
38 "uniqid": "^4.1.1", 38 "uniqid": "^4.1.1",
39 "uuid": "^3.1.0", 39 "uuid": "^3.1.0",
40 "winston": "^2.3.1", 40 "winston": "^2.3.1",
41 "winston-circular-buffer": "^1.0.0", 41 "winston-circular-buffer": "^1.0.0",
42 "winston-daily-rotate-file": "^1.4.6" 42 "winston-daily-rotate-file": "^1.4.6"
43 } 43 }
44 } 44 }
45 45