braintree 3.4.0 → 4.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85d22ee560b343f4bbd3f71272f4e9d5cfaa83672ddc36fceb9fc383b25772e3
4
- data.tar.gz: 8d29ee6fcd9b7f6ccbab6680029b66c70e53867448b369af806feb454cfdb18c
3
+ metadata.gz: a48854f74d17f7c0f06f437ab9cf144f6787cdb634cb4585b96cbf0e8b3eb316
4
+ data.tar.gz: e278599e9a4fe1ec55ed4c25a0c2941c256815adff6240f24d7326dda3c7979b
5
5
  SHA512:
6
- metadata.gz: d35fdc8ebf0d555649b08e401b4b16f6ac58ee52ca3fdb6a0ce899b10a4c7b2db94873fdb940649941c105cf9ca44686a415a9760619be4e7f5d7d9b33883e81
7
- data.tar.gz: 687c698cd56953bc23694112256bfe422b53e0a0f0697e5c6626567933ecaab332a1fc6732f4085747ef68178a1d76d6f76a372ec070feb365c8557db8301f51
6
+ metadata.gz: dbe42e3ee49bffddde129c228d9dc9ea9a8e7615140d184211378d58add503f13a666f2aaf8c393fafbb330db77685a5953b10344c712da5719c630f1ab64e5a
7
+ data.tar.gz: ae8af00364f7853fb0e6eb82f585ebc30015f0b6ac7014f41eccdfe732348f3b3f715b474afc516b17b913550f9ae339b587a53296cc823bb30c5954ecbda146
data/braintree.gemspec CHANGED
@@ -12,8 +12,7 @@ Gem::Specification.new do |s|
12
12
  s.homepage = "https://www.braintreepayments.com/"
13
13
  s.files = Dir.glob ["README.rdoc", "LICENSE", "lib/**/*.{rb,crt}", "spec/**/*", "*.gemspec"]
14
14
  s.add_dependency "builder", ">= 3.2.4"
15
- s.add_dependency "libxml-ruby", ">= 3.2.0"
16
- s.required_ruby_version = ">=2.5.0"
15
+ s.required_ruby_version = ">=2.6.0"
17
16
  s.metadata = {
18
17
  "bug_tracker_uri" => "https://github.com/braintree/braintree_ruby/issues",
19
18
  "changelog_uri" => "https://github.com/braintree/braintree_ruby/blob/master/CHANGELOG.md",
data/lib/braintree.rb CHANGED
@@ -59,6 +59,7 @@ require "braintree/discount_gateway"
59
59
  require "braintree/dispute"
60
60
  require "braintree/dispute_gateway"
61
61
  require "braintree/dispute/evidence"
62
+ require "braintree/dispute/paypal_message"
62
63
  require "braintree/dispute/status_history"
63
64
  require "braintree/dispute/transaction"
64
65
  require "braintree/dispute/transaction_details"
@@ -87,6 +88,8 @@ require "braintree/payment_instrument_type"
87
88
  require "braintree/payment_method"
88
89
  require "braintree/payment_method_gateway"
89
90
  require "braintree/payment_method_nonce"
91
+ require "braintree/payment_method_nonce_details"
92
+ require "braintree/payment_method_nonce_details_payer_info"
90
93
  require "braintree/payment_method_nonce_gateway"
91
94
  require "braintree/payment_method_parser"
92
95
  require "braintree/paypal_account"
@@ -160,4 +163,5 @@ require "braintree/webhook_testing_gateway"
160
163
  require "braintree/xml"
161
164
  require "braintree/xml/generator"
162
165
  require "braintree/xml/libxml"
166
+ require "braintree/xml/rexml"
163
167
  require "braintree/xml/parser"
@@ -14,6 +14,7 @@ module Braintree
14
14
  attr_reader :id
15
15
  attr_reader :last_name
16
16
  attr_reader :locality
17
+ attr_reader :phone_number
17
18
  attr_reader :postal_code
18
19
  attr_reader :region
19
20
  attr_reader :street_address
@@ -19,6 +19,7 @@ module Braintree
19
19
  attr_reader :paypal_accounts
20
20
  attr_reader :phone
21
21
  attr_reader :samsung_pay_cards
22
+ attr_reader :tax_identifiers
22
23
  attr_reader :updated_at
23
24
  attr_reader :us_bank_accounts
24
25
  attr_reader :venmo_accounts
@@ -90,6 +91,7 @@ module Braintree
90
91
  @visa_checkout_cards = (@visa_checkout_cards|| []).map { |pm| VisaCheckoutCard._new gateway, pm }
91
92
  @samsung_pay_cards = (@samsung_pay_cards|| []).map { |pm| SamsungPayCard._new gateway, pm }
92
93
  @addresses = (@addresses || []).map { |addr| Address._new gateway, addr }
94
+ @tax_identifiers = (@tax_identifiers || []).map { |addr| TaxIdentifier._new gateway, addr }
93
95
  @custom_fields = attributes[:custom_fields].is_a?(Hash) ? attributes[:custom_fields] : {}
94
96
  end
95
97
 
@@ -124,7 +126,7 @@ module Braintree
124
126
 
125
127
  def inspect # :nodoc:
126
128
  first = [:id]
127
- last = [:addresses, :credit_cards, :paypal_accounts]
129
+ last = [:addresses, :credit_cards, :paypal_accounts, :tax_identifiers]
128
130
  order = first + (self.class._attributes - first - last) + last
129
131
  nice_attributes = order.map do |attr|
130
132
  "#{attr}: #{send(attr).inspect}"
@@ -148,7 +150,7 @@ module Braintree
148
150
  def self._attributes # :nodoc:
149
151
  [
150
152
  :addresses, :company, :credit_cards, :email, :fax, :first_name, :id, :last_name, :phone, :website,
151
- :created_at, :updated_at
153
+ :created_at, :updated_at, :tax_identifiers
152
154
  ]
153
155
  end
154
156
 
@@ -80,6 +80,7 @@ module Braintree
80
80
  {:risk_data => [:customer_browser, :customer_ip]},
81
81
  {:credit_card => credit_card_signature},
82
82
  {:paypal_account => paypal_account_signature},
83
+ {:tax_identifiers => [:country_code, :identifier]},
83
84
  {:options => options},
84
85
  {:custom_fields => :_any_key_}
85
86
  ]
