braintree 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/lib/braintree.rb +36 -46
  2. data/lib/braintree/address.rb +14 -14
  3. data/lib/braintree/base_module.rb +3 -3
  4. data/lib/braintree/configuration.rb +16 -16
  5. data/lib/braintree/credit_card.rb +39 -30
  6. data/lib/braintree/credit_card_verification.rb +4 -3
  7. data/lib/braintree/customer.rb +22 -22
  8. data/lib/braintree/digest.rb +2 -8
  9. data/lib/braintree/error_codes.rb +16 -3
  10. data/lib/braintree/error_result.rb +5 -5
  11. data/lib/braintree/exceptions.rb +58 -0
  12. data/lib/braintree/http.rb +7 -7
  13. data/lib/braintree/paged_collection.rb +14 -14
  14. data/lib/braintree/ssl_expiration_check.rb +5 -1
  15. data/lib/braintree/subscription.rb +110 -0
  16. data/lib/braintree/successful_result.rb +3 -3
  17. data/lib/braintree/test/credit_card_numbers.rb +1 -1
  18. data/lib/braintree/test/transaction_amounts.rb +18 -0
  19. data/lib/braintree/transaction.rb +52 -25
  20. data/lib/braintree/transaction/address_details.rb +2 -2
  21. data/lib/braintree/transaction/credit_card_details.rb +12 -4
  22. data/lib/braintree/transaction/customer_details.rb +9 -1
  23. data/lib/braintree/transaction/status_details.rb +1 -1
  24. data/lib/braintree/transparent_redirect.rb +15 -15
  25. data/lib/braintree/util.rb +7 -7
  26. data/lib/braintree/validation_error.rb +1 -1
  27. data/lib/braintree/validation_error_collection.rb +6 -6
  28. data/lib/braintree/version.rb +3 -3
  29. data/lib/braintree/xml/generator.rb +2 -2
  30. data/lib/braintree/xml/libxml.rb +1 -1
  31. data/lib/braintree/xml/parser.rb +1 -1
  32. data/spec/integration/braintree/address_spec.rb +12 -12
  33. data/spec/integration/braintree/credit_card_spec.rb +189 -37
  34. data/spec/integration/braintree/customer_spec.rb +35 -35
  35. data/spec/integration/braintree/http_spec.rb +3 -3
  36. data/spec/integration/braintree/subscription_spec.rb +362 -0
  37. data/spec/integration/braintree/transaction_spec.rb +130 -58
  38. data/spec/integration/spec_helper.rb +1 -1
  39. data/spec/spec_helper.rb +4 -4
  40. data/spec/unit/braintree/address_spec.rb +6 -6
  41. data/spec/unit/braintree/base_module_spec.rb +18 -0
  42. data/spec/unit/braintree/configuration_spec.rb +10 -10
  43. data/spec/unit/braintree/credit_card_spec.rb +15 -15
  44. data/spec/unit/braintree/credit_card_verification_spec.rb +4 -2
  45. data/spec/unit/braintree/customer_spec.rb +8 -8
  46. data/spec/unit/braintree/digest_spec.rb +4 -0
  47. data/spec/unit/braintree/http_spec.rb +2 -2
  48. data/spec/unit/braintree/paged_collection_spec.rb +12 -12
  49. data/spec/unit/braintree/ssl_expiration_check_spec.rb +18 -9
  50. data/spec/unit/braintree/transaction/credit_card_details_spec.rb +15 -0
  51. data/spec/unit/braintree/transaction/customer_details_spec.rb +19 -0
  52. data/spec/unit/braintree/transaction_spec.rb +14 -14
  53. data/spec/unit/braintree/transparent_redirect_spec.rb +11 -11
  54. data/spec/unit/braintree/util_spec.rb +8 -8
  55. data/spec/unit/braintree/validation_error_collection_spec.rb +6 -6
  56. data/spec/unit/braintree/validation_error_spec.rb +2 -2
  57. data/spec/unit/braintree/xml/libxml_spec.rb +5 -5
  58. data/spec/unit/braintree/xml_spec.rb +16 -16
  59. data/spec/unit/braintree_spec.rb +11 -0
  60. metadata +8 -2
@@ -38,6 +38,20 @@ module Braintree
38
38
  _data(params)
39
39
  end
40
40
 
41
+ def self.parse_and_validate_query_string(query_string) # :nodoc:
42
+ params = Util.symbolize_keys(Util.parse_query_string(query_string))
43
+ query_string_without_hash = query_string[/(.*)&hash=.*/, 1]
44
+ if _hash(query_string_without_hash) == params[:hash]
45
+ if params[:http_status] == '200'
46
+ params
47
+ else
48
+ Util.raise_exception_for_status_code(params[:http_status])
49
+ end
50
+ else
51
+ raise ForgedQueryString
52
+ end
53
+ end
54
+
41
55
  # Returns the tr_data string for creating a transaction.
42
56
  def self.transaction_data(params)
