braintree 2.3.1 → 2.4.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.
@@ -6,7 +6,8 @@ module Braintree
6
6
  include BaseModule # :nodoc:
7
7
 
8
8
  attr_reader :company, :country_name, :created_at, :customer_id, :extended_address, :first_name, :id,
9
- :last_name, :locality, :postal_code, :region, :street_address, :updated_at
9
+ :last_name, :locality, :postal_code, :region, :street_address, :updated_at,
10
+ :country_code_alpha2, :country_code_alpha3, :country_code_numeric
10
11
 
11
12
  def self.create(attributes)
12
13
  Util.verify_keys(_create_signature, attributes)
@@ -99,8 +100,7 @@ module Braintree
99
100
  end
100
101
 
101
102
  def self._create_signature # :nodoc:
102
- [:company, :country_name, :customer_id, :extended_address, :first_name,
103
- :last_name, :locality, :postal_code, :region, :street_address]
103
+ _shared_signature + [:customer_id]
104
104
  end
105
105
 
106
106
  def self._determine_customer_id(customer_or_customer_id) # :nodoc:
@@ -111,6 +111,12 @@ module Braintree
111
111
  customer_id
112
112
  end
113
113
 
114
+ def self._shared_signature # :nodoc:
115
+ [:company, :country_code_alpha2, :country_code_alpha3, :country_code_numeric,
116
+ :country_name, :extended_address, :first_name,
117
+ :last_name, :locality, :postal_code, :region, :street_address]
118
+ end
119
+
114
120
  def self._new(*args) # :nodoc:
115
121
  self.new *args
116
122
  end
@@ -66,6 +66,10 @@ module Braintree
66
66
  return_object_or_raise(:transaction) { credit(token, transaction_attributes) }
67
67
  end
68
68
 
69
+ def self.delete(token)
70
+ Http.delete("/payment_methods/#{token}")
71
+ end
72
+
69
73
  # Returns a ResourceCollection of expired credit cards.
70
74
  def self.expired(options = {})
71
75
  response = Http.post("/payment_methods/all/expired_ids")
@@ -152,7 +156,7 @@ module Braintree
152
156
  end
153
157
 
154
158
  def delete
155
- Http.delete("/payment_methods/#{token}")
159
+ CreditCard.delete(token)
156
160
  end
157
161
 
158
162
  # Returns true if this credit card is the customer's default.
@@ -261,7 +265,7 @@ module Braintree
261
265
  end
262
266
 
263
267
  def self._signature(type) # :nodoc:
264
- billing_address_params = [:company, :country_name, :extended_address, :first_name, :last_name, :locality, :postal_code, :region, :street_address]
268
+ billing_address_params = Address._shared_signature
265
269
  signature = [
266
270
  :cardholder_name, :cvv, :expiration_date, :expiration_month, :expiration_year, :number, :token,
267
271
  {:options => [:make_default, :verification_merchant_account_id, :verify_card]},
@@ -3,7 +3,8 @@ module Braintree
3
3
  include BaseModule
4
4
 
5
5
  attr_reader :avs_error_response_code, :avs_postal_code_response_code, :avs_street_address_response_code,
6
- :cvv_response_code, :merchant_account_id, :processor_response_code, :processor_response_text, :status
6
+ :cvv_response_code, :merchant_account_id, :processor_response_code, :processor_response_text, :status,
7
+ :gateway_rejection_reason
7
8
 
8
9
  def initialize(attributes) # :nodoc:
9
10
  set_instance_variables_from_hash(attributes)
@@ -14,7 +15,7 @@ module Braintree
14
15
  :status, :processor_response_code, :processor_response_text,
15
16
  :cvv_response_code, :avs_error_response_code,
16
17
  :avs_postal_code_response_code, :avs_street_address_response_code,
17
- :merchant_account_id
18
+ :merchant_account_id, :gateway_rejection_reason
18
19
  ]
19
20
  formatted_attrs = attr_order.map do |attr|
20
21
  "#{attr}: #{send(attr).inspect}"
@@ -7,8 +7,12 @@ module Braintree
7
7
  CannotBeBlank = "81801"
8
8
  CompanyIsTooLong = "81802"
9
9
  CountryNameIsNotAccepted = "91803"
10
+ CountryCodeAlpha2IsNotAccepted = "91814"
11
+ CountryCodeAlpha3IsNotAccepted = "91816"
12
+ CountryCodeNumericIsNotAccepted = "91817"
10
13
  ExtendedAddressIsTooLong = "81804"
11
14
  FirstNameIsTooLong = "81805"
15
+ InconsistentCountry = "91815"
12
16
  LastNameIsTooLong = "81806"
13
17
  LocalityIsTooLong = "81807"
14
18
  PostalCodeInvalidCharacters = "81813"
@@ -55,18 +59,19 @@ module Braintree
55
59
  CustomFieldIsInvalid = "91602"
56
60
  CustomFieldIsTooLong = "81603"
57
61
  EmailIsInvalid = "81604"
58
- EmailIsTooLong = "81605"
59
62
  EmailIsRequired = "81606"
63
+ EmailIsTooLong = "81605"
60
64
  FaxIsTooLong = "81607"
61
65
  FirstNameIsTooLong = "81608"
62
66
  IdIsInUse = "91609"
63
67
  IdIsInvaild = "91610"
64
68
  IdIsNotAllowed = "91611"
69
+ IdIsRequired = "91613"
65
70
  IdIsTooLong = "91612"
66
71
  LastNameIsTooLong = "81613"
67
72
  PhoneIsTooLong = "81614"
68
- WebsiteIsTooLong = "81615"
69
73
  WebsiteIsInvalid = "81616"
74
+ WebsiteIsTooLong = "81615"
70
75
  end
71
76
 
72
77
  module Subscription
@@ -17,11 +17,12 @@ module Braintree
17
17
  # end
18
18
  class ErrorResult
19
19
 
20
- attr_reader :credit_card_verification, :transaction, :errors, :params
20
+ attr_reader :credit_card_verification, :transaction, :errors, :params, :message
21
21
 
22
22
  def initialize(data) # :nodoc:
23
23
  @params = data[:params]
24
24
  @credit_card_verification = CreditCardVerification._new(data[:verification]) if data[:verification]
