diff --git a/index.js b/index.js
index 833540a..7665c35 100644
--- a/index.js
+++ b/index.js
@@ -28,5 +28,5 @@ if (config.cluster && cluster.isMaster) {
     // eslint-disable-next-line global-require
     require('./lib/core-callback');
     // eslint-disable-next-line global-require
-    require('./lib/listener-partner');
+    require('./lib/partner-listener');
 }
diff --git a/lib/listener-partner/index.js b/lib/listener-partner/index.js
deleted file mode 100644
index 36a087e..0000000
--- a/lib/listener-partner/index.js
+++ /dev/null
@@ -1,36 +0,0 @@
-const DEFAULT_LISTENER_FROM_PARTNER_PORT = 25614;
-
-const express = require('express');
-
-const config = require('komodo-sdk/config');
-const logger = require('komodo-sdk/logger');
-
-const middlewareCommon = require('../middlewares/common');
-
-const routerInquiry = require('./routers/inquiry');
-const routerPay = require('./routers/pay');
-const routerTopup = require('./routers/topup');
-const routerTrxStatus = require('./routers/trx-status');
-
-const app = express();
-
-app.use(express.json({ extended: true }));
-app.use(express.urlencoded({ extended: true }));
-app.use(middlewareCommon);
-
-app.use('/inquiry', routerInquiry);
-app.use('/pay', routerPay);
-app.use('/topup', routerTopup);
-app.use('/trx-status', routerTrxStatus);
-
-app.use((req, res) => {
-    const { xid } = res.locals;
-    res.status(404).end(`KOMODO-HTTP-GET-X CENTER.\n404: Method not found.\n\nXID: ${xid}.\n`);
-});
-
-app.listen(config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT, () => {
-    logger.info(`Listen from partner request on port ${config.listener.partner.port}`);
-}).on('error', (e) => {
-    logger.error(`Can not listen request from partner on port ${config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT}. ${e.toString()}`);
-    process.exit(1);
-});
diff --git a/lib/listener-partner/routers/inquiry.js b/lib/listener-partner/routers/inquiry.js
deleted file mode 100644
index b82341b..0000000
--- a/lib/listener-partner/routers/inquiry.js
+++ /dev/null
@@ -1,106 +0,0 @@
-const axios = require('axios').default;
-const express = require('express');
-const coreUrl = require('komodo-sdk/core-url');
-
-const config = require('komodo-sdk/config');
-const logger = require('komodo-sdk/logger');
-
-const getFromBodyQsParams = require('../../get-from-body-qs-params');
-const ipv6ToIpv4 = require('../../ipv6-to-ipv4');
-
-const router = express.Router();
-module.exports = router;
-
-const CORE_ENDPOINT = `${coreUrl}/postpaid2/inquiry`;
-
-const mainHandler = async (req, res) => {
-    const { xid } = res.locals;
-
-    const requestId = (getFromBodyQsParams(req, 'request_id') || '').toString().trim();
-    const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim();
-    const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`;
-    const productName = (getFromBodyQsParams(req, 'product_name') || '').trim().toUpperCase();
-    const destination = (getFromBodyQsParams(req, 'destination') || '').toString().trim();
-    const password = getFromBodyQsParams(req, 'password');
-    const reverseUrl = getFromBodyQsParams(req, 'reverse_url');
-
-    if (!requestId || !terminalNameWithoutIp || !productName || !destination) {
-        res.end('INVALID REQUEST. Missing request_id or terminal_name or product_name or destination.');
-        return;
-    }
-
-    const params = {
-        origin: config.name,
-        report_ip: config.listener.core.from_ip,
-        report_port: config.listener.core.port || 25614,
-        request_id: requestId,
-        terminal_name: terminalName,
-        product_name: productName,
-        destination,
-        terminal_password: password,
-        reverse_url: reverseUrl,
-    };
-
-    logger.info('Forwarding INQUIRY request to CORE', { xid, params });
-    try {
-        const result = await axios.get(CORE_ENDPOINT, {
-            params,
-            timeout: 10000,
-        });
-
-        if (!result || !result.data) {
-            const newError = new Error('8002EB0D: Empty CORE INQUIRY direct-response');
-            logger.warn(newError.message, { xid });
-            throw newError;
-        }
-
-        logger.verbose('Got INQUIRY direct-response from CORE', {
-            xid,
-            coreResponse: result.data,
-        });
-
-        const resultForPartner = {
-            httpgetx_xid: xid,
-            command: result.data.command,
-            request_id: result.data.request_id && result.data.request_id.toString(),
-            transaction_id: result.data.transaction_id && result.data.transaction_id.toString(),
-            transaction_date: result.data.transaction_date,
-            store_name: result.data.store_name,
-            terminal_name: result.data.terminal_name,
-            product_name: result.data.product_name,
-            destination: result.data.destination,
-            rc: result.data.rc,
-            sn: result.data.sn,
-            message: result.data.message,
-            amount: result.data.amount,
-            ending_balance: result.data.ending_balance,
-            amount_to_charge: result.data.amount_to_charge,
-        };
-
-        logger.verbose('Forwarding CORE direct-response to partner', {
-            xid,
-            resultForPartner,
-        });
-
-        res.json(resultForPartner);
-    } catch (e) {
-        logger.warn('EXCEPTION on forwarding INQUIRY request to CORE', {
-            xid,
-            errCode: e.code,
-            errMessage: e.message,
-        });
-
-        res.json({
-            httpgetx_xid: xid,
-            command: 'INQUIRY',
-            request_id: requestId,
-            terminal_name: terminalName,
-            product_name: productName,
-            destination,
-            rc: '68',
-            message: 'CORE tidak merespon dengan benar, tidak dapat mengetahui status request anda',
-        });
-    }
-};
-
-router.all('/', mainHandler);
diff --git a/lib/listener-partner/routers/pay.js b/lib/listener-partner/routers/pay.js
deleted file mode 100644
index 031f023..0000000
--- a/lib/listener-partner/routers/pay.js
+++ /dev/null
@@ -1,105 +0,0 @@
-const axios = require('axios').default;
-const express = require('express');
-const coreUrl = require('komodo-sdk/core-url');
-
-const config = require('komodo-sdk/config');
-const logger = require('komodo-sdk/logger');
-
-const getFromBodyQsParams = require('../../get-from-body-qs-params');
-const ipv6ToIpv4 = require('../../ipv6-to-ipv4');
-
-const router = express.Router();
-module.exports = router;
-
-const CORE_ENDPOINT = `${coreUrl}/postpaid2/pay`;
-
-const mainHandler = async (req, res) => {
-    const { xid } = res.locals;
-
-    const requestId = (getFromBodyQsParams(req, 'request_id') || '').toString().trim();
-    const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim();
-    const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`;
-    const productName = (getFromBodyQsParams(req, 'product_name') || '').trim().toUpperCase();
-    const destination = (getFromBodyQsParams(req, 'destination') || '').toString().trim();
-    const password = getFromBodyQsParams(req, 'password');
-    const reverseUrl = getFromBodyQsParams(req, 'reverse_url');
-
-    if (!requestId || !terminalNameWithoutIp || !productName || !destination) {
-        res.end('INVALID REQUEST. Missing request_id or terminal_name or product_name or destination.');
-        return;
-    }
-
-    const params = {
-        origin: config.name,
-        report_ip: config.listener.core.from_ip,
-        report_port: config.listener.core.port || 25614,
-        request_id: requestId,
-        terminal_name: terminalName,
-        product_name: productName,
-        destination,
-        terminal_password: password,
-        reverse_url: reverseUrl,
-    };
-
-    logger.info('Forwarding PAY request to CORE', { xid, params });
-    try {
-        const result = await axios.get(CORE_ENDPOINT, {
-            params,
-            timeout: 10000,
-        });
-
-        if (!result || !result.data) {
-            const newError = new Error('0D428E4C: Empty CORE PAY direct-response');
-            logger.warn(newError.message, { xid });
-            throw newError;
-        }
-
-        logger.verbose('Got PAY direct-response from CORE', {
-            xid,
-            coreResponse: result.data,
-        });
-
-        const resultForPartner = {
-            httpgetx_xid: xid,
-            command: result.data.command,
-            request_id: result.data.request_id && result.data.request_id.toString(),
-            transaction_id: result.data.transaction_id && result.data.transaction_id.toString(),
-            transaction_date: result.data.transaction_date,
-            store_name: result.data.store_name,
-            terminal_name: result.data.terminal_name,
-            product_name: result.data.product_name,
-            destination: result.data.destination,
-            rc: result.data.rc,
-            sn: result.data.sn,
-            message: result.data.message,
-            amount: result.data.amount,
-            ending_balance: result.data.ending_balance,
-        };
-
-        logger.verbose('Forwarding CORE PAY direct-response to partner', {
-            xid,
-            resultForPartner,
-        });
-
-        res.json(resultForPartner);
-    } catch (e) {
-        logger.warn('EXCEPTION on forwarding PAY request to CORE', {
-            xid,
-            errCode: e.code,
-            errMessage: e.message,
-        });
-
-        res.json({
-            httpgetx_xid: xid,
-            command: 'PAY',
-            request_id: requestId,
-            terminal_name: terminalName,
-            product_name: productName,
-            destination,
-            rc: '68',
-            message: 'CORE tidak merespon dengan benar, tidak dapat mengetahui status request anda',
-        });
-    }
-};
-
-router.all('/', mainHandler);
diff --git a/lib/listener-partner/routers/topup.js b/lib/listener-partner/routers/topup.js
deleted file mode 100644
index 28deb58..0000000
--- a/lib/listener-partner/routers/topup.js
+++ /dev/null
@@ -1,87 +0,0 @@
-const express = require('express');
-
-const config = require('komodo-sdk/config');
-const logger = require('komodo-sdk/logger');
-const coreapi = require('komodo-sdk/coreapi');
-// const coreapi = require('../../coreapi');
-
-const router = express.Router();
-module.exports = router;
-
-function onInvalidParameter(missingParameter, req, res) {
-    logger.verbose(`TOPUP: Undefined ${missingParameter} parameter`, {
-        xid: res.locals.xid,
-        ip: req.ip,
-        terminal_name: req.body.terminal_name || req.query.terminal_name,
-        request_id: req.body.request_id || req.query.request_id,
-        product_name: req.body.product_name || req.query.product_name,
-        destination: req.body.destination || req.query.destination,
-    });
-    res.end('INVALID REQUEST');
-}
-
-function pagePrerequisite(req, res, next) {
-    if (!req.body) req.body = {};
-
-    if (!req.body.terminal_name && !req.query.terminal_name) {
-        onInvalidParameter('terminal_name', req, res);
-        return;
-    }
-
-    if (!req.body.password && !req.query.password) {
-        onInvalidParameter('password', req, res);
-        return;
-    }
-
-    if (!req.body.request_id && !req.query.request_id) {
-        onInvalidParameter('request_id', req, res);
-        return;
-    }
-
-    if (!req.body.product_name && !req.query.product_name) {
-        onInvalidParameter('product_name', req, res);
-        return;
-    }
-
-    if (!req.body.destination && !req.query.destination) {
-        onInvalidParameter('destination', req, res);
-        return;
-    }
-
-    next();
-}
-
-async function pageIndex(req, res) {
-    const terminalName = `${req.body.terminal_name || req.query.terminal_name}@${req.ip.replace(/^::ffff:/, '')}`;
-
-    const [err, coreResponse] = await coreapi({
-        xid: res.locals.xid,
-        path: '/prepaid/buy',
-        qs: {
-            terminal_name: terminalName,
-            password: req.body.password || req.query.password,
-            request_id: req.body.request_id || req.query.request_id,
-            product_name: req.body.product_name || req.query.product_name,
-            destination: req.body.destination || req.query.destination,
-            origin: config.name || 'HTTPGETX',
-            report_ip: config.listener.core.ip || null,
-            report_port: config.listener.core.port,
-            reverse_url: req.body.reverse_url || req.query.reverse_url || null,
-        },
-    });
-
-    logger.verbose('Got CORE response', { xid: res.locals.xid, err, coreResponse });
-
-    if (err) {
-        logger.warn('TOPUP: ERROR on /prepaid/buy response', {
-            xid: res.locals.xid, err, coreResponseTypeof: typeof coreResponse, coreResponse,
-        });
-        res.end('INVALID CORE RESPONSE');
-        return;
-    }
-
-    res.end('OK');
-}
-
-router.all('/', (req, res) => { res.status(404).end('404: Not implemented yet'); });
-router.get('/', pagePrerequisite, pageIndex);
diff --git a/lib/listener-partner/routers/trx-status.js b/lib/listener-partner/routers/trx-status.js
deleted file mode 100644
index 6c3c152..0000000
--- a/lib/listener-partner/routers/trx-status.js
+++ /dev/null
@@ -1,109 +0,0 @@
-const express = require('express');
-const moment = require('moment');
-
-const logger = require('komodo-sdk/logger');
-
-const coreapi = require('../../coreapi');
-
-const router = express.Router();
-module.exports = router;
-
-async function pageIndex(req, res) {
-    if (!req.body) req.body = {};
-
-    if (!req.body.terminal_name && !req.query.terminal_name) {
-        res.json({
-            error: 'Parameter terminal_name tidak terdefinisi',
-        });
-        return;
-    }
-
-    if (!req.body.password && !req.query.password) {
-        res.json({
-            error: true,
-            message: 'Parameter password tidak terdefinisi',
-        });
-        return;
-    }
-
-    if (!req.body.request_id && !req.query.request_id) {
-        res.json({
-            error: true,
-            message: 'Parameter request_id tidak terdefinisi',
-        });
-        return;
-    }
-
-    const remoteIp = req.ip.replace(/^::ffff:/, '');
-    const askerTerminalName = `${req.body.terminal_name || req.query.terminal_name}@${remoteIp}`;
-
-    const coreResponse = await coreapi({
-        xid: res.locals.xid,
-        path: '/trx-status/view',
-        qs: {
-            asker_terminal_name: askerTerminalName,
-            asker_terminal_password: req.body.password || req.query.password,
-            request_id: req.body.request_id || req.query.request_id,
-        },
-    });
-
-    if (!coreResponse || !coreResponse.status) {
-        const msg = 'Status transaksi tidak dapat diketahui karena suatu kesalahan pada sistem';
-
-        logger.warn(msg, {
-            xid: res.locals.xid,
-            ip: req.ip,
-            terminal_name: req.body.terminal_name || req.query.terminal_name,
-            request_id: req.body.request_id || req.query.request_id,
-        });
-
-        res.json({
-            error: true,
-            from_ip: remoteIp,
-            terminal_name: req.body.terminal_name || req.query.terminal_name,
-            full_terminal_name: askerTerminalName,
-            password: req.body.password || req.query.password,
-            message: msg,
-        });
-        return;
-    }
-
-    const trx = coreResponse && coreResponse.result ? {
-        id: coreResponse.result.id,
-        request_id: coreResponse.result.request_id,
-        store_id: coreResponse.result.store_id,
-        store_name: coreResponse.result.store_name,
-        terminal_id: coreResponse.result.terminal_id,
-        terminal_name: coreResponse.result.terminal_name,
-
-        created: moment(coreResponse.result.created).format('YYYY-MM-DD HH:mm:ss'),
-        modified: moment(coreResponse.result.modified).format('YYYY-MM-DD HH:mm:ss'),
-
-        product_name: coreResponse.result.product_name,
-        destination: coreResponse.result.destination,
-        amount: coreResponse.result.amount,
-        ending_balance: coreResponse.result.ending_balance,
-        rc: coreResponse.result.rc,
-        message: coreResponse.result.reply_message,
-        sn: coreResponse.result.sn,
-    }
-        : null;
-
-    const result = {
-        error: coreResponse.status !== 'OK',
-        from_ip: remoteIp,
-        terminal_name: req.body.terminal_name || req.query.terminal_name,
-        full_terminal_name: askerTerminalName,
-        password: req.body.password || req.query.password,
-        message: coreResponse.message,
-        trx_found: Boolean(trx),
-        trx,
-        // original_trx: coreResponse.result,
-    };
-
-    res.json(result);
-
-    logger.info('Partner request responded', { xid: res.locals.xid, processing_time_in_ms: new Date() - res.locals.x_http_request_ts, result });
-}
-
-router.get('/', pageIndex);
diff --git a/lib/partner-listener/index.js b/lib/partner-listener/index.js
new file mode 100644
index 0000000..36a087e
--- /dev/null
+++ b/lib/partner-listener/index.js
@@ -0,0 +1,36 @@
+const DEFAULT_LISTENER_FROM_PARTNER_PORT = 25614;
+
+const express = require('express');
+
+const config = require('komodo-sdk/config');
+const logger = require('komodo-sdk/logger');
+
+const middlewareCommon = require('../middlewares/common');
+
+const routerInquiry = require('./routers/inquiry');
+const routerPay = require('./routers/pay');
+const routerTopup = require('./routers/topup');
+const routerTrxStatus = require('./routers/trx-status');
+
+const app = express();
+
+app.use(express.json({ extended: true }));
+app.use(express.urlencoded({ extended: true }));
+app.use(middlewareCommon);
+
+app.use('/inquiry', routerInquiry);
+app.use('/pay', routerPay);
+app.use('/topup', routerTopup);
+app.use('/trx-status', routerTrxStatus);
+
+app.use((req, res) => {
+    const { xid } = res.locals;
+    res.status(404).end(`KOMODO-HTTP-GET-X CENTER.\n404: Method not found.\n\nXID: ${xid}.\n`);
+});
+
+app.listen(config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT, () => {
+    logger.info(`Listen from partner request on port ${config.listener.partner.port}`);
+}).on('error', (e) => {
+    logger.error(`Can not listen request from partner on port ${config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT}. ${e.toString()}`);
+    process.exit(1);
+});
diff --git a/lib/partner-listener/routers/inquiry.js b/lib/partner-listener/routers/inquiry.js
new file mode 100644
index 0000000..b82341b
--- /dev/null
+++ b/lib/partner-listener/routers/inquiry.js
@@ -0,0 +1,106 @@
+const axios = require('axios').default;
+const express = require('express');
+const coreUrl = require('komodo-sdk/core-url');
+
+const config = require('komodo-sdk/config');
+const logger = require('komodo-sdk/logger');
+
+const getFromBodyQsParams = require('../../get-from-body-qs-params');
+const ipv6ToIpv4 = require('../../ipv6-to-ipv4');
+
+const router = express.Router();
+module.exports = router;
+
+const CORE_ENDPOINT = `${coreUrl}/postpaid2/inquiry`;
+
+const mainHandler = async (req, res) => {
+    const { xid } = res.locals;
+
+    const requestId = (getFromBodyQsParams(req, 'request_id') || '').toString().trim();
+    const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim();
+    const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`;
+    const productName = (getFromBodyQsParams(req, 'product_name') || '').trim().toUpperCase();
+    const destination = (getFromBodyQsParams(req, 'destination') || '').toString().trim();
+    const password = getFromBodyQsParams(req, 'password');
+    const reverseUrl = getFromBodyQsParams(req, 'reverse_url');
+
+    if (!requestId || !terminalNameWithoutIp || !productName || !destination) {
+        res.end('INVALID REQUEST. Missing request_id or terminal_name or product_name or destination.');
+        return;
+    }
+
+    const params = {
+        origin: config.name,
+        report_ip: config.listener.core.from_ip,
+        report_port: config.listener.core.port || 25614,
+        request_id: requestId,
+        terminal_name: terminalName,
+        product_name: productName,
+        destination,
+        terminal_password: password,
+        reverse_url: reverseUrl,
+    };
+
+    logger.info('Forwarding INQUIRY request to CORE', { xid, params });
+    try {
+        const result = await axios.get(CORE_ENDPOINT, {
+            params,
+            timeout: 10000,
+        });
+
+        if (!result || !result.data) {
+            const newError = new Error('8002EB0D: Empty CORE INQUIRY direct-response');
+            logger.warn(newError.message, { xid });
+            throw newError;
+        }
+
+        logger.verbose('Got INQUIRY direct-response from CORE', {
+            xid,
+            coreResponse: result.data,
+        });
+
+        const resultForPartner = {
+            httpgetx_xid: xid,
+            command: result.data.command,
+            request_id: result.data.request_id && result.data.request_id.toString(),
+            transaction_id: result.data.transaction_id && result.data.transaction_id.toString(),
+            transaction_date: result.data.transaction_date,
+            store_name: result.data.store_name,
+            terminal_name: result.data.terminal_name,
+            product_name: result.data.product_name,
+            destination: result.data.destination,
+            rc: result.data.rc,
+            sn: result.data.sn,
+            message: result.data.message,
+            amount: result.data.amount,
+            ending_balance: result.data.ending_balance,
+            amount_to_charge: result.data.amount_to_charge,
+        };
+
+        logger.verbose('Forwarding CORE direct-response to partner', {
+            xid,
+            resultForPartner,
+        });
+
+        res.json(resultForPartner);
+    } catch (e) {
+        logger.warn('EXCEPTION on forwarding INQUIRY request to CORE', {
+            xid,
+            errCode: e.code,
+            errMessage: e.message,
+        });
+
+        res.json({
+            httpgetx_xid: xid,
+            command: 'INQUIRY',
+            request_id: requestId,
+            terminal_name: terminalName,
+            product_name: productName,
+            destination,
+            rc: '68',
+            message: 'CORE tidak merespon dengan benar, tidak dapat mengetahui status request anda',
+        });
+    }
+};
+
+router.all('/', mainHandler);
diff --git a/lib/partner-listener/routers/pay.js b/lib/partner-listener/routers/pay.js
new file mode 100644
index 0000000..031f023
--- /dev/null
+++ b/lib/partner-listener/routers/pay.js
@@ -0,0 +1,105 @@
+const axios = require('axios').default;
+const express = require('express');
+const coreUrl = require('komodo-sdk/core-url');
+
+const config = require('komodo-sdk/config');
+const logger = require('komodo-sdk/logger');
+
+const getFromBodyQsParams = require('../../get-from-body-qs-params');
+const ipv6ToIpv4 = require('../../ipv6-to-ipv4');
+
+const router = express.Router();
+module.exports = router;
+
+const CORE_ENDPOINT = `${coreUrl}/postpaid2/pay`;
+
+const mainHandler = async (req, res) => {
+    const { xid } = res.locals;
+
+    const requestId = (getFromBodyQsParams(req, 'request_id') || '').toString().trim();
+    const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim();
+    const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`;
+    const productName = (getFromBodyQsParams(req, 'product_name') || '').trim().toUpperCase();
+    const destination = (getFromBodyQsParams(req, 'destination') || '').toString().trim();
+    const password = getFromBodyQsParams(req, 'password');
+    const reverseUrl = getFromBodyQsParams(req, 'reverse_url');
+
+    if (!requestId || !terminalNameWithoutIp || !productName || !destination) {
+        res.end('INVALID REQUEST. Missing request_id or terminal_name or product_name or destination.');
+        return;
+    }
+
+    const params = {
+        origin: config.name,
+        report_ip: config.listener.core.from_ip,
+        report_port: config.listener.core.port || 25614,
+        request_id: requestId,
+        terminal_name: terminalName,
+        product_name: productName,
+        destination,
+        terminal_password: password,
+        reverse_url: reverseUrl,
+    };
+
+    logger.info('Forwarding PAY request to CORE', { xid, params });
+    try {
+        const result = await axios.get(CORE_ENDPOINT, {
+            params,
+            timeout: 10000,
+        });
+
+        if (!result || !result.data) {
+            const newError = new Error('0D428E4C: Empty CORE PAY direct-response');
+            logger.warn(newError.message, { xid });
+            throw newError;
+        }
+
+        logger.verbose('Got PAY direct-response from CORE', {
+            xid,
+            coreResponse: result.data,
+        });
+
+        const resultForPartner = {
+            httpgetx_xid: xid,
+            command: result.data.command,
+            request_id: result.data.request_id && result.data.request_id.toString(),
+            transaction_id: result.data.transaction_id && result.data.transaction_id.toString(),
+            transaction_date: result.data.transaction_date,
+            store_name: result.data.store_name,
+            terminal_name: result.data.terminal_name,
+            product_name: result.data.product_name,
+            destination: result.data.destination,
+            rc: result.data.rc,
+            sn: result.data.sn,
+            message: result.data.message,
+            amount: result.data.amount,
+            ending_balance: result.data.ending_balance,
+        };
+
+        logger.verbose('Forwarding CORE PAY direct-response to partner', {
+            xid,
+            resultForPartner,
+        });
+
+        res.json(resultForPartner);
+    } catch (e) {
+        logger.warn('EXCEPTION on forwarding PAY request to CORE', {
+            xid,
+            errCode: e.code,
+            errMessage: e.message,
+        });
+
+        res.json({
+            httpgetx_xid: xid,
+            command: 'PAY',
+            request_id: requestId,
+            terminal_name: terminalName,
+            product_name: productName,
+            destination,
+            rc: '68',
+            message: 'CORE tidak merespon dengan benar, tidak dapat mengetahui status request anda',
+        });
+    }
+};
+
+router.all('/', mainHandler);
diff --git a/lib/partner-listener/routers/topup.js b/lib/partner-listener/routers/topup.js
new file mode 100644
index 0000000..28deb58
--- /dev/null
+++ b/lib/partner-listener/routers/topup.js
@@ -0,0 +1,87 @@
+const express = require('express');
+
+const config = require('komodo-sdk/config');
+const logger = require('komodo-sdk/logger');
+const coreapi = require('komodo-sdk/coreapi');
+// const coreapi = require('../../coreapi');
+
+const router = express.Router();
+module.exports = router;
+
+function onInvalidParameter(missingParameter, req, res) {
+    logger.verbose(`TOPUP: Undefined ${missingParameter} parameter`, {
+        xid: res.locals.xid,
+        ip: req.ip,
+        terminal_name: req.body.terminal_name || req.query.terminal_name,
+        request_id: req.body.request_id || req.query.request_id,
+        product_name: req.body.product_name || req.query.product_name,
+        destination: req.body.destination || req.query.destination,
+    });
+    res.end('INVALID REQUEST');
+}
+
+function pagePrerequisite(req, res, next) {
+    if (!req.body) req.body = {};
+
+    if (!req.body.terminal_name && !req.query.terminal_name) {
+        onInvalidParameter('terminal_name', req, res);
+        return;
+    }
+
+    if (!req.body.password && !req.query.password) {
+        onInvalidParameter('password', req, res);
+        return;
+    }
+
+    if (!req.body.request_id && !req.query.request_id) {
+        onInvalidParameter('request_id', req, res);
+        return;
+    }
+
+    if (!req.body.product_name && !req.query.product_name) {
+        onInvalidParameter('product_name', req, res);
+        return;
+    }
+
+    if (!req.body.destination && !req.query.destination) {
+        onInvalidParameter('destination', req, res);
+        return;
+    }
+
+    next();
+}
+
+async function pageIndex(req, res) {
+    const terminalName = `${req.body.terminal_name || req.query.terminal_name}@${req.ip.replace(/^::ffff:/, '')}`;
+
+    const [err, coreResponse] = await coreapi({
+        xid: res.locals.xid,
+        path: '/prepaid/buy',
+        qs: {
+            terminal_name: terminalName,
+            password: req.body.password || req.query.password,
+            request_id: req.body.request_id || req.query.request_id,
+            product_name: req.body.product_name || req.query.product_name,
+            destination: req.body.destination || req.query.destination,
+            origin: config.name || 'HTTPGETX',
+            report_ip: config.listener.core.ip || null,
+            report_port: config.listener.core.port,
+            reverse_url: req.body.reverse_url || req.query.reverse_url || null,
+        },
+    });
+
+    logger.verbose('Got CORE response', { xid: res.locals.xid, err, coreResponse });
+
+    if (err) {
+        logger.warn('TOPUP: ERROR on /prepaid/buy response', {
+            xid: res.locals.xid, err, coreResponseTypeof: typeof coreResponse, coreResponse,
+        });
+        res.end('INVALID CORE RESPONSE');
+        return;
+    }
+
+    res.end('OK');
+}
+
+router.all('/', (req, res) => { res.status(404).end('404: Not implemented yet'); });
+router.get('/', pagePrerequisite, pageIndex);
diff --git a/lib/partner-listener/routers/trx-status.js b/lib/partner-listener/routers/trx-status.js
new file mode 100644
index 0000000..6c3c152
--- /dev/null
+++ b/lib/partner-listener/routers/trx-status.js
@@ -0,0 +1,109 @@
+const express = require('express');
+const moment = require('moment');
+
+const logger = require('komodo-sdk/logger');
+
+const coreapi = require('../../coreapi');
+
+const router = express.Router();
+module.exports = router;
+
+async function pageIndex(req, res) {
+    if (!req.body) req.body = {};
+
+    if (!req.body.terminal_name && !req.query.terminal_name) {
+        res.json({
+            error: 'Parameter terminal_name tidak terdefinisi',
+        });
+        return;
+    }
+
+    if (!req.body.password && !req.query.password) {
+        res.json({
+            error: true,
+            message: 'Parameter password tidak terdefinisi',
+        });
+        return;
+    }
+
+    if (!req.body.request_id && !req.query.request_id) {
+        res.json({
+            error: true,
+            message: 'Parameter request_id tidak terdefinisi',
+        });
+        return;
+    }
+
+    const remoteIp = req.ip.replace(/^::ffff:/, '');
+    const askerTerminalName = `${req.body.terminal_name || req.query.terminal_name}@${remoteIp}`;
+
+    const coreResponse = await coreapi({
+        xid: res.locals.xid,
+        path: '/trx-status/view',
+        qs: {
+            asker_terminal_name: askerTerminalName,
+            asker_terminal_password: req.body.password || req.query.password,
+            request_id: req.body.request_id || req.query.request_id,
+        },
+    });
+
+    if (!coreResponse || !coreResponse.status) {
+        const msg = 'Status transaksi tidak dapat diketahui karena suatu kesalahan pada sistem';
+
+        logger.warn(msg, {
+            xid: res.locals.xid,
+            ip: req.ip,
+            terminal_name: req.body.terminal_name || req.query.terminal_name,
+            request_id: req.body.request_id || req.query.request_id,
+        });
+
+        res.json({
+            error: true,
+            from_ip: remoteIp,
+            terminal_name: req.body.terminal_name || req.query.terminal_name,
+            full_terminal_name: askerTerminalName,
+            password: req.body.password || req.query.password,
+            message: msg,
+        });
+        return;
+    }
+
+    const trx = coreResponse && coreResponse.result ? {
+        id: coreResponse.result.id,
+        request_id: coreResponse.result.request_id,
+        store_id: coreResponse.result.store_id,
+        store_name: coreResponse.result.store_name,
+        terminal_id: coreResponse.result.terminal_id,
+        terminal_name: coreResponse.result.terminal_name,
+
+        created: moment(coreResponse.result.created).format('YYYY-MM-DD HH:mm:ss'),
+        modified: moment(coreResponse.result.modified).format('YYYY-MM-DD HH:mm:ss'),
+
+        product_name: coreResponse.result.product_name,
+        destination: coreResponse.result.destination,
+        amount: coreResponse.result.amount,
+        ending_balance: coreResponse.result.ending_balance,
+        rc: coreResponse.result.rc,
+        message: coreResponse.result.reply_message,
+        sn: coreResponse.result.sn,
+    }
+        : null;
+
+    const result = {
+        error: coreResponse.status !== 'OK',
+        from_ip: remoteIp,
+        terminal_name: req.body.terminal_name || req.query.terminal_name,
+        full_terminal_name: askerTerminalName,
+        password: req.body.password || req.query.password,
+        message: coreResponse.message,
+        trx_found: Boolean(trx),
+        trx,
+        // original_trx: coreResponse.result,
+    };
+
+    res.json(result);
+
+    logger.info('Partner request responded', { xid: res.locals.xid, processing_time_in_ms: new Date() - res.locals.x_http_request_ts, result });
+}
+
+router.get('/', pageIndex);