braintree 2.31.0 → 2.32.1

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.
Files changed (51) hide show
  1. data/README.rdoc +2 -2
  2. data/lib/braintree.rb +12 -0
  3. data/lib/braintree/client_token.rb +5 -0
  4. data/lib/braintree/client_token_gateway.rb +2 -1
  5. data/lib/braintree/configuration.rb +1 -1
  6. data/lib/braintree/credit_card.rb +1 -1
  7. data/lib/braintree/credit_card_gateway.rb +3 -3
  8. data/lib/braintree/customer.rb +18 -4
  9. data/lib/braintree/customer_gateway.rb +2 -2
  10. data/lib/braintree/customer_search.rb +1 -0
  11. data/lib/braintree/error_codes.rb +81 -14
  12. data/lib/braintree/exceptions.rb +2 -0
  13. data/lib/braintree/gateway.rb +16 -0
  14. data/lib/braintree/payment_instrument_type.rb +7 -0
  15. data/lib/braintree/payment_method.rb +17 -0
  16. data/lib/braintree/payment_method_gateway.rb +58 -0
  17. data/lib/braintree/paypal_account.rb +47 -0
  18. data/lib/braintree/paypal_account_gateway.rb +41 -0
  19. data/lib/braintree/sepa_bank_account.rb +34 -0
  20. data/lib/braintree/sepa_bank_account_gateway.rb +16 -0
  21. data/lib/braintree/successful_result.rb +1 -1
  22. data/lib/braintree/test/nonce.rb +10 -0
  23. data/lib/braintree/test_transaction.rb +15 -0
  24. data/lib/braintree/testing_gateway.rb +35 -0
  25. data/lib/braintree/transaction.rb +6 -0
  26. data/lib/braintree/transaction/paypal_details.rb +14 -0
  27. data/lib/braintree/transaction_gateway.rb +3 -1
  28. data/lib/braintree/transaction_search.rb +4 -0
  29. data/lib/braintree/unknown_payment_method.rb +20 -0
  30. data/lib/braintree/version.rb +2 -2
  31. data/lib/braintree/webhook_testing_gateway.rb +1 -1
  32. data/spec/integration/braintree/client_api/client_token_spec.rb +80 -17
  33. data/spec/integration/braintree/client_api/spec_helper.rb +93 -10
  34. data/spec/integration/braintree/credit_card_spec.rb +28 -27
  35. data/spec/integration/braintree/customer_search_spec.rb +23 -0
  36. data/spec/integration/braintree/customer_spec.rb +83 -1
  37. data/spec/integration/braintree/payment_method_spec.rb +315 -0
  38. data/spec/integration/braintree/paypal_account_spec.rb +188 -0
  39. data/spec/integration/braintree/subscription_spec.rb +50 -20
  40. data/spec/integration/braintree/test_transaction_spec.rb +104 -0
  41. data/spec/integration/braintree/transaction_search_spec.rb +60 -0
  42. data/spec/integration/braintree/transaction_spec.rb +583 -8
  43. data/spec/integration/spec_helper.rb +22 -0
  44. data/spec/spec_helper.rb +8 -2
  45. data/spec/unit/braintree/customer_spec.rb +24 -4
  46. data/spec/unit/braintree/payment_method_spec.rb +25 -0
  47. data/spec/unit/braintree/paypal_account_spec.rb +31 -0
  48. data/spec/unit/braintree/unknown_payment_method_spec.rb +29 -0
  49. metadata +141 -120
  50. checksums.yaml +0 -7
  51. data/spec/httpsd.pid +0 -1
