Compare View

switch
from
...
to
 
Commits (2)

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 if (!config || !config.push_server || !!config.push_server.apikey || !config.push_server.advice || !config.push_server.advice.url || !config.push_server.advice.port) return; 11 if (!config || !config.push_server || !!config.push_server.apikey || !config.push_server.advice || !config.push_server.advice.url || !config.push_server.advice.port) return;
12 12
13 const app = express(); 13 const app = express();
14 14
15 let partner = null; 15 let partner = null;
16 16
17 function setPartner(_partner) { 17 function setPartner(_partner) {
18 partner = _partner; 18 partner = _partner;
19 19
20 app.listen(config.push_server.advice.port, function () { 20 app.listen(config.push_server.advice.port, function () {
21 logger.info('Advice server listening', {port: config.push_server.advice.port}); 21 logger.info('Advice server listening', {port: config.push_server.advice.port});
22 }); 22 });
23 } 23 }
24 24
25 function isValidApikey(req, res, next) { 25 function isValidApikey(req, res, next) {
26 if (req.params.apikey === config.push_server.apikey) { 26 if (req.params.apikey === config.push_server.apikey) {
27 next(); 27 next();
28 } 28 }
29 else { 29 else {
30 res.end('INVALID_APIKEY'); 30 res.end('INVALID_APIKEY');
31 } 31 }
32 } 32 }
33 33
34 function adviceHandler(req, res, next) { 34 function adviceHandler(req, res, next) {
35 35
36 if (!partner) { 36 if (!partner) {
37 logger.warn('PUSH-ADVICE: Undefined partner, skipped'); 37 logger.warn('PUSH-ADVICE: Undefined partner, skipped');
38 res.end('UNDEFINED_PARTNER'); 38 res.end('UNDEFINED_PARTNER');
39 return; 39 return;
40 } 40 }
41 41
42 if (!partner.advice) { 42 if (!partner.advice) {
43 logger.warn('PUSH-ADVICE: Partner does not have ADVICE capabilities'); 43 logger.warn('PUSH-ADVICE: Partner does not have ADVICE capabilities');
44 res.end('UNSUPPORTED'); 44 res.end('UNSUPPORTED');
45 return; 45 return;
46 } 46 }
47 47
48 let task = null; 48 let task = null;
49 49
50 try { 50 try {
51 task = JSON.parse(coreMessage); 51 task = JSON.parse(coreMessage);
52 } 52 }
53 catch(e) { 53 catch(e) {
54 logger.warn('PUSH-ADVICE: Exception on parsing task to advice', {err: e}); 54 logger.warn('PUSH-ADVICE: Exception on parsing task to advice', {err: e});
55 } 55 }
56 56
57 if (!task) { 57 if (!task) {
58 res.end('INVALID_TASK'); 58 res.end('INVALID_TASK');
59 return; 59 return;
60 } 60 }
61 61
62 task.remote_product = pull.getRemoteProduct(task.product); 62 task.remote_product = pull.getRemoteProduct(task.product);
63 partner.advice(task); 63 partner.advice(task);
64 } 64 }
65 65
66 app.use(bodyParser.json()); 66 app.use(bodyParser.json());
67 app.use('/apikey/:apikey', isValidApikey); 67 app.use('/apikey/:apikey', isValidApikey);
68 app.use('/apikey/:apikey/advice', adviceHandler); 68 app.use('/apikey/:apikey/advice', adviceHandler);
69 69
70 exports.setPartner = setPartner; 70 exports.setPartner = setPartner;
71 71
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) {
133 if (!data.misc) {
134 data.misc = {};
135 }
136
137 data.misc.advice_url = config.push_server.advice.url;
138 }
139
132 if (config && config.push_server && config.push_server.apikey && config.push_server.advice && config.push_server.advice.url && config.push_server.advice.port) { 140 let options = {
133 if (!data.misc) { 141 url: core_pull_report_url,
134 data.misc = {}; 142 form: {
135 } 143 trx_id: data.trx_id,
136 144 rc: replaceRc(data.rc),
137 data.misc.advice_url = config.push_server.advice.url; 145 message: data.message,
138 } 146 handler: config.handler_name,
139 147 sn: data.sn,
140 let options = { 148 amount: data.amount,
141 url: core_pull_report_url, 149 raw: data.raw,
142 form: { 150 misc: data.misc
143 trx_id: data.trx_id, 151 }
144 rc: replaceRc(data.rc), 152 }
145 message: data.message, 153
146 handler: config.handler_name, 154 if (!config.do_not_verbose_log_report) {
147 sn: data.sn, 155 logger.verbose('Report to CORE using HTTP POST');
148 amount: data.amount, 156 }
149 raw: data.raw, 157
150 misc: data.misc 158 request.post(options, function(error, response, body) {
151 } 159 if (error) {
152 } 160 logger.warn('Error reporting to CORE', {error: error});
153 161 resendReport(data);
154 if (!config.do_not_verbose_log_report) { 162 }
155 logger.verbose('Report to CORE using HTTP POST'); 163 else if (response.statusCode != 200) {
156 } 164 logger.warn('Error reporting to CORE, http response status is not 200', {requestOptions: options, http_response_status: response.statusCode});
157 165 resendReport(data);
158 request.post(options, function(error, response, body) { 166 }
159 if (error) { 167 else if (!config.do_not_verbose_log_report) {
160 logger.warn('Error reporting to CORE', {error: error}); 168 logger.verbose('Report has been sent to CORE', {requestOptions: options});
161 resendReport(data); 169 }
162 } 170 });
163 else if (response.statusCode != 200) { 171 }
164 logger.warn('Error reporting to CORE, http response status is not 200', {requestOptions: options, http_response_status: response.statusCode}); 172
165 resendReport(data); 173 function resendReport(data) {
166 } 174 const sleepBeforeResend = Math.round(Math.random() * MAX_SLEEP_BEFORE_RESEND_MS)
167 else if (!config.do_not_verbose_log_report) { 175 logger.verbose('Resend report to CORE in ' + sleepBeforeResend + 'ms')
168 logger.verbose('Report has been sent to CORE', {requestOptions: options}); 176
169 } 177 setTimeout(
170 }); 178 function() {
171 } 179 report(data);
172 180 },
173 function resendReport(data) { 181 sleepBeforeResend
174 const sleepBeforeResend = Math.round(Math.random() * MAX_SLEEP_BEFORE_RESEND_MS) 182 )
175 logger.verbose('Resend report to CORE in ' + sleepBeforeResend + 'ms') 183 }
176 184
177 setTimeout( 185 function isPaused() {
178 function() { 186 return matrix.paused;
179 report(data); 187 }
180 }, 188
181 sleepBeforeResend 189 function pause() {
182 ) 190 matrix.paused = true;
183 } 191 }
184 192
185 function isPaused() { 193 function resume() {
186 return matrix.paused; 194 matrix.pause = false;
187 } 195 }
188 196
189 function pause() { 197 function initMatrix() {
190 matrix.paused = true; 198 if (!matrix) {
191 } 199 matrix = {};
192 200 }
193 function resume() { 201
194 matrix.pause = false; 202 matrix.counter = {
195 } 203 trx: 0
196 204 }
197 function initMatrix() { 205 }
198 if (!matrix) { 206
199 matrix = {}; 207 function incrementCounterTrx() {
200 } 208 matrix.counter.trx++;
201 209 }
202 matrix.counter = { 210
203 trx: 0 211 function getRemoteProduct(product) {
204 } 212 let remoteProduct = config.remote_products[product];
205 } 213 return remoteProduct || product;
206 214 }
207 function incrementCounterTrx() { 215
208 matrix.counter.trx++; 216 initMatrix();
209 } 217 setInterval(pullTask, config.pull_interval_ms || 1000);
210 218
211 function getRemoteProduct(product) { 219 exports.setPartner = setPartner;
212 let remoteProduct = config.remote_products[product]; 220 exports.isPaused = isPaused;
213 return remoteProduct || product; 221 exports.pause = pause;
214 } 222 exports.resume = resume;
215 223 exports.report = report;
216 initMatrix(); 224 exports.getRemoteProduct = getRemoteProduct;
217 setInterval(pullTask, config.pull_interval_ms || 1000); 225
1 { 1 {
2 "name": "komodo-sdk", 2 "name": "komodo-sdk",
3 "version": "1.17.0", 3 "version": "1.17.1",
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