Commit ae566890d7b00355bb41ead28ecb86ffd2d13301
1 parent
2e715a750f
Exists in
master
Webhook support
Showing 3 changed files with 33 additions and 0 deletions Inline Diff
config.sample.json
1 | { | 1 | { |
2 | "name": "HTTPGETX", | 2 | "name": "HTTPGETX", |
3 | 3 | ||
4 | "# core_url": "Silahkan diisi dengan core url, bisa dikosongkan jika ingin membaca dari main config komodo", | 4 | "# core_url": "Silahkan diisi dengan core url, bisa dikosongkan jika ingin membaca dari main config komodo", |
5 | "core_url": "", | 5 | "core_url": "", |
6 | 6 | ||
7 | "listener": { | 7 | "listener": { |
8 | "partner": { | 8 | "partner": { |
9 | "trust_proxy": ["loopback", "linklocal"], | 9 | "trust_proxy": ["loopback", "linklocal"], |
10 | "port": 25614, | 10 | "port": 25614, |
11 | "# webhook": "http://PLEASE_CHANGE_ME/PLEASE_CHANGE_ME", | ||
11 | "dump": false | 12 | "dump": false |
12 | }, | 13 | }, |
13 | "core": { | 14 | "core": { |
14 | "port": 25615, | 15 | "port": 25615, |
15 | "dump": false | 16 | "dump": false |
16 | }, | 17 | }, |
17 | "apiserver": { | 18 | "apiserver": { |
18 | "port": 25617, | 19 | "port": 25617, |
19 | "apikey": "PLEASE_CHANGE_ME" | 20 | "apikey": "PLEASE_CHANGE_ME" |
20 | } | 21 | } |
21 | }, | 22 | }, |
22 | 23 | ||
23 | "callback_sender": { | 24 | "callback_sender": { |
24 | "http_timeout_ms": 30000, | 25 | "http_timeout_ms": 30000, |
25 | "sleep_before_retry_ms": 10000, | 26 | "sleep_before_retry_ms": 10000, |
26 | "max_retry": 10 | 27 | "max_retry": 10 |
27 | }, | 28 | }, |
28 | 29 | ||
29 | "terminals_with_location": [], | 30 | "terminals_with_location": [], |
30 | 31 | ||
31 | "# cluster": "Isi dengan boolean atau angka jumlah anak yang akan dibuat. Jika diisi boolean true, jumlah anak akan dihitung otomatis", | 32 | "# cluster": "Isi dengan boolean atau angka jumlah anak yang akan dibuat. Jika diisi boolean true, jumlah anak akan dihitung otomatis", |
32 | "cluster": false | 33 | "cluster": false |
33 | } | 34 | } |
lib/core-callback/sender.js
1 | const MODULE_NAME = 'CORE-CALLBACK.SENDER'; | 1 | const MODULE_NAME = 'CORE-CALLBACK.SENDER'; |
2 | 2 | ||
3 | const axios = require('axios'); | 3 | const axios = require('axios'); |
4 | const config = require('komodo-sdk/config'); | 4 | const config = require('komodo-sdk/config'); |
5 | const logger = require('tektrans-logger'); | 5 | const logger = require('tektrans-logger'); |
6 | 6 | ||
7 | const dumper = require('./dumper/sender'); | 7 | const dumper = require('./dumper/sender'); |
8 | const matrix = require('../matrix'); | 8 | const matrix = require('../matrix'); |
9 | 9 | ||
10 | const HTTP_TIMEOUT = Number( | 10 | const HTTP_TIMEOUT = Number( |
11 | config.callback_sender && config.callback_sender.http_timeout_ms, | 11 | config.callback_sender && config.callback_sender.http_timeout_ms, |
12 | ) || 30 * 1000; | 12 | ) || 30 * 1000; |
13 | 13 | ||
14 | const SLEEP_BEFORE_RETRY_MS = Number( | 14 | const SLEEP_BEFORE_RETRY_MS = Number( |
15 | config.callback_sender && config.callback_sender.sleep_before_retry_ms, | 15 | config.callback_sender && config.callback_sender.sleep_before_retry_ms, |
16 | ) || 10 * 1000; | 16 | ) || 10 * 1000; |
17 | 17 | ||
18 | const MAX_RETRY = Number( | 18 | const MAX_RETRY = Number( |
19 | config.callback_sender && config.callback_sender.max_retry, | 19 | config.callback_sender && config.callback_sender.max_retry, |
20 | ) || 10; | 20 | ) || 10; |
21 | 21 | ||
22 | logger.verbose(`${MODULE_NAME} 848B9104: Initialized`, { | 22 | logger.verbose(`${MODULE_NAME} 848B9104: Initialized`, { |
23 | HTTP_TIMEOUT, | 23 | HTTP_TIMEOUT, |
24 | SLEEP_BEFORE_RETRY_MS, | 24 | SLEEP_BEFORE_RETRY_MS, |
25 | MAX_RETRY, | 25 | MAX_RETRY, |
26 | }); | 26 | }); |
27 | 27 | ||
28 | const axiosHeaders = { | 28 | const axiosHeaders = { |
29 | 'Content-Type': 'application/json', | 29 | 'Content-Type': 'application/json', |
30 | 'User-Agent': 'KOMODO-HTTPGETX callback sender', | 30 | 'User-Agent': 'KOMODO-HTTPGETX callback sender', |
31 | }; | 31 | }; |
32 | 32 | ||
33 | const sleep = require('../sleep'); | 33 | const sleep = require('../sleep'); |
34 | const urlConcatQs = require('../url-concat-qs'); | 34 | const urlConcatQs = require('../url-concat-qs'); |
35 | 35 | ||
36 | const sender = async (data, xid, retry) => { | 36 | const sender = async (data, xid, retry) => { |
37 | if (!data.reverse_url) { | 37 | if (!data.reverse_url) { |
38 | logger.verbose(`${MODULE_NAME} C4FF18FB: Ignoring missing reverse url`, { | 38 | logger.verbose(`${MODULE_NAME} C4FF18FB: Ignoring missing reverse url`, { |
39 | xid, | 39 | xid, |
40 | dataFromCore: data, | 40 | dataFromCore: data, |
41 | }); | 41 | }); |
42 | 42 | ||
43 | return; | 43 | return; |
44 | } | 44 | } |
45 | 45 | ||
46 | const params = { | 46 | const params = { |
47 | httpgetx_xid: xid, | 47 | httpgetx_xid: xid, |
48 | command: data.command, | 48 | command: data.command, |
49 | 49 | ||
50 | request_id: data.request_id && data.request_id.toString(), | 50 | request_id: data.request_id && data.request_id.toString(), |
51 | transaction_id: data.transaction_id && data.transaction_id.toString(), | 51 | transaction_id: data.transaction_id && data.transaction_id.toString(), |
52 | transaction_date: data.transaction_date, | 52 | transaction_date: data.transaction_date, |
53 | 53 | ||
54 | store_name: data.store_name, | 54 | store_name: data.store_name, |
55 | terminal_name: data.terminal_name, | 55 | terminal_name: data.terminal_name, |
56 | 56 | ||
57 | product_name: data.product_name, | 57 | product_name: data.product_name, |
58 | destination: data.destination, | 58 | destination: data.destination, |
59 | 59 | ||
60 | rc: data.rc, | 60 | rc: data.rc, |
61 | sn: data.sn || undefined, | 61 | sn: data.sn || undefined, |
62 | amount: Number(data.amount) || undefined, | 62 | amount: Number(data.amount) || undefined, |
63 | ending_balance: Number(data.ending_balance) || undefined, | 63 | ending_balance: Number(data.ending_balance) || undefined, |
64 | 64 | ||
65 | message: data.message, | 65 | message: data.message, |
66 | 66 | ||
67 | bill_count: Number(data.bill_count) || undefined, | 67 | bill_count: Number(data.bill_count) || undefined, |
68 | bill_amount: Number(data.bill_amount) || undefined, | 68 | bill_amount: Number(data.bill_amount) || undefined, |
69 | fee_per_bill: Number(data.fee) || undefined, | 69 | fee_per_bill: Number(data.fee) || undefined, |
70 | fee_total: Number(data.fee_total) || undefined, | 70 | fee_total: Number(data.fee_total) || undefined, |
71 | 71 | ||
72 | bill_detail: data.bill_detail || undefined, | 72 | bill_detail: data.bill_detail || undefined, |
73 | struk: data.struk || undefined, | 73 | struk: data.struk || undefined, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | if (data.command === 'INQUIRY' && data.amount_to_charge) { | 76 | if (data.command === 'INQUIRY' && data.amount_to_charge) { |
77 | params.amount_to_charge = data.amount_to_charge; | 77 | params.amount_to_charge = data.amount_to_charge; |
78 | } | 78 | } |
79 | 79 | ||
80 | const isPostpaid = ['INQUIRY', 'PAY'].indexOf(data.command) >= 0; | 80 | const isPostpaid = ['INQUIRY', 'PAY'].indexOf(data.command) >= 0; |
81 | const isHttpPost = isPostpaid; | 81 | const isHttpPost = isPostpaid; |
82 | 82 | ||
83 | const endpointUrl = isHttpPost ? data.reverse_url : urlConcatQs(data.reverse_url, params); | 83 | const endpointUrl = isHttpPost ? data.reverse_url : urlConcatQs(data.reverse_url, params); |
84 | 84 | ||
85 | logger.info(`${MODULE_NAME} 8B6A4CEC: Sending to PARTNER`, { | 85 | logger.info(`${MODULE_NAME} 8B6A4CEC: Sending to PARTNER`, { |
86 | xid, | 86 | xid, |
87 | retry: retry || 0, | 87 | retry: retry || 0, |
88 | isPostpaid, | 88 | isPostpaid, |
89 | isHttpPost, | 89 | isHttpPost, |
90 | endpointUrl, | 90 | endpointUrl, |
91 | }); | 91 | }); |
92 | 92 | ||
93 | let responseToDump; | 93 | let responseToDump; |
94 | let errorResponseToDump; | 94 | let errorResponseToDump; |
95 | 95 | ||
96 | try { | 96 | try { |
97 | const response = isHttpPost | 97 | const response = isHttpPost |
98 | ? await axios.post(data.reverse_url, params, { | 98 | ? await axios.post(data.reverse_url, params, { |
99 | timeout: HTTP_TIMEOUT, | 99 | timeout: HTTP_TIMEOUT, |
100 | headers: axiosHeaders, | 100 | headers: axiosHeaders, |
101 | }) | 101 | }) |
102 | : await axios.get(data.reverse_url, { | 102 | : await axios.get(data.reverse_url, { |
103 | params, | 103 | params, |
104 | timeout: HTTP_TIMEOUT, | 104 | timeout: HTTP_TIMEOUT, |
105 | headers: axiosHeaders, | 105 | headers: axiosHeaders, |
106 | }); | 106 | }); |
107 | 107 | ||
108 | responseToDump = response; | 108 | responseToDump = response; |
109 | 109 | ||
110 | matrix.callback_sender.sent += 1; | 110 | matrix.callback_sender.sent += 1; |
111 | matrix.callback_sender.active_count += 1; | 111 | matrix.callback_sender.active_count += 1; |
112 | matrix.callback_sender.active_sending[xid] = { | 112 | matrix.callback_sender.active_sending[xid] = { |
113 | ts: new Date(), | 113 | ts: new Date(), |
114 | trxId: data.trx_id, | 114 | trxId: data.trx_id, |
115 | reverseUrl: data.reverse_url, | 115 | reverseUrl: data.reverse_url, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | if (isPostpaid) { | 118 | if (isPostpaid) { |
119 | matrix.callback_sender.sent_using_post += 1; | 119 | matrix.callback_sender.sent_using_post += 1; |
120 | } else { | 120 | } else { |
121 | matrix.callback_sender.sent_using_get += 1; | 121 | matrix.callback_sender.sent_using_get += 1; |
122 | } | 122 | } |
123 | 123 | ||
124 | logger.info(`${MODULE_NAME} 3641FBD7: Has been sent to PARTNER successfully`, { | 124 | logger.info(`${MODULE_NAME} 3641FBD7: Has been sent to PARTNER successfully`, { |
125 | xid, | 125 | xid, |
126 | retry, | 126 | retry, |
127 | httpStatus: response.status, | 127 | httpStatus: response.status, |
128 | responseBody: response && response.data, | 128 | responseBody: response && response.data, |
129 | }); | 129 | }); |
130 | } catch (e) { | 130 | } catch (e) { |
131 | matrix.callback_sender.sent_failed += 1; | 131 | matrix.callback_sender.sent_failed += 1; |
132 | matrix.callback_sender.last_error = { | 132 | matrix.callback_sender.last_error = { |
133 | xid, | 133 | xid, |
134 | ts: new Date(), | 134 | ts: new Date(), |
135 | eCode: e.code, | 135 | eCode: e.code, |
136 | eMessage: e.message, | 136 | eMessage: e.message, |
137 | trxId: data.trx_id, | 137 | trxId: data.trx_id, |
138 | reverseUrl: data.reverse_url, | 138 | reverseUrl: data.reverse_url, |
139 | httpStatus: e.response && e.response.status, | 139 | httpStatus: e.response && e.response.status, |
140 | responseBody: e.response && e.response.data, | 140 | responseBody: e.response && e.response.data, |
141 | }; | 141 | }; |
142 | 142 | ||
143 | responseToDump = e.response && e.response.data; | 143 | responseToDump = e.response && e.response.data; |
144 | errorResponseToDump = e; | 144 | errorResponseToDump = e; |
145 | 145 | ||
146 | logger.warn(`${MODULE_NAME} A1EC9E70: Failed on sending to PARTNER`, { | 146 | logger.warn(`${MODULE_NAME} A1EC9E70: Failed on sending to PARTNER`, { |
147 | xid, | 147 | xid, |
148 | retry, | 148 | retry, |
149 | maxRetry: MAX_RETRY, | 149 | maxRetry: MAX_RETRY, |
150 | errCode: e.code, | 150 | errCode: e.code, |
151 | errMessage: e.message, | 151 | errMessage: e.message, |
152 | reverseUrl: data.reverse_url, | 152 | reverseUrl: data.reverse_url, |
153 | endpointUrl, | 153 | endpointUrl, |
154 | httpStatus: e.response && e.response.status, | 154 | httpStatus: e.response && e.response.status, |
155 | responseBody: e.response && e.response.data, | 155 | responseBody: e.response && e.response.data, |
156 | }); | 156 | }); |
157 | 157 | ||
158 | if (e.response && e.response.status) { | 158 | if (e.response && e.response.status) { |
159 | logger.verbose(`${MODULE_NAME} 10AE785C: Skip retry on http status presence`, { | 159 | logger.verbose(`${MODULE_NAME} 10AE785C: Skip retry on http status presence`, { |
160 | xid, | 160 | xid, |
161 | httpStatus: e.response && e.response.status, | 161 | httpStatus: e.response && e.response.status, |
162 | }); | 162 | }); |
163 | return; | 163 | return; |
164 | } | 164 | } |
165 | 165 | ||
166 | if ((retry || 0) < MAX_RETRY) { | 166 | if ((retry || 0) < MAX_RETRY) { |
167 | await sleep(SLEEP_BEFORE_RETRY_MS); | 167 | await sleep(SLEEP_BEFORE_RETRY_MS); |
168 | 168 | ||
169 | logger.verbose(`${MODULE_NAME} D8958695: Going to retry sending CORE-CALLBACK TO PARTNER`, { | 169 | logger.verbose(`${MODULE_NAME} D8958695: Going to retry sending CORE-CALLBACK TO PARTNER`, { |
170 | xid, | 170 | xid, |
171 | retried: retry, | 171 | retried: retry, |
172 | sleepTime: SLEEP_BEFORE_RETRY_MS, | 172 | sleepTime: SLEEP_BEFORE_RETRY_MS, |
173 | }); | 173 | }); |
174 | 174 | ||
175 | sender(data, xid, (retry || 0) + 1); | 175 | sender(data, xid, (retry || 0) + 1); |
176 | } | 176 | } |
177 | } finally { | 177 | } finally { |
178 | matrix.callback_sender.active_count -= 1; | 178 | matrix.callback_sender.active_count -= 1; |
179 | if (matrix.callback_sender.active_sending[xid]) { | 179 | if (matrix.callback_sender.active_sending[xid]) { |
180 | delete matrix.callback_sender.active_sending[xid]; | 180 | delete matrix.callback_sender.active_sending[xid]; |
181 | } | 181 | } |
182 | 182 | ||
183 | if (config.listener.partner.webhook) { | ||
184 | try { | ||
185 | axios.post(config.listener.partner.webhook, { | ||
186 | webhookType: 'KOMODO-CENTER-HTTPGETX.CORE-CALLBACK', | ||
187 | body: params, | ||
188 | }); | ||
189 | } catch (e) { | ||
190 | logger.warn(`${MODULE_NAME} F722520A: Exception on calling webhook`, { | ||
191 | xid, | ||
192 | eCode: e.code, | ||
193 | eMessage: e.message || e.toString(), | ||
194 | }); | ||
195 | } | ||
196 | } | ||
197 | |||
183 | dumper( | 198 | dumper( |
184 | xid, | 199 | xid, |
185 | isHttpPost ? 'POST' : 'GET', | 200 | isHttpPost ? 'POST' : 'GET', |
186 | endpointUrl, | 201 | endpointUrl, |
187 | params, | 202 | params, |
188 | responseToDump, | 203 | responseToDump, |
189 | errorResponseToDump, | 204 | errorResponseToDump, |
190 | ); | 205 | ); |
191 | } | 206 | } |
192 | }; | 207 | }; |
193 | 208 | ||
194 | module.exports = sender; | 209 | module.exports = sender; |
195 | 210 |
lib/partner-listener/routers/topup.js
1 | const MODULE_NAME = 'PARTNER-LISTENER.ROUTER.TOPUP'; | 1 | const MODULE_NAME = 'PARTNER-LISTENER.ROUTER.TOPUP'; |
2 | 2 | ||
3 | const express = require('express'); | 3 | const express = require('express'); |
4 | const axios = require('axios'); | ||
4 | 5 | ||
5 | const config = require('komodo-sdk/config'); | 6 | const config = require('komodo-sdk/config'); |
6 | const logger = require('tektrans-logger'); | 7 | const logger = require('tektrans-logger'); |
7 | const coreapi = require('komodo-sdk/coreapi'); | 8 | const coreapi = require('komodo-sdk/coreapi'); |
8 | // const coreapi = require('../../coreapi'); | 9 | // const coreapi = require('../../coreapi'); |
9 | const matrix = require('../../matrix'); | 10 | const matrix = require('../../matrix'); |
10 | const dumper = require('../dumper'); | 11 | const dumper = require('../dumper'); |
11 | 12 | ||
12 | const router = express.Router(); | 13 | const router = express.Router(); |
13 | module.exports = router; | 14 | module.exports = router; |
14 | 15 | ||
15 | const terminalsWithLocation = Array.isArray(config.terminals_with_location) | 16 | const terminalsWithLocation = Array.isArray(config.terminals_with_location) |
16 | ? config.terminals_with_location | 17 | ? config.terminals_with_location |
17 | .filter((item) => typeof item === 'string') | 18 | .filter((item) => typeof item === 'string') |
18 | .map((item) => (item.trim().toLowerCase())) | 19 | .map((item) => (item.trim().toLowerCase())) |
19 | : []; | 20 | : []; |
20 | 21 | ||
21 | function onInvalidParameter(missingParameter, req, res) { | 22 | function onInvalidParameter(missingParameter, req, res) { |
22 | logger.verbose(`${MODULE_NAME} 1536D577: Undefined ${missingParameter} parameter`, { | 23 | logger.verbose(`${MODULE_NAME} 1536D577: Undefined ${missingParameter} parameter`, { |
23 | xid: res.locals.xid, | 24 | xid: res.locals.xid, |
24 | ip: req.ip, | 25 | ip: req.ip, |
25 | terminal_name: req.body.terminal_name || req.query.terminal_name, | 26 | terminal_name: req.body.terminal_name || req.query.terminal_name, |
26 | request_id: req.body.request_id || req.query.request_id, | 27 | request_id: req.body.request_id || req.query.request_id, |
27 | product_name: req.body.product_name || req.query.product_name, | 28 | product_name: req.body.product_name || req.query.product_name, |
28 | destination: req.body.destination || req.query.destination, | 29 | destination: req.body.destination || req.query.destination, |
29 | }); | 30 | }); |
30 | res.end('INVALID REQUEST'); | 31 | res.end('INVALID REQUEST'); |
31 | } | 32 | } |
32 | 33 | ||
33 | function pagePrerequisite(req, res, next) { | 34 | function pagePrerequisite(req, res, next) { |
34 | if (!req.body) req.body = {}; | 35 | if (!req.body) req.body = {}; |
35 | 36 | ||
36 | const terminalName = req.body.terminal_name || req.query.terminal_name; | 37 | const terminalName = req.body.terminal_name || req.query.terminal_name; |
37 | if (!terminalName || typeof terminalName !== 'string') { | 38 | if (!terminalName || typeof terminalName !== 'string') { |
38 | onInvalidParameter('terminal_name', req, res); | 39 | onInvalidParameter('terminal_name', req, res); |
39 | return; | 40 | return; |
40 | } | 41 | } |
41 | 42 | ||
42 | if (!req.body.password && !req.query.password) { | 43 | if (!req.body.password && !req.query.password) { |
43 | onInvalidParameter('password', req, res); | 44 | onInvalidParameter('password', req, res); |
44 | return; | 45 | return; |
45 | } | 46 | } |
46 | 47 | ||
47 | if (!req.body.request_id && !req.query.request_id) { | 48 | if (!req.body.request_id && !req.query.request_id) { |
48 | onInvalidParameter('request_id', req, res); | 49 | onInvalidParameter('request_id', req, res); |
49 | return; | 50 | return; |
50 | } | 51 | } |
51 | 52 | ||
52 | if (!req.body.product_name && !req.query.product_name) { | 53 | if (!req.body.product_name && !req.query.product_name) { |
53 | onInvalidParameter('product_name', req, res); | 54 | onInvalidParameter('product_name', req, res); |
54 | return; | 55 | return; |
55 | } | 56 | } |
56 | 57 | ||
57 | if (!req.body.destination && !req.query.destination) { | 58 | if (!req.body.destination && !req.query.destination) { |
58 | onInvalidParameter('destination', req, res); | 59 | onInvalidParameter('destination', req, res); |
59 | return; | 60 | return; |
60 | } | 61 | } |
61 | 62 | ||
62 | next(); | 63 | next(); |
63 | } | 64 | } |
64 | 65 | ||
65 | async function pageIndex(req, res) { | 66 | async function pageIndex(req, res) { |
66 | const { xid } = res.locals; | 67 | const { xid } = res.locals; |
67 | 68 | ||
68 | const terminalNameWithoutIp = ((req.body.terminal_name || req.query.terminal_name) || '').trim(); | 69 | const terminalNameWithoutIp = ((req.body.terminal_name || req.query.terminal_name) || '').trim(); |
69 | const terminalName = `${terminalNameWithoutIp}@${req.ip.replace(/^::ffff:/, '')}`; | 70 | const terminalName = `${terminalNameWithoutIp}@${req.ip.replace(/^::ffff:/, '')}`; |
70 | 71 | ||
71 | const qs = { | 72 | const qs = { |
72 | terminal_name: terminalName, | 73 | terminal_name: terminalName, |
73 | password: req.body.password || req.query.password, | 74 | password: req.body.password || req.query.password, |
74 | request_id: req.body.request_id || req.query.request_id, | 75 | request_id: req.body.request_id || req.query.request_id, |
75 | product_name: req.body.product_name || req.query.product_name, | 76 | product_name: req.body.product_name || req.query.product_name, |
76 | destination: req.body.destination || req.query.destination, | 77 | destination: req.body.destination || req.query.destination, |
77 | origin: config.name || 'HTTPGETX', | 78 | origin: config.name || 'HTTPGETX', |
78 | report_ip: config.listener.core.ip || null, | 79 | report_ip: config.listener.core.ip || null, |
79 | report_port: config.listener.core.port, | 80 | report_port: config.listener.core.port, |
80 | reverse_url: req.body.reverse_url || req.query.reverse_url || null, | 81 | reverse_url: req.body.reverse_url || req.query.reverse_url || null, |
81 | }; | 82 | }; |
82 | 83 | ||
83 | if (terminalsWithLocation.indexOf(terminalNameWithoutIp.toLowerCase()) >= 0) { | 84 | if (terminalsWithLocation.indexOf(terminalNameWithoutIp.toLowerCase()) >= 0) { |
84 | const location = req.body.location | 85 | const location = req.body.location |
85 | || req.body.location_id | 86 | || req.body.location_id |
86 | || req.query.location | 87 | || req.query.location |
87 | || req.query.location_id; | 88 | || req.query.location_id; |
88 | 89 | ||
89 | if (location) { | 90 | if (location) { |
90 | logger.verbose(`${MODULE_NAME} 5C41FBFA: Including location from partner request`, { | 91 | logger.verbose(`${MODULE_NAME} 5C41FBFA: Including location from partner request`, { |
91 | xid, | 92 | xid, |
92 | terminalName, | 93 | terminalName, |
93 | location, | 94 | location, |
94 | }); | 95 | }); |
95 | 96 | ||
96 | qs.location = location; | 97 | qs.location = location; |
97 | } | 98 | } |
98 | } | 99 | } |
99 | 100 | ||
100 | matrix.core.sent += 1; | 101 | matrix.core.sent += 1; |
101 | 102 | ||
102 | const [err, coreResponse] = await coreapi({ | 103 | const [err, coreResponse] = await coreapi({ |
103 | xid, | 104 | xid, |
104 | path: '/prepaid/buy', | 105 | path: '/prepaid/buy', |
105 | qs, | 106 | qs, |
106 | }); | 107 | }); |
107 | 108 | ||
108 | if (err || !coreResponse) { | 109 | if (err || !coreResponse) { |
109 | matrix.core.sent_failed += 1; | 110 | matrix.core.sent_failed += 1; |
110 | matrix.core.last_error = { | 111 | matrix.core.last_error = { |
111 | xid, | 112 | xid, |
112 | ts: new Date(), | 113 | ts: new Date(), |
113 | e: err, | 114 | e: err, |
114 | eCode: err.code, | 115 | eCode: err.code, |
115 | eMessage: err.message, | 116 | eMessage: err.message, |
116 | }; | 117 | }; |
117 | 118 | ||
118 | logger.warn(`${MODULE_NAME} 8DEBE15F: ERROR on /prepaid/buy response`, { | 119 | logger.warn(`${MODULE_NAME} 8DEBE15F: ERROR on /prepaid/buy response`, { |
119 | xid, | 120 | xid, |
120 | err, | 121 | err, |
121 | coreResponseTypeof: typeof coreResponse, | 122 | coreResponseTypeof: typeof coreResponse, |
122 | coreResponse, | 123 | coreResponse, |
123 | }); | 124 | }); |
124 | res.end('INVALID CORE RESPONSE'); | 125 | res.end('INVALID CORE RESPONSE'); |
125 | 126 | ||
126 | dumper(xid, req, 'INVALID CORE RESPONSE'); | 127 | dumper(xid, req, 'INVALID CORE RESPONSE'); |
127 | return; | 128 | return; |
128 | } | 129 | } |
129 | 130 | ||
130 | logger.verbose(`${MODULE_NAME} 2528A9B4: Got CORE response`, { | 131 | logger.verbose(`${MODULE_NAME} 2528A9B4: Got CORE response`, { |
131 | xid, | 132 | xid, |
132 | coreResponse, | 133 | coreResponse, |
133 | }); | 134 | }); |
134 | 135 | ||
135 | const responseToPartner = { | 136 | const responseToPartner = { |
136 | httpgetx_xid: xid, | 137 | httpgetx_xid: xid, |
137 | request_id: coreResponse.request_id, | 138 | request_id: coreResponse.request_id, |
138 | transaction_id: coreResponse.transaction_id, | 139 | transaction_id: coreResponse.transaction_id, |
139 | transaction_date: coreResponse.transaction_date, | 140 | transaction_date: coreResponse.transaction_date, |
140 | store_name: coreResponse.store_name, | 141 | store_name: coreResponse.store_name, |
141 | terminal_name: coreResponse.terminal_name, | 142 | terminal_name: coreResponse.terminal_name, |
142 | product_name: coreResponse.product_name, | 143 | product_name: coreResponse.product_name, |
143 | destination: coreResponse.destination, | 144 | destination: coreResponse.destination, |
144 | rc: coreResponse.rc, | 145 | rc: coreResponse.rc, |
145 | sn: coreResponse.sn || undefined, | 146 | sn: coreResponse.sn || undefined, |
146 | amount: Number(coreResponse.amount) || undefined, | 147 | amount: Number(coreResponse.amount) || undefined, |
147 | ending_balance: Number(coreResponse.ending_balance) || undefined, | 148 | ending_balance: Number(coreResponse.ending_balance) || undefined, |
148 | message: coreResponse.message, | 149 | message: coreResponse.message, |
149 | }; | 150 | }; |
150 | 151 | ||
151 | res.json(responseToPartner); | 152 | res.json(responseToPartner); |
153 | |||
154 | if (config.listener.partner.webhook) { | ||
155 | try { | ||
156 | axios.post(config.listener.partner.webhook, { | ||
157 | webhookType: 'KOMODO-CENTER-HTTPGETX.PARTNER-LISTENER.DIRECT-RESPONSE', | ||
158 | body: responseToPartner, | ||
159 | }); | ||
160 | } catch (e) { | ||
161 | logger.warn(`${MODULE_NAME} ECC37ECA: Exception on calling webhook`, { | ||
162 | xid, | ||
163 | eCode: e.code, | ||
164 | eMessage: e.message || e.toString(), | ||
165 | }); | ||
166 | } | ||
167 | } | ||
168 | |||
152 | dumper(xid, req, responseToPartner); | 169 | dumper(xid, req, responseToPartner); |
153 | } | 170 | } |
154 | 171 | ||
155 | // router.all('/', (req, res) => { res.status(404).end('404: Not implemented yet'); }); | 172 | // router.all('/', (req, res) => { res.status(404).end('404: Not implemented yet'); }); |
156 | router.get('/', pagePrerequisite, pageIndex); | 173 | router.get('/', pagePrerequisite, pageIndex); |
157 | 174 |