@@ -141,6 +142,7 @@ module Braintree
141
142
  :company, :email, :fax, :first_name, :id, :last_name, :phone, :website,
142
143
  :device_data, :payment_method_nonce, :default_payment_method_token,
143
144
  {:credit_card => credit_card_signature},
145
+ {:tax_identifiers => [:country_code, :identifier]},
144
146
  {:options => options},
145
147
  {:custom_fields => :_any_key_}
146
148
  ]
@@ -7,6 +7,7 @@ module Braintree
7
7
  attr_reader :amount_disputed
8
8
  attr_reader :amount_won
9
9
  attr_reader :case_number
10
+ attr_reader :chargeback_protection_level
10
11
  attr_reader :created_at
11
12
  attr_reader :currency_iso_code
12
13
  attr_reader :date_opened
@@ -17,6 +18,7 @@ module Braintree
17
18
  attr_reader :kind
18
19
  attr_reader :merchant_account_id
19
20
  attr_reader :original_dispute_id
21
+ attr_reader :paypal_messages
20
22
  attr_reader :processor_comments
21
23
  attr_reader :reason
22
24
  attr_reader :reason_code
@@ -65,6 +67,14 @@ module Braintree
65
67
  All = constants.map { |c| const_get(c) }
66
68
  end
67
69
 
70
+ module ChargebackProtectionLevel
71
+ Effortless = "effortless"
72
+ Standard = "standard"
73
+ NotProtected = "not_protected"
74
+
75
+ All = constants.map { |c| const_get(c) }
76
+ end
77
+
68
78
  class << self
69
79
  protected :new
70
80
  def _new(*args) # :nodoc:
@@ -114,6 +124,10 @@ module Braintree
114
124
  Braintree::Dispute::Evidence.new(record)
115
125
  end unless evidence.nil?
116
126
 
127
+ @paypal_messages = paypal_messages.map do |record|
128
+ Braintree::Dispute::PayPalMessage.new(record)
129
+ end unless paypal_messages.nil?
130
+
117
131
  @transaction_details = TransactionDetails.new(transaction)
118
132
  @transaction = Transaction.new(transaction)
119
133
 
@@ -0,0 +1,15 @@
1
+ module Braintree
2
+ class Dispute
3
+ class PayPalMessage # :nodoc:
4
+ include BaseModule
5
+
6
+ attr_reader :message,
7
+ :sender,
8
+ :sent_at
9
+
10
+ def initialize(attributes)
11
+ set_instance_variables_from_hash attributes unless attributes.nil?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -8,6 +8,7 @@ module Braintree
8
8
  :transaction_id,
9
9
  )
10
10
 
11
+ multiple_value_field :chargeback_protection_level, :allows => Dispute::ChargebackProtectionLevel::All
11
12
  multiple_value_field :kind, :allows => Dispute::Kind::All
12
13
  multiple_value_field :merchant_account_id
13
14
  multiple_value_field :reason, :allows => Dispute::Reason::All
@@ -517,8 +517,6 @@ module Braintree
517
517
  end
518
518
 
519
519
  module ExternalVault
520
- # NEXT_MAJOR_VERSION remove this validation error as it is no longer returned by the gateway
521
- CardTypeIsInvalid = "915178"
522
520
  PreviousNetworkTransactionIdIsInvalid = "915179"
523
521
  StatusIsInvalid = "915175"