@@ -0,0 +1,188 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+ require File.expand_path(File.dirname(__FILE__) + "/client_api/spec_helper")
3
+
4
+ describe Braintree::PayPalAccount do
5
+ describe "self.find" do
6
+ it "returns a PayPalAccount" do
7
+ customer = Braintree::Customer.create!
8
+ payment_method_token = "paypal-account-#{Time.now.to_i}"
9
+
10
+ nonce = nonce_for_paypal_account(
11
+ :consent_code => "consent-code",
12
+ :token => payment_method_token
13
+ )
14
+ result = Braintree::PaymentMethod.create(
15
+ :payment_method_nonce => nonce,
16
+ :customer_id => customer.id
17
+ )
18
+ result.should be_success
19
+
20
+ paypal_account = Braintree::PayPalAccount.find(payment_method_token)
21
+ paypal_account.should be_a(Braintree::PayPalAccount)
22
+ paypal_account.token.should == payment_method_token
23
+ paypal_account.email.should == "jane.doe@example.com"
24
+ paypal_account.image_url.should_not be_nil
25
+ paypal_account.created_at.should_not be_nil
26
+ paypal_account.updated_at.should_not be_nil
27
+ end
28
+
29
+ it "raises if the payment method token is not found" do
30
+ expect do
31
+ Braintree::PayPalAccount.find("nonexistant-paypal-account")
32
+ end.to raise_error(Braintree::NotFoundError)
33
+ end
34
+
35
+ it "does not return a different payment method type" do
36
+ customer = Braintree::Customer.create!
37
+ result = Braintree::CreditCard.create(
38
+ :customer_id => customer.id,
39
+ :number => Braintree::Test::CreditCardNumbers::Visa,
40
+ :expiration_date => "05/2009",
41
+ :cvv => "100",
42
+ :token => "CREDIT_CARD_TOKEN"
43
+ )
44
+
45
+ expect do
46
+ Braintree::PayPalAccount.find("CREDIT_CARD_TOKEN")
47
+ end.to raise_error(Braintree::NotFoundError)
48
+ end
49
+ end
50
+
51
+ describe "self.update" do
52
+ it "updates a paypal account's token" do
53
+ customer = Braintree::Customer.create!
54
+ original_token = "paypal-account-#{Time.now.to_i}"
55
+ nonce = nonce_for_paypal_account(
56
+ :consent_code => "consent-code",
57
+ :token => original_token
58
+ )
59
+ original_result = Braintree::PaymentMethod.create(
60
+ :payment_method_nonce => nonce,
61
+ :customer_id => customer.id
62
+ )
63
+
64
+ updated_token = "UPDATED_TOKEN-" + rand(36**3).to_s(36)
65
+ updated_result = Braintree::PayPalAccount.update(
66
+ original_token,
67
+ :token => updated_token
68
+ )
69
+
70
+ updated_paypal_account = Braintree::PayPalAccount.find(updated_token)
71
+ updated_paypal_account.email.should == original_result.payment_method.email
72
+
73
+ expect do
74
+ Braintree::PayPalAccount.find(original_token)
75
+ end.to raise_error(Braintree::NotFoundError, "payment method with token \"#{original_token}\" not found")
76
+ end
77
+
78
+ it "can make a paypal account the default payment method" do
79
+ customer = Braintree::Customer.create!
80
+ result = Braintree::CreditCard.create(
81
+ :customer_id => customer.id,
82
+ :number => Braintree::Test::CreditCardNumbers::Visa,
83
+ :expiration_date => "05/2009",
84
+ :options => {:make_default => true}
85
+ )
86
+ result.should be_success
87
+
88
+ nonce = nonce_for_paypal_account(:consent_code => "consent-code")
89
+ original_token = Braintree::PaymentMethod.create(
90
+ :payment_method_nonce => nonce,
91
+ :customer_id => customer.id
92
+ ).payment_method.token
93
+
94
+ updated_result = Braintree::PayPalAccount.update(
95
+ original_token,
96
+ :options => {:make_default => true}
97
+ )
98
+
99
+ updated_paypal_account = Braintree::PayPalAccount.find(original_token)
100
+ updated_paypal_account.should be_default
101
+ end
102
+
103
+ it "returns an error if a token for account is used to attempt an update" do
104
+ customer = Braintree::Customer.create!
105
+ first_token = "paypal-account-#{rand(36**3).to_s(36)}"
106
+ second_token = "paypal-account-#{rand(36**3).to_s(36)}"
107
+
108
+ first_nonce = nonce_for_paypal_account(
109
+ :consent_code => "consent-code",
110
+ :token => first_token
111
+ )
112
+ first_result = Braintree::PaymentMethod.create(
113
+ :payment_method_nonce => first_nonce,
114
+ :customer_id => customer.id
115
+ )
116
+
117
+ second_nonce = nonce_for_paypal_account(
118
+ :consent_code => "consent-code",
119
+ :token => second_token
120
+ )
121
+ second_result = Braintree::PaymentMethod.create(
122
+ :payment_method_nonce => second_nonce,
123
+ :customer_id => customer.id
124
+ )
125
+
126
+ updated_result = Braintree::PayPalAccount.update(
127
+ first_token,
128
+ :token => second_token
129
+ )
130
+
131
+ updated_result.should_not be_success
132
+ updated_result.errors.first.code.should == "92906"
133
+ end
134
+ end
135
+
136
+ context "self.delete" do
137
+ it "deletes a PayPal account" do
138
+ customer = Braintree::Customer.create!
139
+ token = "paypal-account-#{Time.now.to_i}"
140
+
141
+ nonce = nonce_for_paypal_account(
142
+ :consent_code => "consent-code",
143
+ :token => token
144
+ )
145
+ Braintree::PaymentMethod.create(
146
+ :payment_method_nonce => nonce,
147
+ :customer_id => customer.id
148
+ )
149
+
150
+ result = Braintree::PayPalAccount.delete(token)
151
+
152
+ expect do
153
+ Braintree::PayPalAccount.find(token)
154
+ end.to raise_error(Braintree::NotFoundError, "payment method with token \"#{token}\" not found")
155
+ end
156
+ end
157
+
158
+ context "self.sale" do
159
+ it "creates a transaction using a paypal account and returns a result object" do
160
+ customer = Braintree::Customer.create!(
161
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment
162
+ )
163
+
164
+ result = Braintree::PayPalAccount.sale(customer.paypal_accounts[0].token, :amount => "100.00")
165
+
166
+ result.success?.should == true
167
+ result.transaction.amount.should == BigDecimal.new("100.00")
168
+ result.transaction.type.should == "sale"
169
+ result.transaction.customer_details.id.should == customer.id
170
+ result.transaction.paypal_details.token.should == customer.paypal_accounts[0].token
171
+ end
172
+ end
173
+
174
+ context "self.sale!" do
175
+ it "creates a transaction using a paypal account and returns a transaction" do
176
+ customer = Braintree::Customer.create!(
177
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment
178
+ )
179
+
180
+ transaction = Braintree::PayPalAccount.sale!(customer.paypal_accounts[0].token, :amount => "100.00")
181
+
182
+ transaction.amount.should == BigDecimal.new("100.00")
183
+ transaction.type.should == "sale"
184
+ transaction.customer_details.id.should == customer.id
185
+ transaction.paypal_details.token.should == customer.paypal_accounts[0].token
186
+ end
187
+ end
188
+ end
@@ -64,26 +64,56 @@ describe Braintree::Subscription do
64
64
  result.subscription.id.should == new_id
65
65
  end
66
66
 
67
- it "creates a subscription when given a payment_method_nonce" do
68
- nonce = nonce_for_new_credit_card(
69
- :credit_card => {
70
- :number => Braintree::Test::CreditCardNumbers::Visa,
71
- :expiration_month => "11",
72
- :expiration_year => "2099",
73
- },
74
- :client_token_options => {
75
- :customer_id => @credit_card.customer_id
76
- }
77
- )
78
- result = Braintree::Subscription.create(
79
- :payment_method_nonce => nonce,
80
- :plan_id => SpecHelper::TriallessPlan[:id]
81
- )
67
+ context "with payment_method_nonces" do
68
+ it "creates a subscription when given a credit card payment_method_nonce" do
69
+ nonce = nonce_for_new_payment_method(
70
+ :credit_card => {
71
+ :number => Braintree::Test::CreditCardNumbers::Visa,
72
+ :expiration_month => "11",
73
+ :expiration_year => "2099",
74
+ },
75
+ :client_token_options => {
76
+ :customer_id => @credit_card.customer_id
77
+ }
78
+ )
79
+ result = Braintree::Subscription.create(
80
+ :payment_method_nonce => nonce,
81
+ :plan_id => SpecHelper::TriallessPlan[:id]
82
+ )
82
83
 
