braintree-rails 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <address>
3
3
  <id>address_id</id>
4
- <customer-id>8404776</customer-id>
4
+ <customer-id>customer_id</customer-id>
5
5
  <first-name>Brain</first-name>
6
6
  <last-name>Tree</last-name>
7
7
  <company>Braintree</company>
@@ -51,7 +51,7 @@
51
51
  </credit-cards>
52
52
  <addresses type="array">
53
53
  <address>
54
- <id>wx</id>
54
+ <id>address_id</id>
55
55
  <customer-id>customer_id</customer-id>
56
56
  <first-name>Brain</first-name>
57
57
  <last-name>Tree</last-name>
@@ -0,0 +1,100 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <transaction>
3
+ <id>transactionid</id>
4
+ <status>authorized</status>
5
+ <type>sale</type>
6
+ <currency-iso-code>USD</currency-iso-code>
7
+ <amount>10.00</amount>
8
+ <merchant-account-id>merchant_id</merchant-account-id>
9
+ <order-id nil="true"></order-id>
10
+ <created-at type="datetime">2012-09-15T01:07:58Z</created-at>
11
+ <updated-at type="datetime">2012-09-15T01:07:58Z</updated-at>
12
+ <customer>
13
+ <id>customer_id</id>
14
+ <first-name>Brain</first-name>
15
+ <last-name>Tree</last-name>
16
+ <company>Braintree</company>
17
+ <email>braintree@example.com</email>
18
+ <website>www.braintreepayments.com</website>
19
+ <phone>877.434.2894</phone>
20
+ <fax>888.781.6495</fax>
21
+ </customer>
22
+ <billing>
23
+ <id>address_id</id>
24
+ <first-name>Brain</first-name>
25
+ <last-name>Tree</last-name>
26
+ <company>Braintree</company>
27
+ <street-address>1134 Crane Avenue</street-address>
28
+ <extended-address>Suite 200</extended-address>
29
+ <locality>Menlo Park</locality>
30
+ <region>California</region>
31
+ <postal-code>94025</postal-code>
32
+ <country-name>United States of America</country-name>
33
+ <country-code-alpha2>US</country-code-alpha2>
34
+ <country-code-alpha3>USA</country-code-alpha3>
35
+ <country-code-numeric>840</country-code-numeric>
36
+ </billing>
37
+ <refund-id nil="true"></refund-id>
38
+ <refund-ids type="array"/>
39
+ <refunded-transaction-id nil="true"></refunded-transaction-id>
40
+ <settlement-batch-id nil="true"></settlement-batch-id>
41
+ <shipping>
42
+ <id nil="true"></id>
43
+ <first-name nil="true"></first-name>
44
+ <last-name nil="true"></last-name>
45
+ <company nil="true"></company>
46
+ <street-address nil="true"></street-address>
47
+ <extended-address nil="true"></extended-address>
48
+ <locality nil="true"></locality>
49
+ <region nil="true"></region>
50
+ <postal-code nil="true"></postal-code>
51
+ <country-name nil="true"></country-name>
52
+ <country-code-alpha2 nil="true"></country-code-alpha2>
53
+ <country-code-alpha3 nil="true"></country-code-alpha3>
54
+ <country-code-numeric nil="true"></country-code-numeric>
55
+ </shipping>
56
+ <custom-fields>
57
+ </custom-fields>
58
+ <avs-error-response-code nil="true"></avs-error-response-code>
59
+ <avs-postal-code-response-code>M</avs-postal-code-response-code>
60
+ <avs-street-address-response-code>M</avs-street-address-response-code>
61
+ <cvv-response-code>I</cvv-response-code>
62
+ <gateway-rejection-reason nil="true"></gateway-rejection-reason>
63
+ <processor-authorization-code>796RN2</processor-authorization-code>
64
+ <processor-response-code>1000</processor-response-code>
65
+ <processor-response-text>Approved</processor-response-text>
66
+ <purchase-order-number nil="true"></purchase-order-number>
67
+ <tax-amount nil="true"></tax-amount>
68
+ <tax-exempt type="boolean">false</tax-exempt>
69
+ <credit-card>
70
+ <token>credit_card_id</token>
71
+ <cardholder-name>Brain Tree</cardholder-name>
72
+ <customer-location>US</customer-location>
73
+ <card-type>MasterCard</card-type>
74
+ <bin>555555</bin>
75
+ <last-4>4444</last-4>
76
+ <expiration-month>05</expiration-month>
77
+ <expiration-year>2037</expiration-year>
78
+ </credit-card>
79
+ <status-history type="array">
80
+ <status-event>
81
+ <timestamp type="datetime">2012-09-15T01:07:58Z</timestamp>
82
+ <status>authorized</status>
83
+ <amount>10.00</amount>
84
+ <user>linyang84</user>
85
+ <transaction-source>API</transaction-source>
86
+ </status-event>
87
+ </status-history>
88
+ <plan-id nil="true"></plan-id>
89
+ <subscription-id nil="true"></subscription-id>
90
+ <subscription>
91
+ <billing-period-end-date nil="true"></billing-period-end-date>
92
+ <billing-period-start-date nil="true"></billing-period-start-date>
93
+ </subscription>
94
+ <add-ons type="array"/>
95
+ <discounts type="array"/>
96
+ <descriptor>
97
+ <name nil="true"></name>
98
+ <phone nil="true"></phone>
99
+ </descriptor>
100
+ </transaction>
@@ -0,0 +1,25 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <api-error-response>
3
+ <message>Cannot submit for settlement unless status is authorized.</message>
4
+ <errors>
5
+ <transaction>
6
+ <errors type="array">
7
+ <error>
8
+ <code>91507</code>
9
+ <message>Cannot submit for settlement unless status is authorized.</message>
10
+ <attribute type="symbol">base</attribute>
11
+ </error>
12
+ </errors>
13
+ </transaction>
14
+ <errors type="array"/>
15
+ </errors>
16
+ <params>
17
+ <merchant-id>merchant_id</merchant-id>
18
+ <action>submit_for_settlement</action>
19
+ <id>transactionid</id>
20
+ <transaction>
21
+ <amount nil="true"></amount>
22
+ </transaction>
23
+ <controller>transactions</controller>
24
+ </params>
25
+ </api-error-response>
@@ -7,17 +7,6 @@ describe 'Address Integration' do
7
7
 
