Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit f26b35e0f63209e79fafc9e5c52f0000db2b7830 @jamescarr committed Aug 2, 2010
@@ -0,0 +1,43 @@
+# paynode
+Paynode is the new superset payment gateway module that will provide nodejs
+adapters for various payment gateways.
+
+This is all a rapid rework of my exisiting paypal-payflowpro module so expect
+some API changes to happen quite rapidly.
+
+
+## Supported Gateways
+ * Paypal Payflow Pro
+ * Authorize.net (AIM only)
+ * more to come!
+
+## Installation
+Installation is available via npm
+
+ npm install paynode
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2010 James Carr <james.r.carr@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
@@ -0,0 +1,5 @@
+== TODO Items ==
+ * unify api across board
+ * change callbacks to use function(err, result) form
+ * unit over integration tests
+ * get rid of prenuptials
@@ -0,0 +1,121 @@
+# payment-paypal-payflowpro
+This is a node based wrapper for Paypal's Payflow Pro API (https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/howto_gateway_payflowpro). The plan will be to implement all of the API methods available as well as the many authentication modes.
+
+All fields returned by the API are represented as object properties in the result object, with the exception of list elements (keys prefixed by L_) which will be located in a hash representative of the fields (errors for error name-value pairs, balances for balance related NVPs).
+
+More to come, but please feel free to make suggestions!
+
+## Installation
+This has been published as an npm package, meaning there are two ways of
+installing. One is by cloning the git repo and installing it, the other is by
+installing it via npm
+
+ npm install payment-paypal-payflowpro
+
+
+## Supported Authentication Methods
+ - 3 Token
+ - Certificate based auth
+
+## Supported API methods
+ - addressVerify
+ - doDirectPayment
+ - getBalance
+ - getTransactionDetails
+ - setExpressCheckout
+ - getExpressCheckoutDetails
+ - doExpressCheckoutPayment
+ - (more to come)
+
+See https://cms.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/howto_api_reference for required fields for each API method.
+## Examples
+
+### Creating a client using SSL Certificate based Auth:
+ var client = payflow.createClient({level:payflow.levels.sandbox
+ , user:'username'
+ , password:'LXLDUTRFGA39YR25'
+ , cert:'string representing your cert'
+ , key:'key representing your key'
+ })
+
+### Process a payment
+ var payflow = require('payment-paypal-payflowpro')
+
+ var client = payflow.createClient({level:payflow.levels.sandbox
+ , user:'username'
+ , password:'password'
+ , signature: 'signature'
+ })
+
+ client.doDirectPayment({amt:'99.06'
+ ,paymentaction:'Sale'
+ ,ipaddress:'1.1.1.1'
+ ,creditcardtype:'Visa'
+ ,acct:'4834907016040081'
+ ,expdate:'032011'
+ ,cvv2:'000'
+ ,firstname:'John'
+ ,lastname:'Doe'
+ ,street:'123 test st'
+ ,city: 'omaha'
+ ,state: 'NE'
+ ,countrycode:'US'
+ ,zip:'68102'
+ }).on('success', function(result){
+ // do something based on a succesful transaction
+ }).on('failure', function(result){
+ // do something based on a failed transaction
+ result.errors.forEach(function(err){
+ /**
+ * { errorcode: '10527'
+ * , shortmessage: 'Invalid Data'
+ * , longmessage: 'This transaction cannot be processed. Please enter a valid credit card number and type.'
+ * , severitycode: 'Error'
+ * }
+ **/
+ })
+ })
+
+### Get the balances of your account
+ var payflow = require('payment-paypal-payflowpro')
+
+ var client = payflow.createClient({level:payflow.levels.sandbox
+ , user:'username'
+ , password:'password'
+ , signature: 'signature'
+ })
+ client.getBalance().on('success', function(result){
+ result.balances.forEach(function(balance){
+ sys.puts(balance.amt)
+ sys.puts(balance.currencycode)
+ })
+ })
+
+## Contribute
+All code is written BDD style using vowsjs. I've included a few sh scripts to run all specs, unit-specs, and integration-specs.
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2010 James Carr <james.r.carr@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
@@ -0,0 +1,34 @@
+
+var EventEmitter = require('events').EventEmitter,
+ GatewayClient = require('../gateway-client').GatewayClient,
+ response = require('authorizenet/response-parser')
+
+exports.createClient = function(options, netClient){
+ var conn = netClient || new GatewayClient({
+ host:options.level
+ ,path:'/gateway/transact.dll'
+ ,contentType:'text/keyvalue',
+ responseParser:response})
+
+ return new Client(options, conn)
+}
+
+function Client(options, netClient){
+ var addOptionAttributes = function(req){
+ req.x_login= options.login
+ req.x_tran_key=options.tran_key
+ req.x_version= "3.1"
+ req.x_delim_data= "TRUE"
+ req.x_delim_char= "|"
+ req.x_relay_response= "FALSE"
+ return req
+ }
+ this.performAimTransaction = function(request){
+ var emitter = new EventEmitter()
+ netClient.request(addOptionAttributes(request), function(response){
+ emitter.emit('success', null, response)
+ })
+ return emitter
+ }
+
+}
@@ -0,0 +1,4 @@
+exports.levels = {
+ sandbox:'test.authorize.net'
+ ,live:'secure.authorize.net'
+}
@@ -0,0 +1,57 @@
+var s = require('sys')
+var fieldDefinitions = {
+ 0:'responsecode'
+,1: 'responsesubcode'
+,2: 'responsereasoncode'
+,3: 'responsereasontext'
+,4: 'authorizationcode'
+,5: 'avsresponse'
+,6: 'transactionid'
+,7: 'invoicenumber'
+,8: 'description'
+,9: 'amount'
+,10: 'method'
+,11: 'transactiontype'
+,12: 'customerid'
+,13: 'firstname'
+,14: 'lastname'
+,15: 'company'
+,16: 'address'
+,17: 'city'
+,18: 'state'
+,19: 'zipcode'
+,20: 'country'
+,21: 'phone'
+,22: 'fax'
+,23: 'email'
+,24: 'shiptofirstname'
+,25: 'shiptolastname'
+,26: 'shiptocompany'
+,27: 'shiptoaddress'
+,28: 'shiptocity'
+,29: 'shiptostate'
+,30: 'shiptozipcode'
+,31: 'shiptocountry'
+,32: 'tax'
+,33: 'duty'
+,34: 'freight'
+,35:'taxexempt'
+,36:'purchaseordernumber'
+,37: 'md5hash'
+,38:'cardresponsecode'
+,39:'cavvresponse'
+,50:'accountnumber'
+,51:'cardtype'
+}
+
+
+exports.parseResponse = function(response){
+ var result = {}
+ console.log(response.split('|').length)
+ response.split('|').forEach(function(value, index){
+ var key = fieldDefinitions[index]
+ if(key != undefined)
+ result[key] = value
+ })
+ return result
+}
@@ -0,0 +1,28 @@
+var http = require('http'),
+ qs = require('querystring'),
+ crypto = require('crypto'),
+ sys = require('sys')
+
+function GatewayClient(opts, authInfo){
+ var createClient = !authInfo?
+ function(){ return http.createClient(443, opts.host, true) }
+ :
+ function(){
+ var cred = crypto.createCredentials({cert:authInfo.cert, key:authInfo.key})
+ return http.createClient(443, opts.host, true, cred)
+ }
+ this.request = function(request, callback){
+ var requestString = qs.stringify(request)
+ var req = createClient().request('POST', opts.path, {host:opts.host
+ ,'Content-Length':requestString.length
+ ,'Content-Type':opts.contentType})
+ req.end(requestString)
+ req.on('response', function(res){
+ res.on('data', function(data){
+ callback(opts.responseParser.parseResponse(data.toString()))
+ })
+ })
+ }
+}
+
+exports.GatewayClient = GatewayClient
@@ -0,0 +1,51 @@
+require.paths.unshift(__dirname)
+
+var EventEmitter = require('events').EventEmitter,
+ PaypalNetworkClient = require('paypal-network-client').PaypalNetworkClient,
+ requestBuilder = require("request-builder")
+
+exports.levels = {
+ sandbox:function(opts){return (opts.cert)? 'api.sandbox.paypal.com' : 'api-3t.sandbox.paypal.com'}
+ ,live:function(opts){ return (opts.cert)? 'api.paypal.com' : 'api-3t.paypal.com'}
+}
+
+exports.createClient = function(options){
+ options.version='63.0'
+ var client = options.cert?
+ new PaypalNetworkClient(options.level(options), {cert:options.cert, key:options.key})
+ :
+ new PaypalNetworkClient(options.level(options))
+
+ return new Client(options, client)
+}
+
+
+
+function Client(options, paypal){
+ options.__defineGetter__('pwd', function(){ return options.password})
+ var self = this
+ ;['getBalance', 'getTransactionDetails','addressVerify', 'doDirectPayment',
+ 'setExpressCheckout', 'getExpressCheckoutDetails', 'doExpressCheckoutPayment'].forEach(function(name){
+ self[name] = function(){
+ var req = {method:name}
+ for(var i =0; i < arguments.length; i++){
+ merge(req, arguments[i])
+ }
+ requestBuilder.buildRequest(merge(req, options))
+
+ var emitter = new EventEmitter()
+ paypal.request(req, function(data){
+ emitter.emit(data.ack.toLowerCase(), data)
+ });
+ return emitter
+ }
+ })
+}
+
+function merge(a, b){
+ var no = ['cert', 'key', 'password', 'level']
+ Object.keys(b).filter(function(s){ return no.indexOf(s) ==-1}).forEach(function(k){
+ a[k] = b[k]
+ })
+ return a
+}
@@ -0,0 +1,14 @@
+
+var GatewayClient = require('./gateway-client').GatewayClient,
+ paypalResponse = require('./response-parser')
+
+function PaypalNetworkClient(host, authInfo){
+ var client = new GatewayClient({host:host
+ ,contentType:'text/namevalue'
+ ,path:'/nvp'
+ ,responseParser:paypalResponse
+ }, authInfo)
+ this.request = client.request
+}
+
+exports.PaypalNetworkClient = PaypalNetworkClient
Oops, something went wrong.

0 comments on commit f26b35e

Please sign in to comment.