83
- result.success?.should == true
84
- transaction = result.subscription.transactions[0]
85
- transaction.credit_card_details.bin.should == Braintree::Test::CreditCardNumbers::Visa[0, 6]
86
- transaction.credit_card_details.last_4.should == Braintree::Test::CreditCardNumbers::Visa[-4, 4]
84
+ result.success?.should == true
85
+ transaction = result.subscription.transactions[0]
86
+ transaction.credit_card_details.bin.should == Braintree::Test::CreditCardNumbers::Visa[0, 6]
87
+ transaction.credit_card_details.last_4.should == Braintree::Test::CreditCardNumbers::Visa[-4, 4]
88
+ end
89
+
90
+ it "creates a subscription when given a paypal account payment_method_nonce" do
91
+ customer = Braintree::Customer.create!
92
+ payment_method_result = Braintree::PaymentMethod.create(
93
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment,
94
+ :customer_id => customer.id
95
+ )
96
+
97
+ result = Braintree::Subscription.create(
98
+ :payment_method_token => payment_method_result.payment_method.token,
99
+ :plan_id => SpecHelper::TriallessPlan[:id]
100
+ )
101
+
102
+ result.should be_success
103
+ transaction = result.subscription.transactions[0]
104
+ transaction.paypal_details.payer_email.should == "payer@example.com"
105
+ end
106
+
107
+ it "returns an error if the payment_method_nonce hasn't been vaulted" do
108
+ customer = Braintree::Customer.create!
109
+ result = Braintree::Subscription.create(
110
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment,
111
+ :plan_id => SpecHelper::TriallessPlan[:id]
112
+ )
113
+
114
+ result.should_not be_success
115
+ result.errors.for(:subscription).on(:payment_method_nonce).first.code.should == '91925'
116
+ end
87
117
  end
88
118
 
89
119
  context "billing_day_of_month" do
@@ -691,7 +721,7 @@ describe Braintree::Subscription do
691
721
  end
692
722
 
693
723
  it "allows changing the payment_method by payment_method_nonce" do
