Compare View

switch
from
...
to
 
Commits (3)

Changes

Showing 3 changed files Inline Diff

center/messaging/trx-center.js
1 "use strict"; 1 "use strict";
2 2
3 /** 3 /**
4 * Trx Handler untuk center messaging 4 * Trx Handler untuk center messaging
5 */ 5 */
6 6
7 const module_name = require('path').basename(__filename); 7 const module_name = require('path').basename(__filename);
8 8
9 const request = require('request'); 9 const request = require('request');
10 const strftime = require('strftime'); 10 const strftime = require('strftime');
11 const config = require('../../config'); 11 const config = require('../../config');
12 const logger = require('../../logger'); 12 const logger = require('../../logger');
13 const httpResponseServer = require('../http-response-server'); 13 const httpResponseServer = require('../http-response-server');
14 const controlPanel = require('../../control-panel'); 14 const controlPanel = require('../../control-panel');
15 const heartbeat = require('../../heartbeat'); 15 const heartbeat = require('../../heartbeat');
16 16
17 let transport; 17 let transport;
18 18
19 heartbeat.setModuleType('center') 19 heartbeat.setModuleType('center')
20 20
21 function onOnline(params) { 21 function onOnline(params) {
22 logger.info('CENTER is ONLINE, ready to communicate'); 22 logger.info('CENTER is ONLINE, ready to communicate');
23 } 23 }
24 24
25 function onIncomingMessage(paramsFromTransport, cb) { 25 function onIncomingMessage(paramsFromTransport, cb) {
26 logger.verbose('Reporting message to CORE') 26 logger.verbose('Reporting message to CORE')
27 27
28 const command = paramsFromTransport.msg.split(/[\., ]+/)[0].toUpperCase(); 28 const command = paramsFromTransport.msg.split(/[\., ]+/)[0].toUpperCase();
29 29
30 if (config.commands && config.commands.balance && config.commands.balance.indexOf(command) >= 0) { 30 if (config.commands && config.commands.balance && config.commands.balance.indexOf(command) >= 0) {
31 executeBalanceCheck(paramsFromTransport, cb); 31 executeBalanceCheck(paramsFromTransport, cb);
32 } 32 }
33 else if (config.commands && config.commands.price && config.commands.price.indexOf(command) >= 0) { 33 else if (config.commands && config.commands.price && config.commands.price.indexOf(command) >= 0) {
34 executePriceCheck(paramsFromTransport, cb); 34 executePriceCheck(paramsFromTransport, cb);
35 } 35 }
36 else if (config.commands && config.commands.postpaid_inquiry && config.commands.postpaid_inquiry.indexOf(command) >= 0) { 36 else if (config.commands && config.commands.postpaid_inquiry && config.commands.postpaid_inquiry.indexOf(command) >= 0) {
37 executePostpaidInquiry(paramsFromTransport, cb); 37 executePostpaidInquiry(paramsFromTransport, cb);
38 38
39 } 39 }
40 else if (config.commands && config.commands.postpaid_pay && config.commands.postpaid_pay.indexOf(command) >= 0) { 40 else if (config.commands && config.commands.postpaid_pay && config.commands.postpaid_pay.indexOf(command) >= 0) {
41 executePostpaidPay(paramsFromTransport, cb); 41 executePostpaidPay(paramsFromTransport, cb);
42 } 42 }
43 else { 43 else {
44 executePrepaidBuy(paramsFromTransport, cb); 44 executePrepaidBuy(paramsFromTransport, cb);
45 } 45 }
46 } 46 }
47 47
48 function executeBalanceCheck(paramsFromTransport) { 48 function executeBalanceCheck(paramsFromTransport) {
49 const terminal_name = paramsFromTransport.partner.toLowerCase(); 49 const terminal_name = paramsFromTransport.partner.toLowerCase();
50 const password = paramsFromTransport.msg.trim().split(/[\., ]+/)[1]; 50 const password = paramsFromTransport.msg.trim().split(/[\., ]+/)[1];
51 51
52 const requestOptions = { 52 const requestOptions = {
53 url: config.core_url + '/services/balance', 53 url: config.core_url + '/services/balance',
54 qs: { 54 qs: {
55 terminal_name: terminal_name, 55 terminal_name: terminal_name,
56 password: password, 56 password: password,
57 msg: paramsFromTransport.msg 57 msg: paramsFromTransport.msg
58 } 58 }
59 } 59 }
60 60
61 requestToCore(requestOptions); 61 requestToCore(requestOptions);
62 } 62 }
63 63
64 function executePriceCheck(paramsFromTransport) { 64 function executePriceCheck(paramsFromTransport) {
65 const requestOptions = { 65 const requestOptions = {
66 url: config.core_url + '/services/pricelist', 66 url: config.core_url + '/services/pricelist',
67 qs: { 67 qs: {
68 terminal_name: paramsFromTransport.partner.toLowerCase(), 68 terminal_name: paramsFromTransport.partner.toLowerCase(),
69 keyword: paramsFromTransport.msg.trim().split(/[\., ]+/)[1], 69 keyword: paramsFromTransport.msg.trim().split(/[\., ]+/)[1],
70 password: paramsFromTransport.msg.trim().split(/[\., ]+/)[2], 70 password: paramsFromTransport.msg.trim().split(/[\., ]+/)[2],
71 postpaid: 0, 71 postpaid: 0,
72 msg: paramsFromTransport.msg 72 msg: paramsFromTransport.msg
73 } 73 }
74 } 74 }
75 75
76 requestToCore(requestOptions); 76 requestToCore(requestOptions);
77 } 77 }
78 78
79 function parseCoreMessage(body) { 79 function parseCoreMessage(body) {
80 let coreRes; 80 let coreRes;
81 81
82 try { 82 try {
83 coreRes = JSON.parse(body) 83 coreRes = JSON.parse(body)
84 } 84 }
85 catch(err) { 85 catch(err) {
86 logger.warn('Exception on parsing CORE response as JSON', {body: body, err: err}); 86 logger.warn('Exception on parsing CORE response as JSON', {body: body, err: err});
87 coreRes = null; 87 coreRes = null;
88 } 88 }
89 89
90 return coreRes; 90 return coreRes;
91 } 91 }
92 92
93 function generateRequestId(req) { 93 function generateRequestId(req) {
94 //return 'AUTO_' + req.product_name + '_' + req.destination + '_' + strftime('%Y%m%d'); 94 //return 'AUTO_' + req.product_name + '_' + req.destination + '_' + strftime('%Y%m%d');
95 return '';
95 return ''; 96 }
96 } 97
97 98 function executePrepaidBuy(paramsFromTransport, cb) {
98 function executePrepaidBuy(paramsFromTransport, cb) { 99 let tokens = paramsFromTransport.msg.trim().split(/[\., ]+/);
99 let tokens = paramsFromTransport.msg.trim().split(/[\., ]+/); 100
100 101 let qs = {
101 let qs = { 102 request_id: tokens[3],
102 request_id: tokens[3], 103 terminal_name: paramsFromTransport.partner.toLowerCase(),
103 terminal_name: paramsFromTransport.partner.toLowerCase(), 104 product_name: tokens[0].toUpperCase(),
104 product_name: tokens[0].toUpperCase(), 105 destination: tokens[1].toUpperCase(),
105 destination: tokens[1].toUpperCase(), 106 password: tokens[2],
106 password: tokens[2], 107 origin: config.origin || config.username,
107 origin: config.origin || config.username, 108 report_port: config.listen_port || '80',
108 report_port: config.listen_port || '80', 109 msg: paramsFromTransport.msg,
109 msg: paramsFromTransport.msg, 110 reverse_url: paramsFromTransport.reverse_url
110 reverse_url: paramsFromTransport.reverse_url 111 }
111 } 112
112 113 if (!config.do_not_prefix_request_id) {
113 if (!config.do_not_prefix_request_id) { 114 qs.request_id = generateRequestId(qs);
114 qs.request_id = generateRequestId(qs); 115 if (tokens[3]) {
115 if (tokens[3]) { 116 qs.request_id += '_' + tokens[3];
116 qs.request_id += '_' + tokens[3]; 117 }
117 } 118 }
118 } 119
119 120 let requestOptions = {
120 let requestOptions = { 121 url: config.core_url + '/prepaid/buy',
121 url: config.core_url + '/prepaid/buy', 122 qs: qs
122 qs: qs 123 }
123 } 124
124 125 requestToCore(requestOptions, cb);
125 requestToCore(requestOptions, cb); 126 }
126 } 127
127 128 function executePostpaidInquiry(paramsFromTransport, cb) {
128 function executePostpaidInquiry(paramsFromTransport, cb) { 129 // PAY.PLN.1234567890.PIN
129 // PAY.PLN.1234567890.PIN 130
130 131 let tokens = paramsFromTransport.msg.trim().split(/[\., ]+/);
131 let tokens = paramsFromTransport.msg.trim().split(/[\., ]+/); 132
132 133 let qs = {
133 let qs = { 134 request_id: tokens[4],
134 request_id: tokens[4], 135 terminal_name: paramsFromTransport.partner.toLowerCase(),
135 terminal_name: paramsFromTransport.partner.toLowerCase(), 136 product_name: tokens[1].toUpperCase(),
136 product_name: tokens[1].toUpperCase(), 137 destination: tokens[2].toUpperCase(),
137 destination: tokens[2].toUpperCase(), 138 password: tokens[3],
138 password: tokens[3], 139 origin: config.origin || config.username,
139 origin: config.origin || config.username, 140 report_port: config.listen_port || '80',
140 report_port: config.listen_port || '80', 141 msg: paramsFromTransport.msg,
141 msg: paramsFromTransport.msg, 142 reverse_url: paramsFromTransport.reverse_url
142 reverse_url: paramsFromTransport.reverse_url 143 }
143 } 144
144 145 if (!config.do_not_prefix_request_id) {
145 if (!config.do_not_prefix_request_id) { 146 qs.request_id = generateRequestId(qs);
146 qs.request_id = generateRequestId(qs); 147 if (tokens[3]) {
147 if (tokens[3]) { 148 qs.request_id += '_' + tokens[3];
148 qs.request_id += '_' + tokens[3]; 149 }
149 } 150 }
150 } 151
151 152 let requestOptions = {
152 let requestOptions = { 153 url: config.core_url + '/postpaid/inquiry',
153 url: config.core_url + '/postpaid/inquiry', 154 qs: qs
154 qs: qs 155 }
155 } 156
156 157 requestToCore(requestOptions, cb);
157 requestToCore(requestOptions, cb); 158 }
158 } 159
159 160 function executePostpaidPay(paramsFromTransport, cb) {
160 function executePostpaidPay(paramsFromTransport, cb) { 161 let tokens = paramsFromTransport.msg.trim().split(/[\., ]+/);
161 let tokens = paramsFromTransport.msg.trim().split(/[\., ]+/); 162
162 163 let qs = {
163 let qs = { 164 request_id: tokens[4],
164 request_id: tokens[4], 165 terminal_name: paramsFromTransport.partner.toLowerCase(),
165 terminal_name: paramsFromTransport.partner.toLowerCase(), 166 product_name: tokens[1].toUpperCase(),
166 product_name: tokens[1].toUpperCase(), 167 destination: tokens[2].toUpperCase(),
167 destination: tokens[2].toUpperCase(), 168 password: tokens[3],
168 password: tokens[3], 169 origin: config.origin || config.username,
169 origin: config.origin || config.username, 170 report_port: config.listen_port || '80',
170 report_port: config.listen_port || '80', 171 msg: paramsFromTransport.msg,
171 msg: paramsFromTransport.msg, 172 reverse_url: paramsFromTransport.reverse_url
172 reverse_url: paramsFromTransport.reverse_url 173 }
173 } 174
174 175 if (!config.do_not_prefix_request_id) {
175 if (!config.do_not_prefix_request_id) { 176 qs.request_id = generateRequestId(qs);
176 qs.request_id = generateRequestId(qs); 177 if (tokens[3]) {
177 if (tokens[3]) { 178 qs.request_id += '_' + tokens[3];
178 qs.request_id += '_' + tokens[3]; 179 }
179 } 180 }
180 } 181
181 182 let requestOptions = {
182 let requestOptions = { 183 url: config.core_url + '/postpaid/pay',
183 url: config.core_url + '/postpaid/pay', 184 qs: qs
184 qs: qs 185 }
185 } 186
186 187 requestToCore(requestOptions, cb);
187 requestToCore(requestOptions, cb); 188 }
188 } 189
189 190 function requestToCore(requestOptions, cb) {
190 function requestToCore(requestOptions, cb) { 191 logger.verbose('Requesting service to CORE', requestOptions);
191 logger.verbose('Requesting service to CORE', requestOptions); 192
192 193 request(requestOptions, function(err, res, body) {
193 request(requestOptions, function(err, res, body) { 194 if (err || res.statusCode != 200) {
194 if (err || res.statusCode != 200) { 195 logger.warn('Error requesting to CORE', {module_name: module_name, method_name: 'requestToCore', requestOptions: requestOptions, err: err});
195 logger.warn('Error requesting to CORE', {module_name: module_name, method_name: 'requestToCore', requestOptions: requestOptions, err: err}); 196 let msg = "INTERNAL ERROR";
196 let msg = "INTERNAL ERROR"; 197 if (requestOptions.qs.msg) {
197 if (requestOptions.qs.msg) { 198 msg = requestOptions.qs.msg + ": " + msg;
198 msg = requestOptions.qs.msg + ": " + msg; 199 }
199 } 200
200 201 if (cb) {
201 if (cb) { 202 cb(null, {msg: msg});
202 cb(null, {msg: msg}); 203 }
203 } 204 else if (transport.send) {
204 else if (transport.send) { 205 transport.send(requestOptions.qs.terminal_name, msg);
205 transport.send(requestOptions.qs.terminal_name, msg); 206 }
206 } 207 return;
207 return; 208 }
208 } 209
209 210 let result = parseCoreMessage(body);
210 let result = parseCoreMessage(body); 211 if (!result || !result.message) {
211 if (!result || !result.message) { 212 let msg = "INTERNAL ERROR";
212 let msg = "INTERNAL ERROR"; 213 if (requestOptions.qs.msg) {
213 if (requestOptions.qs.msg) { 214 msg = requestOptions.qs.msg + ": " + msg;
214 msg = requestOptions.qs.msg + ": " + msg; 215 }
215 } 216
216 217 if (cb) {
217 if (cb) { 218 cb(null, {msg: msg});
218 cb(null, {msg: msg}); 219 }
219 } 220 else if (transport.send) {
220 else if (transport.send) { 221 transport.send(requestOptions.qs.terminal_name, msg);
221 transport.send(requestOptions.qs.terminal_name, msg); 222 }
222 } 223 return;
223 return; 224 }
224 } 225
225 226 if (cb) {
226 if (cb) { 227 cb(null, result);
227 cb(null, result); 228 }
228 } 229 else if (transport.send) {
229 else if (transport.send) { 230 transport.send(requestOptions.qs.terminal_name, result.message);
230 transport.send(requestOptions.qs.terminal_name, result.message); 231
231 232 }
232 } 233 })
233 }) 234 }
234 } 235
235 236 function setTransport(_transport) {
236 function setTransport(_transport) { 237 transport = _transport;
237 transport = _transport; 238 httpResponseServer.setTransport(transport);
238 httpResponseServer.setTransport(transport); 239 }
239 } 240
240 241 const callback = {
241 const callback = { 242 onOnline: onOnline,
242 onOnline: onOnline, 243 onIncomingMessage: onIncomingMessage
243 onIncomingMessage: onIncomingMessage 244 }
244 } 245
245 246 exports.callback = callback;
246 exports.callback = callback; 247 exports.setTransport = setTransport;
247 exports.setTransport = setTransport; 248
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 heartbeat.setModuleType('gateway'); 11 heartbeat.setModuleType('gateway');
12 12
13 var partner; 13 var partner;
14 14
15 function setPartner(_partner) { 15 function setPartner(_partner) {
16 partner = _partner; 16 partner = _partner;
17 } 17 }
18 18
19 function pullTask() { 19 function pullTask() {
20 if (!partner) { 20 if (!partner) {
21 return; 21 return;
22 } 22 }
23 23
24 let core_pull_task_url; 24 let core_pull_task_url;
25 25
26 if (config.core_url) { 26 if (config.core_url) {
27 core_pull_task_url = config.core_url + '/pull/task'; 27 core_pull_task_url = config.core_url + '/pull/task';
28 } else if (config.pull_url.task) { 28 } else if (config.pull_url.task) {
29 core_pull_task_url = config.pull_url.task.replace('<CORE_APIKEY>', config.core_apikey); 29 core_pull_task_url = config.pull_url.task.replace('<CORE_APIKEY>', config.core_apikey);
30 } 30 }
31 31
32 if (!core_pull_task_url) { 32 if (!core_pull_task_url) {
33 logger.warn('Unknown CORE task url'); 33 logger.warn('Unknown CORE task url');
34 return; 34 return;
35 } 35 }
36 36
37 let options = { 37 let options = {
38 url: core_pull_task_url, 38 url: core_pull_task_url,
39 qs: { 39 qs: {
40 handler: config.handler_name, 40 handler: config.handler_name,
41 products: config.products.join(',') 41 products: config.products.join(',')
42 } 42 }
43 } 43 }
44 44
45 request(options, function(error, response, body) { 45 request(options, function(error, response, body) {
46 if (error) { 46 if (error) {
47 if (matrix.core_is_healthy) { 47 if (matrix.core_is_healthy) {
48 logger.warn('Error pulling task from CORE', {error: error}); 48 logger.warn('Error pulling task from CORE', {error: error});
49 } 49 }
50 matrix.core_is_healthy = false; 50 matrix.core_is_healthy = false;
51 return; 51 return;
52 } 52 }
53 53
54 if (response.statusCode != 200) { 54 if (response.statusCode != 200) {
55 if (matrix.core_is_healthy) { 55 if (matrix.core_is_healthy) {
56 logger.warn('CORE http response status code for pull task is not 200', {http_response_status: response.statusCode}); 56 logger.warn('CORE http response status code for pull task is not 200', {http_response_status: response.statusCode});
57 } 57 }
58 matrix.core_is_healthy = false; 58 matrix.core_is_healthy = false;
59 return; 59 return;
60 } 60 }
61 61
62 if (!matrix.core_is_healthy) { 62 if (!matrix.core_is_healthy) {
63 logger.verbose('CORE is healthy'); 63 logger.verbose('CORE is healthy');
64 } 64 }
65 matrix.core_is_healthy = true; 65 matrix.core_is_healthy = true;
66 66
67 if (body == 'NONE') { 67 if (body == 'NONE') {
68 return; 68 return;
69 } 69 }
70 70
71 forwardCoreTaskToPartner(body); 71 forwardCoreTaskToPartner(body);
72 }); 72 });
73 } 73 }
74 74
75 function forwardCoreTaskToPartner(coreMessage) { 75 function forwardCoreTaskToPartner(coreMessage) {
76 let task; 76 let task;
77 77
78 try { 78 try {
79 task = JSON.parse(coreMessage); 79 task = JSON.parse(coreMessage);
80 } 80 }
81 catch(e) { 81 catch(e) {
82 logger.warn('Exception on parsing CORE pull task response', {coreMessage: coreMessage, error: e}); 82 logger.warn('Exception on parsing CORE pull task response', {coreMessage: coreMessage, error: e});
83 } 83 }
84 84
85 task.remote_product = getRemoteProduct(task.product); 85 task.remote_product = getRemoteProduct(task.product);
86 86
87 partner.buy(task); 87 partner.buy(task);
88 } 88 }
89 89
90 function report(data) { 90 function report(data) {
91 91
92 let core_pull_report_url; 92 let core_pull_report_url;
93 93
94 if (config.core_url) { 94 if (config.core_url) {
95 core_pull_report_url = config.core_url + '/pull/report'; 95 core_pull_report_url = config.core_url + '/pull/report';
96 } else if (config.pull_url.report) { 96 } else if (config.pull_url.report) {
97 core_pull_report_url = config.pull_url.report.replace('<CORE_APIKEY>', config.core_apikey); 97 core_pull_report_url = config.pull_url.report.replace('<CORE_APIKEY>', config.core_apikey);
98 } 98 }
99 99
100 if (!core_pull_report_url) { 100 if (!core_pull_report_url) {
101 logger.warn('Unknown CORE report url'); 101 logger.warn('Unknown CORE report url');
102 return; 102 return;
103 } 103 }
104 104
105 let options = { 105 let options = {
106 url: core_pull_report_url, 106 url: core_pull_report_url,
107 form: { 107 form: {
108 trx_id: data.trx_id, 108 trx_id: data.trx_id,
109 rc: data.rc, 109 rc: data.rc,
110 message: data.message, 110 message: data.message,
111 handler: config.handler_name, 111 handler: config.handler_name,
112 sn: data.sn, 112 sn: data.sn,
113 amount: data.amount, 113 amount: data.amount,
114 handler: config.handler_name,
114 handler: config.handler_name, 115 raw: data.raw,
115 raw: data.raw, 116 misc: data.misc
116 misc: data.misc 117 }
117 } 118 }
118 } 119
119 120 logger.verbose('Report to CORE using HTTP POST');
120 logger.verbose('Report to CORE using HTTP POST'); 121 request.post(options, function(error, response, body) {
121 request.post(options, function(error, response, body) { 122 if (error) {
122 if (error) { 123 logger.warn('Error reporting to CORE', {error: error});
123 logger.warn('Error reporting to CORE', {error: error}); 124 }
124 } 125 else if (response.statusCode != 200) {
125 else if (response.statusCode != 200) { 126 logger.warn('CORE http response status is not 200', {requestOptions: options, http_response_status: response.statusCode});
126 logger.warn('CORE http response status is not 200', {requestOptions: options, http_response_status: response.statusCode}); 127 }
127 } 128 else {
128 else { 129 logger.verbose('Report has been sent to CORE', {requestOptions: options});
129 logger.verbose('Report has been sent to CORE', {requestOptions: options}); 130 }
130 } 131 });
131 }); 132 }
132 } 133
133 134 function resendReport(data) {
134 function resendReport(data) { 135 let sleepBeforeResend = 1000;
135 let sleepBeforeResend = 1000; 136 logger.verbose('Resend report to CORE in ' + sleepBeforeResend + 'ms')
136 logger.verbose('Resend report to CORE in ' + sleepBeforeResend + 'ms') 137
137 138 setTimeout(
138 setTimeout( 139 function() {
139 function() { 140 report(data);
140 report(data); 141 },
141 }, 142 sleepBeforeResend
142 sleepBeforeResend 143 )
143 ) 144 }
144 } 145
145 146 function isPaused() {
146 function isPaused() { 147 return matrix.paused;
147 return matrix.paused; 148 }
148 } 149
149 150 function pause() {
150 function pause() { 151 matrix.paused = true;
151 matrix.paused = true; 152 }
152 } 153
153 154 function resume() {
154 function resume() { 155 matrix.pause = false;
155 matrix.pause = false; 156 }
156 } 157
157 158 function initMatrix() {
158 function initMatrix() { 159 if (!matrix) {
159 if (!matrix) { 160 matrix = {};
160 matrix = {}; 161 }
161 } 162
162 163 matrix.counter = {
163 matrix.counter = { 164 trx: 0
164 trx: 0 165 }
165 } 166 }
166 } 167
167 168 function incrementCounterTrx() {
168 function incrementCounterTrx() { 169 matrix.counter.trx++;
169 matrix.counter.trx++; 170 }
170 } 171
171 172 function getRemoteProduct(product) {
172 function getRemoteProduct(product) { 173 let remoteProduct = config.remote_products[product];
173 let remoteProduct = config.remote_products[product]; 174 return remoteProduct || product;
174 return remoteProduct || product; 175 }
175 } 176
176 177 initMatrix();
177 initMatrix(); 178 setInterval(pullTask, config.pull_interval_ms || 1000);
178 setInterval(pullTask, config.pull_interval_ms || 1000); 179
179 180 exports.setPartner = setPartner;
180 exports.setPartner = setPartner; 181 exports.isPaused = isPaused;
181 exports.isPaused = isPaused; 182 exports.pause = pause;
182 exports.pause = pause; 183 exports.resume = resume;
183 exports.resume = resume; 184 exports.report = report;
184 exports.report = report; 185
1 { 1 {
2 "name": "komodo-sdk", 2 "name": "komodo-sdk",
3 "version": "1.13.5", 3 "version": "1.13.6",
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.2", 24 "express": "^4.16.2",
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 "moment": "^2.19.1", 27 "moment": "^2.19.1",
28 "numeral": "^2.0.6", 28 "numeral": "^2.0.6",
29 "nunjucks": "^3.0.1", 29 "nunjucks": "^3.0.1",
30 "request": "^2.81.0", 30 "request": "^2.81.0",
31 "simple-git": "^1.80.1", 31 "simple-git": "^1.80.1",
32 "strftime": "^0.10.0", 32 "strftime": "^0.10.0",
33 "uniqid": "^4.1.1", 33 "uniqid": "^4.1.1",
34 "uuid": "^3.1.0", 34 "uuid": "^3.1.0",
35 "winston": "^2.3.1", 35 "winston": "^2.3.1",
36 "winston-circular-buffer": "^1.0.0", 36 "winston-circular-buffer": "^1.0.0",
37 "winston-daily-rotate-file": "^1.4.6" 37 "winston-daily-rotate-file": "^1.4.6"
38 } 38 }
39 } 39 }
40 40