Commit a9aef2698af6df3b6134632af50b65f7d08afe62
1 parent
432f85471d
Exists in
master
Separate webhook sender
Showing 6 changed files with 123 additions and 80 deletions Side-by-side Diff
config.sample.json
... | ... | @@ -8,7 +8,6 @@ |
8 | 8 | "partner": { |
9 | 9 | "trust_proxy": ["loopback", "linklocal"], |
10 | 10 | "port": 25614, |
11 | - "# webhook": "http://PLEASE_CHANGE_ME/PLEASE_CHANGE_ME", | |
12 | 11 | "dump": false |
13 | 12 | }, |
14 | 13 | "core": { |
... | ... | @@ -27,6 +26,11 @@ |
27 | 26 | "max_retry": 10 |
28 | 27 | }, |
29 | 28 | |
29 | + "webhook": { | |
30 | + "url": null, | |
31 | + "dump": false | |
32 | + }, | |
33 | + | |
30 | 34 | "terminals_with_location": [], |
31 | 35 | |
32 | 36 | "# cluster": "Isi dengan boolean atau angka jumlah anak yang akan dibuat. Jika diisi boolean true, jumlah anak akan dihitung otomatis", |
lib/core-callback/sender.js
... | ... | @@ -7,6 +7,8 @@ const logger = require('tektrans-logger'); |
7 | 7 | const dumper = require('./dumper/sender'); |
8 | 8 | const matrix = require('../matrix'); |
9 | 9 | |
10 | +const webhookSender = require('../webhook-sender'); | |
11 | + | |
10 | 12 | const HTTP_TIMEOUT = Number( |
11 | 13 | config.callback_sender && config.callback_sender.http_timeout_ms, |
12 | 14 | ) || 30 * 1000; |
... | ... | @@ -180,45 +182,6 @@ const sender = async (data, xid, retry) => { |
180 | 182 | delete matrix.callback_sender.active_sending[xid]; |
181 | 183 | } |
182 | 184 | |
183 | - if (config.listener.partner.webhook) { | |
184 | - try { | |
185 | - const webhookType = 'KOMODO-CENTER-HTTPGETX.CORE-CALLBACK'; | |
186 | - | |
187 | - logger.verbose(`${MODULE_NAME} E21E3DC6: Sending webhook`, { | |
188 | - xid, | |
189 | - webhookType, | |
190 | - partner: config.listener.partner.webhook, | |
191 | - trxId: data.transaction_id && data.transaction_id.toString(), | |
192 | - request_id: data.request_id && data.request_id.toString(), | |
193 | - product_name: data.product_name, | |
194 | - destination: data.destination, | |
195 | - rc: data.rc, | |
196 | - }); | |
197 | - | |
198 | - axios.post(config.listener.partner.webhook, { | |
199 | - webhookType: 'KOMODO-CENTER-HTTPGETX.CORE-CALLBACK', | |
200 | - body: params, | |
201 | - }); | |
202 | - | |
203 | - logger.verbose(`${MODULE_NAME} 26BCA07F: Webhook sent`, { | |
204 | - xid, | |
205 | - webhookType, | |
206 | - partner: config.listener.partner.webhook, | |
207 | - trxId: data.transaction_id && data.transaction_id.toString(), | |
208 | - request_id: data.request_id && data.request_id.toString(), | |
209 | - product_name: data.product_name, | |
210 | - destination: data.destination, | |
211 | - rc: data.rc, | |
212 | - }); | |
213 | - } catch (e) { | |
214 | - logger.warn(`${MODULE_NAME} F722520A: Exception on calling webhook`, { | |
215 | - xid, | |
216 | - eCode: e.code, | |
217 | - eMessage: e.message || e.toString(), | |
218 | - }); | |
219 | - } | |
220 | - } | |
221 | - | |
222 | 185 | dumper( |
223 | 186 | xid, |
224 | 187 | isHttpPost ? 'POST' : 'GET', |
... | ... | @@ -227,6 +190,9 @@ const sender = async (data, xid, retry) => { |
227 | 190 | responseToDump, |
228 | 191 | errorResponseToDump, |
229 | 192 | ); |
193 | + | |
194 | + const webhookType = 'KOMODO-CENTER-HTTPGETX.CORE-CALLBACK'; | |
195 | + webhookSender(xid, webhookType, params); | |
230 | 196 | } |
231 | 197 | }; |
232 | 198 |
lib/partner-listener/routers/topup.js
1 | 1 | const MODULE_NAME = 'PARTNER-LISTENER.ROUTER.TOPUP'; |
2 | 2 | |
3 | 3 | const express = require('express'); |
4 | -const axios = require('axios'); | |
5 | 4 | |
6 | 5 | const config = require('komodo-sdk/config'); |
7 | 6 | const logger = require('tektrans-logger'); |
... | ... | @@ -9,6 +8,7 @@ const coreapi = require('komodo-sdk/coreapi'); |
9 | 8 | // const coreapi = require('../../coreapi'); |
10 | 9 | const matrix = require('../../matrix'); |
11 | 10 | const dumper = require('../dumper'); |
11 | +const webhookSender = require('../../webhook-sender'); | |
12 | 12 | |
13 | 13 | const router = express.Router(); |
14 | 14 | module.exports = router; |
... | ... | @@ -151,40 +151,10 @@ async function pageIndex(req, res) { |
151 | 151 | |
152 | 152 | res.json(responseToPartner); |
153 | 153 | |
154 | - if (config.listener.partner.webhook) { | |
155 | - try { | |
156 | - const webhookType = 'KOMODO-CENTER-HTTPGETX.PARTNER-LISTENER.DIRECT-RESPONSE'; | |
157 | - | |
158 | - logger.verbose(`${MODULE_NAME} 2CA59ED3: Sending webhook`, { | |
159 | - xid, | |
160 | - webhookType, | |
161 | - partner: config.listener.partner.webhook, | |
162 | - trxId: coreResponse.transaction_id, | |
163 | - request_id: req.body.request_id || req.query.request_id, | |
164 | - }); | |
165 | - | |
166 | - axios.post(config.listener.partner.webhook, { | |
167 | - webhookType, | |
168 | - body: responseToPartner, | |
169 | - }); | |
170 | - | |
171 | - logger.verbose(`${MODULE_NAME} 50BE8D98: Webhook sent`, { | |
172 | - xid, | |
173 | - webhookType, | |
174 | - partner: config.listener.partner.webhook, | |
175 | - trxId: coreResponse.transaction_id, | |
176 | - request_id: req.body.request_id || req.query.request_id, | |
177 | - }); | |
178 | - } catch (e) { | |
179 | - logger.warn(`${MODULE_NAME} ECC37ECA: Exception on calling webhook`, { | |
180 | - xid, | |
181 | - eCode: e.code, | |
182 | - eMessage: e.message || e.toString(), | |
183 | - }); | |
184 | - } | |
185 | - } | |
186 | - | |
187 | 154 | dumper(xid, req, responseToPartner); |
155 | + | |
156 | + const webhookType = 'KOMODO-CENTER-HTTPGETX.PARTNER-LISTENER.DIRECT-RESPONSE'; | |
157 | + webhookSender(xid, webhookType, responseToPartner); | |
188 | 158 | } |
189 | 159 | |
190 | 160 | // router.all('/', (req, res) => { res.status(404).end('404: Not implemented yet'); }); |
lib/webhook-sender.js
... | ... | @@ -0,0 +1,89 @@ |
1 | +const MODULE_NAME = 'WEBHOOK-SENDER'; | |
2 | + | |
3 | +const axios = require('axios'); | |
4 | +const moment = require('moment'); | |
5 | +const fs = require('fs'); | |
6 | +const path = require('path'); | |
7 | +const stringify = require('json-stringify-pretty-compact'); | |
8 | +const config = require('komodo-sdk/config'); | |
9 | +const logger = require('tektrans-logger'); | |
10 | + | |
11 | +const DEFAULT_MAX_RETRY = 10; | |
12 | +const DEFAULT_SLEEP_BEFORE_RETRY_MS = 10 * 1000; | |
13 | + | |
14 | +const maxRetry = Number(config.webhook && config.webhook.max_retry) | |
15 | + || DEFAULT_MAX_RETRY; | |
16 | +const sleepBeforeRetryMs = Number(config.webhook && config.webhook.sleep_before_retry_ms) | |
17 | + || DEFAULT_SLEEP_BEFORE_RETRY_MS; | |
18 | + | |
19 | +const baseDumpDir = path.join('dump', 'webhook-sender'); | |
20 | +if (!fs.existsSync(baseDumpDir)) { | |
21 | + fs.mkdirSync(baseDumpDir, { recursive: true }); | |
22 | +} | |
23 | +const lastDumpFileName = path.join(baseDumpDir, 'last'); | |
24 | + | |
25 | +const dumper = async (xid, webhookType, body) => { | |
26 | + if (!config.webhook || !config.webhook.dump) { | |
27 | + return; | |
28 | + } | |
29 | + | |
30 | + await fs.promises.writeFile( | |
31 | + path.join(baseDumpDir, [moment().format('YYYYMMDD-HHmmssSSS'), xid].join('_')), | |
32 | + stringify({ webhookType, body }), | |
33 | + ); | |
34 | + | |
35 | + await fs.promises.writeFile( | |
36 | + lastDumpFileName, | |
37 | + stringify({ webhookType, body }), | |
38 | + ); | |
39 | +}; | |
40 | + | |
41 | +const sender = async (xid, webhookType, body, retry) => { | |
42 | + if (!config.webhook || !config.webhook.url) { | |
43 | + return; | |
44 | + } | |
45 | + | |
46 | + try { | |
47 | + logger.verbose(`${MODULE_NAME} 2CA59ED3: Sending webhook`, { | |
48 | + xid, | |
49 | + webhookType, | |
50 | + partner: config.webhook.url, | |
51 | + trxId: body.transaction_id, | |
52 | + request_id: body.request_id, | |
53 | + }); | |
54 | + | |
55 | + axios.post(config.listener.partner.webhook, { | |
56 | + webhookType, | |
57 | + body, | |
58 | + }); | |
59 | + | |
60 | + await dumper(xid, webhookType, body); | |
61 | + | |
62 | + logger.verbose(`${MODULE_NAME} 50BE8D98: Webhook sent`, { | |
63 | + xid, | |
64 | + webhookType, | |
65 | + partner: config.listener.partner.webhook, | |
66 | + }); | |
67 | + } catch (e) { | |
68 | + logger.warn(`${MODULE_NAME} ECC37ECA: Exception on calling webhook`, { | |
69 | + xid, | |
70 | + eCode: e.code, | |
71 | + eMessage: e.message || e.toString(), | |
72 | + retried: retry || 0, | |
73 | + maxRetry, | |
74 | + }); | |
75 | + | |
76 | + if ((retry || 0) >= maxRetry) { | |
77 | + logger.warn(`${MODULE_NAME} 4A60B406: Max retry exceeded`, { | |
78 | + xid, | |
79 | + }); | |
80 | + | |
81 | + return; | |
82 | + } | |
83 | + | |
84 | + setTimeout(() => { | |
85 | + sender(xid, webhookType, body, (retry || 0) + 1); | |
86 | + }, sleepBeforeRetryMs); | |
87 | + } | |
88 | +}; | |
89 | +module.exports = sender; |
package-lock.json
... | ... | @@ -13,6 +13,7 @@ |
13 | 13 | "express": "^4.17.1", |
14 | 14 | "express-rate-limit": "^6.6.0", |
15 | 15 | "join-path": "^1.1.1", |
16 | + "json-stringify-pretty-compact": "^4.0.0", | |
16 | 17 | "komodo-sdk": "^1.45.6", |
17 | 18 | "mkdirp": "^1.0.4", |
18 | 19 | "moment": "^2.24.0", |
... | ... | @@ -2087,9 +2088,10 @@ |
2087 | 2088 | "dev": true |
2088 | 2089 | }, |
2089 | 2090 | "node_modules/json-stringify-pretty-compact": { |
2090 | - "version": "3.0.0", | |
2091 | - "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", | |
2092 | - "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==" | |
2091 | + "version": "4.0.0", | |
2092 | + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz", | |
2093 | + "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==", | |
2094 | + "license": "MIT" | |
2093 | 2095 | }, |
2094 | 2096 | "node_modules/json-stringify-safe": { |
2095 | 2097 | "version": "5.0.1", |
... | ... | @@ -2148,6 +2150,12 @@ |
2148 | 2150 | "sd-notify": "^2.8.0" |
2149 | 2151 | } |
2150 | 2152 | }, |
2153 | + "node_modules/komodo-sdk/node_modules/json-stringify-pretty-compact": { | |
2154 | + "version": "3.0.0", | |
2155 | + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", | |
2156 | + "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==", | |
2157 | + "license": "MIT" | |
2158 | + }, | |
2151 | 2159 | "node_modules/komodo-sdk/node_modules/uniqid": { |
2152 | 2160 | "version": "4.1.1", |
2153 | 2161 | "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", |
... | ... | @@ -6327,9 +6335,9 @@ |
6327 | 6335 | "dev": true |
6328 | 6336 | }, |
6329 | 6337 | "json-stringify-pretty-compact": { |
6330 | - "version": "3.0.0", | |
6331 | - "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", | |
6332 | - "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==" | |
6338 | + "version": "4.0.0", | |
6339 | + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz", | |
6340 | + "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==" | |
6333 | 6341 | }, |
6334 | 6342 | "json-stringify-safe": { |
6335 | 6343 | "version": "5.0.1", |
... | ... | @@ -6383,6 +6391,11 @@ |
6383 | 6391 | "uuid": "^3.4.0" |
6384 | 6392 | }, |
6385 | 6393 | "dependencies": { |
6394 | + "json-stringify-pretty-compact": { | |
6395 | + "version": "3.0.0", | |
6396 | + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", | |
6397 | + "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==" | |
6398 | + }, | |
6386 | 6399 | "uniqid": { |
6387 | 6400 | "version": "4.1.1", |
6388 | 6401 | "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", |