Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

0.5.0

  • Loading branch information...
commit d31fa32b83a7b06ac6728bcb34859e3288577983 1 parent 19b29e1
@braintreeps braintreeps authored
View
2  .gitignore
@@ -1,6 +1,6 @@
/node_modules/.bin
/node_modules/coffee-script
-/node_modules/o3-xml
+/node_modules/xml2js
/node_modules/underscore
/node_modules/vows
/tags
View
82 README.md
@@ -11,19 +11,19 @@ should be minimal. We're using [semantic versioning](http://semver.org/).
### From NPM
-* npm install braintree
-* var braintree = require('braintree')
+* `npm install braintree`
+* `var braintree = require('braintree')`
### From Source
* clone the latest tag somewhere in your require.paths
-* var braintree = require('braintree-node/lib/braintree')
+* `var braintree = require('braintree-node/lib/braintree')`
### Dependencies
-* node ~0.4.7
+* node ~0.6.6
* coffee-script ~1.1
-* o3-xml ~0.1.0
+* xml2js >= 0.1.13
## Not Yet Implemented
@@ -35,44 +35,34 @@ should be minimal. We're using [semantic versioning](http://semver.org/).
* [Bug Tracker](http://github.com/braintree/braintree_node/issues)
## Quick Start
-
- var sys = require('sys'),
- braintree = require('braintree');
-
- var gateway = braintree.connect({
- environment: braintree.Environment.Sandbox,
- merchantId: 'your_merchant_id',
- publicKey: 'your_public_key',
- privateKey: 'your_private_key'
- });
-
- gateway.transaction.sale({
- amount: '5.00',
- creditCard: {
- number: '5105105105105100',
- expirationDate: '05/12'
- }
- }, function (err, result) {
- if (err) throw err;
-
- if (result.success) {
- sys.puts('Transaction ID: ' + result.transaction.id);
- } else {
- sys.puts(result.message);
- }
- });
-
-## Maintainers
-
-The Braintree Node library is maintained by the Braintree dev team.
-
-* [Dan Manges](https://github.com/dan-manges)
-* [Patrick Schless](https://github.com/plainlystated)
-* [Paul Gross](https://github.com/pgr0ss)
-* [Drew Olson](https://github.com/drewolson)
-* [Hammer](https://github.com/thehammer)
-* [Paul Hinze](https://github.com/phinze)
-* [Ali Aghareza](https://github.com/aghareza)
-* [Tony Pitluga](https://github.com/pitluga)
-* [Ben Mills](https://github.com/benmills)
-
+```javascript
+var sys = require('sys'),
+ braintree = require('braintree');
+
+var gateway = braintree.connect({
+ environment: braintree.Environment.Sandbox,
+ merchantId: 'your_merchant_id',
+ publicKey: 'your_public_key',
+ privateKey: 'your_private_key'
+});
+
+gateway.transaction.sale({
+ amount: '5.00',
+ creditCard: {
+ number: '5105105105105100',
+ expirationDate: '05/12'
+ }
+}, function (err, result) {
+ if (err) throw err;
+
+ if (result.success) {
+ sys.puts('Transaction ID: ' + result.transaction.id);
+ } else {
+ sys.puts(result.message);
+ }
+});
+```
+
+## License
+
+See the LICENSE file.
View
1  lib/braintree.coffee
@@ -1,4 +1,3 @@
-sys = require "sys"
{Config} = require("./braintree/config")
{Environment} = require("./braintree/environment")
{BraintreeGateway} = require("./braintree/braintree_gateway")
View
1  lib/braintree/digest.coffee
@@ -1,4 +1,3 @@
-sys = require('sys')
crypto = require('crypto')
class Digest
View
8 lib/braintree/http.coffee
@@ -1,15 +1,16 @@
-sys = require('sys')
http = require('http')
https = require('https')
{Buffer} = require('buffer')
braintree = require('../braintree')
-{XmlParser} = require('./xml_parser')
+xml2js = require('xml2js')
exceptions = require('./exceptions')
{Util} = require('./util')
class Http
constructor: (@config) ->
+ @parser = new xml2js.Parser
+ explicitRoot: true
checkHttpStatus: (status) ->
switch status.toString()
@@ -64,7 +65,8 @@ class Http
error = @checkHttpStatus(response.statusCode)
return callback(error, null) if error
if body isnt ' '
- callback(null, XmlParser.parse(body))
+ @parser.parseString body, (err, result) ->
+ callback(null, Util.convertNodeToObject(result))
else
callback(null, null)
)
View
34 lib/braintree/util.coffee
@@ -16,7 +16,41 @@ class Util
newObj[newKey] = value
newObj
+ @convertNodeToObject: (obj) ->
+ if typeof(obj) is 'object' and obj['@']
+ if obj['@'].type is 'array'
+ newArray = []
+ for key, value of obj when key isnt '@'
+ if value instanceof Array
+ for item in value
+ newArray.push(@convertNodeToObject(item))
+ else
+ newArray.push(@convertNodeToObject(value))
+ newArray
+ else if obj['@'].nil is 'true'
+ null
+ else if obj['@'].type is 'boolean'
+ obj['#'] is 'true'
+ else
+ obj['#']
+ else if obj instanceof Array
+ @convertNodeToObject(item) for item in obj
+ else if typeof(obj) is 'object' and @objectIsEmpty(obj)
+ ''
+ else if typeof(obj) is 'object'
+ newObj = {}
+ for key, value of obj
+ newObj[@toCamelCase(key)] = @convertNodeToObject(value)
+ newObj
+ else
+ obj
+
+ @objectIsEmpty: (obj) ->
+ return false for key, value of obj
+ return true
+
@toCamelCase: (string) ->
+
string.replace(/([\-\_][a-z0-9])/g, (match) -> match.toUpperCase().replace('-','').replace('_',''))
@toUnderscore: (string) ->
View
39 lib/braintree/xml_parser.coffee
@@ -1,39 +0,0 @@
-sys = require('sys')
-xml = require('o3-xml')
-{Util} = require('./util')
-
-class XmlParser
- TEXT_NODE = 3
-
- @parse: (text) ->
- new XmlParser().parse(text)
-
- convertNodeToObject: (node) ->
- object = {}
- obj = {}
- for child in node.childNodes
- if child.nodeType isnt TEXT_NODE
- name = Util.toCamelCase(child.nodeName)
- if child.childNodes.length is 1 && child.childNodes[0].nodeType is TEXT_NODE
- if child.attributes.length is 1 && child.attributes[0].name is 'type' && child.attributes[0].value is 'boolean'
- obj[name] = if child.childNodes[0].nodeValue is 'true' then true else false
- else
- obj[name] = child.childNodes[0].nodeValue
- else if child.childNodes.length is 0 && child.attributes.length is 1 && child.attributes[0].name is 'nil'
- obj[name] = null
- else if child.childNodes.length is 0 && child.attributes.length is 1 && child.attributes[0].name is 'type' && child.attributes[0].value is 'array'
- obj[name] = []
- else if child.attributes.length is 1 && child.attributes[0].name is 'type' && child.attributes[0].value is 'array'
- obj[name] = (@convertNodeToObject(arrayItem)[Util.toCamelCase(arrayItem.nodeName)] for arrayItem in child.childNodes when arrayItem.nodeType isnt TEXT_NODE)
- else if child.childNodes.length is 0 && child.attributes.length is 0
- obj[name] = ''
- else
- obj[name] = @convertNodeToObject(child)[Util.toCamelCase(child.nodeName)]
- object[Util.toCamelCase(node.nodeName)] = obj
- object
-
- parse: (body) ->
- doc = xml.parseFromString(body)
- @convertNodeToObject(doc.documentElement)
-
-exports.XmlParser = XmlParser
View
6 package.json
@@ -1,6 +1,6 @@
{
"name" : "braintree",
- "version" : "1.0.105",
+ "version" : "0.5.0",
"description" : "A library for integrating with Braintree.",
"keywords" : ["payments"],
"homepage" : "http://github.com/braintree/braintree_node",
@@ -8,11 +8,11 @@
"main" : "./lib/braintree.js",
"repository" : { "type": "git", "url" : "https://github.com/braintree/braintree_node.git" },
"dependencies" : {},
- "engines" : { "node": "~0.4.7" },
+ "engines" : { "node": "~0.6.6" },
"bundledDependencies" : [ "dateformat" ],
"dependencies" : {
"coffee-script" : "~1.1",
- "o3-xml" : "~0.1.0"
+ "xml2js" : ">=0.1.13"
},
"devDependencies" : {
"underscore" : "=1.1.6",
View
89 spec/braintree/util_spec.js
@@ -44,6 +44,95 @@ vows.describe('Util').addBatch({
}
},
+ 'convertNodeToObject': {
+ 'single value': {
+ topic: Util.convertNodeToObject('foobar'),
+ 'is converted to an object': function (result) {
+ assert.equal(result, 'foobar');
+ }
+ },
+
+ 'hash of values': {
+ topic: Util.convertNodeToObject({'foo-bar': 'baz', 'ping': 'pong'}),
+ 'is converted to an object': function (result) {
+ assert.deepEqual(result, {'fooBar': 'baz', 'ping': 'pong'});
+ }
+ },
+
+ 'hash of hash of values': {
+ topic: Util.convertNodeToObject({'foo-bar': 'baz', 'hash': {'ping-pong': 'paddle'}}),
+ 'is converted to an object': function (result) {
+ assert.deepEqual(result, {'fooBar': 'baz', 'hash': {'pingPong': 'paddle'}});
+ }
+ },
+
+ 'array as object with no items': {
+ topic: Util.convertNodeToObject({'@':{'type': 'array'}}),
+ 'is converted to an object': function (result) {
+ assert.deepEqual(result, []);
+ }
+ },
+
+ 'array as object with one item': {
+ topic: Util.convertNodeToObject({'@':{'type': 'array'}, 'item': {'foo': 'bar'}}),
+ 'is converted to an object': function (result) {
+ assert.deepEqual(result, [{'foo': 'bar'}]);
+ }
+ },
+
+ 'array as object with multiple items': {
+ topic: Util.convertNodeToObject({'@':{'type': 'array'}, 'item':[{'prop': 'value'}, {'prop': 'value'}]}),
+ 'is converted to an object': function (result) {
+ assert.deepEqual(result, [{'prop': 'value'}, {'prop': 'value'}]);
+ }
+ },
+
+ 'array as object with root element': {
+ topic: Util.convertNodeToObject({'items':{'@':{'type': 'array'}, 'item':[{'prop': 'value'}, {'prop': 'value'}]}}),
+ 'is converted to an object': function (result) {
+ assert.deepEqual(result, {'items':[{'prop': 'value'}, {'prop': 'value'}]});
+ }
+ },
+
+ 'nil object': {
+ topic: Util.convertNodeToObject({'@': {nil: 'true'}}),
+ 'is converted to null': function (result) {
+ assert.isNull(result);
+ }
+ },
+
+ 'symbol': {
+ topic: Util.convertNodeToObject({attribute: { '#': 'country_name', '@': { type: 'symbol' } } }),
+ 'is converted to string': function (result) {
+ assert.deepEqual(result, {'attribute': 'country_name'})
+ }
+ },
+
+ 'integer': {
+ topic: Util.convertNodeToObject({attribute: { '#': '1234', '@': { type: 'integer' } } }),
+ 'is converted to integer': function (result) {
+ assert.deepEqual(result, {'attribute': 1234})
+ }
+ },
+
+ 'boolean': {
+ topic: Util.convertNodeToObject({'a1': { '#': 'true', '@': { type: 'boolean' } }, 'a2': { '#': 'false', '@': { type: 'boolean' } } }),
+ 'is converted to boolean': function (result) {
+ assert.isTrue(result.a1)
+ assert.isFalse(result.a2)
+ }
+ },
+
+ 'empty object': {
+ topic: Util.convertNodeToObject({attribute: {}}),
+ 'is converted to empty string': function (result) {
+ assert.deepEqual(result, {'attribute': ''})
+ }
+ }
+
+
+ },
+
'toCamelCase': {
'string with underscores': {
topic: Util.toCamelCase('one_two_three'),
View
134 spec/braintree/xml_parser_spec.js
@@ -1,134 +0,0 @@
-require('../spec_helper');
-var XmlParser = require('../../lib/braintree/xml_parser').XmlParser;
-
-var CUSTOMER_XML = [
-'<?xml version="1.0" encoding="UTF-8"?>',
-'<customer>',
-' <id>403123</id>',
-' <merchant-id>integration_merchant_id</merchant-id>',
-' <first-name>Dan</first-name>',
-' <last-name nil="true"></last-name>',
-' <company></company>',
-' <email nil="true"></email>',
-' <phone nil="true"></phone>',
-' <fax nil="true"></fax>',
-' <website nil="true"></website>',
-' <created-at type="datetime">2011-05-28T15:13:43Z</created-at>',
-' <updated-at type="datetime">2011-05-28T15:13:43Z</updated-at>',
-' <custom-fields>',
-' </custom-fields>',
-' <credit-cards type="array">',
-' <credit-card>',
-' <bin>510510</bin>',
-' <cardholder-name nil="true"></cardholder-name>',
-' <card-type>MasterCard</card-type>',
-' <created-at type="datetime">2011-05-28T15:13:43Z</created-at>',
-' <customer-id>403123</customer-id>',
-' <default type="boolean">true</default>',
-' <expiration-month>05</expiration-month>',
-' <expiration-year>2012</expiration-year>',
-' <expired type="boolean">false</expired>',
-' <customer-location>US</customer-location>',
-' <last-4>5100</last-4>',
-' <subscriptions type="array"/>',
-' <token>7j5g</token>',
-' <updated-at type="datetime">2011-05-28T15:13:43Z</updated-at>',
-' </credit-card>',
-' </credit-cards>',
-' <addresses type="array"/>',
-'</customer>',
-].join("\n");
-
-var VALIDATION_ERRORS_XML = [
-'<?xml version="1.0" encoding="UTF-8"?>',
-'<api-error-response>',
-' <params>',
-' <payment-method-token>invalid_token</payment-method-token>',
-' <plan-id>invalid_plan_id</plan-id>',
-' </params>',
-' <message>Payment method token is invalid.',
-'Plan ID is invalid.</message>',
-' <errors>',
-' <subscription>',
-' <add-ons>',
-' <errors type="array"/>',
-' </add-ons>',
-' <discounts>',
-' <errors type="array"/>',
-' </discounts>',
-' <errors type="array">',
-' <error>',
-' <message>Payment method token is invalid.</message>',
-' <code>91903</code>',
-' <attribute type="symbol">payment_method_token</attribute>',
-' </error>',
-' <error>',
-' <message>Plan ID is invalid.</message>',
-' <code>91904</code>',
-' <attribute type="symbol">plan_id</attribute>',
-' </error>',
-' </errors>',
-' </subscription>',
-' <errors type="array"/>',
-' </errors>',
-'</api-error-response>',
-].join("\n");
-
-vows.describe('XmlParser').addBatch({
- 'parse': {
- 'parsing customer xml': {
- topic: XmlParser.parse(CUSTOMER_XML),
- 'parses customer attributes': function (result) {
- assert.equal(result.customer.id, '403123');
- assert.equal(result.customer.merchantId, 'integration_merchant_id');
- assert.equal(result.customer.firstName, 'Dan');
- },
- 'parses nil values': function (result) {
- assert.equal(result.customer.lastName, null);
- },
- 'parses empty values': function (result) {
- assert.equal(result.customer.company, '');
- },
- 'parses boolean values': function (result) {
- assert.equal(result.customer.creditCards[0].default, true);
- assert.equal(result.customer.creditCards[0].expired, false);
- },
- 'parses empty arrays': function (result) {
- assert.equal(result.customer.addresses.length, 0);
- assert.isEmptyArray(result.customer.addresses);
- },
- 'parses an array of credit cards': function (result) {
- assert.equal(result.customer.creditCards.length, 1);
- var creditCard = result.customer.creditCards[0];
- assert.equal(creditCard.bin, '510510');
- assert.equal(creditCard.cardholderName, null);
- assert.equal(creditCard.cardType, 'MasterCard');
- assert.equal(creditCard.customerId, '403123');
- assert.equal(creditCard.last4, '5100');
- assert.isEmptyArray(creditCard.subscriptions);
- }
- },
-
- 'parsing validation errors on subscriptions': {
- topic: XmlParser.parse(VALIDATION_ERRORS_XML),
- 'parses the message': function (result) {
- assert.equal(result.apiErrorResponse.message, "Payment method token is invalid.\nPlan ID is invalid.");
- },
- 'parses top level errors': function (result) {
- assert.isEmptyArray(result.apiErrorResponse.errors.errors);
- },
- 'parses subscription errors': function (result) {
- var subscriptionErrors = result.apiErrorResponse.errors.subscription.errors;
- assert.isArray(subscriptionErrors);
- assert.equal(subscriptionErrors.length, 2);
- assert.equal(subscriptionErrors[0].message, 'Payment method token is invalid.');
- assert.equal(subscriptionErrors[0].code, '91903');
- assert.equal(subscriptionErrors[0].attribute, 'payment_method_token');
- assert.equal(subscriptionErrors[1].message, 'Plan ID is invalid.');
- assert.equal(subscriptionErrors[1].code, '91904');
- assert.equal(subscriptionErrors[1].attribute, 'plan_id');
- }
- }
- }
-}).export(module);
-
View
3  spec/spec_helper.coffee
@@ -1,7 +1,6 @@
http = require('http')
{Util} = require('../lib/braintree/util')
querystring = require('../vendor/querystring.node.js.511d6a2/querystring')
-sys = require('sys')
GLOBAL.vows = require('vows')
GLOBAL.assert = require('assert')
@@ -11,7 +10,7 @@ GLOBAL.assert.isEmptyArray = (array) ->
assert.equal(array.length, 0)
GLOBAL.inspect = (object) ->
- sys.puts(sys.inspect(object))
+ console.dir(object)
braintree = require('./../lib/braintree.js')

0 comments on commit d31fa32

Please sign in to comment.
Something went wrong with that request. Please try again.