25
+ @message = data[:message]
25
26
  @transaction = Transaction._new(data[:transaction]) if data[:transaction]
26
27
  @errors = Errors.new(data[:errors])
27
28
  end
@@ -128,6 +128,13 @@ module Braintree
128
128
  Token = 'token'
129
129
  end
130
130
 
131
+ module GatewayRejectionReason
132
+ AVS = "avs"
133
+ AVS_AND_CVV = "avs_and_cvv"
134
+ CVV = "cvv"
135
+ DUPLICATE = "duplicate"
136
+ end
137
+
131
138
  module Status
132
139
  Authorizing = 'authorizing'
133
140
  Authorized = 'authorized'
@@ -137,7 +144,6 @@ module Braintree
137
144
  Settled = 'settled'
138
145
  SettlementFailed = 'settlement_failed'
139
146
  SubmittedForSettlement = 'submitted_for_settlement'
140
- Unknown = 'unknown'
141
147
  Voided = 'voided'
142
148
 
143
149
  All = constants.map { |c| const_get(c) }
@@ -159,6 +165,7 @@ module Braintree
159
165
  attr_reader :currency_iso_code
160
166
  attr_reader :custom_fields
161
167
  attr_reader :cvv_response_code
168
+ attr_reader :gateway_rejection_reason
162
169
  attr_reader :merchant_account_id
163
170
  attr_reader :order_id
164
171
  attr_reader :billing_details, :shipping_details
@@ -408,8 +415,12 @@ module Braintree
408
415
  :amount, :customer_id, :merchant_account_id, :order_id, :payment_method_token, :type,
409
416
  {:credit_card => [:token, :cardholder_name, :cvv, :expiration_date, :expiration_month, :expiration_year, :number]},
410
417
  {:customer => [:id, :company, :email, :fax, :first_name, :last_name, :phone, :website]},
411
- {:billing => [:first_name, :last_name, :company, :country_name, :extended_address, :locality, :postal_code, :region, :street_address]},
412
- {:shipping => [:first_name, :last_name, :company, :country_name, :extended_address, :locality, :postal_code, :region, :street_address]},
418
+ {
419
+ :billing => Address._shared_signature
420
+ },
421
+ {
422
+ :shipping => Address._shared_signature
423
+ },
413
424
  {:options => [:store_in_vault, :submit_for_settlement, :add_billing_address_to_payment_method, :store_shipping_address_in_vault]},
414
425
  {:custom_fields => :_any_key_}
415
426
  ]
@@ -5,7 +5,8 @@ module Braintree
5
5
 
6
6
  attr_reader :id, :first_name, :last_name, :company,
7
7
  :street_address, :extended_address, :locality, :region,
8
- :postal_code, :country_name
8
+ :postal_code, :country_code_alpha2, :country_code_alpha3,
9
+ :country_code_numeric, :country_name
9
10
 
10
11
  def initialize(attributes)
11
12
  set_instance_variables_from_hash attributes unless attributes.nil?
@@ -1,8 +1,8 @@
1
1
  module Braintree
2
2
  module Version
3
3
  Major = 2
4
- Minor = 3
5
- Tiny = 1
4
+ Minor = 4
5
+ Tiny = 0
6
6
 
7
7
  String = "#{Major}.#{Minor}.#{Tiny}"
8
8
  end
@@ -8,6 +8,7 @@ module Braintree
8
8
  "Bignum" => "integer",
9
9
  "TrueClass" => "boolean",
10
10
  "FalseClass" => "boolean",
11
+ "Date" => "datetime",
11
12
  "DateTime" => "datetime",
12
13
  "Time" => "datetime",
13
14
  }
@@ -19,7 +20,9 @@ module Braintree
19
20
 