524
522
  StatusWithPreviousNetworkTransactionIdIsInvalid = "915177"
@@ -786,8 +784,6 @@ module Braintree
786
784
  end
787
785
 
788
786
  module RiskData
789
- # NEXT_MAJOR_VERSION Remove CustomerBrowserIsTooLong (this validation is no longer applied)
790
- CustomerBrowserIsTooLong = "94701"
791
787
  CustomerDeviceIdIsTooLong = "94702"
792
788
  CustomerLocationZipInvalidCharacters = "94703"
793
789
  CustomerLocationZipIsInvalid = "94704"
@@ -186,8 +186,6 @@ module Braintree
186
186
  options << :fail_on_duplicate_payment_method
187
187
  signature << :customer_id
188
188
  signature << :paypal_refresh_token
189
- # NEXT_MAJOR_VERSION remove this from the signature
190
- signature << :paypal_vault_without_upgrade
191
189
  when :update
192
190
  billing_address_params << {:options => [:update_existing]}
193
191
  else
@@ -25,7 +25,7 @@ module Braintree
25
25
  @gateway = gateway
26
26
  @nonce = attributes.fetch(:nonce)
27
27
  @type = attributes.fetch(:type)
28
- @details = attributes.fetch(:details)
28
+ @details = PaymentMethodNonceDetails.new(attributes[:details]) if attributes[:details]
29
29
  @authentication_insight = attributes.fetch(:authentication_insight, nil)
30
30
  @three_d_secure_info = ThreeDSecureInfo.new(attributes[:three_d_secure_info]) if attributes[:three_d_secure_info]
31
31
  @bin_data = BinData.new(attributes[:bin_data]) if attributes[:bin_data]
@@ -0,0 +1,37 @@
1
+ module Braintree
2
+ class PaymentMethodNonceDetails # :nodoc:
3
+ include BaseModule
4
+
5
+ attr_reader :bin
6
+ attr_reader :card_type
7
+ attr_reader :expiration_month
8
+ attr_reader :expiration_year
9
+ attr_reader :is_network_tokenized
10
+ attr_reader :last_two
11
+ attr_reader :payer_info
12
+
13
+ alias_method :is_network_tokenized?, :is_network_tokenized
14
+
15
+ def initialize(attributes)
16
+ set_instance_variables_from_hash attributes unless attributes.nil?
17
+ @payer_info = PaymentMethodNonceDetailsPayerInfo.new(attributes[:payer_info]) if attributes[:payer_info]
18
+ end
19
+
20
+ def inspect
21
+ attr_order = [
22
+ :bin,
23
+ :card_type,
24
+ :expiration_month,
25
+ :expiration_year,
26
+ :is_network_tokenized,
27
+ :last_two,
28
+ :payer_info,
29
+ ]
30
+
31
+ formatted_attrs = attr_order.map do |attr|
32
+ "#{attr}: #{send(attr).inspect}"
33
+ end
34
+ "#<PaymentMethodNonceDetails #{formatted_attrs.join(", ")}>"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,32 @@
1
+ module Braintree
2
+ class PaymentMethodNonceDetailsPayerInfo # :nodoc:
3
+ include BaseModule
4
+
5
+ attr_reader :billing_agreement_id
6
+ attr_reader :country_code
7
+ attr_reader :email
8
+ attr_reader :first_name
9
+ attr_reader :last_name
10
+ attr_reader :payer_id
11
+
12
+ def initialize(attributes)
13
+ set_instance_variables_from_hash attributes unless attributes.nil?
14
+ end
15
+
16
+ def inspect
17
+ attr_order = [
18
+ :billing_agreement_id,
19
+ :country_code,
20
+ :email,
21
+ :first_name,
22
+ :last_name,
23
+ :payer_id,
24
+ ]
25
+
26
+ formatted_attrs = attr_order.map do |attr|
27
+ "#{attr}: #{send(attr).inspect}"
28
+ end
29
+ "#<PaymentMethodNonceDetailsPayerInfo #{formatted_attrs.join(", ")}>"
30
+ end
31
+ end
32
+ end
@@ -1,7 +1,7 @@
1
1
  module Braintree
2
2
  module Version
3
- Major = 3
4
- Minor = 4
3
+ Major = 4
4
+ Minor = 0
5
5
  Tiny = 0
6
6
 
7
7
  String = "#{Major}.#{Minor}.#{Tiny}"
@@ -1,4 +1,3 @@
1
- require "libxml"
2
1
  # Portions of this code were copied and modified from Ruby on Rails, released
3
2
  # under the MIT license, copyright (c) 2005-2009 David Heinemeier Hansson
4
3
  module Braintree
@@ -11,12 +11,22 @@ module Braintree
11
11
  "boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.strip) },
12
12
  }
13
13
 
