gentong.js 7.9 KB
var fs = require('fs');
var https = require('https');
var http = require('http');
var url = require('url');
var request = require('request');
var xml2js = require('xml2js').parseString;
var strftime = require('strftime');
var redis = require('redis');

var Router = require('node-simple-router');

var winston = require('winston');

var logger;
var config;
var httpServer;
var redisClient;

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

var aaa;

var logTag = __filename.split('/').reverse()[0];

function getRedisKey(timestamp) {
    var prefix = config.globals.gateway_name;
    if (config.globals.redis_prefix) {
        prefix = config.globals.redis_prefix;
    }
    return prefix + '.ts:' + timestamp + '.rid';
}

function generateTimestamp(request_id) {
    var ts = strftime('%F %T', new Date());
    
    var key = getRedisKey(ts);
    redisClient.set(key, request_id);
    redisClient.expire(key, 3600*48);
    
    return ts;
}

function topupRequest(task) {
    var ts = strftime('%F %T', new Date());
    ts = generateTimestamp(task['requestId']);
    
    var options = {
        url: config.h2h_out.partner,
        qs: {
            code: task['remoteProduct'],
            msisdn: task['destination'],
            user_id: config.h2h_out.userid,
            password: config.h2h_out.password,
            ts: ts
        }
    };

    logger.info('Creating http request to gateway', {options: options});

    request(options, function (error, response, body) {
        
        logger.info(logTag + ': DIRECT RESPONSE');
        
        if (error) {
            
            var error_message = 'Error on http connection to gateway: ' + error;
            logger.warn(error_message);
            callbackReport(task['requestId'], '91', error_message);
            return;

        } 
        
        if (response.statusCode != 200) {
            
            var error_message = 'Gateway error, http response code: ' + response.statusCode;
            logger.warn(error_message);
            callbackReport(task['requestId'], '91', error_message);
            return;
        }
        
        var responseCode = 40;
        var responseMessage;
        
        xml2js(body, function (err, result) {
            if (err) {
                logger.warn('Error parsing XML', {response_body: body});
                callbackReport(task['requestId'], '40', body);
                return;
            }
            
            logger.info(result);
            
            try {
                if (result.direct_ack.request_status == 'OK') {
                    responseCode = 68;
                } else {
                    responseCode = 40;
                    
                    var new_response_code = responseCodeFromMessage(result.direct_ack.info);
                    if (new_response_code) {
                        responseCode = new_response_code;
                    }
                    
                }

                responseMessage =  result.direct_ack.info;
            }
            catch(err) {
                logger.warn('Exception on parsing request response');
                responseCode = 40;
                responseMessage = 'Invalid response from gateway';
            }
            
            callbackReport(task['requestId'], responseCode, responseMessage);
            
        });
        
    });
}

function createRedisClient() {
    redisClient = redis.createClient(config.globals.redis_port, config.globals.redis_host);
}

function parseSN(message, _config) {
    
    if (!_config) {
        _config = config;
    }
    
    var sn_regex = new RegExp(_config.h2h_out.sn_pattern);
    var sn_match = message.match(sn_regex);
        
    if (sn_match <= 0) {
        logger.info('SN Not found: ' + message);
        return '';
    }
    
    var sn = sn_match[0];
    var sn_remove_patterns = _config.h2h_out.sn_remove_patterns.split(_config.h2h_out.sn_remove_patterns_separator);
    
    var count = sn_remove_patterns.length;
    
    for(var i = 0; i < count; i++) {
        sn = sn.replace(sn_remove_patterns[i], '');
    }
    
    return sn.trim();
}

function createServer() {
    var httpServer = http.createServer(function(request, response) {
        
        var response_code = '68';
        var sn = '';
        
        var qs = url.parse(request.url, true).query;
        
        logger.info('Got reverse report from gateway', {qs: qs});
        
        if (qs.topup_status == 'S') {
            response_code = '00';
            if (qs.sn) {
                sn = qs.sn;
            } else {
                sn = parseSN(qs.info);
            }
        } else if (qs.topup_status == 'R') {
            
            response_code = '40';

        }
        
        try {
            
            var new_response_code = responseCodeFromMessage(qs.info);
            if (new_response_code) {
                response_code = new_response_code;
            }
            
        }
        catch(err) {
            logger.warn('Exception on parsing reverse report', {exception: err} );
            response_code = '40';
        }
        
        message = qs.info;
        //updateBalance(message);
        if (sn) {
            message = 'SN=' + sn + '; ' + message;
        }
        
        response.end('OK');
        
        var key = getRedisKey(qs.ts);
        redisClient.get(key, function(err, request_id) {
            if (err) {
                logger.warn('Error when requesting request id for ts:' + qs.ts + ' (' + key + ')', {redis_error: err});
                return;
            }
            
            callbackReport(request_id, response_code, message);
        });
    });
    
    httpServer.listen(config.h2h_out.listen_port, function() {
        logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port);
    });
}

function responseCodeFromMessage(message) {
    if (message.indexOf('Nomor salah/tidak terdaftar') >= 0) {
        return '14';
    }
    else if (message.indexOf('Nomor tidak di temukan/tidak aktif') >= 0) {
        return '14';
    }
    else if (message.indexOf('Kode produk tidak sesuai nomor tujuan') >= 0) {
        return '14';
    }
    else if (message.indexOf('nomor yang anda masukan salah') >= 0) {
        return '14';
    }
    else if (message.indexOf('bulk or forbidden request') >= 0) {
        return '55';
    }
    else if (message.indexOf('Sudah pernah dilakukan') >= 0) {
        return '55';
    }
    else if (message.indexOf('Mohon maaf saat ini stock belum tersedia') >= 0) {
        return '13';
    }
    
    return;
}

function updateBalance(message) {
    var balance = getBalanceFromMessage(message);
    if (balance) {
        logger.info('Balance: ' + balance);
        
        try {
            aaa.updateBalance(balance);
        }
        catch(err) {
            logger.warn('Exception on partner.updateBalance: ' + err, {exception: err});
        }
    }
}

function getBalanceFromMessage(message, balance_regex) {
    if (!balance_regex) {
        if (config && config.globals && config.globals.balance_regex) {
            balance_regex = config.globals.balance_regex;
        }
    }
    
    if (!balance_regex) {
        return;
    }
    
    try {
        var re = new RegExp(balance_regex);
        var matches = message.match(re);
        
        var result = matches[1];
        result = result.replace(/\./g, '');
        result = result.replace(/,/g, '');
        
        
        return Number(result);
    }
    catch(err) {
        return;
    }
}

function start(_config, _callbackReport, options) {
    config = _config;
    callbackReport = _callbackReport
    
    if (options && options.aaa) {
            aaa = options.aaa;
    }
    
    if (options && options.logger) {
        logger = options.logger;
    } else {
        logger = new winston.Logger({
            transports: [
              new (winston.transports.Console)()
            ]
        });
    }
    
    createRedisClient();
    createServer();
}

exports.start = start;
exports.topupRequest = topupRequest;