8
8
  it 'should be able to add address' do
9
9
  customer = BraintreeRails::Customer.create!(:first_name => 'Brain', :last_name => 'Tree')
10
- address_hash = {
11
- :first_name => 'Brain',
12
- :last_name => 'Tree',
13
- :company => 'Braintree',
14
- :street_address => '1134 Crane Avenue',
15
- :extended_address => 'Suite 200',
16
- :locality => 'Menlo Park',
17
- :region => 'California',
18
- :postal_code => '94025',
19
- :country_name => 'United States of America'
20
- }
21
10
  customer.addresses.create!(address_hash)
22
11
  braintree_customer = Braintree::Customer.find(customer.id)
23
12
  braintree_address = braintree_customer.addresses.first
@@ -29,17 +18,6 @@ describe 'Address Integration' do
29
18
 
30
19
  it 'should be able to update existing address' do
31
20
  customer = BraintreeRails::Customer.create!(:first_name => 'Brain', :last_name => 'Tree')
32
- address_hash = {
33
- :first_name => 'Brain',
34
- :last_name => 'Tree',
35
- :company => 'Braintree',
36
- :street_address => '1134 Crane Avenue',
37
- :extended_address => 'Suite 200',
38
- :locality => 'Menlo Park',
39
- :region => 'California',
40
- :postal_code => '94025',
41
- :country_name => 'United States of America'
42
- }
43
21
  address = customer.addresses.create!(address_hash)
44
22
  address.update_attributes!(:first_name => 'Foo', :last_name => 'Bar')
45
23
  braintree_customer = Braintree::Customer.find(customer.id)
@@ -51,17 +29,6 @@ describe 'Address Integration' do
51
29
 
52
30
  it 'should be able to destroy existing address' do
53
31
  customer = BraintreeRails::Customer.create!(:first_name => 'Brain', :last_name => 'Tree')