14
- def self.hash_from_xml(xml)
15
- standardized_hash_structure = ::Braintree::Xml::Libxml.parse(xml)
14
+ def self.hash_from_xml(xml, parser = _determine_parser)
15
+ standardized_hash_structure = parser.parse(xml)
16
16
  transformed_xml = _transform_xml(standardized_hash_structure)
17
17
  Util.symbolize_keys(transformed_xml)
18
18
  end
19
19
 
20
+ def self._determine_parser
21
+ # If LibXML is not available, we fall back to REXML
22
+ # This allows us to be compatible with JRuby, which LibXML does not support
23
+ if defined?(::LibXML::XML) && ::LibXML::XML.respond_to?(:default_keep_blanks=)
24
+ ::Braintree::Xml::Libxml
25
+ else
26
+ ::Braintree::Xml::Rexml
27
+ end
28
+ end
29
+
20
30
  # Transform into standard Ruby types and convert all keys to snake_case instead of dash-case
21
31
  def self._transform_xml(value)
22
32
  case value.class.to_s
@@ -0,0 +1,70 @@
1
+ # Portions of this code were copied and modified from Ruby on Rails, released
2
+ # under the MIT license, copyright (c) 2005-2009 David Heinemeier Hansson
3
+ module Braintree
4
+ module Xml # :nodoc:
5
+ module Rexml # :nodoc:
6
+
7
+ CONTENT_KEY = "__content__".freeze
8
+
9
+ def self.parse(string)
10
+ require "rexml/document" unless defined?(REXML::Document)
11
+ doc = REXML::Document.new(string)
12
+ _merge_element!({}, doc.root)
13
+ end
14
+
15
+ def self._merge_element!(hash, element)
16
+ _merge!(hash, element.name, _collapse(element))
17
+ end
18
+
19
+ def self._collapse(element)
20
+ hash = _get_attributes(element)
21
+
22
+ if element.has_elements?
23
+ element.each_element { |child| _merge_element!(hash, child) }
24
+ _merge_texts!(hash, element) unless _empty_content?(element)
25
+ hash
26
+ else
27
+ _merge_texts!(hash, element)
28
+ end
29
+ end
30
+
31
+ def self._merge_texts!(hash, element)
32
+ unless element.has_text?
33
+ hash
34
+ else
35
+ # must use value to prevent double-escaping
36
+ _merge!(
37
+ hash,
38
+ CONTENT_KEY,
39
+ element.texts.map { |t| t.value }.join,
40
+ )
41
+ end
42
+ end
43
+
44
+ def self._merge!(hash, key, value)
45
+ if hash.has_key?(key)
46
+ if hash[key].instance_of?(Array)
47
+ hash[key] << value
48
+ else
49
+ hash[key] = [hash[key], value]
50
+ end
51
+ elsif value.instance_of?(Array)
52
+ hash[key] = [value]
53
+ else
54
+ hash[key] = value
55
+ end
56
+ hash
57
+ end
58
+
59
+ def self._get_attributes(element)
60
+ attributes = {}
61
+ element.attributes.each { |n,v| attributes[n] = v }
62
+ attributes
63
+ end
64
+
65
+ def self._empty_content?(element)
66
+ element.texts.join.strip == ""
67
+ end
68
+ end
69
+ end
70
+ end
@@ -14,6 +14,7 @@ describe Braintree::Address do
14
14
  :extended_address => "Suite 200",
15
15
  :locality => "Chicago",
16
16
  :region => "Illinois",
17
+ :phone_number => "5551231234",
17
18
  :postal_code => "60622",
18
19
  :country_name => "United States of America",
19
20
  )
@@ -26,6 +27,7 @@ describe Braintree::Address do
26
27
  result.address.extended_address.should == "Suite 200"
27
28
  result.address.locality.should == "Chicago"
28
29
  result.address.region.should == "Illinois"
30
+ result.address.phone_number.should == "5551231234"
29
31
  result.address.postal_code.should == "60622"
30
32
  result.address.country_name.should == "United States of America"
31
33
  result.address.country_code_alpha2.should == "US"
@@ -131,6 +133,7 @@ describe Braintree::Address do
131
133
  :extended_address => "Suite 201",
132
134
  :locality => "Bartlett",
133
135
  :region => "IL",
136
+ :phone_number => "5551231234",
134
137
  :postal_code => "60623",
135
138
  :country_name => "United States of America",
136
139
  )
@@ -139,6 +142,7 @@ describe Braintree::Address do
139
142
  address.extended_address.should == "Suite 201"
140
143
  address.locality.should == "Bartlett"
141
144
  address.region.should == "IL"
145
+ address.phone_number.should == "5551231234"
142
146
  address.postal_code.should == "60623"
143
147
  address.country_name.should == "United States of America"
144
148
  end
@@ -40,6 +40,7 @@ describe Braintree::Customer do
40
40
  :phone => "312.555.1234",
41
41
  :fax => "614.555.5678",
42
42
  :website => "www.microsoft.com",
