UNPKG

node-payments

Version:

node-payments is a express based facade to multiple payment services.

161 lines (133 loc) 4.51 kB
config = require( "../../lib/config" ) request = require( "request" ) crypto = require( "crypto" ) _ = require( "lodash" ) async = require( "async" ) xml2js = require( "xml2js" ) xmlParser = new xml2js.Parser() class ClickAndBuyMMS extends require( "../_base/main" ) initialize: => @cbConfig = config.get( "clickandbuy" ) @initialized = false @_currencies = config.get( "defaultcurrency" ) #@initIPN() return init: ( @main )=> if not @initialized @initialized = true server = @main.getExpress() server.post @config.receiverPath, @verify, @input return answer200: ( req, res, next )=> @debug "IPN Input", req.body res.send( "OK" ) next() return checkSignature: ( xml, sig, secret )=> _cleanXML = ( xml.replace( "<signature>#{sig}</signature>", "<signature />" ) ) _hs = "#{secret}#{_cleanXML}" _hash = crypto.createHash('sha1').update( _hs ).digest('hex') #console.log _hash, sig, _cleanXML if sig is _hash return true else return false verify: ( req, res, next )=> @debug "REQUEST INCOME", req.body if not req.body.xml? # if no payload exists is't just a ping to verify the availibility of this endpoint. res.send( "OK" ) return xmlParser.parseString req.body.xml, ( err, bodyObj )=> if err @error( "parse xml", err ) res.send( "FAILED", 500 ) return signature = bodyObj?.eventlist?.signature?[ 0 ] req._mmsevents = bodyObj?.eventlist?.payEvent if @checkSignature( req.body.xml, signature, @config.cryptokey ) next() else @_handleError( null, "ECBMMSINVALIDSIGNATURE" ) res.send( "FAILED", 500 ) return return input: ( req, res )=> afns = [] for _event in req._mmsevents afns.push( @processEvent( _event ) ) async.series afns, ( err )=> @info "processed #{afns.length} mms events" if err? @error( err ) res.send( "FAILED", 500 ) return res.send( "OK" ) return return processEvent: ( data )=> return ( cb )=> try _pid = data.externalID[ 0 ] _rawstate = data.newState[ 0 ] _transaction = data.transactionID[ 0 ] _merchantID = data.merchantID[ 0 ] _dataAmout = data.merchantAmount[ 0 ] _currency = _dataAmout.currency[ 0 ] _payer = data.crn?[ 0 ] _atype = @_currencies[ _currency ] if _atype is "int" _amount = parseInt( _dataAmout.amount[ 0 ], 10 ) else _amount = parseFloat( _dataAmout.amount[ 0 ], 10 ) if @cbConfig.merchantid? and _merchantID isnt @cbConfig.merchantid @_handleError( cb, "ECBMMSINVALIDMERCHANT", { got: _merchantID, needed: @cbConfig.merchantid } ) return @main.getPayment _pid, ( err, payment )=> if err if not config.get( "productionmode" ) and err?.name is "EPAYMENTNOTFOUND" @warning( "Payment not found in system so return a 200 to IPN" ) cb( null ) return cb( err ) return @debug "MMS returned", _pid, payment.valueOf() if _currency isnt payment.currency @_handleError( cb, "ECBMMSINVALIDCURRENCY", { got: _currency, needed: payment.currency } ) return if Math.abs( _amount ) isnt payment.amount @_handleError( cb, "ECBMMSINVALIDAMOUNT", { got: _amount, needed: payment.amount } ) return try _state = payment._translateState( _rawstate ) payment.set( "rawProviderState", _rawstate ) payment.set( "payer_id", _payer ) if _payer?.length payment.set( "state", _state ) payment.set( "transaction", _transaction ) payment.set( "verified", true ) catch _err @error( _err ) cb( _err ) return payment.persist ( err )=> if err cb( err ) return @main.emit( "payment", "verfied", payment ) @main.emit( "payment:#{payment.id}", "verfied", payment ) @main.emit( "verfied", payment ) cb( null ) return return catch _err @error( _err ) cb( _err ) return return ERRORS: => @extend super, "ECBMMSINVALIDMERCHANT": "The click and buy MMS sends a completed message for a wrong receiver. Has to be `<%= needed %>` bot got `<%= got %>`." "ECBMMSINVALIDCURRENCY": "The click and buy MMS sends a currency unlike the expected. Has to be `<%= needed %>` bot got `<%= got %>`." "ECBMMSINVALIDAMOUNT": "The click and buy MMS sends a amount unlike the expected. Has to be `<%= needed %>` bot got `<%= got %>`." "ECBMMSINVALIDSIGNATURE": "The signature check failed." module.exports = new ClickAndBuyMMS()