43
57
  Util.verify_keys(TransactionSignature, params)
@@ -78,20 +92,6 @@ module Braintree
78
92
  _data(params)
79
93
  end
80
94
 
81
- def self.parse_and_validate_query_string(query_string) # :nodoc:
82
- params = Util.symbolize_keys(Util.parse_query_string(query_string))
83
- query_string_without_hash = query_string[/(.*)&hash=.*/, 1]
84
- if _hash(query_string_without_hash) == params[:hash]
85
- if params[:http_status] == '200'
86
- params
87
- else
88
- Util.raise_exception_for_status_code(params[:http_status])
89
- end
90
- else
91
- raise ForgedQueryString
92
- end
93
- end
94
-
95
95
  def self._data(params) # :nodoc:
96
96
  raise ArgumentError, "expected params to contain :redirect_url" unless params[:redirect_url]
97
97
  tr_data_segment = Util.hash_to_query_string(params.merge(
@@ -102,7 +102,7 @@ module Braintree
102
102
  tr_data_hash = _hash(tr_data_segment)
103
103
  "#{tr_data_hash}|#{tr_data_segment}"
104
104
  end
105
-
105
+
106
106
  def self._hash(string) # :nodoc:
107
107
  ::Braintree::Digest.hexdigest(string)
108
108
  end
@@ -15,7 +15,7 @@ module Braintree
15
15
  end
16
16
  end.sort * '&'
17
17
  end
18
-
18
+
19
19
  def self.parse_query_string(qs)
20
20
  qs.split('&').inject({}) do |result, couplet|
21
21
  pair = couplet.split('=')
@@ -23,7 +23,7 @@ module Braintree
23
23
  result
24
24
  end
25
25
  end
26
-
26
+
27
27
  def self.url_encode(text)
28
28
  CGI.escape text.to_s
29
29
  end
@@ -37,10 +37,10 @@ module Braintree
37
37
  elsif value.is_a?(Array) && value.all? { |v| v.is_a?(Hash) }
38
38
  value.each { |v| symbolize_keys(v) }
39
39
  end
40
- end
40
+ end
41
41
  hash
42
42
  end
43
-
43
+
44
44
  def self.raise_exception_for_status_code(status_code)
45
45
  case status_code.to_i
46
46
  when 401
@@ -57,7 +57,7 @@ module Braintree
57
57
  raise UnexpectedError, "Unexpected HTTP_RESPONSE #{status_code.to_i}"
58
58
  end
59
59
  end
60
-
60
+
61
61
  def self.verify_keys(valid_keys, hash)
62
62
  flattened_valid_keys = _flatten_valid_keys(valid_keys)
63
63
  invalid_keys = _flatten_hash_keys(hash) - flattened_valid_keys
@@ -67,7 +67,7 @@ module Braintree
67
67
  raise ArgumentError, "invalid keys: #{sorted}"
68
68
  end
69
69
  end
70
-
70
+
71
71
  def self._flatten_valid_keys(valid_keys, namespace = nil)
72
72
  valid_keys.inject([]) do |result, key|
73
73
  if key.is_a?(Hash)
@@ -85,7 +85,7 @@ module Braintree
85
85
  result
86
86
  end.sort
87
87
  end
88
-
88
+
89
89
  def self._flatten_hash_keys(hash, namespace = nil)
90
90
  hash.inject([]) do |result, (key, value)|
91
91
  full_key = (namespace ? "#{namespace}[#{key}]" : key.to_s)
@@ -7,7 +7,7 @@ module Braintree
7
7
  def initialize(attributes)
8
8
  set_instance_variables_from_hash attributes
9
9
  end
10
-
10
+
11
11
  def inspect # :nodoc:
12
12
  "#<#{self.class} (#{code}) #{message}>"
13
13
  end
@@ -20,7 +20,7 @@ module Braintree
20
20
  # #=> [#<Braintree::ValidationError (91803) Country name is not an accepted country.>]
21
21
  class ValidationErrorCollection
22
22
  include Enumerable
23
-
23
+
24
24
  def initialize(data) # :nodoc:
25
25
  @errors = data[:errors].map { |hash| Braintree::ValidationError.new(hash) }
26
26
  @nested = {}
@@ -29,7 +29,7 @@ module Braintree
29
29
  @nested[key] = ValidationErrorCollection.new(data[key])
30
30
  end
31
31
  end
32
-
32
+
33
33
  # Accesses the error at the given index.
34
34
  def [](index)
35
35
  @errors[index]
@@ -38,7 +38,7 @@ module Braintree
38
38
  def deep_size # :nodoc:
39
39
  size + @nested.values.inject(0) { |count, error_collection| count + error_collection.deep_size }
40
40
  end
41
-
41
+
42
42
  # Iterates over errors at the current level. Nested errors will not be yielded.
43
43
  def each(&block)
44
44
  @errors.each(&block)
@@ -58,11 +58,11 @@ module Braintree
58
58
  def on(attribute)
59
59
  @errors.select { |error| error.attribute == attribute.to_s }
60
60
  end
61
-
61
+
62
62
  # The number of errors at this level. This does not include nested errors.
63
63
  def size
64
64
  @errors.size
65
- end
65
+ end
66
66
 
67
67
  def _inner_inspect(scope = []) # :nodoc:
68
68
  all = []
@@ -75,6 +75,6 @@ module Braintree
75
75
  end
76
76
  all.join(", ")
77
77
  end
78
- end
78
+ end
79
79
  end
80
80
 
@@ -1,9 +1,9 @@
1
1
  module Braintree
2
2
  module Version
3
3
  Major = 1
4
- Minor = 0
5
- Tiny = 1
6
-
4
+ Minor = 1
5
+ Tiny = 0
6
+
7
7
  String = "#{Major}.#{Minor}.#{Tiny}"
8
8
  end
9
9
  end
@@ -15,7 +15,7 @@ module Braintree
15
15
  "symbol" => Proc.new { |symbol| symbol.to_s },
16
16
  "datetime" => Proc.new { |time| time.xmlschema },
17
17
  }
18
-
18
+
19
19
  def self.hash_to_xml(hash)
20
20
  root, contents = hash.keys[0], hash.values[0]
21
21
 
@@ -60,7 +60,7 @@ module Braintree
60
60
  end
61
61
 
62
62
  end
63
-
63
+
64
64
  def self._array_to_xml(array, options = {})
65
65
  raise "expected all elements to be hashes" unless array.all? { |e| e.is_a?(Hash) }
66
66
  raise "expected options[:root]" unless options[:root]
@@ -13,7 +13,7 @@ module Braintree
13
13
  ensure
14
14
  ::LibXML::XML.default_keep_blanks = old_keep_blanks_setting
15
15
  end
16
-
16
+
17
17
  def self._node_to_hash(node, hash = {})
18
18
  if node.text?
19
19
  raise ::LibXML::XML::Error if node.content.length >= LIB_XML_LIMIT
@@ -48,7 +48,7 @@ module Braintree
48
48
  ""
49
49
  elsif value.nil? || value['nil'] == 'true'
50
50
  nil
51
- # If the type is the only element which makes it then
51
+ # If the type is the only element which makes it then
52
52
  # this still makes the value nil, except if type is
53
53
  # a XML node(where type['value'] is a Hash)
54
54
  elsif value['type'] && value.size == 1 && !value['type'].is_a?(::Hash)
@@ -28,7 +28,7 @@ describe Braintree::Address do
28
28
  result.address.postal_code.should == "60622"
29
29
  result.address.country_name.should == "United States of America"
30
30
  end
31
-
31
+
32
32
  it "returns an error response if invalid" do
33
33
  customer = Braintree::Customer.create!(:last_name => "Wilson")
34
34
  result = Braintree::Address.create(
@@ -72,7 +72,7 @@ describe Braintree::Address do
72
72
  address.postal_code.should == "60623"
73
73
  address.country_name.should == "United States of America"
74
74
  end
75
-
75
+
76
76
  it "raises a ValidationsFailed if invalid" do
77
77
  customer = Braintree::Customer.create!(:last_name => "Wilson")
78
78
  expect do
@@ -83,7 +83,7 @@ describe Braintree::Address do
83
83
  end.to raise_error(Braintree::ValidationsFailed)
84
84
  end
85
85
  end
86
-
86
+
87
87
  describe "self.delete" do
88
88
  it "deletes the address given a customer id and an address id" do
89
89
  customer = Braintree::Customer.create!(:last_name => "Wilson")
@@ -103,7 +103,7 @@ describe Braintree::Address do
103
103
  end.to raise_error(Braintree::NotFoundError)
104
104
  end
105
105
  end
106
-
106
+
107
107
  describe "self.find" do
108
108
  it "finds the address given a customer and an address id" do
109
109
  customer = Braintree::Customer.create!(:last_name => "Wilson")
@@ -116,7 +116,7 @@ describe Braintree::Address do
116
116
  address = Braintree::Address.create!(:customer_id => customer.id, :street_address => "123 E Main St")
117
117
  Braintree::Address.find(customer.id, address.id).should == address
118
118
  end
119
-
119
+
120
120
  it "raises a NotFoundError if it cannot be found because of customer id" do
121
121
  customer = Braintree::Customer.create!(:last_name => "Wilson")
122
122
  address = Braintree::Address.create!(:customer_id => customer.id, :street_address => "123 E Main St")
@@ -137,7 +137,7 @@ describe Braintree::Address do
137
137
  "address for customer \"#{customer.id}\" with id \"invalid\" not found")
138
138
  end
139
139
  end
140
-
140
+
141
141
  describe "self.update" do
142
142
  it "raises NotFoundError if the address can't be found" do
143
143
  customer = Braintree::Customer.create!(:last_name => "Wilson")
@@ -176,7 +176,7 @@ describe Braintree::Address do
176
176
  result.address.postal_code.should == "60621"
177
177
  result.address.country_name.should == "United States of America"
178
178
  end
179
-
179
+
180
180
  it "returns an error response if invalid" do
181
181
  customer = Braintree::Customer.create!(:last_name => "Miller")
182
182
  address = Braintree::Address.create!(
@@ -232,7 +232,7 @@ describe Braintree::Address do
232
232
  updated_address.postal_code.should == "60621"
233
233
  updated_address.country_name.should == "United States of America"
234
234
  end
235
-
235
+
236
236
  it "raises a ValidationsFailed invalid" do
237
237
  customer = Braintree::Customer.create!(:last_name => "Miller")
238
238
  address = Braintree::Address.create!(
@@ -250,7 +250,7 @@ describe Braintree::Address do
250
250
  end
251
251
  end
252
252
 
253
-
253
+
254
254
  describe "delete" do
255
255
  it "deletes the address" do
256
256
  customer = Braintree::Customer.create!(:last_name => "Wilson")
@@ -261,7 +261,7 @@ describe Braintree::Address do
261
261
  end.to raise_error(Braintree::NotFoundError)
262
262
  end
263
263
  end
264
-
264
+
265
265
  describe "update" do
266
266
  it "returns a success response and updates the address if valid" do
267
267
  customer = Braintree::Customer.create!(:last_name => "Miller")
@@ -291,7 +291,7 @@ describe Braintree::Address do
291
291
  address.postal_code.should == "60621"
292
292
  address.country_name.should == "United States of America"
293
293
  end
294
-
294
+
295
295
  it "returns an error response if invalid" do
296
296
  customer = Braintree::Customer.create!(:last_name => "Miller")
297
297
  address = Braintree::Address.create!(
@@ -334,7 +334,7 @@ describe Braintree::Address do
334
334
  address.postal_code.should == "60621"
335
335
  address.country_name.should == "United States of America"
336
336
  end
337
-
337
+
338
338
  it "raises a ValidationsFailed invalid" do
339
339
  customer = Braintree::Customer.create!(:last_name => "Miller")
340
340
  address = Braintree::Address.create!(
@@ -53,6 +53,8 @@ describe Braintree::CreditCard do
53
53
  )
54
54
  result.success?.should == false
55
55
  result.credit_card_verification.status.should == "processor_declined"
56
+ result.credit_card_verification.processor_response_code.should == "2000"
57
+ result.credit_card_verification.processor_response_text.should == "Do Not Honor"
56
58
  result.credit_card_verification.cvv_response_code.should == "I"
57
59
  result.credit_card_verification.avs_error_response_code.should == nil
58
60
  result.credit_card_verification.avs_postal_code_response_code.should == "I"
@@ -69,7 +71,7 @@ describe Braintree::CreditCard do
69
71
  )
70
72
  result.success?.should == true
71
73
  end
72
-
74
+
73
75
  it "adds credit card with billing address to customer" do
74
76
  customer = Braintree::Customer.create!
75
77
  result = Braintree::CreditCard.create(
@@ -88,7 +90,7 @@ describe Braintree::CreditCard do
88
90
  credit_card.bin.should == Braintree::Test::CreditCardNumbers::MasterCard[0, 6]
89
91
  credit_card.billing_address.street_address.should == "123 Abc Way"
90
92
  end
91
-
93
+
92
94
  it "returns an error response if unsuccessful" do
93
95
  customer = Braintree::Customer.create!
94
96
  result = Braintree::CreditCard.create(
@@ -127,7 +129,7 @@ describe Braintree::CreditCard do
127
129
  end.to raise_error(Braintree::ValidationsFailed)
128
130
  end
129
131
  end
130
-
132
+
131
133
  describe "self.credit" do
132
134
  it "creates a credit transaction using the payment method token, returning a result object" do
133
135
  customer = Braintree::Customer.create!(
@@ -141,7 +143,7 @@ describe Braintree::CreditCard do
141
143
  :amount => "100.00"
142
144
  )
143
145
  result.success?.should == true
144
- result.transaction.amount.should == "100.00"
146
+ result.transaction.amount.should == BigDecimal.new("100.00")
145
147
  result.transaction.type.should == "credit"
146
148
  result.transaction.customer_details.id.should == customer.id
147
149
  result.transaction.credit_card_details.token.should == customer.credit_cards[0].token
@@ -150,7 +152,7 @@ describe Braintree::CreditCard do
150
152
  result.transaction.credit_card_details.expiration_date.should == "05/2010"
151
153
  end
152
154
  end
153
-
155
+
154
156
  describe "self.credit!" do
155
157
  it "creates a credit transaction using the payment method token, returning the transaction" do
156
158
  customer = Braintree::Customer.create!(
@@ -163,7 +165,7 @@ describe Braintree::CreditCard do
163
165
  customer.credit_cards[0].token,
164
166
  :amount => "100.00"
165
167
  )
166
- transaction.amount.should == "100.00"
168
+ transaction.amount.should == BigDecimal.new("100.00")
167
169
  transaction.type.should == "credit"
168
170
  transaction.customer_details.id.should == customer.id
169
171
  transaction.credit_card_details.token.should == customer.credit_cards[0].token
@@ -202,7 +204,7 @@ describe Braintree::CreditCard do
202
204
  credit_card.expiration_date.should == "05/2012"
203
205
  credit_card.customer_id.should == customer.id
204
206
  end
205
-
207
+
206
208
  it "returns xml with nested errors if validation errors" do
207
209
  customer = Braintree::Customer.create.customer
208
210
  params = {
@@ -218,7 +220,7 @@ describe Braintree::CreditCard do
218
220
  }
219
221
  }
220
222
  query_string_response = create_credit_card_via_tr(params, tr_data_params)
221
- result = Braintree::CreditCard.create_from_transparent_redirect(query_string_response)
223
+ result = Braintree::CreditCard.create_from_transparent_redirect(query_string_response)
222
224
  result.success?.should == false
223
225
  result.params[:customer_id] == customer.id
224
226
  result.params[:credit_card]["cardholder_name"] == customer.id
@@ -227,6 +229,156 @@ describe Braintree::CreditCard do
227
229
  end
228
230
  end
229
231
 
232
+ describe "self.update" do
233
+ it "updates the credit card" do
234
+ customer = Braintree::Customer.create!
235
+ credit_card = Braintree::CreditCard.create!(
236
+ :cardholder_name => "Original Holder",
237
+ :customer_id => customer.id,
238
+ :cvv => "123",
239
+ :number => Braintree::Test::CreditCardNumbers::Visa,
240
+ :expiration_date => "05/2012"
241
+ )
242
+ update_result = Braintree::CreditCard.update(credit_card.token,
243
+ :cardholder_name => "New Holder",
244
+ :cvv => "456",
245
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
246
+ :expiration_date => "06/2013"
247
+ )
248
+ update_result.success?.should == true
249
+ update_result.credit_card.should == credit_card
250
+ updated_credit_card = update_result.credit_card
251
+ updated_credit_card.bin.should == Braintree::Test::CreditCardNumbers::MasterCard[0, 6]
252
+ updated_credit_card.last_4.should == Braintree::Test::CreditCardNumbers::MasterCard[-4..-1]
253
+ updated_credit_card.expiration_date.should == "06/2013"
254
+ updated_credit_card.cardholder_name.should == "New Holder"
255
+ end
256
+
257
+ it "verifies the update if options[verify_card]=true" do
258
+ customer = Braintree::Customer.create!
259
+ credit_card = Braintree::CreditCard.create!(
260
+ :cardholder_name => "Original Holder",
261
+ :customer_id => customer.id,
262
+ :cvv => "123",
263
+ :number => Braintree::Test::CreditCardNumbers::Visa,
264
+ :expiration_date => "05/2012"
265
+ )
266
+ update_result = Braintree::CreditCard.update(credit_card.token,
267
+ :cardholder_name => "New Holder",
268
+ :cvv => "456",
269
+ :number => Braintree::Test::CreditCardNumbers::FailsSandboxVerification::MasterCard,
270
+ :expiration_date => "06/2013",
271
+ :options => {:verify_card => true}
272
+ )
273
+ update_result.success?.should == false
274
+ update_result.credit_card_verification.status.should == "processor_declined"
275
+ end
276
+
277
+ it "can update the billing address" do
278
+ customer = Braintree::Customer.create!
279
+ credit_card = Braintree::CreditCard.create!(
280
+ :cardholder_name => "Original Holder",
281
+ :customer_id => customer.id,
282
+ :cvv => "123",
283
+ :number => Braintree::Test::CreditCardNumbers::Visa,
284
+ :expiration_date => "05/2012",
285
+ :billing_address => {
286
+ :first_name => "Old First Name",
287
+ :last_name => "Old Last Name",
288
+ :company => "Old Company",
289
+ :street_address => "123 Old St",
290
+ :extended_address => "Apt Old",
291
+ :locality => "Old City",
292
+ :region => "Old State",
293
+ :postal_code => "12345",
294
+ :country_name => "Canada"
295
+ }
296
+ )
297
+ result = Braintree::CreditCard.update(credit_card.token,
298
+ :options => {:verify_card => false},
299
+ :billing_address => {
300
+ :first_name => "New First Name",
301
+ :last_name => "New Last Name",
302
+ :company => "New Company",
303
+ :street_address => "123 New St",
304
+ :extended_address => "Apt New",
305
+ :locality => "New City",
306
+ :region => "New State",
307
+ :postal_code => "56789",
308
+ :country_name => "United States of America"
309
+ }
310
+ )
311
+ result.success?.should == true
312
+ address = result.credit_card.billing_address
313
+ address.first_name.should == "New First Name"
314
+ address.last_name.should == "New Last Name"
315
+ address.company.should == "New Company"
316
+ address.street_address.should == "123 New St"
317
+ address.extended_address.should == "Apt New"
318
+ address.locality.should == "New City"
319
+ address.region.should == "New State"
320
+ address.postal_code.should == "56789"
321
+ address.country_name.should == "United States of America"
322
+ end
323
+
324
+ it "returns an error response if invalid" do
325
+ customer = Braintree::Customer.create!
326
+ credit_card = Braintree::CreditCard.create!(
327
+ :cardholder_name => "Original Holder",
328
+ :customer_id => customer.id,
329
+ :number => Braintree::Test::CreditCardNumbers::Visa,
330
+ :expiration_date => "05/2012"
331
+ )
332
+ update_result = Braintree::CreditCard.update(credit_card.token,
333
+ :cardholder_name => "New Holder",
334
+ :number => "invalid",
335
+ :expiration_date => "05/2014"
336
+ )
337
+ update_result.success?.should == false
338
+ update_result.errors.for(:credit_card).on(:number)[0].message.should == "Credit card number must be 12-19 digits."
339
+ end
340
+ end
341
+
342
+ describe "self.update!" do
343
+ it "updates the credit card and returns true if valid" do
344
+ customer = Braintree::Customer.create!
345
+ credit_card = Braintree::CreditCard.create!(
346
+ :cardholder_name => "Original Holder",
347
+ :customer_id => customer.id,
348
+ :number => Braintree::Test::CreditCardNumbers::Visa,
349
+ :expiration_date => "05/2012"
350
+ )
351
+ updated_credit_card = Braintree::CreditCard.update!(credit_card.token,
352
+ :cardholder_name => "New Holder",
353
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
354
+ :expiration_date => "06/2013"
355
+ )
356
+ updated_credit_card.token.should == credit_card.token
357
+ updated_credit_card.bin.should == Braintree::Test::CreditCardNumbers::MasterCard[0, 6]
358
+ updated_credit_card.last_4.should == Braintree::Test::CreditCardNumbers::MasterCard[-4..-1]
359
+ updated_credit_card.expiration_date.should == "06/2013"
360
+ updated_credit_card.cardholder_name.should == "New Holder"
361
+ updated_credit_card.updated_at.between?(Time.now - 5, Time.now).should == true
362
+ end
363
+
364
+ it "raises a ValidationsFailed if invalid" do
365
+ customer = Braintree::Customer.create!
366
+ credit_card = Braintree::CreditCard.create!(
367
+ :cardholder_name => "Original Holder",
368
+ :customer_id => customer.id,
369
+ :number => Braintree::Test::CreditCardNumbers::Visa,
370
+ :expiration_date => "05/2012"
371
+ )
372
+ expect do
373
+ Braintree::CreditCard.update!(credit_card.token,
374
+ :cardholder_name => "New Holder",
375
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
376
+ :expiration_date => "invalid/date"
377
+ )
378
+ end.to raise_error(Braintree::ValidationsFailed)
379
+ end
380
+ end
381
+
230
382
  describe "self.update_from_transparent_redirect" do
231
383
  it "updates the credit card" do
232
384
  old_token = "token#{rand(1_000_000)}"
@@ -276,7 +428,7 @@ describe Braintree::CreditCard do
276
428
  :amount => "100.00"
277
429
  )
278
430
  result.success?.should == true
279
- result.transaction.amount.should == "100.00"
431
+ result.transaction.amount.should == BigDecimal.new("100.00")
280
432
  result.transaction.type.should == "credit"
281
433
  result.transaction.customer_details.id.should == customer.id
282
434
  result.transaction.credit_card_details.token.should == customer.credit_cards[0].token
@@ -295,7 +447,7 @@ describe Braintree::CreditCard do
295
447
  }
296
448
  )
297
449
  transaction = customer.credit_cards[0].credit!(:amount => "100.00")
298
- transaction.amount.should == "100.00"
450
+ transaction.amount.should == BigDecimal.new("100.00")
299
451
  transaction.type.should == "credit"
300
452
  transaction.customer_details.id.should == customer.id
301
453
  transaction.credit_card_details.token.should == customer.credit_cards[0].token
@@ -303,7 +455,7 @@ describe Braintree::CreditCard do
303
455
  transaction.credit_card_details.last_4.should == Braintree::Test::CreditCardNumbers::Visa[-4..-1]
304
456
  transaction.credit_card_details.expiration_date.should == "05/2010"
305
457
  end
306
-
458
+
307
459
  it "raises a ValidationsFailed if invalid" do
308
460
  customer = Braintree::Customer.create!(
309
461
  :credit_card => {
@@ -316,16 +468,16 @@ describe Braintree::CreditCard do
316
468
  end.to raise_error(Braintree::ValidationsFailed)
317
469
  end
318
470
  end
319
-
471
+
320
472
  describe "delete" do
321
473
  it "deletes the credit card" do
322
474
  customer = Braintree::Customer.create.customer
323
475
  result = Braintree::CreditCard.create(
324
476
  :customer_id => customer.id,
325
477
  :number => Braintree::Test::CreditCardNumbers::Visa,
326
- :expiration_date => "05/2012"
478
+ :expiration_date => "05/2012"
327
479
  )
328
-
480
+
329
481
  result.success?.should == true
330
482
  credit_card = result.credit_card
331
483
  credit_card.delete.should == true
@@ -334,7 +486,7 @@ describe Braintree::CreditCard do
334
486
  end.to raise_error(Braintree::NotFoundError)
335
487
  end
336
488
  end
337
-
489
+
338
490
  describe "self.expired" do
339
491
  it "finds expired payment methods, paginated" do
340
492
  first_page = Braintree::CreditCard.expired
@@ -353,7 +505,7 @@ describe Braintree::CreditCard do
353
505
  # second_page.all? { |pm| pm.expired?.should == true }
354
506
  end
355
507
  end
356
-
508
+
357
509
  describe "self.expiring_between" do
358
510
  it "finds payment methods expiring between the given dates" do
359
511
  next_year = Time.now.year + 1
@@ -382,7 +534,7 @@ describe Braintree::CreditCard do
382
534
  result = Braintree::CreditCard.create(
383
535
  :customer_id => customer.id,
384
536
  :number => Braintree::Test::CreditCardNumbers::Visa,
385
- :expiration_date => "05/2012"
537
+ :expiration_date => "05/2012"
386
538
  )
387
539
  result.success?.should == true
388
540
  credit_card = Braintree::CreditCard.find(result.credit_card.token)
@@ -391,14 +543,14 @@ describe Braintree::CreditCard do
391
543
  credit_card.token.should == result.credit_card.token
392
544
  credit_card.expiration_date.should == "05/2012"
393
545
  end
394
-
546
+
395
547
  it "raises a NotFoundError exception if payment method cannot be found" do
396
548
  expect do
397
549
  Braintree::CreditCard.find("invalid-token")
398
550
  end.to raise_error(Braintree::NotFoundError, 'payment method with token "invalid-token" not found')
399
551
  end
400
552
  end
401
-
553
+
402
554
  describe "self.sale" do
403
555
  it "creates a sale transaction using the credit card, returning a result object" do
404
556
  customer = Braintree::Customer.create!(
@@ -410,7 +562,7 @@ describe Braintree::CreditCard do
410
562
  result = Braintree::CreditCard.sale(customer.credit_cards[0].token, :amount => "100.00")
411
563
 
412
564
  result.success?.should == true
413
- result.transaction.amount.should == "100.00"
565
+ result.transaction.amount.should == BigDecimal.new("100.00")
414
566
  result.transaction.type.should == "sale"
415
567
  result.transaction.customer_details.id.should == customer.id
416
568
  result.transaction.credit_card_details.token.should == customer.credit_cards[0].token
@@ -429,7 +581,7 @@ describe Braintree::CreditCard do
429
581
  }
430
582
  )
431
583
  transaction = Braintree::CreditCard.sale!(customer.credit_cards[0].token, :amount => "100.00")
432
- transaction.amount.should == "100.00"
584
+ transaction.amount.should == BigDecimal.new("100.00")
433
585
  transaction.type.should == "sale"
434
586
  transaction.customer_details.id.should == customer.id
435
587
  transaction.credit_card_details.token.should == customer.credit_cards[0].token
@@ -438,7 +590,7 @@ describe Braintree::CreditCard do
438
590
  transaction.credit_card_details.expiration_date.should == "05/2010"
439
591
  end
440
592
  end
441
-
593
+
442
594
  describe "sale" do
443
595
  it "creates a sale transaction using the credit card, returning a result object" do
444
596
  customer = Braintree::Customer.create!(
@@ -451,7 +603,7 @@ describe Braintree::CreditCard do
451
603
  :amount => "100.00"
452
604
  )
453
605
  result.success?.should == true
454
- result.transaction.amount.should == "100.00"
606
+ result.transaction.amount.should == BigDecimal.new("100.00")
455
607
  result.transaction.type.should == "sale"
456
608
  result.transaction.customer_details.id.should == customer.id
457
609
  result.transaction.credit_card_details.token.should == customer.credit_cards[0].token
@@ -470,7 +622,7 @@ describe Braintree::CreditCard do
470
622
  }
471
623
  )