43
+ :tax_identifiers => [{:country_code => "US", :identifier => "987654321"}],
43
44
  )
44
45
  result.success?.should == true
45
46
  result.customer.id.should =~ /^\d{6,}$/
@@ -114,6 +115,17 @@ describe Braintree::Customer do
114
115
  result.should be_success
115
116
  end
116
117
 
118
+ it "supports creation with tax_identifiers" do
119
+ result = Braintree::Customer.create(
120
+ :tax_identifiers => [
121
+ {:country_code => "US", :identifier => "987654321"},
122
+ {:country_code => "CL", :identifier => "123456789"}
123
+ ],
124
+ )
125
+
126
+ result.should be_success
127
+ end
128
+
117
129
  it "can create without any attributes" do
118
130
  result = Braintree::Customer.create
119
131
  result.success?.should == true
@@ -1333,6 +1345,21 @@ describe Braintree::Customer do
1333
1345
  result.success?.should == true
1334
1346
  end
1335
1347
 
1348
+ it "can update a tax_identifier" do
1349
+ customer = Braintree::Customer.create!(
1350
+ :tax_identifiers => [
1351
+ {:country_code => "US", :identifier => "987654321"},
1352
+ {:country_code => "CL", :identifier => "123456789"}
1353
+ ],
1354
+ )
1355
+
1356
+ result = Braintree::Customer.update(
1357
+ customer.id,
1358
+ :tax_identifiers => [{:country_code => "US", :identifier => "567891234"}],
1359
+ )
1360
+ result.success?.should == true
1361
+ end
1362
+
1336
1363
  it "validates presence of three_d_secure_version in 3ds pass thru params" do