20
21
  XML_FORMATTING = {
21
22
  "symbol" => Proc.new { |symbol| symbol.to_s },
22
- "datetime" => Proc.new { |time| time.xmlschema },
23
+ "datetime" => Proc.new do |date_or_time|
24
+ date_or_time.respond_to?(:xmlschema) ? date_or_time.xmlschema : date_or_time.to_s
25
+ end,
23
26
  "bigdecimal" => Proc.new do |bigdecimal|
24
27
  str = bigdecimal.to_s('F')
25
28
  if str =~ /\.\d$/
@@ -27,6 +27,65 @@ describe Braintree::Address do
27
27
  result.address.region.should == "Illinois"
28
28
  result.address.postal_code.should == "60622"
29
29
  result.address.country_name.should == "United States of America"
30
+ result.address.country_code_alpha2.should == "US"
31
+ result.address.country_code_alpha3.should == "USA"
32
+ result.address.country_code_numeric.should == "840"
33
+ end
34
+
35
+ it "accepts country_codes" do
36
+ customer = Braintree::Customer.create!
37
+ result = Braintree::Address.create(
38
+ :customer_id => customer.id,
39
+ :country_code_alpha2 => "AS",
40
+ :country_code_alpha3 => "ASM",
41
+ :country_code_numeric => "16"
42
+ )
43
+ result.success?.should == true
44
+ result.address.country_name.should == "American Samoa"
45
+ result.address.country_code_alpha2.should == "AS"
46
+ result.address.country_code_alpha3.should == "ASM"
47
+ result.address.country_code_numeric.should == "016"
48
+ end
49
+
50
+ it "returns an error response given inconsistent country codes" do
51
+ customer = Braintree::Customer.create!
52
+ result = Braintree::Address.create(
53
+ :customer_id => customer.id,
54
+ :country_code_alpha2 => "AS",
55
+ :country_code_alpha3 => "USA"
56
+ )
57
+ result.success?.should == false
58
+ result.errors.for(:address).on(:base).map {|e| e.code}.should include(Braintree::ErrorCodes::Address::InconsistentCountry)
59
+ end
60
+
61
+ it "returns an error response given an invalid country_code_alpha2" do
62
+ customer = Braintree::Customer.create!
63
+ result = Braintree::Address.create(
64
+ :customer_id => customer.id,
65
+ :country_code_alpha2 => "zz"
66
+ )
67
+ result.success?.should == false
68
+ result.errors.for(:address).on(:country_code_alpha2).map {|e| e.code}.should include(Braintree::ErrorCodes::Address::CountryCodeAlpha2IsNotAccepted)
69
+ end
70
+
71
+ it "returns an error response given an invalid country_code_alpha3" do
72
+ customer = Braintree::Customer.create!
73
+ result = Braintree::Address.create(
74
+ :customer_id => customer.id,
75
+ :country_code_alpha3 => "zzz"
76
+ )
77
+ result.success?.should == false
78
+ result.errors.for(:address).on(:country_code_alpha3).map {|e| e.code}.should include(Braintree::ErrorCodes::Address::CountryCodeAlpha3IsNotAccepted)
79
+ end
80
+
81
+ it "returns an error response given an invalid country_code_numeric" do
82
+ customer = Braintree::Customer.create!
83
+ result = Braintree::Address.create(
84
+ :customer_id => customer.id,
85
+ :country_code_numeric => "zz"
86
+ )
87
+ result.success?.should == false
88
+ result.errors.for(:address).on(:country_code_numeric).map {|e| e.code}.should include(Braintree::ErrorCodes::Address::CountryCodeNumericIsNotAccepted)
30
89
  end
31
90
 
32
91
  it "returns an error response if invalid" do
@@ -175,6 +234,28 @@ describe Braintree::Address do
175
234
  result.address.region.should == "Illinois"
176
235
  result.address.postal_code.should == "60621"
177
236
  result.address.country_name.should == "United States of America"
237
+ result.address.country_code_alpha2.should == "US"
238
+ result.address.country_code_alpha3.should == "USA"
239
+ result.address.country_code_numeric.should == "840"
240
+ end
241
+
242
+ it "accepts country_codes" do
243
+ customer = Braintree::Customer.create!(:last_name => "Miller")
244
+ address = Braintree::Address.create!(
245
+ :customer_id => customer.id,
246
+ :country_name => "Angola"
247
+ )
248
+ result = Braintree::Address.update(
249
+ customer.id,
250
+ address.id,
251
+ :country_name => "Azerbaijan"
252
+ )
253
+
254
+ result.success?.should == true
255
+ result.address.country_name.should == "Azerbaijan"
256
+ result.address.country_code_alpha2.should == "AZ"
257
+ result.address.country_code_alpha3.should == "AZE"
258
+ result.address.country_code_numeric.should == "031"
178
259
  end
179
260
 
180
261
  it "returns an error response if invalid" do
@@ -1,7 +1,6 @@
1
1
  require File.dirname(__FILE__) + "/../spec_helper"
2
2
 
3
3
  describe Braintree::CreditCard do
4
-
5
4
  describe "self.create" do
6
5
  it "throws and ArgumentError if given exipiration_date and any combination of expiration_month and expiration_year" do
7
6
  expect do
@@ -76,6 +75,33 @@ describe Braintree::CreditCard do
76
75
  result.credit_card_verification.avs_street_address_response_code.should == "I"
77
76
  end
78
77
 
78
+ it "exposes the gateway rejection reason on verification" do
79
+ old_merchant = Braintree::Configuration.merchant_id
80
+ old_public_key = Braintree::Configuration.public_key
81
+ old_private_key = Braintree::Configuration.private_key
82
+
83
+ begin
84
+ Braintree::Configuration.merchant_id = "processing_rules_merchant_id"
85
+ Braintree::Configuration.public_key = "processing_rules_public_key"
86
+ Braintree::Configuration.private_key = "processing_rules_private_key"
87
+
88
+ customer = Braintree::Customer.create!
89
+ result = Braintree::CreditCard.create(
90
+ :customer_id => customer.id,
91
+ :number => Braintree::Test::CreditCardNumbers::Visa,
92
+ :expiration_date => "05/2009",
93
+ :cvv => "200",
94
+ :options => {:verify_card => true}
95
+ )
96
+ result.success?.should == false
97
+ result.credit_card_verification.gateway_rejection_reason.should == Braintree::Transaction::GatewayRejectionReason::CVV
98
+ ensure
99
+ Braintree::Configuration.merchant_id = old_merchant
100
+ Braintree::Configuration.public_key = old_public_key
101
+ Braintree::Configuration.private_key = old_private_key
102
+ end
103
+ end
104
+
79
105
  it "allows user to specify merchant account for verification" do
80
106
  customer = Braintree::Customer.create!
81
107
  result = Braintree::CreditCard.create(
@@ -121,6 +147,42 @@ describe Braintree::CreditCard do
121
147
  credit_card.billing_address.street_address.should == "123 Abc Way"
122
148
  end
123
149
 
150
+ it "adds credit card with billing using country_code" do
151
+ customer = Braintree::Customer.create!
152
+ result = Braintree::CreditCard.create(
153
+ :customer_id => customer.id,
154
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
155
+ :expiration_date => "12/2009",
156
+ :billing_address => {
157
+ :country_name => "United States of America",
158
+ :country_code_alpha2 => "US",
159
+ :country_code_alpha3 => "USA",
160
+ :country_code_numeric => "840"
161
+ }
162
+ )
163
+ result.success?.should == true
164
+ credit_card = result.credit_card
165
+ credit_card.billing_address.country_name.should == "United States of America"
166
+ credit_card.billing_address.country_code_alpha2.should == "US"
167
+ credit_card.billing_address.country_code_alpha3.should == "USA"
168
+ credit_card.billing_address.country_code_numeric.should == "840"
169
+ end
170
+
171
+ it "returns an error when given inconsistent country information" do
172
+ customer = Braintree::Customer.create!
173
+ result = Braintree::CreditCard.create(
174
+ :customer_id => customer.id,
175
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
176
+ :expiration_date => "12/2009",
177
+ :billing_address => {
178
+ :country_name => "Mexico",
179
+ :country_code_alpha2 => "US"
180
+ }
181
+ )
182
+ result.success?.should == false
183
+ result.errors.for(:credit_card).for(:billing_address).on(:base).map { |e| e.code }.should include(Braintree::ErrorCodes::Address::InconsistentCountry)
184
+ end
185
+
124
186
  it "returns an error response if unsuccessful" do
125
187
  customer = Braintree::Customer.create!
126
188
  result = Braintree::CreditCard.create(
@@ -386,6 +448,33 @@ describe Braintree::CreditCard do
386
448
  updated_credit_card.billing_address.street_address.should == "123 Nigeria Ave"
387
449
  updated_credit_card.billing_address.id.should == credit_card.billing_address.id
388
450
  end
451
+
452
+ it "updates the country via codes" do
453
+ customer = Braintree::Customer.create!
454
+ credit_card = Braintree::CreditCard.create!(
455
+ :customer_id => customer.id,
456
+ :number => Braintree::Test::CreditCardNumbers::Visa,
457
+ :expiration_date => "05/2012",
458
+ :billing_address => {
459
+ :street_address => "123 Nigeria Ave"
460
+ }
461
+ )
462
+ update_result = Braintree::CreditCard.update(credit_card.token,
463
+ :billing_address => {
464
+ :country_name => "American Samoa",
465
+ :country_code_alpha2 => "AS",
466
+ :country_code_alpha3 => "ASM",
467
+ :country_code_numeric => "016",
468
+ :options => {:update_existing => true}
469
+ }
470
+ )
471
+ update_result.success?.should == true
472
+ updated_credit_card = update_result.credit_card
473
+ updated_credit_card.billing_address.country_name.should == "American Samoa"
474
+ updated_credit_card.billing_address.country_code_alpha2.should == "AS"
475
+ updated_credit_card.billing_address.country_code_alpha3.should == "ASM"
476
+ updated_credit_card.billing_address.country_code_numeric.should == "016"
477
+ end
389
478
  end
390
479
 
391
480
  it "can pass expiration_month and expiration_year" do
@@ -425,6 +514,7 @@ describe Braintree::CreditCard do
425
514
  )
426
515
  update_result.success?.should == false
427
516
  update_result.credit_card_verification.status.should == Braintree::Transaction::Status::ProcessorDeclined
517
+ update_result.credit_card_verification.gateway_rejection_reason.should be_nil
428
518
  end
429
519
 
430
520
  it "can update the billing address" do
@@ -680,6 +770,24 @@ describe Braintree::CreditCard do
680
770
  end
681
771
  end
682
772
 
773
+ describe "self.delete" do
774
+ it "deletes the credit card" do
775
+ customer = Braintree::Customer.create.customer
776
+ result = Braintree::CreditCard.create(
777
+ :customer_id => customer.id,
778
+ :number => Braintree::Test::CreditCardNumbers::Visa,
779
+ :expiration_date => "05/2012"
780
+ )
781
+
782
+ result.success?.should == true
783
+ credit_card = result.credit_card
784
+ Braintree::CreditCard.delete(credit_card.token).should == true
785
+ expect do
786
+ Braintree::CreditCard.find(credit_card.token)
787
+ end.to raise_error(Braintree::NotFoundError)
788
+ end
789
+ end
790
+
683
791
  describe "delete" do
684
792
  it "deletes the credit card" do
685
793
  customer = Braintree::Customer.create.customer
@@ -159,6 +159,28 @@ describe Braintree::Customer do
159
159
  result.customer.addresses[0].country_name.should == "United States of America"
160
160
  end
161
161
 
162
+ it "can use any country code" do
163
+ result = Braintree::Customer.create(
164
+ :first_name => "James",
165
+ :last_name => "Conroy",
166
+ :credit_card => {
167
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
168
+ :expiration_date => "05/2010",
169
+ :billing_address => {
170
+ :country_name => "Comoros",
171
+ :country_code_alpha2 => "KM",
172
+ :country_code_alpha3 => "COM",
173
+ :country_code_numeric => "174"
174
+ }
175
+ }
176
+ )
177
+ result.success?.should == true
178
+ result.customer.addresses[0].country_name.should == "Comoros"
179
+ result.customer.addresses[0].country_code_alpha2.should == "KM"
180
+ result.customer.addresses[0].country_code_alpha3.should == "COM"
181
+ result.customer.addresses[0].country_code_numeric.should == "174"
182
+ end
183
+
162
184
  it "stores custom fields when valid" do
163
185
  result = Braintree::Customer.create(
164
186
  :first_name => "Bill",
@@ -187,6 +209,72 @@ describe Braintree::Customer do
187
209
  result.errors.for(:customer).for(:credit_card).for(:billing_address).on(:country_name)[0].message.should == "Country name is not an accepted country."
188
210
  end
189
211
 
212
+ it "returns errors if country codes are inconsistent" do
213
+ result = Braintree::Customer.create(
214
+ :first_name => "Olivia",
215
+ :last_name => "Dupree",
216
+ :credit_card => {
217
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
218
+ :expiration_date => "05/2010",
219
+ :billing_address => {
220
+ :country_name => "Comoros",
221
+ :country_code_alpha2 => "US",
222
+ :country_code_alpha3 => "COM",
223
+ }
224
+ }
225
+ )
226
+ result.success?.should == false
227
+ result.errors.for(:customer).for(:credit_card).for(:billing_address).on(:base).map {|e| e.code}.should include(Braintree::ErrorCodes::Address::InconsistentCountry)
228
+ end
229
+
230
+ it "returns an error if country code alpha2 is invalid" do
231
+ result = Braintree::Customer.create(
232
+ :first_name => "Melissa",
233
+ :last_name => "Henderson",
234
+ :credit_card => {
235
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
236
+ :expiration_date => "05/2010",
237
+ :billing_address => {
238
+ :country_code_alpha2 => "zz",
239
+ }
240
+ }
241
+ )
242
+ result.success?.should == false
243
+ result.errors.for(:customer).for(:credit_card).for(:billing_address).on(:country_code_alpha2).map {|e| e.code}.should include(Braintree::ErrorCodes::Address::CountryCodeAlpha2IsNotAccepted)
244
+ end
245
+
246
+ it "returns an error if country code alpha3 is invalid" do
247
+ result = Braintree::Customer.create(
248
+ :first_name => "Andrew",
249
+ :last_name => "Patterson",
250
+ :credit_card => {
251
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
252
+ :expiration_date => "05/3010",
253
+ :billing_address => {
254
+ :country_code_alpha3 => "zzz",
255
+ }
256
+ }
257
+ )
258
+ result.success?.should == false
259
+ result.errors.for(:customer).for(:credit_card).for(:billing_address).on(:country_code_alpha3).map {|e| e.code}.should include(Braintree::ErrorCodes::Address::CountryCodeAlpha3IsNotAccepted)
260
+ end
261
+
262
+ it "returns an error if country code numeric is invalid" do
263
+ result = Braintree::Customer.create(
264
+ :first_name => "Steve",
265
+ :last_name => "Hamlin",
266
+ :credit_card => {
267
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
268
+ :expiration_date => "05/3010",
269
+ :billing_address => {
270
+ :country_code_numeric => "zzz",
271
+ }
272
+ }
273
+ )
274
+ result.success?.should == false
275
+ result.errors.for(:customer).for(:credit_card).for(:billing_address).on(:country_code_numeric).map {|e| e.code}.should include(Braintree::ErrorCodes::Address::CountryCodeNumericIsNotAccepted)
276
+ end
277
+
190
278
  it "returns errors if custom_fields are not registered" do
191
279
  result = Braintree::Customer.create(
192
280
  :first_name => "Jack",
@@ -571,6 +659,33 @@ describe Braintree::Customer do
571
659
  result.customer.custom_fields[:store_me].should == "a value"
572
660
  end
573
661
 
662
+ it "can use any country code" do
663
+ customer = Braintree::Customer.create!(
664
+ :first_name => "Alex",
665
+ :last_name => "Matterson"
666
+ )
667
+ result = Braintree::Customer.update(
668
+ customer.id,
669
+ :first_name => "Sammy",
670
+ :last_name => "Banderton",
671
+ :credit_card => {
672
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
673
+ :expiration_date => "05/2010",
674
+ :billing_address => {
675
+ :country_name => "Fiji",
676
+ :country_code_alpha2 => "FJ",
677
+ :country_code_alpha3 => "FJI",
678
+ :country_code_numeric => "242"
679
+ }
680
+ }
681
+ )
682
+ result.success?.should == true
683
+ result.customer.addresses[0].country_name.should == "Fiji"
684
+ result.customer.addresses[0].country_code_alpha2.should == "FJ"
685
+ result.customer.addresses[0].country_code_alpha3.should == "FJI"
686
+ result.customer.addresses[0].country_code_numeric.should == "242"
687
+ end
688
+
574
689
  it "can update the customer, credit card, and billing address in one request" do
575
690
  customer = Braintree::Customer.create!(
576
691
  :first_name => "Joe",
@@ -131,6 +131,17 @@ describe Braintree::Subscription do
131
131
  result.subscription.trial_period.should == false
132
132
  end
133
133
 
134
+ it "doesn't create a transaction if there's a trial period" do
135
+ result = Braintree::Subscription.create(
136
+ :payment_method_token => @credit_card.token,
137
+ :plan_id => TrialPlan[:id]
138
+ )
139
+
140
+ result.subscription.transactions.size.should == 0
141
+ end
142
+ end
143
+
144
+ context "no trial period" do
134
145
  it "creates a transaction if no trial period" do
135
146
  result = Braintree::Subscription.create(
136
147
  :payment_method_token => @credit_card.token,
@@ -144,13 +155,16 @@ describe Braintree::Subscription do
144
155
  result.subscription.transactions.first.subscription_id.should == result.subscription.id
145
156
  end
146
157
 
147
- it "doesn't create a transaction if there's a trial period" do
158
+ it "does not create the subscription and returns the transaction if the transaction is not successful" do
148
159
  result = Braintree::Subscription.create(
149
160
  :payment_method_token => @credit_card.token,
150
- :plan_id => TrialPlan[:id]
161
+ :plan_id => TriallessPlan[:id],
162
+ :price => Braintree::Test::TransactionAmounts::Decline
151
163
  )
152
164
 
153
- result.subscription.transactions.size.should == 0
165
+ result.success?.should be_false
166
+ result.transaction.status.should == Braintree::Transaction::Status::ProcessorDeclined
167
+ result.message.should == "Do Not Honor"
154
168
  end
155
169
  end
156
170
 
@@ -227,7 +241,6 @@ describe Braintree::Subscription do
227
241
  result.success?.should == false
228
242
  result.errors.for(:subscription).on(:trial_duration_unit)[0].message.should == "Trial Duration Unit is invalid."
229
243
  end
230
-
231
244
  end
232
245
  end
233
246
 
@@ -508,103 +508,126 @@ describe Braintree::Transaction, "search" do
508
508
  end
509
509
  end
510
510
 
511
- it "searches on created_at in UTC" do
512
- transaction = Braintree::Transaction.sale!(
513
- :amount => Braintree::Test::TransactionAmounts::Authorize,
514
- :credit_card => {
515
- :number => Braintree::Test::CreditCardNumbers::Visa,
516
- :expiration_date => "05/12"
517
- }
518
- )
511
+ context "created_at" do
512
+ it "searches on created_at in UTC" do
513
+ transaction = Braintree::Transaction.sale!(
514
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
515
+ :credit_card => {
516
+ :number => Braintree::Test::CreditCardNumbers::Visa,
517
+ :expiration_date => "05/12"
518
+ }
519
+ )
519
520
 
520
- created_at = transaction.created_at
521
- created_at.should be_utc
521
+ created_at = transaction.created_at
522
+ created_at.should be_utc
522
523
 
523
- collection = Braintree::Transaction.search do |search|
524
- search.id.is transaction.id
525
- search.created_at.between(
526
- created_at - 60,
527
- created_at + 60
528
- )
529
- end
524
+ collection = Braintree::Transaction.search do |search|
525
+ search.id.is transaction.id
526
+ search.created_at.between(
527
+ created_at - 60,
528
+ created_at + 60
529
+ )
530
+ end
530
531
 
531
- collection.maximum_size.should == 1
532
- collection.first.id.should == transaction.id
532
+ collection.maximum_size.should == 1
533
+ collection.first.id.should == transaction.id
533
534
 
534
- collection = Braintree::Transaction.search do |search|
535
- search.id.is transaction.id
536
- search.created_at >= created_at - 1
537
- end
535
+ collection = Braintree::Transaction.search do |search|
536
+ search.id.is transaction.id
537
+ search.created_at >= created_at - 1
538
+ end
538
539
 
539
- collection.maximum_size.should == 1
540
- collection.first.id.should == transaction.id
540
+ collection.maximum_size.should == 1
541
+ collection.first.id.should == transaction.id
541
542
 
542
- collection = Braintree::Transaction.search do |search|
543
- search.id.is transaction.id
544
- search.created_at <= created_at + 1
545
- end
543
+ collection = Braintree::Transaction.search do |search|
544
+ search.id.is transaction.id
545
+ search.created_at <= created_at + 1
546
+ end
546
547
 
547
- collection.maximum_size.should == 1
548
- collection.first.id.should == transaction.id
548
+ collection.maximum_size.should == 1
549
+ collection.first.id.should == transaction.id
549
550
 
550
- collection = Braintree::Transaction.search do |search|
551
- search.id.is transaction.id
552
- search.created_at.between(
553
- created_at - 300,
554
- created_at - 100
555
- )
551
+ collection = Braintree::Transaction.search do |search|
552
+ search.id.is transaction.id
553
+ search.created_at.between(
554
+ created_at - 300,
555
+ created_at - 100
556
+ )
557
+ end
558
+
559
+ collection.maximum_size.should == 0
556
560
  end
557
561
 
558
- collection.maximum_size.should == 0
559
- end
562
+ it "searches on created_at in local time" do
563
+ transaction = Braintree::Transaction.sale!(
564
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
565
+ :credit_card => {
566
+ :number => Braintree::Test::CreditCardNumbers::Visa,
567
+ :expiration_date => "05/12"
568
+ }
569
+ )
560
570
 
561
- it "searches on created_at in local time" do
562
- transaction = Braintree::Transaction.sale!(
563
- :amount => Braintree::Test::TransactionAmounts::Authorize,
564
- :credit_card => {
565
- :number => Braintree::Test::CreditCardNumbers::Visa,
566
- :expiration_date => "05/12"
567
- }
568
- )
571
+ now = Time.now
569
572
 
570
- now = Time.now
573
+ collection = Braintree::Transaction.search do |search|
574
+ search.id.is transaction.id
575
+ search.created_at.between(
576
+ now - 60,
577
+ now + 60
578
+ )
579
+ end
571
580
 
572
- collection = Braintree::Transaction.search do |search|
573
- search.id.is transaction.id
574
- search.created_at.between(
575
- now - 60,
576
- now + 60
577
- )
578
- end
581
+ collection.maximum_size.should == 1
582
+ collection.first.id.should == transaction.id
579
583
 
580
- collection.maximum_size.should == 1
581
- collection.first.id.should == transaction.id
584
+ collection = Braintree::Transaction.search do |search|
585
+ search.id.is transaction.id
586
+ search.created_at >= now - 60
587
+ end
582
588
 
583
- collection = Braintree::Transaction.search do |search|
584
- search.id.is transaction.id
585
- search.created_at >= now - 60
586
- end
589
+ collection.maximum_size.should == 1
590
+ collection.first.id.should == transaction.id
587
591
 
588
- collection.maximum_size.should == 1
589
- collection.first.id.should == transaction.id
592
+ collection = Braintree::Transaction.search do |search|
593
+ search.id.is transaction.id
594
+ search.created_at <= now + 60
595
+ end
590
596
 
591
- collection = Braintree::Transaction.search do |search|
592
- search.id.is transaction.id
593
- search.created_at <= now + 60
594
- end
597
+ collection.maximum_size.should == 1
598
+ collection.first.id.should == transaction.id
595
599
 
596
- collection.maximum_size.should == 1
597
- collection.first.id.should == transaction.id
600
+ collection = Braintree::Transaction.search do |search|
601
+ search.id.is transaction.id
602
+ search.created_at.between(
603
+ now - 300,
604
+ now - 100
605
+ )
606
+ end
598
607
 
599
- collection = Braintree::Transaction.search do |search|
600
- search.id.is transaction.id
601
- search.created_at.between(
602
- now - 300,
603
- now - 100
604
- )
608
+ collection.maximum_size.should == 0
605
609
  end
606
610
 
607
- collection.maximum_size.should == 0
611
+ it "searches on created_at with dates" do
612
+ transaction = Braintree::Transaction.sale!(
613
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
614
+ :credit_card => {
615
+ :number => Braintree::Test::CreditCardNumbers::Visa,
616
+ :expiration_date => "05/12"
617
+ }
618
+ )
619
+
620
+ collection = Braintree::Transaction.search do |search|
621
+ search.id.is transaction.id
622
+ search.created_at.between(
623
+ Date.today - 1,
624
+ Date.today + 1
625
+ )
626
+ end
627
+
628
+ collection.maximum_size.should == 1
629
+ collection.first.id.should == transaction.id
630
+ end
608
631
  end
609
632
  end
610
633
 
@@ -39,6 +39,207 @@ describe Braintree::Transaction do
39
39
  result.transaction.processor_response_text.should == "Do Not Honor"
40
40
  end
41
41
 
42
+ it "accepts all four country codes" do
43
+ result = Braintree::Transaction.sale(
44
+ :amount => "100",
45
+ :customer => {
46
+ :last_name => "Adama",
47
+ },
48
+ :credit_card => {
49
+ :number => "5105105105105100",
50
+ :expiration_date => "05/2012"
51
+ },
52
+ :billing => {
53
+ :country_name => "Botswana",
54
+ :country_code_alpha2 => "BW",
55
+ :country_code_alpha3 => "BWA",
56
+ :country_code_numeric => "072"
57
+ },
58
+ :shipping => {
59
+ :country_name => "Bhutan",
60
+ :country_code_alpha2 => "BT",
61
+ :country_code_alpha3 => "BTN",
62
+ :country_code_numeric => "064"
63
+ },
64
+ :options => {
65
+ :add_billing_address_to_payment_method => true,
66
+ :store_in_vault => true
67
+ }
68
+ )
69
+ result.success?.should == true
70
+ transaction = result.transaction
71
+ transaction.billing_details.country_name.should == "Botswana"
72
+ transaction.billing_details.country_code_alpha2.should == "BW"
73
+ transaction.billing_details.country_code_alpha3.should == "BWA"
74
+ transaction.billing_details.country_code_numeric.should == "072"
75
+
76
+ transaction.shipping_details.country_name.should == "Bhutan"
77
+ transaction.shipping_details.country_code_alpha2.should == "BT"
78
+ transaction.shipping_details.country_code_alpha3.should == "BTN"
79
+ transaction.shipping_details.country_code_numeric.should == "064"
80
+
81
+ transaction.vault_credit_card.billing_address.country_name.should == "Botswana"
82
+ transaction.vault_credit_card.billing_address.country_code_alpha2.should == "BW"
83
+ transaction.vault_credit_card.billing_address.country_code_alpha3.should == "BWA"
84
+ transaction.vault_credit_card.billing_address.country_code_numeric.should == "072"
85
+ end
86
+
87
+ it "returns an error if provided inconsistent country information" do
88
+ result = Braintree::Transaction.sale(
89
+ :amount => "100",
90
+ :credit_card => {
91
+ :number => "5105105105105100",
92
+ :expiration_date => "05/2012"
93
+ },
94
+ :billing => {
95
+ :country_name => "Botswana",
96
+ :country_code_alpha2 => "US",
97
+ }
98
+ )
99
+
100
+ result.success?.should == false
101
+ result.errors.for(:transaction).for(:billing).on(:base).map { |e| e.code }.should include(Braintree::ErrorCodes::Address::InconsistentCountry)
102
+ end
103
+
104
+ it "returns an error if given an incorrect alpha2 code" do
105
+ result = Braintree::Transaction.sale(
106
+ :amount => "100",
107
+ :credit_card => {
108
+ :number => "5105105105105100",
109
+ :expiration_date => "05/2012"
110
+ },
111
+ :billing => {
112
+ :country_code_alpha2 => "ZZ"
113
+ }
114
+ )
115
+
116
+ result.success?.should == false
117
+ codes = result.errors.for(:transaction).for(:billing).on(:country_code_alpha2).map { |e| e.code }
118
+ codes.should include(Braintree::ErrorCodes::Address::CountryCodeAlpha2IsNotAccepted)
119
+ end
120
+
121
+ it "returns an error if given an incorrect alpha3 code" do
122
+ result = Braintree::Transaction.sale(
123
+ :amount => "100",
124
+ :credit_card => {
125
+ :number => "5105105105105100",
126
+ :expiration_date => "05/2012"
127
+ },
128
+ :billing => {
129
+ :country_code_alpha3 => "ZZZ"
130
+ }
131
+ )
132
+
133
+ result.success?.should == false
134
+ codes = result.errors.for(:transaction).for(:billing).on(:country_code_alpha3).map { |e| e.code }
135
+ codes.should include(Braintree::ErrorCodes::Address::CountryCodeAlpha3IsNotAccepted)
136
+ end
137
+
138
+ it "returns an error if given an incorrect numeric code" do
139
+ result = Braintree::Transaction.sale(
140
+ :amount => "100",
141
+ :credit_card => {
142
+ :number => "5105105105105100",
143
+ :expiration_date => "05/2012"
144
+ },
145
+ :billing => {
146
+ :country_code_numeric => "FOO"
147
+ }
148
+ )
149
+
150
+ result.success?.should == false
151
+ codes = result.errors.for(:transaction).for(:billing).on(:country_code_numeric).map { |e| e.code }
152
+ codes.should include(Braintree::ErrorCodes::Address::CountryCodeNumericIsNotAccepted)
153
+ end
154
+
155
+ context "gateway rejection reason" do
156
+ it "exposes the cvv gateway rejection reason" do
157
+ old_merchant = Braintree::Configuration.merchant_id
158
+ old_public_key = Braintree::Configuration.public_key
159
+ old_private_key = Braintree::Configuration.private_key
160
+
161
+ begin
162
+ Braintree::Configuration.merchant_id = "processing_rules_merchant_id"
163
+ Braintree::Configuration.public_key = "processing_rules_public_key"
164
+ Braintree::Configuration.private_key = "processing_rules_private_key"
165
+
166
+ result = Braintree::Transaction.sale(
167
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
168
+ :credit_card => {
169
+ :number => Braintree::Test::CreditCardNumbers::Visa,
170
+ :expiration_date => "05/2009",
171
+ :cvv => "200"
172
+ }
173
+ )
174
+ result.success?.should == false
175
+ result.transaction.gateway_rejection_reason.should == Braintree::Transaction::GatewayRejectionReason::CVV
176
+ ensure
177
+ Braintree::Configuration.merchant_id = old_merchant
178
+ Braintree::Configuration.public_key = old_public_key
179
+ Braintree::Configuration.private_key = old_private_key
180
+ end
181
+ end
182
+
183
+ it "exposes the avs gateway rejection reason" do
184
+ old_merchant = Braintree::Configuration.merchant_id
185
+ old_public_key = Braintree::Configuration.public_key
186
+ old_private_key = Braintree::Configuration.private_key
187
+
188
+ begin
189
+ Braintree::Configuration.merchant_id = "processing_rules_merchant_id"
190
+ Braintree::Configuration.public_key = "processing_rules_public_key"
191
+ Braintree::Configuration.private_key = "processing_rules_private_key"
192
+
193
+ result = Braintree::Transaction.sale(
194
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
195
+ :billing => {
196
+ :street_address => "200 Fake Street"
197
+ },
198
+ :credit_card => {
199
+ :number => Braintree::Test::CreditCardNumbers::Visa,
200
+ :expiration_date => "05/2009"
201
+ }
202
+ )
203
+ result.success?.should == false
204
+ result.transaction.gateway_rejection_reason.should == Braintree::Transaction::GatewayRejectionReason::AVS
205
+ ensure
206
+ Braintree::Configuration.merchant_id = old_merchant
207
+ Braintree::Configuration.public_key = old_public_key
208
+ Braintree::Configuration.private_key = old_private_key
209
+ end
210
+ end
211
+
212
+ it "exposes the avs_and_cvv gateway rejection reason" do
213
+ old_merchant = Braintree::Configuration.merchant_id
214
+ old_public_key = Braintree::Configuration.public_key
215
+ old_private_key = Braintree::Configuration.private_key
216
+
217
+ begin
218
+ Braintree::Configuration.merchant_id = "processing_rules_merchant_id"
219
+ Braintree::Configuration.public_key = "processing_rules_public_key"
220
+ Braintree::Configuration.private_key = "processing_rules_private_key"
221
+
222
+ result = Braintree::Transaction.sale(
223
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
224
+ :billing => {
225
+ :postal_code => "20000"
226
+ },
227
+ :credit_card => {
228
+ :number => Braintree::Test::CreditCardNumbers::Visa,
229
+ :expiration_date => "05/2009",
230
+ :cvv => "200"
231
+ }
232
+ )
233
+ result.success?.should == false
234
+ result.transaction.gateway_rejection_reason.should == Braintree::Transaction::GatewayRejectionReason::AVS_AND_CVV
235
+ ensure
236
+ Braintree::Configuration.merchant_id = old_merchant
237
+ Braintree::Configuration.public_key = old_public_key
238
+ Braintree::Configuration.private_key = old_private_key
239
+ end
240
+ end
241
+ end
242
+
42
243
  it "accepts credit card expiration month and expiration year" do
43
244
  result = Braintree::Transaction.create(
44
245
  :type => "sale",
@@ -63,6 +264,7 @@ describe Braintree::Transaction do
63
264
  )
64
265
  result.success?.should == false
65
266
  result.errors.for(:transaction).on(:customer_id)[0].code.should == "91510"
267
+ result.message.should == "Customer ID is invalid."
66
268
  end
67
269
 
68
270
  it "can create custom fields" do
@@ -374,6 +576,9 @@ describe Braintree::Transaction do
374
576
  transaction.billing_details.region.should == "IL"
375
577
  transaction.billing_details.postal_code.should == "60622"
376
578
  transaction.billing_details.country_name.should == "United States of America"
579
+ transaction.billing_details.country_code_alpha2.should == "US"
580
+ transaction.billing_details.country_code_alpha3.should == "USA"
581
+ transaction.billing_details.country_code_numeric.should == "840"
377
582
  transaction.shipping_details.first_name.should == "Andrew"
378
583
  transaction.shipping_details.last_name.should == "Mason"
379
584
  transaction.shipping_details.company.should == "Braintree"
@@ -383,6 +588,9 @@ describe Braintree::Transaction do
383
588
  transaction.shipping_details.region.should == "IL"
384
589
  transaction.shipping_details.postal_code.should == "60103"
385
590
  transaction.shipping_details.country_name.should == "United States of America"
591
+ transaction.shipping_details.country_code_alpha2.should == "US"
592
+ transaction.shipping_details.country_code_alpha3.should == "USA"
593
+ transaction.shipping_details.country_code_numeric.should == "840"
386
594
  end
387
595
 
388
596
  it "allows merchant account to be specified" do
@@ -22,6 +22,9 @@ describe Braintree::CreditCard do
22
22
  {:options => [:make_default, :verification_merchant_account_id, :verify_card]},
23
23
  {:billing_address => [
24
24
  :company,
25
+ :country_code_alpha2,
26
+ :country_code_alpha3,
27
+ :country_code_numeric,
25
28
  :country_name,
26
29
  :extended_address,
27
30
  :first_name,
@@ -49,6 +52,9 @@ describe Braintree::CreditCard do
49
52
  {:options => [:make_default, :verification_merchant_account_id, :verify_card]},
50
53
  {:billing_address => [
51
54
  :company,
55
+ :country_code_alpha2,
56
+ :country_code_alpha3,
57
+ :country_code_numeric,
52
58
  :country_name,
53
59
  :extended_address,
54
60
  :first_name,
@@ -13,7 +13,7 @@ describe Braintree::CreditCardVerification do
13
13
  :processor_response_text => "Do Not Honor",
14
14
  :merchant_account_id => "some_id"
15
15
  )
16
- verification.inspect.should == %(#<Braintree::CreditCardVerification status: "verified", processor_response_code: "2000", processor_response_text: "Do Not Honor", cvv_response_code: "I", avs_error_response_code: "I", avs_postal_code_response_code: "I", avs_street_address_response_code: "I", merchant_account_id: "some_id">)
16
+ verification.inspect.should == %(#<Braintree::CreditCardVerification status: "verified", processor_response_code: "2000", processor_response_text: "Do Not Honor", cvv_response_code: "I", avs_error_response_code: "I", avs_postal_code_response_code: "I", avs_street_address_response_code: "I", merchant_account_id: "some_id", gateway_rejection_reason: nil>)
17
17
  end
18
18
  end
19
19
  end
@@ -70,6 +70,9 @@ describe Braintree::Customer do
70
70
  {:options => [:make_default, :verification_merchant_account_id, :verify_card]},
71
71
  {:billing_address => [
72
72
  :company,
73
+ :country_code_alpha2,
74
+ :country_code_alpha3,
75
+ :country_code_numeric,
73
76
  :country_name,
74
77
  :extended_address,
75
78
  :first_name,
@@ -112,6 +115,9 @@ describe Braintree::Customer do
112
115
  ]},
113
116
  {:billing_address => [
114
117
  :company,
118
+ :country_code_alpha2,
119
+ :country_code_alpha3,
120
+ :country_code_numeric,
115
121
  :country_name,
116
122
  :extended_address,
117
123
  :first_name,
@@ -2,25 +2,10 @@ require File.dirname(__FILE__) + "/../spec_helper"
2
2
 
3
3
  describe Braintree::ErrorResult do
4
4
  describe "initialize" do
5
- it "initializes params and errors" do
6
- errors = {
7
- :scope => {
8
- :errors => [{:code => "123", :message => "something is invalid", :attribute => "something"}]
9
- }
10
- }
11
- result = Braintree::ErrorResult.new(:params => "params", :errors => errors)
12
- result.success?.should == false
13
- result.params.should == "params"
14
- result.errors.size.should == 1
15
- result.errors.for(:scope)[0].message.should == "something is invalid"
16
- result.errors.for(:scope)[0].attribute.should == "something"
17
- result.errors.for(:scope)[0].code.should == "123"
18
- end
19
-
20
- it "ignores data other than params and errors" do
5
+ it "ignores data other than params, errors, and message" do
21
6
  # so that we can add more data into the response in the future without breaking the client lib
22
7
  expect do
23
- result = Braintree::ErrorResult.new(:params => "params", :errors => {:errors => []}, :extra => "is ignored")
8
+ result = Braintree::ErrorResult.new(:params => "params", :errors => {:errors => []}, :extra => "is ignored", :message => "foo bar")
24
9
  end.to_not raise_error
25
10
  end
26
11
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: braintree
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
- - 3
9
- - 1
10
- version: 2.3.1
8
+ - 4
9
+ - 0
10
+ version: 2.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Braintree Payment Solutions
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-24 00:00:00 -05:00
18
+ date: 2010-07-09 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency