Commit d5fe86d04fda8ae13c450c11161f0ecd9a532908

Authored by Adhidarma Hadiwinoto
1 parent f1928f0351
Exists in master

ready to proof

Showing 5 changed files with 287 additions and 0 deletions Side-by-side Diff

... ... @@ -0,0 +1,19 @@
  1 +"use strict";
  2 +
  3 +const Logger = require("./lib/logger");
  4 +Logger.init();
  5 +const logger = Logger.get();
  6 +
  7 +const pull = require('./lib/pull');
  8 +const partner = require("./lib/partner");
  9 +
  10 +const config = require("./config.json");
  11 +
  12 +let options = {
  13 + matrix: {},
  14 + config: config,
  15 + partner: partner
  16 +}
  17 +
  18 +partner.init(options);
  19 +pull.init(options);
... ... @@ -0,0 +1,67 @@
  1 +"use strict";
  2 +
  3 +const fs = require('fs');
  4 +const strftime = require('strftime');
  5 +const winston = require('winston');
  6 +require('winston-daily-rotate-file');
  7 +
  8 +var loggerTimestamp = function() {
  9 + return strftime('%F %T', new Date());
  10 +}
  11 +
  12 +var logger;
  13 +
  14 +function init(_filenamePrefix) {
  15 + //console.trace('Inisialisasi logger');
  16 +
  17 + const logDirectory = 'logs';
  18 + fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory);
  19 +
  20 + let filenamePrefix;
  21 +
  22 + if (_filenamePrefix) {
  23 + filenamePrefix = logDirectory + '/' + _filenamePrefix;
  24 + }
  25 + else {
  26 + filenamePrefix = logDirectory + "/log";
  27 + }
  28 +
  29 + logger = new winston.Logger({
  30 + transports: [
  31 + new (winston.transports.Console)({
  32 + timestamp: function() {
  33 + return strftime('%F %T', new Date());
  34 + },
  35 + level: 'verbose',
  36 + }),
  37 +
  38 + new (winston.transports.DailyRotateFile) ({
  39 + name: 'log-file-txt',
  40 + filename: filenamePrefix,
  41 + timestamp: loggerTimestamp,
  42 + formatter: function(options) {
  43 + return options.timestamp()
  44 + +' ' + options.level.toUpperCase()
  45 + +' ' + (undefined !== options.message ? options.message : '')
  46 + + (options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta) : '' );
  47 + },
  48 + level: 'debug',
  49 + }),
  50 + ]
  51 + });
  52 +
  53 + logger.verbose(__filename + ': initialized');
  54 + return logger;
  55 +}
  56 +
  57 +function get() {
  58 + if (!logger) {
  59 + console.trace('Logger uninitialized, aborting process');
  60 + process.exit(1);
  61 + } else {
  62 + return logger;
  63 + }
  64 +}
  65 +
  66 +exports.init = init;
  67 +exports.get = get;
... ... @@ -0,0 +1,39 @@
  1 +"use strict";
  2 +
  3 +const moment = require('moment');
  4 +
  5 +const pull = require('./pull');
  6 +const logger = require('./logger').get();
  7 +
  8 +var config;
  9 +var matrix;
  10 +
  11 +function init(options) {
  12 + config = options.config;
  13 + matrix = options.matrix;
  14 +}
  15 +
  16 +function _buy(task) {
  17 + let destination = Number(task.destination);
  18 + if (destination % 2) {
  19 + let msg = 'Isi ' + task.remote_product + ' ke ' + task.destination + ' gagal karena nomor tujuan ganjil';
  20 + pull.report(task.trx_id, '14', msg);
  21 + } else {
  22 + let sn = moment().format('YYYYMMDDHHmmssSSS')
  23 + let msg = 'Isi ' + task.remote_product + ' ke ' + task.destination + ' berhasil karena nomor tujuan genap dengan SN=' + sn;
  24 + pull.report(task.trx_id, '00', msg, sn);
  25 + }
  26 +}
  27 +
  28 +function buy(task) {
  29 + logger.verbose('Buy on partner', {task: task});
  30 + setTimeout(
  31 + function() {
  32 + _buy(task);
  33 + },
  34 + 2000
  35 + )
  36 +}
  37 +
  38 +exports.init = init;
  39 +exports.buy = buy;
... ... @@ -0,0 +1,135 @@
  1 +"use strict";
  2 +
  3 +const request = require('request');
  4 +const logger = require('./logger').get();
  5 +
  6 +var config;
  7 +var matrix;
  8 +var partner;
  9 +
  10 +function init(options) {
  11 + config = options.config;
  12 + matrix = options.matrix;
  13 + partner = options.partner;
  14 +
  15 + initMatrix();
  16 +
  17 + setInterval(pullTask, config.pull_interval_ms || 1000);
  18 +}
  19 +
  20 +function pullTask() {
  21 + let options = {
  22 + url: config.pull_url.task,
  23 + qs: {
  24 + handler: config.handler_name,
  25 + products: config.products.join(',')
  26 + }
  27 + }
  28 +
  29 + request(options, function(error, response, body) {
  30 + if (error) {
  31 + logger.warn('Error pulling task from CORE', {error: error});
  32 + return;
  33 + }
  34 +
  35 + if (response.statusCode != 200) {
  36 + logger.warn('CORE http response status code for pull task is not 200', {http_response_status: response.statusCode});
  37 + return;
  38 + }
  39 +
  40 + if (body == 'NONE') {
  41 + return;
  42 + }
  43 +
  44 + forwardCoreTaskToPartner(body);
  45 + });
  46 +}
  47 +
  48 +function forwardCoreTaskToPartner(coreMessage) {
  49 + let task;
  50 +
  51 + try {
  52 + task = JSON.parse(coreMessage);
  53 + }
  54 + catch(e) {
  55 + logger.warn('Exception on parsing CORE pull task response', {coreMessage: coreMessage, error: e});
  56 + }
  57 +
  58 + task.remote_product = getRemoteProduct(task.product);
  59 +
  60 + partner.buy(task);
  61 +}
  62 +
  63 +function report(trx_id, rc, message, sn) {
  64 + let options = {
  65 + url: config.pull_url.report,
  66 + qs: {
  67 + trx_id: trx_id,
  68 + rc: rc,
  69 + message: message,
  70 + handler: config.handler_name,
  71 + sn: sn
  72 + }
  73 + }
  74 +
  75 + request(options, function(error, response, body) {
  76 + if (error) {
  77 + logger.warn('Error reporting to CORE', {error: error});
  78 + }
  79 + else if (response.statusCode != 200) {
  80 + logger.warn('CORE http response status is not 200', {requestOptions: options, http_response_status: response.statusCode});
  81 + }
  82 + else {
  83 + logger.verbose('Report has been sent to CORE', {requestOptions: options});
  84 + }
  85 + });
  86 +}
  87 +
  88 +function resendReport(trx_id, rc, message, sn) {
  89 + let sleepBeforeResend = 1000;
  90 + logger.verbose('Resend report to CORE in ' + sleepBeforeResend + 'ms')
  91 +
  92 + setTimeout(
  93 + function() {
  94 + report(trx_id, rc, message, sn);
  95 + },
  96 + sleepBeforeResend
  97 + )
  98 +}
  99 +
  100 +function isPaused() {
  101 + return matrix.paused;
  102 +}
  103 +
  104 +function pause() {
  105 + matrix.paused = true;
  106 +}
  107 +
  108 +function resume() {
  109 + matrix.pause = false;
  110 +}
  111 +
  112 +function initMatrix() {
  113 + if (!matrix) {
  114 + matrix = {};
  115 + }
  116 +
  117 + matrix.counter = {
  118 + trx: 0
  119 + }
  120 +}
  121 +
  122 +function incrementCounterTrx() {
  123 + matrix.counter.trx++;
  124 +}
  125 +
  126 +function getRemoteProduct(product) {
  127 + let remoteProduct = config.remote_products[product];
  128 + return remoteProduct || product;
  129 +}
  130 +
  131 +exports.init = init;
  132 +exports.isPaused = isPaused;
  133 +exports.pause = pause;
  134 +exports.resume = resume;
  135 +exports.report = report;
... ... @@ -0,0 +1,27 @@
  1 +{
  2 + "name": "komodo-gw-oddeven",
  3 + "version": "1.0.0",
  4 + "description": "Contoh dummy gateway / handler komodo",
  5 + "main": "index.js",
  6 + "dependencies": {
  7 + "moment": "^2.17.1",
  8 + "request": "^2.79.0",
  9 + "strftime": "^0.9.2",
  10 + "winston": "^2.3.0",
  11 + "winston-daily-rotate-file": "^1.4.0"
  12 + },
  13 + "devDependencies": {},
  14 + "scripts": {
  15 + "test": "mocha"
  16 + },
  17 + "repository": {
  18 + "type": "git",
  19 + "url": "git@gitlab.kodesumber.com:adhisimon/komodo-gw-oddeven.git"
  20 + },
  21 + "keywords": [
  22 + "komodo",
  23 + "ppob"
  24 + ],
  25 + "author": "Adhidarma Hadiwinoto <me@adhisimon.org>",
  26 + "license": "ISC"
  27 +}