694
- nonce = nonce_for_new_credit_card(
724
+ nonce = nonce_for_new_payment_method(
695
725
  :credit_card => {
696
726
  :number => Braintree::Test::CreditCardNumbers::MasterCard,
697
727
  :expiration_date => "05/2010"
@@ -0,0 +1,104 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+ require File.expand_path(File.dirname(__FILE__) + "/client_api/spec_helper")
3
+
4
+ describe Braintree::TestTransaction do
5
+ context "testing" do
6
+ it "changes transaction status to settled" do
7
+ sale_result = Braintree::Transaction.sale(
8
+ :amount => "100",
9
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment,
10
+ :options => {
11
+ :submit_for_settlement => true
12
+ }
13
+ )
14
+ sale_result.success?.should == true
15
+ sale_result.transaction.status.should == Braintree::Transaction::Status::SubmittedForSettlement
16
+
17
+ settle_result = Braintree::TestTransaction.settle(sale_result.transaction.id)
18
+ settle_result.transaction.status.should == Braintree::Transaction::Status::Settled
19
+ settle_result.success?.should == true
20
+ end
21
+
22
+ it "changes transaction status to settlement_confirmed" do
23
+ sale_result = Braintree::Transaction.sale(
24
+ :amount => "100",
25
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment,
26
+ :options => {
27
+ :submit_for_settlement => true
28
+ }
29
+ )
30
+ sale_result.success?.should == true
31
+ sale_result.transaction.status.should == Braintree::Transaction::Status::SubmittedForSettlement
32
+
33
+ settle_result = Braintree::TestTransaction.settlement_confirm(sale_result.transaction.id)
34
+ settle_result.transaction.status.should == Braintree::Transaction::Status::SettlementConfirmed
35
+ settle_result.success?.should == true
36
+ end
37
+
38
+ it "changes transaction status to settlement_declined" do
39
+ sale_result = Braintree::Transaction.sale(
40
+ :amount => "100",
41
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment,
42
+ :options => {
43
+ :submit_for_settlement => true
44
+ }
45
+ )
46
+ sale_result.success?.should == true
47
+ sale_result.transaction.status.should == Braintree::Transaction::Status::SubmittedForSettlement
48
+
49
+ settle_result = Braintree::TestTransaction.settlement_decline(sale_result.transaction.id)
50
+ settle_result.transaction.status.should == Braintree::Transaction::Status::SettlementDeclined
51
+ settle_result.success?.should == true
52
+ end
53
+
54
+ it "returns a validation error when invalid transition is specified" do
55
+ sale_result = Braintree::Transaction.sale(
56
+ :amount => "100",
57
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment
58
+ )
59
+ sale_result.success?.should == true
60
+
61
+ settle_result = Braintree::TestTransaction.settlement_decline(sale_result.transaction.id)
62
+ settle_result.success?.should be_false
63
+ settle_result.errors.for(:transaction).on(:base).first.code.should == Braintree::ErrorCodes::Transaction::CannotSimulateTransactionSettlement
64
+ end
65
+ end
66
+
67
+ context "mistakenly testing in production" do
68
+ def in_prod
69
+ old_environment = Braintree::Configuration.environment
70
+ Braintree::Configuration.environment = :production
71
+ begin
72
+ yield
73
+ ensure
74
+ Braintree::Configuration.environment = old_environment
75
+ end
76
+ end
77
+
78
+
79
+ it "raises an exception if settle is called in a production environment" do
80
+ expect do
81
+ in_prod do
82
+ Braintree::TestTransaction.settle(nil)
83
+ end
84
+ end.to raise_error(Braintree::TestOperationPerformedInProduction)
85
+ end
86
+
87
+ it "raises an exception if settlement_decline is called in a production environment" do
88
+ expect do
89
+ in_prod do
90
+ Braintree::TestTransaction.settlement_decline(nil)
91
+ end
92
+ end.to raise_error(Braintree::TestOperationPerformedInProduction)
93
+ end
94
+
95
+ it "raises an exception if settlement_confirm is called in a production environment" do
96
+ expect do
97
+ in_prod do
98
+ Braintree::TestTransaction.settlement_confirm(nil)
99
+ end
100
+ end.to raise_error(Braintree::TestOperationPerformedInProduction)
101
+ end
102
+ end
103
+
104
+ end
@@ -1,4 +1,5 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+ require File.expand_path(File.dirname(__FILE__) + "/client_api/spec_helper")
2
3
 
3
4
  describe Braintree::Transaction, "search" do
4
5
  context "advanced" do
@@ -127,6 +128,65 @@ describe Braintree::Transaction, "search" do
127
128
  collection.first.id.should == transaction.id
128
129
  end
129
130
 
131
+ it "searches on paypal transactions" do
132
+ transaction = Braintree::Transaction.sale!(
133
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
134
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment
135
+ )
136
+
137
+ paypal_details = transaction.paypal_details
138
+
139
+ collection = Braintree::Transaction.search do |search|
140
+ search.paypal_payment_id.is paypal_details.payment_id
141
+ search.paypal_authorization_id.is paypal_details.authorization_id
142
+ search.paypal_payer_email.is paypal_details.payer_email
143
+ end
144
+
145
+ collection.maximum_size.should == 1
146
+ collection.first.id.should == transaction.id
147
+ end
148
+
149
+ context "SEPA bank account transactions" do
150
+ it "does" do
151
+ with_altpay_merchant do
152
+ config = Braintree::Configuration.instantiate
153
+ customer = Braintree::Customer.create.customer
154
+ raw_client_token = Braintree::ClientToken.generate(:customer_id => customer.id, :sepa_mandate_type => Braintree::SEPABankAccount::MandateType::Business)
155
+ client_token = decode_client_token(raw_client_token)
156
+ authorization_fingerprint = client_token["authorizationFingerprint"]
157
+ http = ClientApiHttp.new(
158
+ config,
159
+ :authorization_fingerprint => authorization_fingerprint
160
+ )
161
+
162
+ nonce = http.create_sepa_bank_account_nonce(
163
+ :accountHolderName => "Bob Holder",
164
+ :iban => "DE89370400440532013000",
165
+ :bic => "DEUTDEFF",
166
+ :locale => "en-US",
167
+ :billingAddress => {
168
+ :region => "Hesse",
169
+ :country_name => "Germany"
170
+ }
171
+ )
172
+ nonce.should_not == nil
173
+
174
+ transaction = Braintree::Transaction.sale!(
175
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
176
+ :payment_method_nonce => nonce,
177
+ :merchant_account_id => "fake_sepa_ma"
178
+ )
179
+
180
+ collection = Braintree::Transaction.search do |search|
181
+ search.sepa_bank_account_iban.is "DE89370400440532013000"
182
+ end
183
+
184
+ collection.maximum_size.should >= 1
185
+ collection.map(&:id).should include(transaction.id)
186
+ end
187
+ end
188
+ end
189
+
130
190
  context "multiple value fields" do
131
191
  it "searches on created_using" do
132
192
  transaction = Braintree::Transaction.sale!(
@@ -133,6 +133,136 @@ describe Braintree::Transaction do
133
133
  }
134
134
  )
135
135
  result.transaction.credit_card_details.prepaid.should == Braintree::CreditCard::Prepaid::Yes
136
+ result.transaction.payment_instrument_type.should == Braintree::PaymentInstrumentType::CreditCard
137
+ end
138
+ end
139
+
140
+ describe "industry data" do
141
+ it "accepts valid industry data" do
142
+ result = Braintree::Transaction.create(
143
+ :type => "sale",
144
+ :amount => 1_00,
145
+ :credit_card => {
146
+ :number => Braintree::Test::CreditCardNumbers::CardTypeIndicators::Prepaid,
147
+ :expiration_date => "05/2009"
148
+ },
149
+ :industry => {
150
+ :industry_type => Braintree::Transaction::IndustryType::Lodging,
151
+ :data => {
152
+ :folio_number => "ABCDEFG",
153
+ :check_in_date => "2014-06-01",
154
+ :check_out_date => "2014-06-30"
155
+ }
156
+ }
157
+ )
158
+ result.success?.should be_true
159
+ end
160
+
161
+ it "returns errors if validations on industry data fails" do
162
+ result = Braintree::Transaction.create(
163
+ :type => "sale",
164
+ :amount => 1_00,
165
+ :credit_card => {
166
+ :number => Braintree::Test::CreditCardNumbers::CardTypeIndicators::Prepaid,
167
+ :expiration_date => "05/2009"
168
+ },
169
+ :industry => {
170
+ :industry_type => Braintree::Transaction::IndustryType::Lodging,
171
+ :data => {
172
+ :folio_number => "foo bar",
173
+ :check_in_date => "2014-06-30",
174
+ :check_out_date => "2014-06-01"
175
+ }
176
+ }
177
+ )
178
+ result.success?.should be_false
179
+ result.errors.for(:transaction).for(:industry).map { |e| e.code }.sort.should == ["93403", "93406"]
180
+ end
181
+ end
182
+
183
+ describe "industry data" do
184
+ it "accepts valid industry data" do
185
+ result = Braintree::Transaction.create(
186
+ :type => "sale",
187
+ :amount => 1_00,
188
+ :credit_card => {
189
+ :number => Braintree::Test::CreditCardNumbers::CardTypeIndicators::Prepaid,
190
+ :expiration_date => "05/2009"
191
+ },
192
+ :industry => {
193
+ :industry_type => Braintree::Transaction::IndustryType::Lodging,
194
+ :data => {
195
+ :folio_number => "ABCDEFG",
196
+ :check_in_date => "2014-06-01",
197
+ :check_out_date => "2014-06-30"
198
+ }
199
+ }
200
+ )
201
+ result.success?.should be_true
202
+ end
203
+
204
+ it "returns errors if validations on industry data fails" do
205
+ result = Braintree::Transaction.create(
206
+ :type => "sale",
207
+ :amount => 1_00,
208
+ :credit_card => {
209
+ :number => Braintree::Test::CreditCardNumbers::CardTypeIndicators::Prepaid,
210
+ :expiration_date => "05/2009"
211
+ },
212
+ :industry => {
213
+ :industry_type => Braintree::Transaction::IndustryType::Lodging,
214
+ :data => {
215
+ :folio_number => "foo bar",
216
+ :check_in_date => "2014-06-30",
217
+ :check_out_date => "2014-06-01"
218
+ }
219
+ }
220
+ )
221
+ result.success?.should be_false
222
+ result.errors.for(:transaction).for(:industry).map { |e| e.code }.sort.should == ["93403", "93406"]
223
+ end
224
+ end
225
+
226
+ describe "industry data" do
227
+ it "accepts valid industry data" do
228
+ result = Braintree::Transaction.create(
229
+ :type => "sale",
230
+ :amount => 1_00,
231
+ :credit_card => {
232
+ :number => Braintree::Test::CreditCardNumbers::CardTypeIndicators::Prepaid,
233
+ :expiration_date => "05/2009"
234
+ },
235
+ :industry => {
236
+ :industry_type => Braintree::Transaction::IndustryType::Lodging,
237
+ :data => {
238
+ :folio_number => "ABCDEFG",
239
+ :check_in_date => "2014-06-01",
240
+ :check_out_date => "2014-06-30"
241
+ }
242
+ }
243
+ )
244
+ result.success?.should be_true
245
+ end
246
+
247
+ it "returns errors if validations on industry data fails" do
248
+ result = Braintree::Transaction.create(
249
+ :type => "sale",
250
+ :amount => 1_00,
251
+ :credit_card => {
252
+ :number => Braintree::Test::CreditCardNumbers::CardTypeIndicators::Prepaid,
253
+ :expiration_date => "05/2009"
254
+ },
255
+ :industry => {
256
+ :industry_type => Braintree::Transaction::IndustryType::Lodging,
257
+ :data => {
258
+ :folio_number => "foo bar",
259
+ :check_in_date => "2014-06-30",
260
+ :check_out_date => "2014-06-01"
261
+ }
262
+ }
263
+ )
264
+ result.success?.should be_false
265
+ result.errors.for(:transaction).for(:industry).map { |e| e.code }.sort.should == ["93403", "93406"]
136
266
  end
137
267
  end
138
268
 
@@ -1099,8 +1229,8 @@ describe Braintree::Transaction do
1099
1229
  end
1100
1230
 
1101
1231
  context "client API" do
1102
- it "can create a transaction with a nonce" do
1103
- nonce = nonce_for_new_credit_card(
1232
+ it "can create a transaction with a shared card nonce" do
1233
+ nonce = nonce_for_new_payment_method(
1104
1234
  :credit_card => {
1105
1235
  :number => "4111111111111111",
1106
1236
  :expiration_month => "11",
@@ -1108,16 +1238,383 @@ describe Braintree::Transaction do
1108
1238
  },
1109
1239
  :share => true
1110
1240
  )
1241
+ nonce.should_not be_nil
1111
1242
 
1112
1243
  result = Braintree::Transaction.create(
1113
1244
  :type => "sale",
1114
1245
  :amount => Braintree::Test::TransactionAmounts::Authorize,
1115
1246
  :payment_method_nonce => nonce
1116
1247
  )
1248
+ result.success?.should == true
1249
+ end
1117
1250
 
1251
+ it "can create a transaction with a vaulted card nonce" do
1252
+ customer = Braintree::Customer.create!
1253
+ nonce = nonce_for_new_payment_method(
1254
+ :credit_card => {
1255
+ :number => "4111111111111111",
1256
+ :expiration_month => "11",
1257
+ :expiration_year => "2099",
1258
+ },
1259
+ :client_token_options => {
1260
+ :customer_id => customer.id,
1261
+ }
1262
+ )
1263
+ nonce.should_not be_nil
1264
+
1265
+ result = Braintree::Transaction.create(
1266
+ :type => "sale",
1267
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1268
+ :payment_method_nonce => nonce
1269
+ )
1270
+ result.success?.should == true
1271
+ end
1272
+
1273
+ it "can create a transaction with a vaulted PayPal account" do
1274
+ customer = Braintree::Customer.create!
1275
+ nonce = nonce_for_new_payment_method(
1276
+ :paypal_account => {
1277
+ :consent_code => "PAYPAL_CONSENT_CODE",
1278
+ },
1279
+ :client_token_options => {
1280
+ :customer_id => customer.id,
1281
+ }
1282
+ )
1283
+ nonce.should_not be_nil
1284
+
1285
+ result = Braintree::Transaction.create(
1286
+ :type => "sale",
1287
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1288
+ :payment_method_nonce => nonce
1289
+ )
1290
+ result.success?.should == true
1291
+ end
1292
+
1293
+ it "can create a transaction with a params nonce with PayPal account params" do
1294
+ customer = Braintree::Customer.create!
1295
+ nonce = nonce_for_new_payment_method(
1296
+ :paypal_account => {
1297
+ :consent_code => "PAYPAL_CONSENT_CODE",
1298
+ }
1299
+ )
1300
+ nonce.should_not be_nil
1301
+
1302
+ result = Braintree::Transaction.create(
1303
+ :type => "sale",
1304
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1305
+ :payment_method_nonce => nonce
1306
+ )
1118
1307
  result.success?.should == true
1119
1308
  end
1120
1309
  end
1310
+
1311
+ context "three_d_secure" do
1312
+ it "can create a transaction with a three_d_secure token" do
1313
+ three_d_secure_token = SpecHelper.create_3ds_verification(
1314
+ SpecHelper::ThreeDSecureMerchantAccountId,
1315
+ :number => Braintree::Test::CreditCardNumbers::Visa,
1316
+ :expiration_month => "12",
1317
+ :expiration_year => "2012"
1318
+ )
1319
+
1320
+ result = Braintree::Transaction.create(
1321
+ :type => "sale",
1322
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1323
+ :credit_card => {
1324
+ :number => Braintree::Test::CreditCardNumbers::Visa,
1325
+ :expiration_date => "12/12",
1326
+ },
1327
+ :three_d_secure_token => three_d_secure_token
1328
+ )
1329
+
1330
+ result.success?.should == true
1331
+ end
1332
+
1333
+ it "can create a transaction without a three_d_secure token" do
1334
+ result = Braintree::Transaction.create(
1335
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
1336
+ :type => "sale",
1337
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1338
+ :credit_card => {
1339
+ :number => Braintree::Test::CreditCardNumbers::Visa,
1340
+ :expiration_date => "12/12",
1341
+ }
1342
+ )
1343
+ result.success?.should == true
1344
+ end
1345
+
1346
+ it "returns an error if sent a nil three_d_secure token" do
1347
+ result = Braintree::Transaction.create(
1348
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
1349
+ :type => "sale",
1350
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1351
+ :credit_card => {
1352
+ :number => Braintree::Test::CreditCardNumbers::Visa,
1353
+ :expiration_date => "12/12",
1354
+ },
1355
+ :three_d_secure_token => nil
1356
+ )
1357
+ result.success?.should == false
1358
+ result.errors.for(:transaction).on(:three_d_secure_token)[0].code.should == Braintree::ErrorCodes::Transaction::ThreeDSecureTokenIsInvalid
1359
+ end
1360
+
1361
+ it "returns an error if 3ds lookup data does not match txn data" do
1362
+ three_d_secure_token = SpecHelper.create_3ds_verification(
1363
+ SpecHelper::ThreeDSecureMerchantAccountId,
1364
+ :number => Braintree::Test::CreditCardNumbers::Visa,
1365
+ :expiration_month => "12",
1366
+ :expiration_year => "2012"
1367
+ )
1368
+
1369
+ result = Braintree::Transaction.create(
1370
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
1371
+ :type => "sale",
1372
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1373
+ :credit_card => {
1374
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
1375
+ :expiration_date => "12/12",
1376
+ },
1377
+ :three_d_secure_token => three_d_secure_token
1378
+ )
1379
+ result.success?.should == false
1380
+ result.errors.for(:transaction).on(:three_d_secure_token)[0].code.should == Braintree::ErrorCodes::Transaction::ThreeDSecureTransactionDataDoesntMatchVerify
1381
+ end
1382
+ end
1383
+
1384
+ context "paypal" do
1385
+ context "using a vaulted paypal account payment_method_token" do
1386
+ it "can create a transaction" do
1387
+ payment_method_result = Braintree::PaymentMethod.create(
1388
+ :customer_id => Braintree::Customer.create.customer.id,
1389
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment
1390
+ )
1391
+ result = Braintree::Transaction.create(
1392
+ :type => "sale",
1393
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1394
+ :payment_method_token => payment_method_result.payment_method.token
1395
+ )
1396
+
1397
+ result.should be_success
1398
+ result.transaction.payment_instrument_type.should == Braintree::PaymentInstrumentType::PayPalAccount
1399
+ end
1400
+ end
1401
+
1402
+ context "future" do
1403
+ it "can create a paypal transaction with a nonce without vaulting" do
1404
+ payment_method_token = rand(36**3).to_s(36)
1405
+ nonce = nonce_for_paypal_account(
1406
+ :consent_code => "PAYPAL_CONSENT_CODE",
1407
+ :token => payment_method_token
1408
+ )
1409
+
1410
+ result = Braintree::Transaction.create(
1411
+ :type => "sale",
1412
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1413
+ :payment_method_nonce => nonce
1414
+ )
1415
+
1416
+ result.should be_success
1417
+
1418
+ expect do
1419
+ Braintree::PaymentMethod.find(payment_method_token)
1420
+ end.to raise_error(Braintree::NotFoundError, "payment method with token \"#{payment_method_token}\" not found")
1421
+ end
1422
+
1423
+ it "can create a paypal transaction and vault a paypal account" do
1424
+ payment_method_token = rand(36**3).to_s(36)
1425
+ nonce = nonce_for_paypal_account(
1426
+ :consent_code => "PAYPAL_CONSENT_CODE",
1427
+ :token => payment_method_token
1428
+ )
1429
+
1430
+ result = Braintree::Transaction.create(
1431
+ :type => "sale",
1432
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1433
+ :payment_method_nonce => nonce,
1434
+ :options => {:store_in_vault => true}
1435
+ )
1436
+
1437
+ result.success?.should == true
1438
+
1439
+ found_paypal_account = Braintree::PaymentMethod.find(payment_method_token)
1440
+ found_paypal_account.should be_a(Braintree::PayPalAccount)
1441
+ found_paypal_account.token.should == payment_method_token
1442
+ end
1443
+ end
1444
+
1445
+ context "onetime" do
1446
+ it "can create a paypal transaction with a nonce" do
1447
+ result = Braintree::Transaction.create(
1448
+ :type => "sale",
1449
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1450
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment
1451
+ )
1452
+
1453
+ result.should be_success
1454
+ end
1455
+
1456
+ it "can create a paypal transaction and does not vault even if asked to" do
1457
+ payment_method_token = rand(36**3).to_s(36)
1458
+ nonce = nonce_for_paypal_account(
1459
+ :access_token => "PAYPAL_ACCESS_TOKEN",
1460
+ :token => payment_method_token
1461
+ )
1462
+
1463
+ result = Braintree::Transaction.create(
1464
+ :type => "sale",
1465
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1466
+ :payment_method_nonce => nonce,
1467
+ :options => {:store_in_vault => true}
1468
+ )
1469
+
1470
+ result.success?.should == true
1471
+
1472
+ expect do
1473
+ Braintree::PaymentMethod.find(payment_method_token)
1474
+ end.to raise_error(Braintree::NotFoundError, "payment method with token \"#{payment_method_token}\" not found")
1475
+ end
1476
+ end
1477
+
1478
+ context "submit" do
1479
+ it "submits for settlement if instructed to do so" do
1480
+ result = Braintree::Transaction.sale(
1481
+ :amount => "100",
1482
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment,
1483
+ :options => {
1484
+ :submit_for_settlement => true
1485
+ }
1486
+ )
1487
+ result.success?.should == true
1488
+ result.transaction.status.should == Braintree::Transaction::Status::SubmittedForSettlement
1489
+ end
1490
+ end
1491
+
1492
+ context "void" do
1493
+ it "successfully voids a paypal transaction that's been authorized" do
1494
+ sale_transaction = Braintree::Transaction.sale!(
1495
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1496
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment,
1497
+ :options => {
1498
+ :submit_for_settlement => true
1499
+ }
1500
+ )
1501
+
1502
+ void_transaction = Braintree::Transaction.void!(sale_transaction.id)
1503
+ void_transaction.should == sale_transaction
1504
+ void_transaction.status.should == Braintree::Transaction::Status::Voided
1505
+ end
1506
+
1507
+ it "fails to void a paypal transaction that's been declined" do
1508
+ sale_transaction = Braintree::Transaction.sale(
1509
+ :amount => Braintree::Test::TransactionAmounts::Decline,
1510
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment,
1511
+ :options => {
1512
+ :submit_for_settlement => true
1513
+ }
1514
+ ).transaction
1515
+
1516
+ expect do
1517
+ Braintree::Transaction.void!(sale_transaction.id)
1518
+ end.to raise_error(Braintree::ValidationsFailed)
1519
+ end
1520
+ end
1521
+
1522
+ describe "refund" do
1523
+ context "partial refunds" do
1524
+ it "allows partial refunds" do
1525
+ transaction = create_paypal_transaction_for_refund
1526
+
1527
+ result = Braintree::Transaction.refund(transaction.id, transaction.amount / 2)
1528
+ result.should be_success
1529
+ result.transaction.type.should == "credit"
1530
+ end
1531
+
1532
+ it "allows multiple partial refunds" do
1533
+ transaction = create_paypal_transaction_for_refund
1534
+
1535
+ transaction_1 = Braintree::Transaction.refund(transaction.id, transaction.amount / 2).transaction
1536
+ transaction_2 = Braintree::Transaction.refund(transaction.id, transaction.amount / 2).transaction
1537
+
1538
+ transaction = Braintree::Transaction.find(transaction.id)
1539
+ transaction.refund_ids.sort.should == [transaction_1.id, transaction_2.id].sort
1540
+ end
1541
+ end
1542
+
1543
+ it "returns a successful result if successful" do
1544
+ transaction = create_paypal_transaction_for_refund
1545
+
1546
+ result = Braintree::Transaction.refund(transaction.id)
1547
+ result.success?.should == true
1548
+ result.transaction.type.should == "credit"
1549
+ end
1550
+
1551
+ it "assigns the refund_id on the original transaction" do
1552
+ transaction = create_paypal_transaction_for_refund
1553
+ refund_transaction = Braintree::Transaction.refund(transaction.id).transaction
1554
+ transaction = Braintree::Transaction.find(transaction.id)
1555
+
1556
+ transaction.refund_id.should == refund_transaction.id
1557
+ end
1558
+
1559
+ it "assigns the refunded_transaction_id to the original transaction" do
1560
+ transaction = create_paypal_transaction_for_refund
1561
+ refund_transaction = Braintree::Transaction.refund(transaction.id).transaction
1562
+
1563
+ refund_transaction.refunded_transaction_id.should == transaction.id
1564
+ end
1565
+
1566
+ it "returns an error if already refunded" do
1567
+ transaction = create_paypal_transaction_for_refund
1568
+ result = Braintree::Transaction.refund(transaction.id)
1569
+ result.success?.should == true
1570
+ result = Braintree::Transaction.refund(transaction.id)
1571
+ result.success?.should == false
1572
+ result.errors.for(:transaction).on(:base)[0].code.should == Braintree::ErrorCodes::Transaction::HasAlreadyBeenRefunded
1573
+ end
1574
+
1575
+ it "returns an error result if unsettled" do
1576
+ transaction = Braintree::Transaction.sale!(
1577
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1578
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment,
1579
+ :options => {
1580
+ :submit_for_settlement => true
1581
+ }
1582
+ )
1583
+ result = Braintree::Transaction.refund(transaction.id)
1584
+ result.success?.should == false
1585
+ result.errors.for(:transaction).on(:base)[0].code.should == Braintree::ErrorCodes::Transaction::CannotRefundUnlessSettled
1586
+ end
1587
+ end
1588
+
1589
+ context "handling errors" do
1590
+ it "handles bad unvalidated nonces" do
1591
+ nonce = nonce_for_paypal_account(
1592
+ :access_token => "PAYPAL_ACCESS_TOKEN",
1593
+ :consent_code => "PAYPAL_CONSENT_CODE"
1594
+ )
1595
+
1596
+ result = Braintree::Transaction.create(
1597
+ :type => "sale",
1598
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1599
+ :payment_method_nonce => nonce
1600
+ )
1601
+
1602
+ result.should_not be_success
1603
+ result.errors.for(:transaction).for(:paypal_account).first.code.should == "82903"
1604
+ end
1605
+
1606
+ it "handles non-existent nonces" do
1607
+ result = Braintree::Transaction.create(
1608
+ :type => "sale",
1609
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
1610
+ :payment_method_nonce => "NON_EXISTENT_NONCE"
1611
+ )
1612
+
1613
+ result.should_not be_success
1614
+ result.errors.for(:transaction).first.code.should == "91565"
1615
+ end
1616
+ end
1617
+ end
1121
1618
  end
1122
1619
 
1123
1620
  describe "self.create!" do
@@ -1509,7 +2006,7 @@ describe Braintree::Transaction do
1509
2006
 
1510
2007
  it "can specify the customer id and payment method token" do
1511
2008
  customer_id = "customer_#{rand(10**10)}"
1512
- payment_mehtod_token = "credit_card_#{rand(10**10)}"
2009
+ payment_method_token = "credit_card_#{rand(10**10)}"
1513
2010
  result = Braintree::Transaction.sale(
1514
2011
  :amount => "100",
1515
2012
  :customer => {
@@ -1518,7 +2015,7 @@ describe Braintree::Transaction do
1518
2015
  :last_name => "Williams"
1519
2016
  },
1520
2017
  :credit_card => {
1521
- :token => payment_mehtod_token,
2018
+ :token => payment_method_token,
1522
2019
  :number => "5105105105105100",
1523
2020
  :expiration_date => "05/2012"
1524
2021
  },
@@ -1530,8 +2027,8 @@ describe Braintree::Transaction do
1530
2027
  transaction = result.transaction
1531
2028
  transaction.customer_details.id.should == customer_id
1532
2029
  transaction.vault_customer.id.should == customer_id
1533
- transaction.credit_card_details.token.should == payment_mehtod_token
1534
- transaction.vault_credit_card.token.should == payment_mehtod_token
2030
+ transaction.credit_card_details.token.should == payment_method_token
2031
+ transaction.vault_credit_card.token.should == payment_method_token
1535
2032
  end
1536
2033
 
1537
2034
  it "can specify existing shipping address" do
@@ -2588,6 +3085,19 @@ describe Braintree::Transaction do
2588
3085
  Braintree::Transaction.find(transaction.id)
2589
3086
  end
2590
3087
 
3088
+ def create_paypal_transaction_for_refund
3089
+ transaction = Braintree::Transaction.sale!(
3090
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
3091
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment,
3092
+ :options => {
3093
+ :submit_for_settlement => true
3094
+ }
3095
+ )
3096
+
3097
+ Braintree::Configuration.instantiate.http.put "/transactions/#{transaction.id}/settle"
3098
+ Braintree::Transaction.find(transaction.id)
3099
+ end
3100
+
2591
3101
  def create_escrowed_transcation
2592
3102
  transaction = Braintree::Transaction.sale!(
2593
3103
  :amount => Braintree::Test::TransactionAmounts::Authorize,
@@ -2596,8 +3106,8 @@ describe Braintree::Transaction do
2596
3106
  :number => Braintree::Test::CreditCardNumbers::Visa,
2597
3107
  :expiration_date => "05/2009"
2598
3108
  },
2599
- :service_fee_amount => '1.00',
2600
- :options => { :hold_in_escrow => true }
3109
+ :service_fee_amount => '1.00',
3110
+ :options => { :hold_in_escrow => true }
2601
3111
  )
2602
3112
 
2603
3113
  response = Braintree::Configuration.instantiate.http.put "/transactions/#{transaction.id}/settle"
@@ -2659,4 +3169,69 @@ describe Braintree::Transaction do
2659
3169
  end
2660
3170
  end
2661
3171
  end
3172
+
3173
+ context "paypal" do
3174
+ it "can create a transaction for a paypal account" do
3175
+ result = Braintree::Transaction.sale(
3176
+ :amount => "10.00",
3177
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment
3178
+ )
3179
+ result.success?.should == true
3180
+ result.transaction.paypal_details.payer_email.should == "payer@example.com"
3181
+ result.transaction.paypal_details.payment_id.should match(/PAY-\w+/)
3182
+ result.transaction.paypal_details.authorization_id.should match(/SALE-\w+/)
3183
+ result.transaction.paypal_details.image_url.should_not be_nil
3184
+ end
3185
+
3186
+ it "can vault a paypal account on a transaction" do
3187
+ result = Braintree::Transaction.sale(
3188
+ :amount => "10.00",
3189
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment,
3190
+ :options => {
3191
+ :store_in_vault => true
3192
+ }
3193
+ )
3194
+ result.success?.should == true
3195
+ result.transaction.paypal_details.token.should_not be_nil
3196
+ result.transaction.paypal_details.payer_email.should == "payer@example.com"
3197
+ result.transaction.paypal_details.payment_id.should match(/PAY-\w+/)
3198
+ result.transaction.paypal_details.authorization_id.should match(/SALE-\w+/)
3199
+ end
3200
+
3201
+ it "can create a transaction from a vaulted paypal account" do
3202
+ customer = Braintree::Customer.create!
3203
+ result = Braintree::PaymentMethod.create(
3204
+ :payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment,
3205
+ :customer_id => customer.id
3206
+ )
3207
+
3208
+ result.should be_success
3209
+ result.payment_method.should be_a(Braintree::PayPalAccount)
3210
+ payment_method_token = result.payment_method.token
3211
+
3212
+ result = Braintree::Transaction.sale(
3213
+ :amount => "100",
3214
+ :customer_id => customer.id,
3215
+ :payment_method_token => payment_method_token
3216
+ )
3217
+
3218
+ result.should be_success
3219
+ result.transaction.paypal_details.token.should == payment_method_token
3220
+ result.transaction.paypal_details.payer_email.should == "payer@example.com"
3221
+ result.transaction.paypal_details.payment_id.should match(/PAY-\w+/)
3222
+ result.transaction.paypal_details.authorization_id.should match(/SALE-\w+/)
3223
+ end
3224
+
3225
+ context "validation failure" do
3226
+ it "returns a validation error if consent code and access token are omitted" do
3227
+ nonce = nonce_for_paypal_account(:token => "TOKEN")
3228
+ result = Braintree::Transaction.sale(
3229
+ :amount => "10.00",
3230
+ :payment_method_nonce => nonce
3231
+ )
3232
+ result.should_not be_success
3233
+ result.errors.for(:transaction).for(:paypal_account).first.code.should == Braintree::ErrorCodes::PayPalAccount::IncompletePayPalAccount
3234
+ end
3235
+ end
3236
+ end
2662
3237
  end