UNPKG

ipizza

Version:

Node.js implementation for Estonian(and some other) banklink payments.

227 lines (200 loc) 5.62 kB
var Buffer = require('buffer').Buffer , fs = require('fs') , routes = require('routes') , S = require('string') , log = require('npmlog') , _ = require('lodash')._ var ipizza = Object.create(require('events').EventEmitter.prototype) , opt = {} , providers = {} log.heading = 'ipizza' ipizza.toString = function() { return 'ipizza' } ipizza.error_ = function (pfx, message) { if (ipizza.get('throwOnErrors')) { throw(new Error(pfx + ' ' + message)) } else { log.error(pfx, message) } } ipizza.file_ = function (data) { if (Buffer.isBuffer(data)) { return data.toString('utf8') } else if (typeof data === 'string' && data.length) { if (data.length < 200) { // Path. return fs.readFileSync(data, 'utf8') } else { // Contents. return data } } else { ipizza.error_('file', 'is in unknown format') } } var router; var handler; function createHandler() { if (handler) { handler.stop() } var stopped = false; handler = function(req, resp, next) { // Weird detection to allow simple mocks in tests. if (!req || !req.url || !resp || typeof next !== 'function') { return ipizza.error_( 'Request handler', 'invoked with invalid arguments. ' + 'Expected: http.ServerRequest, http.ServerResponse, function. ' + 'Got: ' + req + ', ' + res + ', ' + next) } if (!router) { return ipizza.error_('Handler function called before routes setup.') } if (stopped) { next() return false } var match = router.match(req.url.split('?')[0]) if (!match || !providers[match.params.provider]) { next() return false } if (resp.write) { match.fn(match.params.provider, req, resp) } return true } handler.stop = function() { stopped = true; } return handler } ipizza.makeRefNumber = function (base) { if (!(typeof base === 'string' && parseInt(base) > 0) && !(base && parseInt(base) === base)) { ipizza.error_('Reference number', 'can\'t be generated from ' + base) } var total = base.toString().split('').reverse().reduce( function (memo, num, i) { return memo + parseInt(num) * [7, 3, 1][i % 3] }, 0) return parseInt(base.toString() + (Math.ceil(total / 10) * 10 - total)) } ipizza.set = function (key, val) { if (typeof key !== 'string') { for (var i in key) { if (key.hasOwnProperty(i)) ipizza.set(i, key[i]) } return } key = S(key).camelize().toString() if (key === 'appHandler') { if (!(val === undefined || typeof val.all === 'function')) { return ipizza.error_('appHandler', 'is not valid' + val) } var f = createHandler() if (val) { val.all('*', f) } val = f } else if (key === 'returnRoute' || key === 'env') { if (!(typeof val === 'string' && val.length)) { return ipizza.error_('returnRoute', 'is not valid' + val) } if (key === 'returnRoute') { if (!/\/\:provider(\/|$)/.test(val)) { if (val.substr(-1) !== '/') { val += '/' } val += ':provider' } router = new routes.Router() router.addRoute(val, ipizza.response) } } opt[key] = val if (key === 'logLevel') log.level = val if (key === 'logStream') log.stream = val } ipizza.get = function (key) { if (!arguments.length) return opt key = S(key).camelize().toString() if (!opt.hasOwnProperty(key)) { log.error('Can\'t get option ' + key + '. No such option.') return } return opt[key] } ipizza.provider = function (provider, opt) { if (provider instanceof Array) { return provider.forEach(ipizza.provider, opt) } opt = opt || {} if (typeof provider === 'string') opt.provider = provider else opt = provider if (opt.privateKey) { opt.privateKey = ipizza.file_(opt.privateKey) } if (opt.certificate) { opt.certificate = ipizza.file_(opt.certificate) } var p = providers[opt.provider] if (opt.alias) { p = providers[opt.alias] = providers[opt.alias] || {klass: p.klass, opt: {}} } if (!p) { ipizza.error_('provider setup', 'No such provider ' + opt.provider) } else { p.opt = _.extend(p.opt, opt) } } ipizza.payment = function (provider, opt) { opt = opt || {} if (typeof provider === 'string') opt.provider = provider else opt = provider if (!providers[opt.provider]) { ipizza.error_('provider for request', 'No such provider ' + opt.provider) return } return new providers[opt.provider].klass( _.extend({}, providers[opt.provider].opt, opt)) } ipizza.response = function (provider, req, resp) { if (providers[provider]) { var payment = new providers[provider].klass(providers[provider].opt) payment.response(req, resp) } else { ipizza.error_('provider for response', 'No such provider ' + provider) } } ipizza.define = function (provider, klass) { providers[provider] = {klass: klass, opt: {}} } // Default parameters. ipizza.set( { appHandler: undefined , returnRoute: '/api/payment/response' , hostname: 'http://' + require('os').hostname() , logLevel: process.env.NODE_ENV == 'production' ? 'info' : 'verbose' , logStream: process.stdout , env: process.env.NODE_ENV || 'development' , throwOnErrors: true }) ipizza.IpizzaBank = require(__dirname + '/providers/ipizzabank.js') // Define providers. ;[ 'swedbank' , 'seb' , 'sampo' , 'krediidipank' , 'lhv' , 'nordea' , 'ec'].forEach(function (provider) { ipizza.define(provider, require(__dirname + '/providers/' + provider + '.js')) }) module.exports = ipizza