54
- address_hash = {
55
- :first_name => 'Brain',
56
- :last_name => 'Tree',
57
- :company => 'Braintree',
58
- :street_address => '1134 Crane Avenue',
59
- :extended_address => 'Suite 200',
60
- :locality => 'Menlo Park',
61
- :region => 'California',
62
- :postal_code => '94025',
63
- :country_name => 'United States of America'
64
- }
65
32
  address = customer.addresses.create!(address_hash)
66
33
  address.destroy!
67
34
  lambda{ Braintree::Address.find(customer.id, address.id) }.must_raise Braintree::NotFoundError
@@ -6,28 +6,6 @@ describe 'Credit Card Integration' do
6
6
  end
7
7
 
8
8
  it 'should be able to fetch from Braintree for given token' do
9
- address_hash = {
10
- :first_name => 'Brain',
11
- :last_name => 'Tree',
12
- :company => 'Braintree',
13
- :street_address => '1134 Crane Avenue',
14
- :extended_address => 'Suite 200',
15
- :locality => 'Menlo Park',
16
- :region => 'California',
17
- :postal_code => '94025',
18
- :country_name => 'United States of America'
19
- }
20
-
21
- credit_card_hash = {
22
- :token => 'credit_card_id',
23
- :number => '4111111111111111',
24
- :cvv => '123',
25
- :cardholder_name => 'Brain Tree',
26
- :expiration_month => '05',
27
- :expiration_year => '2037',
28
- :billing_address => address_hash,
29
- }
30
-
31
9
  braintree_customer = Braintree::Customer.create!(:id => 'customer_id', :first_name => 'Brain', :last_name => 'Tree', :credit_card => credit_card_hash)
32
10
 
33
11
  credit_card = BraintreeRails::CreditCard.new(braintree_customer.credit_cards.first.token)
@@ -43,30 +21,6 @@ describe 'Credit Card Integration' do
43
21
 
44
22
  it 'should be able to add credit card' do
45
23
  customer = BraintreeRails::Customer.create!(:id => 'customer_id', :first_name => 'Brain', :last_name => 'Tree')
46
-
47
- address_hash = {
48
- :first_name => 'Brain',
49
- :last_name => 'Tree',
50
- :company => 'Braintree',
51
- :street_address => '1134 Crane Avenue',
52
- :extended_address => 'Suite 200',
53
- :locality => 'Menlo Park',
54
- :region => 'California',
55
- :postal_code => '94025',
56
- :country_name => 'United States of America'
57
- }
58
-
59
- credit_card_hash = {
60
- :token => 'credit_card_id',
61
- :number => '4111111111111111',
62
- :cvv => '123',
63
- :customer_id => 'customer_id',
64
- :cardholder_name => 'Brain Tree',
65
- :expiration_month => '05',
66
- :expiration_year => '2037',
67
- :billing_address => address_hash,
68
- }
69
-
70
24
  credit_card = customer.credit_cards.create!(credit_card_hash)
71
25
 
72
26
  braintree_credit_card = Braintree::CreditCard.find(credit_card.id)
@@ -82,30 +36,6 @@ describe 'Credit Card Integration' do
82
36
 
83
37
  it 'should be able to update existing credit card' do
84
38
  customer = BraintreeRails::Customer.create!(:id => 'customer_id', :first_name => 'Brain', :last_name => 'Tree')
85
-
86
- address_hash = {
87
- :first_name => 'Brain',
88
- :last_name => 'Tree',
89
- :company => 'Braintree',
90
- :street_address => '1134 Crane Avenue',
91
- :extended_address => 'Suite 200',
92
- :locality => 'Menlo Park',
93
- :region => 'California',
94
- :postal_code => '94025',
95
- :country_name => 'United States of America'
96
- }
97
-
98
- credit_card_hash = {
99
- :token => 'credit_card_id',
100
- :number => '4111111111111111',
101
- :cvv => '123',
102
- :customer_id => 'customer_id',
103
- :cardholder_name => 'Brain Tree',
104
- :expiration_month => '05',
105
- :expiration_year => '2037',
106
- :billing_address => address_hash,
107
- }
108
-
109
39
  credit_card = customer.credit_cards.create!(credit_card_hash)