472
624
  transaction = customer.credit_cards[0].sale!(:amount => "100.00")
473
- transaction.amount.should == "100.00"
625
+ transaction.amount.should == BigDecimal.new("100.00")
474
626
  transaction.type.should == "sale"
475
627
  transaction.customer_details.id.should == customer.id
476
628
  transaction.credit_card_details.token.should == customer.credit_cards[0].token
@@ -478,7 +630,7 @@ describe Braintree::CreditCard do
478
630
  transaction.credit_card_details.last_4.should == Braintree::Test::CreditCardNumbers::Visa[-4..-1]
479
631
  transaction.credit_card_details.expiration_date.should == "05/2010"
480
632
  end
481
-
633
+
482
634
  it "raises a ValidationsFailed if invalid" do
483
635
  customer = Braintree::Customer.create!(
484
636
  :credit_card => {
@@ -491,7 +643,7 @@ describe Braintree::CreditCard do
491
643
  end.to raise_error(Braintree::ValidationsFailed)
492
644
  end
493
645
  end
494
-
646
+
495
647
  describe "update" do
496
648
  it "updates the credit card" do
497
649
  customer = Braintree::Customer.create!
@@ -500,7 +652,7 @@ describe Braintree::CreditCard do
500
652
  :customer_id => customer.id,
501
653
  :cvv => "123",
502
654
  :number => Braintree::Test::CreditCardNumbers::Visa,
503
- :expiration_date => "05/2012"
655
+ :expiration_date => "05/2012"
504
656
  )
505
657
  update_result = credit_card.update(
506
658
  :cardholder_name => "New Holder",
@@ -524,7 +676,7 @@ describe Braintree::CreditCard do
524
676
  :customer_id => customer.id,
525
677
  :cvv => "123",
526
678
  :number => Braintree::Test::CreditCardNumbers::Visa,
527
- :expiration_date => "05/2012"
679
+ :expiration_date => "05/2012"
528
680
  )
529
681
  update_result = credit_card.update(
530
682
  :cardholder_name => "New Holder",
@@ -555,7 +707,7 @@ describe Braintree::CreditCard do
555
707
  :region => "Old State",
556
708
  :postal_code => "12345",
557
709
  :country_name => "Canada"
558
- }
710
+ }
559
711
  )