1337
1364
  result = Braintree::Customer.create(
1338
1365
  :payment_method_nonce => Braintree::Test::Nonce::ThreeDSecureVisaFullAuthentication,
@@ -78,6 +78,31 @@ describe Braintree::Dispute, "search" do
78
78
  dispute = collection.disputes.first
79
79
  end
80
80
 
81
+ it "correctly returns chargeback protected disputes" do
82
+ collection = Braintree::Dispute.search do |search|
83
+ search.case_number.is "CASE-CHARGEBACK-PROTECTED"
84
+ end
85
+
86
+ expect(collection.disputes.count).to eq(1)
87
+ dispute = collection.disputes.first
88
+
89
+ expect(dispute.chargeback_protection_level).to eq(Braintree::Dispute::ChargebackProtectionLevel::Effortless)
90
+ expect(dispute.reason).to eq(Braintree::Dispute::Reason::Fraud)
91
+ end
92
+
93
+ it "correctly returns disputes by chargeback protection level flag" do
94
+ collection = Braintree::Dispute.search do |search|
95
+ search.chargeback_protection_level.in [
96
+ Braintree::Dispute::ChargebackProtectionLevel::Effortless
97
+ ]
98
+ end
99
+ expect(collection.disputes.count).to eq(1)
100
+ dispute = collection.disputes.first
101
+
102
+ expect(dispute.chargeback_protection_level).to eq(Braintree::Dispute::ChargebackProtectionLevel::Effortless)
103
+ expect(dispute.reason).to eq(Braintree::Dispute::Reason::Fraud)
104
+ end
105
+
81
106
  it "correctly returns disputes by effective_date range" do
82
107
  effective_date = transaction.disputes.first.status_history.first.effective_date
83
108
 
@@ -79,33 +79,24 @@ describe Braintree::PaymentMethodNonce do
79
79
  result.should be_success
80
80
  nonce.nonce.should == "fake-valid-nonce"
81
81
  nonce.type.should == "CreditCard"
82
- nonce.details.fetch(:last_two).should == "81"
83
- nonce.details.fetch(:card_type).should == "Visa"
82
+ nonce.details.bin.should == "401288"
83
+ nonce.details.card_type.should == "Visa"
84
+ nonce.details.expiration_month.should == "12"
85
+ nonce.details.expiration_year.should == "2022"
86
+ nonce.details.is_network_tokenized?.should be_nil
87
+ nonce.details.last_two.should == "81"
88
+ nonce.details.payer_info.should be_nil
84
89
  end
85
90
 
86
91
  it "return paypal details if details exist" do
87
92
  result = Braintree::PaymentMethodNonce.find("fake-paypal-one-time-nonce")
88
93
  nonce = result.payment_method_nonce
89
-
90
- nonce.details.fetch(:cobranded_card_label).should_not be_nil
91
- nonce.details.fetch(:shipping_option_id).should_not be_nil
92
- nonce.details.fetch(:billing_address).fetch(:recipient_name).should_not be_nil
93
- nonce.details.fetch(:shipping_address).fetch(:recipient_name).should_not be_nil
94
-
95
- nonce.details.fetch(:payer_info).fetch(:first_name).should_not be_nil
96
- nonce.details.fetch(:payer_info).fetch(:last_name).should_not be_nil
97
- nonce.details.fetch(:payer_info).fetch(:email).should_not be_nil
98
- nonce.details.fetch(:payer_info).fetch(:payer_id).should_not be_nil
99
- end
100
-
101
- it "return venmo details if details exist" do
102
- result = Braintree::PaymentMethodNonce.find("fake-venmo-account-nonce")
103
-
104
- nonce = result.payment_method_nonce
105
-
106
- nonce.details.fetch(:last_two).should == "99"
107
- nonce.details.fetch(:username).should == "venmojoe"
108
- nonce.details.fetch(:venmo_user_id).should == "Venmo-Joe-1"
94
+ nonce.details.payer_info.billing_agreement_id.should be_nil
95
+ nonce.details.payer_info.country_code.should be_nil
96
+ nonce.details.payer_info.email.should_not be_nil
97
+ nonce.details.payer_info.first_name.should_not be_nil
98
+ nonce.details.payer_info.last_name.should_not be_nil
99
+ nonce.details.payer_info.payer_id.should_not be_nil
109
100
  end
110
101
 
111
102
  it "returns null 3ds_info if there isn't any" do
@@ -131,7 +122,7 @@ describe Braintree::PaymentMethodNonce do
131
122
  nonce = result.payment_method_nonce
132
123
  result.should be_success
133
124
  nonce.details.should_not be_nil
134
- nonce.details[:bin].should == "401288"
125
+ nonce.details.bin.should == "401288"
135
126
  end
136
127
 
137
128
  it "returns bin_data with commercial set to Yes" do
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@ unless defined?(SPEC_HELPER_LOADED)
3
3
  project_root = File.expand_path(File.dirname(__FILE__) + "/..")
4
4
  require "rubygems"
5
5
  require "bundler/setup"
6
+ require "libxml"
6
7
  require "rspec"
7
8
  require "pry"
8
9
 
@@ -31,6 +31,7 @@ describe Braintree::Customer do
31
31
  output.should include(%q(addresses: []))
32
32
  output.should include(%q(credit_cards: []))
33
33
  output.should include(%q(paypal_accounts: []))
34
+ output.should include(%q(tax_identifiers: []))
34
35
  output.should include(%Q(created_at: #{customer.created_at.inspect}))
35
36
  output.should include(%Q(updated_at: #{customer.updated_at.inspect}))
36
37
  end
@@ -133,6 +134,10 @@ describe Braintree::Customer do
133
134
  :billing_agreement_id,
134
135
  {:options => [:make_default]},
135
136
  ]},
137
+ {:tax_identifiers => [
138
+ :country_code,
139
+ :identifier
140
+ ]},
136
141
  {:options =>
137
142
  [:paypal => [
138
143
  :payee_email,
@@ -227,6 +232,10 @@ describe Braintree::Customer do
227
232
  :ds_transaction_id,
228
233
  ]},
229
234
  ]},
235
+ {:tax_identifiers => [
236
+ :country_code,
237
+ :identifier
238
+ ]},
230
239
  {:options =>
231
240
  [:paypal => [
232
241
  :payee_email,
@@ -41,6 +41,7 @@ describe Braintree::DisputeSearch do
41
41
  end
42
42
 
43
43
  [
44
+ :chargeback_protection_level,
44
45
  :kind,
45
46
  :reason,
46
47
  :status,
@@ -46,7 +46,14 @@ describe Braintree::Dispute do
46
46
  :order_id => nil,
47
47
  :purchase_order_number => "po",
48
48
  :payment_instrument_subtype => "Visa",
49
- }
49
+ },
50
+ :paypal_messages => [
51
+ {
52
+ :message => "message",
53
+ :sender => "seller",
54
+ :sent_at => Time.utc(2009, 3, 9, 10, 50, 39),
55
+ }
56
+ ]
50
57
  }
51
58
  end
52
59
 
@@ -348,6 +355,16 @@ describe Braintree::Dispute do
348
355
  evidence2.url.should == nil
349
356
  end
350
357
 
358
+ it "converts paypal_messages hash into an array of Dispute::PayPalMessage objects" do
359
+ dispute = Braintree::Dispute._new(attributes)
360
+
361
+ dispute.paypal_messages.length.should == 1
362
+ paypal_message_1 = dispute.paypal_messages.first
363
+ paypal_message_1.message.should == "message"
364
+ paypal_message_1.sender.should == "seller"
365
+ paypal_message_1.sent_at.should == Time.utc(2009, 3, 9, 10, 50, 39)
366
+ end
367
+
351
368
  it "handles nil evidence" do
352
369
  attributes.delete(:evidence)
353
370
 
@@ -356,6 +373,14 @@ describe Braintree::Dispute do
356
373
  dispute.evidence.should == nil
357
374
  end
358
375
 
376
+ it "handles nil paypal_messages" do
377
+ attributes.delete(:paypal_messages)
378
+
379
+ dispute = Braintree::Dispute._new(attributes)
380
+
381
+ dispute.paypal_messages.should == nil
382
+ end
383
+
359
384
  it "sets the older webhook fields for backwards compatibility" do
360
385
  dispute = Braintree::Dispute._new(attributes)
361
386
 
@@ -0,0 +1,31 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ describe Braintree::PaymentMethodNonceDetailsPayerInfo do
4
+ let(:payment_method_nonce_details_payer_info) {
5
+ Braintree::PaymentMethodNonceDetailsPayerInfo.new(
6
+ :billing_agreement_id => "billing-agreement-id",
7
+ :country_code => "US",
8
+ :email => "test@example.com",
9
+ :first_name => "First",
10
+ :last_name => "Last",
11
+ :payer_id => "payer-id",
12
+ )
13
+ }
14
+
15
+ describe "#initialize" do
16
+ it "sets attributes" do
17
+ payment_method_nonce_details_payer_info.billing_agreement_id.should == "billing-agreement-id"
18
+ payment_method_nonce_details_payer_info.country_code.should == "US"
19
+ payment_method_nonce_details_payer_info.email.should == "test@example.com"
20
+ payment_method_nonce_details_payer_info.first_name.should == "First"
21
+ payment_method_nonce_details_payer_info.last_name.should == "Last"
22
+ payment_method_nonce_details_payer_info.payer_id.should == "payer-id"
23
+ end
24
+ end
25
+
26
+ describe "inspect" do
27
+ it "prints the attributes" do
28
+ payment_method_nonce_details_payer_info.inspect.should == %(#<PaymentMethodNonceDetailsPayerInfo billing_agreement_id: \"billing-agreement-id\", country_code: \"US\", email: \"test@example.com\", first_name: \"First\", last_name: \"Last\", payer_id: \"payer-id\">)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ describe Braintree::PaymentMethodNonceDetails do
4
+ let(:payment_method_nonce_details) {
5
+ Braintree::PaymentMethodNonceDetails.new(
6
+ :bin => "bin",
7
+ :card_type => "American Express",
8
+ :expiration_month => "12",
9
+ :expiration_year => "2025",
10
+ :is_network_tokenized => true,
11
+ :last_two => "11",
12
+ :payer_info => {
13
+ :billing_agreement_id => "1234",
14
+ :country_code => "US",
15
+ },
16
+ )
17
+ }
18
+
19
+ describe "#initialize" do
20
+ it "sets attributes" do
21
+ payment_method_nonce_details.bin.should == "bin"
22
+ payment_method_nonce_details.card_type.should == "American Express"
23
+ payment_method_nonce_details.expiration_month.should == "12"
24
+ payment_method_nonce_details.expiration_year.should == "2025"
25
+ payment_method_nonce_details.is_network_tokenized.should == true
26
+ payment_method_nonce_details.last_two.should == "11"
27
+ payment_method_nonce_details.payer_info.billing_agreement_id.should == "1234"
28
+ payment_method_nonce_details.payer_info.country_code.should == "US"
29
+ end
30
+ end
31
+
32
+ describe "inspect" do
33
+ it "prints the attributes" do
34
+ payment_method_nonce_details.inspect.should == %(#<PaymentMethodNonceDetails bin: "bin", card_type: "American Express", expiration_month: "12", expiration_year: "2025", is_network_tokenized: true, last_two: "11", payer_info: #<PaymentMethodNonceDetailsPayerInfo billing_agreement_id: "1234", country_code: "US", email: nil, first_name: nil, last_name: nil, payer_id: nil>>)
35
+ end
36
+ end
37
+
38
+ describe "is_network_tokenized" do
39
+ it "is aliased to is_network_tokenized?" do
40
+ payment_method_nonce_details.is_network_tokenized?.should == true
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ describe Braintree::Xml::Rexml do
4
+ describe "self.parse" do
5
+ it "typecasts integers" do
6
+ xml = "<root><foo type=\"integer\">123</foo></root>"
7
+ Braintree::Xml::Rexml.parse(xml).should == {"root"=>{"foo"=>{"__content__"=>"123", "type"=>"integer"}}}
8
+ end
9
+
10
+ it "works with dashes or underscores" do
11
+ xml = <<-END
12
+ <root>
13
+ <dash-es />
14
+ <under_scores />
15
+ </root>
16
+ END
17
+ Braintree::Xml::Rexml.parse(xml).should == {"root"=>{"dash-es"=>{}, "under_scores"=>{}}}
18
+ end
19
+
20
+ it "uses nil if nil=true, otherwise uses empty string" do
21
+ xml = <<-END
22
+ <root>
23
+ <a_nil_value nil="true"></a_nil_value>
24
+ <an_empty_string></an_empty_string>
25
+ </root>
26
+ END
27
+ Braintree::Xml::Rexml.parse(xml).should == {"root"=>{"a_nil_value"=>{"nil"=>"true"}, "an_empty_string"=>{}}}
28
+ end
29
+
30
+ it "typecasts dates and times" do
31
+ xml = <<-END
32
+ <root>
33
+ <created-at type="datetime">2009-10-28T10:19:49Z</created-at>
34
+ </root>
35
+ END
36
+ Braintree::Xml::Rexml.parse(xml).should == {"root"=>{"created-at"=>{"__content__"=>"2009-10-28T10:19:49Z", "type"=>"datetime"}}}
37
+ end
38
+
39
+ it "builds an array if type=array" do
40
+ xml = <<-END
41
+ <root>
42
+ <customers type="array">
43
+ <customer><name>Adam</name></customer>
44
+ <customer><name>Ben</name></customer>
45
+ </customers>
46
+ </root>
47
+ END
48
+ Braintree::Xml::Rexml.parse(xml).should == {"root"=>{"customers"=>{"type"=>"array", "customer"=>[{"name"=>{"__content__"=>"Adam"}}, {"name"=>{"__content__"=>"Ben"}}]}}}
49
+ end
50
+ end
51
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: braintree
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Braintree
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-12 00:00:00.000000000 Z
11
+ date: 2021-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: builder
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.2.4
27
- - !ruby/object:Gem::Dependency
28
- name: libxml-ruby
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 3.2.0
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: 3.2.0
41
27
  description: Resources and tools for developers to integrate Braintree's global payments
42
28
  platform.
43
29
  email: code@getbraintree.com
@@ -84,6 +70,7 @@ files:
84
70
  - lib/braintree/discount_gateway.rb
85
71
  - lib/braintree/dispute.rb
86
72
  - lib/braintree/dispute/evidence.rb
73
+ - lib/braintree/dispute/paypal_message.rb
87
74
  - lib/braintree/dispute/status_history.rb
88
75
  - lib/braintree/dispute/transaction.rb
89
76
  - lib/braintree/dispute/transaction_details.rb
@@ -121,6 +108,8 @@ files:
121
108
  - lib/braintree/payment_method.rb
122
109
  - lib/braintree/payment_method_gateway.rb
123
110
  - lib/braintree/payment_method_nonce.rb
111
+ - lib/braintree/payment_method_nonce_details.rb
112
+ - lib/braintree/payment_method_nonce_details_payer_info.rb
124
113
  - lib/braintree/payment_method_nonce_gateway.rb
125
114
  - lib/braintree/payment_method_parser.rb
126
115
  - lib/braintree/paypal_account.rb
@@ -192,6 +181,7 @@ files:
192
181
  - lib/braintree/xml/generator.rb
193
182
  - lib/braintree/xml/libxml.rb
194
183
  - lib/braintree/xml/parser.rb
184
+ - lib/braintree/xml/rexml.rb
195
185
  - lib/ssl/api_braintreegateway_com.ca.crt
196
186
  - lib/ssl/securetrust_ca.crt
197
187
  - spec/fixtures/files/bt_logo.png
@@ -268,6 +258,8 @@ files:
268
258
  - spec/unit/braintree/local_payment_completed_spec.rb
269
259
  - spec/unit/braintree/merchant_account_spec.rb
270
260
  - spec/unit/braintree/modification_spec.rb
261
+ - spec/unit/braintree/payment_method_nonce_details_payer_info_spec.rb
262
+ - spec/unit/braintree/payment_method_nonce_details_spec.rb
271
263
  - spec/unit/braintree/payment_method_spec.rb
272
264
  - spec/unit/braintree/paypal_account_spec.rb
273
265
  - spec/unit/braintree/resource_collection_spec.rb
@@ -295,6 +287,7 @@ files:
295
287
  - spec/unit/braintree/webhook_notification_spec.rb
296
288
  - spec/unit/braintree/xml/libxml_spec.rb
297
289
  - spec/unit/braintree/xml/parser_spec.rb
290
+ - spec/unit/braintree/xml/rexml_spec.rb
298
291
  - spec/unit/braintree/xml_spec.rb
299
292
  - spec/unit/braintree_spec.rb
300
293
  - spec/unit/spec_helper.rb
@@ -314,14 +307,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
314
307
  requirements:
315
308
  - - ">="
316
309
  - !ruby/object:Gem::Version
317
- version: 2.5.0
310
+ version: 2.6.0
318
311
  required_rubygems_version: !ruby/object:Gem::Requirement
319
312
  requirements:
320
313
  - - ">="
321
314
  - !ruby/object:Gem::Version
322
315
  version: '0'
323
316
  requirements: []
324
- rubygems_version: 3.0.8
317
+ rubygems_version: 3.2.17
325
318
  signing_key:
326
319
  specification_version: 4
327
320
  summary: Braintree Ruby Server SDK