110
40
 
111
41
  credit_card.update_attributes!(:cardholder_name => 'Foo Bar')
@@ -114,31 +44,9 @@ describe 'Credit Card Integration' do
114
44
  end
115
45
 
116
46
  it 'should be able to destroy existing credit card' do
117
- address_hash = {
118
- :first_name => 'Brain',
119
- :last_name => 'Tree',
120
- :company => 'Braintree',
121
- :street_address => '1134 Crane Avenue',
122
- :extended_address => 'Suite 200',
123
- :locality => 'Menlo Park',
124
- :region => 'California',
125
- :postal_code => '94025',
126
- :country_name => 'United States of America'
127
- }
128
-
129
- credit_card_hash = {
130
- :token => 'credit_card_id',
131
- :number => '4111111111111111',
132
- :cvv => '123',
133
- :cardholder_name => 'Brain Tree',
134
- :expiration_month => '05',
135
- :expiration_year => '2037',
136
- :billing_address => address_hash,
137
- }
138
-
139
47
  braintree_customer = Braintree::Customer.create!(:id => 'customer_id', :first_name => 'Brain', :last_name => 'Tree', :credit_card => credit_card_hash)
140
-
141
48
  credit_card = BraintreeRails::CreditCard.new(braintree_customer.credit_cards.first.token)
49
+
142
50
  credit_card.destroy!
143
51
  lambda{ Braintree::CreditCard.find(credit_card.token) }.must_raise Braintree::NotFoundError
144
52
  credit_card.persisted?.must_equal false
@@ -0,0 +1,50 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../integration_test_helper'))
2
+
3
+ describe 'Transaction Integration' do
4
+ before do
5
+ Braintree::Customer.all.each { |c| Braintree::Customer.delete c.id }
6
+ end
7
+
8
+ it 'should be able to create, submit, void transactions for a customer' do
9
+
10
+ braintree_customer = Braintree::Customer.create!(:id => 'customer_id', :first_name => 'Brain', :last_name => 'Tree', :credit_card => credit_card_hash)
11
+ customer = BraintreeRails::Customer.new(braintree_customer)
12
+ credit_card = customer.credit_cards.first
13
+
14
+ [{:amount => rand(1..10), :customer => customer}, {:amount => rand(1..10), :customer => customer, :credit_card => credit_card}].each do |params|
15
+ transaction = BraintreeRails::Transaction.create!(params)
16
+ transaction.persisted?.must_equal true
17
+ transaction.amount.must_equal params[:amount]
18
+ transaction.status.must_equal Braintree::Transaction::Status::Authorized
19
+
20
+ transaction.submit_for_settlement!
21
+ transaction.status.must_equal Braintree::Transaction::Status::SubmittedForSettlement
22
+
23
+ transaction.void!
24
+ transaction.status.must_equal Braintree::Transaction::Status::Voided
25
+ end
26
+ end
27
+
28
+ it "should be able to load transactions for given customer and credit_card" do
29
+ braintree_customer = Braintree::Customer.create!(:id => 'customer_id', :first_name => 'Brain', :last_name => 'Tree', :credit_card => credit_card_hash)
30
+ customer = BraintreeRails::Customer.new(braintree_customer)
31
+ credit_card = customer.credit_cards.first
32
+ transaction = BraintreeRails::Transaction.create!(:amount => rand(1..10), :customer => customer)
33
+
34
+ customer.transactions.count.must_equal 1
35
+ credit_card.transactions.count.must_equal 1
36
+ end
37
+
38
+ it 'should be able to capture braintree api errors' do
39
+ braintree_customer = Braintree::Customer.create!(:id => 'customer_id', :first_name => 'Brain', :last_name => 'Tree', :credit_card => credit_card_hash)
40
+ customer = BraintreeRails::Customer.new(braintree_customer)
41
+ credit_card = customer.credit_cards.first
42
+ transaction = BraintreeRails::Transaction.create!(:amount => rand(1..10), :customer => customer)
43
+
44
+ transaction.void!
45
+ transaction.submit_for_settlement.must_equal false
46
+ transaction.errors[:base].wont_be :blank?
47
+
48
+ lambda{transaction.submit_for_settlement!}.must_raise Braintree::ValidationsFailed
49
+ end
50
+ end
@@ -19,6 +19,32 @@ MiniTest::Unit::TestCase.class_eval do
19
19
  response = response.reverse_merge(:headers => {'Content-Type' => ['application/xml', 'charset=utf-8'], 'Content-Encoding' => 'gzip'})