560
712
  result = credit_card.update(
561
713
  :options => {:verify_card => false},
@@ -584,14 +736,14 @@ describe Braintree::CreditCard do
584
736
  address.postal_code.should == "56789"
585
737
  address.country_name.should == "United States of America"
586
738
  end
587
-
739
+
588
740
  it "returns an error response if invalid" do
589
741
  customer = Braintree::Customer.create!
590
742
  credit_card = Braintree::CreditCard.create!(
591
743
  :cardholder_name => "Original Holder",
592
744
  :customer_id => customer.id,
593
745
  :number => Braintree::Test::CreditCardNumbers::Visa,
594
- :expiration_date => "05/2012"
746
+ :expiration_date => "05/2012"
595
747
  )
596
748
  update_result = credit_card.update(
597
749
  :cardholder_name => "New Holder",
@@ -610,7 +762,7 @@ describe Braintree::CreditCard do
610
762
  :cardholder_name => "Original Holder",
611
763
  :customer_id => customer.id,
612
764
  :number => Braintree::Test::CreditCardNumbers::Visa,
613
- :expiration_date => "05/2012"
765
+ :expiration_date => "05/2012"
614
766
  )
615
767
  credit_card.update!(
616
768
  :cardholder_name => "New Holder",
@@ -623,14 +775,14 @@ describe Braintree::CreditCard do
623
775
  credit_card.cardholder_name.should == "New Holder"
624
776
  credit_card.updated_at.between?(Time.now - 5, Time.now).should == true
625
777
  end
626
-
778
+
627
779
  it "raises a ValidationsFailed if invalid" do
628
780
  customer = Braintree::Customer.create!
629
781
  credit_card = Braintree::CreditCard.create!(
630
782
  :cardholder_name => "Original Holder",
631
783
  :customer_id => customer.id,
632
784
  :number => Braintree::Test::CreditCardNumbers::Visa,
633
- :expiration_date => "05/2012"
785
+ :expiration_date => "05/2012"
634
786
  )
635
787
  expect do
636
788
  credit_card.update!(
@@ -641,7 +793,7 @@ describe Braintree::CreditCard do
641
793
  end.to raise_error(Braintree::ValidationsFailed)
642
794
  end
643
795
  end
644
-
796
+
645
797
  def create_credit_card_via_tr(regular_params, tr_params = {})
646
798
  response = nil
647
799
  Net::HTTP.start("localhost", Braintree::Configuration.port) do |http|
@@ -652,7 +804,7 @@ describe Braintree::CreditCard do
652
804
  response = http.request(request)
653
805
  end
654
806
  if response.code.to_i == 303
655
- query_string = response["Location"].split("?", 2).last
807
+ query_string = response["Location"].split("?", 2).last
656
808
  else
657
809
  raise "did not receive a valid tr response: #{response.body[0,1000].inspect}"
658
810
  end
@@ -668,7 +820,7 @@ describe Braintree::CreditCard do
668
820
  response = http.request(request)
669
821
  end
670
822
  if response.code.to_i == 303
671
- query_string = response["Location"].split("?", 2).last
823
+ query_string = response["Location"].split("?", 2).last
672
824
  else
673
825
  raise "did not receive a valid tr response: #{response.body[0,1000].inspect}"
674
826
  end