20
20
  stub_request(method, BraintreeBaseUri+path).to_return(response)
21
21
  end
22
+
23
+ def address_hash
24
+ {
25
+ :first_name => 'Brain',
26
+ :last_name => 'Tree',
27
+ :company => 'Braintree',
28
+ :street_address => '1134 Crane Avenue',
29
+ :extended_address => 'Suite 200',
30
+ :locality => 'Menlo Park',
31
+ :region => 'California',
32
+ :postal_code => '94025',
33
+ :country_name => 'United States of America'
34
+ }
35
+ end
36
+
37
+ def credit_card_hash
38
+ {
39
+ :token => 'credit_card_id',
40
+ :number => '4111111111111111',
41
+ :cvv => '123',
42
+ :cardholder_name => 'Brain Tree',
43
+ :expiration_month => '05',
44
+ :expiration_year => '2037',
45
+ :billing_address => address_hash,
46
+ }
47
+ end
22
48
  end
23
49
 
24
50
  String.class_eval do
@@ -0,0 +1,132 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../unit_test_helper'))
2
+
3
+ describe BraintreeRails::Transaction do
4
+ before do
5
+ stub_braintree_request(:get, '/customers/customer_id', :body => fixture('customer.xml'))
6
+ stub_braintree_request(:get, '/payment_methods/credit_card_id', :body => fixture('credit_card.xml'))
7
+ stub_braintree_request(:get, '/transactions/transactionid', :body => fixture('transaction.xml'))
8
+ end
9
+
10
+ describe '#initialize' do
11
+ it 'should find transaction from braintree when given a transaction id' do
12
+ braintree_transaction = Braintree::Transaction.find('transactionid')
13
+ transaction = BraintreeRails::Transaction.new('transactionid')
14
+
15
+ transaction.persisted?.must_equal true
16
+ [:amount, :created_at, :updated_at].each do |attribute|
17
+ transaction.send(attribute).must_equal braintree_transaction.send(attribute)
18
+ end
19
+ end
20
+
21
+ it 'should wrap a Braintree::Transaction' do
22
+ braintree_transaction = Braintree::Transaction.find('transactionid')
23
+ transaction = BraintreeRails::Transaction.new(braintree_transaction)
24
+
25
+ transaction.persisted?.must_equal true
26
+ [:amount, :created_at, :updated_at].each do |attribute|
27
+ transaction.send(attribute).must_equal braintree_transaction.send(attribute)
28
+ end
29
+ end
30
+
31
+ it 'should extract values from hash' do
32
+ transaction = BraintreeRails::Transaction.new(:id => 'new_id')
33
+
34
+ transaction.persisted?.must_equal false
35
+ transaction.id.must_equal 'new_id'
36
+ end
37
+
38
+ it 'should try to extract value from other types' do
39
+ transaction = BraintreeRails::Transaction.new(OpenStruct.new(:id => 'foobar', :amount => '10.00', :persisted? => true))
40
+
41
+ transaction.persisted?.must_equal true
42
+ transaction.id.must_equal 'foobar'
43
+ transaction.amount.must_equal '10.00'
44
+
45
+ transaction = BraintreeRails::Transaction.new(Object.new)
46
+ transaction.persisted?.must_equal false
47
+ end
48
+ end
49
+
50
+ [:customer, :credit_card].each do |association|
51
+ describe association do
52
+ it "should load #{association} for persisted transaction" do
53
+ transaction = BraintreeRails::Transaction.new('transactionid')
54
+ transaction.send(association).persisted?.must_equal true
55
+ end
56
+ end
57
+ end
58
+
59
+ describe 'validations' do
60
+ it 'should validate amount' do
61
+ [nil, 'abc', -1].each do |invalid_value|
62
+ transaction = BraintreeRails::Transaction.new(:amount => invalid_value)
63
+ transaction.valid?.must_equal false
64
+ transaction.errors[:amount].wont_be :blank?
65
+ end
66
+ end
67
+ end
68
+
69
+ describe 'persistence' do
70
+ before do
71
+ stub_braintree_request(:post, '/transactions', :body => fixture('transaction.xml'))
72
+ end
73
+
74
+ it 'should create a sale transaction' do
75
+ customer = BraintreeRails::Customer.find('customer_id')
76
+ credit_card = BraintreeRails::CreditCard.find('credit_card_id')
77
+ transaction = BraintreeRails::Transaction.new(:amount => '10.00', :customer => customer, :credit_card => credit_card)
78
+
79
+ transaction.save.must_equal true
80
+ transaction.status.must_equal Braintree::Transaction::Status::Authorized
81
+ end
82
+
83
+ it 'should use default credit card of customer if credit_card is not specified' do
84
+ customer = BraintreeRails::Customer.find('customer_id')
85
+ transaction = BraintreeRails::Transaction.new(:amount => '10.00', :customer => customer)
86
+ transaction.save.must_equal true
87
+ transaction.status.must_equal Braintree::Transaction::Status::Authorized
88
+ end
89
+
90
+ it "should be able to submit_for_settlement a transaction" do
91
+ customer = BraintreeRails::Customer.find('customer_id')
92
+ credit_card = BraintreeRails::CreditCard.find('credit_card_id')
93
+ transaction = BraintreeRails::Transaction.new(:amount => '10.00', :customer => customer, :credit_card => credit_card)
94
+ transaction.save!
95
+ stub_braintree_request(:put, "/transactions/#{transaction.id}/submit_for_settlement", :body => fixture('transaction.xml'))
96
+ transaction.submit_for_settlement.must_equal true
97
+ end
98
+
99
+ it "should be able to refund a transaction" do
100
+ customer = BraintreeRails::Customer.find('customer_id')
101
+ credit_card = BraintreeRails::CreditCard.find('credit_card_id')
102
+ transaction = BraintreeRails::Transaction.new(:amount => '10.00', :customer => customer, :credit_card => credit_card)
103
+ transaction.save!
104
+ stub_braintree_request(:post, "/transactions/#{transaction.id}/refund", :body => fixture('transaction.xml'))
105
+ transaction.refund.must_equal true
106
+ end
107
+
108
+ it "should be able to void a transaction" do
109
+ customer = BraintreeRails::Customer.find('customer_id')
110
+ credit_card = BraintreeRails::CreditCard.find('credit_card_id')
111
+ transaction = BraintreeRails::Transaction.new(:amount => '10.00', :customer => customer, :credit_card => credit_card)
112
+ transaction.save!
113
+ stub_braintree_request(:put, "/transactions/#{transaction.id}/void", :body => fixture('transaction.xml'))
114
+ transaction.void.must_equal true
115
+ end
116
+
117
+ it 'should show errors when trying to submit already voided transaction' do
118
+ customer = BraintreeRails::Customer.find('customer_id')
119
+ credit_card = BraintreeRails::CreditCard.find('credit_card_id')
120
+ transaction = BraintreeRails::Transaction.new(:amount => '10.00', :customer => customer, :credit_card => credit_card)
121
+ transaction.save!
122
+ stub_braintree_request(:put, "/transactions/#{transaction.id}/void", :body => fixture('transaction.xml'))
123
+ transaction.void.must_equal true
124
+
125
+ stub_braintree_request(:put, "/transactions/#{transaction.id}/submit_for_settlement", :status => 422, :body => fixture('transaction_error.xml'))
126
+ transaction.submit_for_settlement.must_equal false
127
+ transaction.errors[:base].wont_be :blank?
128
+
129
+ lambda{transaction.submit_for_settlement!}.must_raise Braintree::ValidationsFailed
130
+ end
131
+ end
132
+ end