braintree 4.32.0 → 4.33.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/braintree/version.rb +2 -2
- data/lib/braintree/xml/{libxml.rb → nokogiri.rb} +18 -16
- data/lib/braintree/xml/parser.rb +4 -4
- data/lib/braintree.rb +1 -1
- data/spec/spec_helper.rb +4 -5
- data/spec/unit/braintree/client_token_spec.rb +11 -0
- data/spec/unit/braintree/error_result_spec.rb +28 -0
- data/spec/unit/braintree/xml/{libxml_spec.rb → nokogiri_spec.rb} +7 -7
- data/spec/unit/braintree/xml/parser_spec.rb +57 -0
- metadata +8 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4e90519d70f62c557f0f25c54d7c481854711c5206ae20a24d09ca3c7ea77970
|
|
4
|
+
data.tar.gz: f07cc386365888000e3e44f6083b24f1d8fec0e25bba465f0e157a97c9d54e51
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c801cf89c35d0f835fa9f8513e3cffb39e19cd5e3aee3e004db2047a129bf3519ee2f00396ae47ef4ce01bf95f2abc56719ead396733cf5977eb4d9ad8323d80
|
|
7
|
+
data.tar.gz: 57112741f710b8e08c8d03ebba98e1e385be46a6dcac917c52f717f6e1007a3bfeda9a329c7973ed32d3f4e9a1da5669a1ca7b518491cf643d643c88cc81f7ed
|
data/lib/braintree/version.rb
CHANGED
|
@@ -2,24 +2,24 @@
|
|
|
2
2
|
# under the MIT license, copyright (c) 2005-2009 David Heinemeier Hansson
|
|
3
3
|
module Braintree
|
|
4
4
|
module Xml
|
|
5
|
-
module
|
|
6
|
-
|
|
5
|
+
module Nokogiri
|
|
6
|
+
NOKOGIRI_XML_LIMIT = 30000000
|
|
7
7
|
|
|
8
8
|
def self.parse(xml_string)
|
|
9
|
-
|
|
10
|
-
::
|
|
11
|
-
|
|
12
|
-
_node_to_hash(root_node)
|
|
13
|
-
ensure
|
|
14
|
-
::LibXML::XML.default_keep_blanks = old_keep_blanks_setting
|
|
9
|
+
require "nokogiri" unless defined?(::Nokogiri)
|
|
10
|
+
doc = ::Nokogiri::XML(xml_string.strip)
|
|
11
|
+
_node_to_hash(doc.root)
|
|
15
12
|
end
|
|
16
13
|
|
|
17
14
|
def self._node_to_hash(node, hash = {})
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
sub_hash = node.text? ? hash : _build_sub_hash(hash, node.name)
|
|
16
|
+
|
|
17
|
+
if node.text? || (node.children.size == 1 && node.children.first.text?)
|
|
18
|
+
content = node.text? ? node.content : node.children.first.content
|
|
19
|
+
raise "Content too large" if content.length >= NOKOGIRI_XML_LIMIT
|
|
20
|
+
sub_hash[CONTENT_ROOT] = content
|
|
21
|
+
_attributes_to_hash(node, sub_hash) unless node.text?
|
|
21
22
|
else
|
|
22
|
-
sub_hash = _build_sub_hash(hash, node.name)
|
|
23
23
|
_attributes_to_hash(node, sub_hash)
|
|
24
24
|
if _array?(node)
|
|
25
25
|
_children_array_to_hash(node, sub_hash)
|
|
@@ -44,25 +44,27 @@ module Braintree
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def self._children_to_hash(node, hash={})
|
|
47
|
-
node.each { |child| _node_to_hash(child, hash) }
|
|
47
|
+
node.children.each { |child| _node_to_hash(child, hash) unless child.text? && child.content.strip.empty? }
|
|
48
48
|
_attributes_to_hash(node, hash)
|
|
49
49
|
hash
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def self._attributes_to_hash(node, hash={})
|
|
53
|
-
node.
|
|
53
|
+
node.attributes.each { |name, attr| hash[name] = attr.value }
|
|
54
54
|
hash
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def self._children_array_to_hash(node, hash={})
|
|
58
|
-
|
|
58
|
+
first_child = node.children.find { |child| !child.text? }
|
|
59
|
+
hash[first_child.name] = node.children.select { |child| !child.text? }.map do |child|
|
|
59
60
|
_children_to_hash(child, {})
|
|
60
61
|
end
|
|
61
62
|
hash
|
|
62
63
|
end
|
|
63
64
|
|
|
64
65
|
def self._array?(node)
|
|
65
|
-
|
|
66
|
+
non_text_children = node.children.select { |child| !child.text? }
|
|
67
|
+
non_text_children.size > 1 && non_text_children.first.name == non_text_children[1].name
|
|
66
68
|
end
|
|
67
69
|
end
|
|
68
70
|
end
|
data/lib/braintree/xml/parser.rb
CHANGED
|
@@ -18,10 +18,10 @@ module Braintree
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def self._determine_parser
|
|
21
|
-
# If
|
|
22
|
-
#
|
|
23
|
-
if defined?(::
|
|
24
|
-
::Braintree::Xml::
|
|
21
|
+
# If Nokogiri is available, use it for better performance
|
|
22
|
+
# Otherwise fall back to REXML for JRuby compatibility
|
|
23
|
+
if defined?(::Nokogiri)
|
|
24
|
+
::Braintree::Xml::Nokogiri
|
|
25
25
|
else
|
|
26
26
|
::Braintree::Xml::Rexml
|
|
27
27
|
end
|
data/lib/braintree.rb
CHANGED
|
@@ -203,6 +203,6 @@ require "braintree/webhook_testing"
|
|
|
203
203
|
require "braintree/webhook_testing_gateway"
|
|
204
204
|
require "braintree/xml"
|
|
205
205
|
require "braintree/xml/generator"
|
|
206
|
-
require "braintree/xml/
|
|
206
|
+
require "braintree/xml/nokogiri"
|
|
207
207
|
require "braintree/xml/rexml"
|
|
208
208
|
require "braintree/xml/parser"
|
data/spec/spec_helper.rb
CHANGED
|
@@ -3,7 +3,6 @@ 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"
|
|
7
6
|
require "rspec"
|
|
8
7
|
require "pry"
|
|
9
8
|
|
|
@@ -195,10 +194,10 @@ unless defined?(SPEC_HELPER_LOADED)
|
|
|
195
194
|
end
|
|
196
195
|
|
|
197
196
|
def matches?(xml_string)
|
|
198
|
-
@
|
|
199
|
-
if @
|
|
200
|
-
@results = @
|
|
201
|
-
@failed_parser = "
|
|
197
|
+
@xml_parse = Braintree::Xml::Parser.hash_from_xml(xml_string)
|
|
198
|
+
if @xml_parse != @expected_hash
|
|
199
|
+
@results = @xml_parse
|
|
200
|
+
@failed_parser = "xml"
|
|
202
201
|
false
|
|
203
202
|
else
|
|
204
203
|
true
|
|
@@ -33,5 +33,16 @@ module Braintree
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
|
+
|
|
37
|
+
describe "error response handling" do
|
|
38
|
+
it "correctly parses error response with nested structure" do
|
|
39
|
+
error_xml = "<api-error-response><message>Invalid request</message><errors><errors type=\"array\"></errors></errors></api-error-response>"
|
|
40
|
+
result = Braintree::Xml::Parser.hash_from_xml(error_xml)
|
|
41
|
+
|
|
42
|
+
expect(result[:api_error_response]).to be_a(Hash)
|
|
43
|
+
expect(result[:api_error_response][:message]).to eq("Invalid request")
|
|
44
|
+
expect(result[:api_error_response][:errors]).to be_a(Hash)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
36
47
|
end
|
|
37
48
|
end
|
|
@@ -14,6 +14,34 @@ describe Braintree::ErrorResult do
|
|
|
14
14
|
)
|
|
15
15
|
end.to_not raise_error
|
|
16
16
|
end
|
|
17
|
+
|
|
18
|
+
it "handles parsed XML error response structure correctly" do
|
|
19
|
+
data = {
|
|
20
|
+
:message => "Validation failed",
|
|
21
|
+
:errors => {
|
|
22
|
+
:errors => [{:code => "81234", :message => "Field is required"}]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
expect do
|
|
27
|
+
result = Braintree::ErrorResult.new(:gateway, data)
|
|
28
|
+
expect(result.message).to eq("Validation failed")
|
|
29
|
+
expect(result.errors.inspect).to eq("#<Braintree::Errors :[(81234) Field is required]>")
|
|
30
|
+
end.to_not raise_error
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "handles empty error array in parsed XML response" do
|
|
34
|
+
data = {
|
|
35
|
+
:message => "Invalid request",
|
|
36
|
+
:errors => {:errors => []}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
expect do
|
|
40
|
+
result = Braintree::ErrorResult.new(:gateway, data)
|
|
41
|
+
expect(result.message).to eq("Invalid request")
|
|
42
|
+
expect(result.errors).to be_a(Braintree::Errors)
|
|
43
|
+
end.to_not raise_error
|
|
44
|
+
end
|
|
17
45
|
end
|
|
18
46
|
|
|
19
47
|
describe "inspect" do
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
|
|
2
2
|
|
|
3
|
-
describe Braintree::Xml::
|
|
3
|
+
describe Braintree::Xml::Nokogiri do
|
|
4
4
|
describe "self.parse" do
|
|
5
5
|
it "typecasts integers" do
|
|
6
6
|
xml = "<root><foo type=\"integer\">123</foo></root>"
|
|
7
|
-
expect(Braintree::Xml::
|
|
7
|
+
expect(Braintree::Xml::Nokogiri.parse(xml)).to eq({"root"=>{"foo"=>{"__content__"=>"123", "type"=>"integer"}}})
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
it "works with dashes or underscores" do
|
|
@@ -14,7 +14,7 @@ describe Braintree::Xml::Libxml do
|
|
|
14
14
|
<under_scores />
|
|
15
15
|
</root>
|
|
16
16
|
END
|
|
17
|
-
expect(Braintree::Xml::
|
|
17
|
+
expect(Braintree::Xml::Nokogiri.parse(xml)).to eq({"root"=>{"dash-es"=>{}, "under_scores"=>{}}})
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
it "uses nil if nil=true, otherwise uses empty string" do
|
|
@@ -24,7 +24,7 @@ describe Braintree::Xml::Libxml do
|
|
|
24
24
|
<an_empty_string></an_empty_string>
|
|
25
25
|
</root>
|
|
26
26
|
END
|
|
27
|
-
expect(Braintree::Xml::
|
|
27
|
+
expect(Braintree::Xml::Nokogiri.parse(xml)).to eq({"root"=>{"a_nil_value"=>{"nil"=>"true"}, "an_empty_string"=>{}}})
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
it "typecasts dates and times" do
|
|
@@ -33,7 +33,7 @@ describe Braintree::Xml::Libxml do
|
|
|
33
33
|
<created-at type="datetime">2009-10-28T10:19:49Z</created-at>
|
|
34
34
|
</root>
|
|
35
35
|
END
|
|
36
|
-
expect(Braintree::Xml::
|
|
36
|
+
expect(Braintree::Xml::Nokogiri.parse(xml)).to eq({"root"=>{"created-at"=>{"__content__"=>"2009-10-28T10:19:49Z", "type"=>"datetime"}}})
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
it "builds an array if type=array" do
|
|
@@ -45,7 +45,7 @@ describe Braintree::Xml::Libxml do
|
|
|
45
45
|
</customers>
|
|
46
46
|
</root>
|
|
47
47
|
END
|
|
48
|
-
expect(Braintree::Xml::
|
|
48
|
+
expect(Braintree::Xml::Nokogiri.parse(xml)).to eq({"root"=>{"customers"=>{"type"=>"array", "customer"=>[{"name"=>{"__content__"=>"Adam"}}, {"name"=>{"__content__"=>"Ben"}}]}}})
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
|
-
end
|
|
51
|
+
end
|
|
@@ -81,5 +81,62 @@ describe Braintree::Xml::Parser do
|
|
|
81
81
|
END
|
|
82
82
|
expect(xml).to parse_to(:root => {:paypal_details => {:deets => [{:secret_code => "1234"}], :payer_email => "abc@test.com", :payment_id => "1234567890"}})
|
|
83
83
|
end
|
|
84
|
+
|
|
85
|
+
it "does not collapse nested structures with single-child elements" do
|
|
86
|
+
xml = "<api-error-response><message>Test</message><errors><errors type=\"array\"></errors></errors></api-error-response>"
|
|
87
|
+
expect(xml).to parse_to({:api_error_response=>{:message=>"Test", :errors=>{:errors=>[]}}})
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "preserves hash structure when one key has array value" do
|
|
91
|
+
xml = <<-END
|
|
92
|
+
<root>
|
|
93
|
+
<message>Error message</message>
|
|
94
|
+
<items type="array">
|
|
95
|
+
<item>Value1</item>
|
|
96
|
+
</items>
|
|
97
|
+
</root>
|
|
98
|
+
END
|
|
99
|
+
expect(xml).to parse_to({:root => {:message => "Error message", :items => ["Value1"]}})
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "handles error response with nested errors correctly" do
|
|
103
|
+
xml = <<-END
|
|
104
|
+
<api-error-response>
|
|
105
|
+
<message>Validation failed</message>
|
|
106
|
+
<errors>
|
|
107
|
+
<errors type="array">
|
|
108
|
+
<error>
|
|
109
|
+
<code>81234</code>
|
|
110
|
+
<message>Field is required</message>
|
|
111
|
+
</error>
|
|
112
|
+
</errors>
|
|
113
|
+
</errors>
|
|
114
|
+
</api-error-response>
|
|
115
|
+
END
|
|
116
|
+
expect(xml).to parse_to({
|
|
117
|
+
:api_error_response => {
|
|
118
|
+
:message => "Validation failed",
|
|
119
|
+
:errors => {
|
|
120
|
+
:errors => [{:code => "81234", :message => "Field is required"}]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "handles client token error response structure" do
|
|
127
|
+
xml = <<-END
|
|
128
|
+
<api-error-response>
|
|
129
|
+
<message>Invalid request</message>
|
|
130
|
+
<errors>
|
|
131
|
+
<errors type="array"></errors>
|
|
132
|
+
</errors>
|
|
133
|
+
</api-error-response>
|
|
134
|
+
END
|
|
135
|
+
result = Braintree::Xml::Parser.hash_from_xml(xml)
|
|
136
|
+
expect(result[:api_error_response]).to be_a(Hash)
|
|
137
|
+
expect(result[:api_error_response][:message]).to eq("Invalid request")
|
|
138
|
+
expect(result[:api_error_response][:errors]).to be_a(Hash)
|
|
139
|
+
expect(result[:api_error_response][:errors][:errors]).to eq([])
|
|
140
|
+
end
|
|
84
141
|
end
|
|
85
142
|
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: 4.
|
|
4
|
+
version: 4.33.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Braintree
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-10-
|
|
11
|
+
date: 2025-10-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: builder
|
|
@@ -236,7 +236,7 @@ files:
|
|
|
236
236
|
- lib/braintree/webhook_testing_gateway.rb
|
|
237
237
|
- lib/braintree/xml.rb
|
|
238
238
|
- lib/braintree/xml/generator.rb
|
|
239
|
-
- lib/braintree/xml/
|
|
239
|
+
- lib/braintree/xml/nokogiri.rb
|
|
240
240
|
- lib/braintree/xml/parser.rb
|
|
241
241
|
- lib/braintree/xml/rexml.rb
|
|
242
242
|
- lib/ssl/api_braintreegateway_com.ca.crt
|
|
@@ -390,7 +390,7 @@ files:
|
|
|
390
390
|
- spec/unit/braintree/venmo_profile_data_spec.rb
|
|
391
391
|
- spec/unit/braintree/visa_checkout_card_spec.rb
|
|
392
392
|
- spec/unit/braintree/webhook_notification_spec.rb
|
|
393
|
-
- spec/unit/braintree/xml/
|
|
393
|
+
- spec/unit/braintree/xml/nokogiri_spec.rb
|
|
394
394
|
- spec/unit/braintree/xml/parser_spec.rb
|
|
395
395
|
- spec/unit/braintree/xml/rexml_spec.rb
|
|
396
396
|
- spec/unit/braintree/xml_spec.rb
|
|
@@ -405,7 +405,7 @@ metadata:
|
|
|
405
405
|
changelog_uri: https://github.com/braintree/braintree_ruby/blob/master/CHANGELOG.md
|
|
406
406
|
source_code_uri: https://github.com/braintree/braintree_ruby
|
|
407
407
|
documentation_uri: https://developer.paypal.com/braintree/docs
|
|
408
|
-
post_install_message:
|
|
408
|
+
post_install_message:
|
|
409
409
|
rdoc_options: []
|
|
410
410
|
require_paths:
|
|
411
411
|
- lib
|
|
@@ -420,8 +420,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
420
420
|
- !ruby/object:Gem::Version
|
|
421
421
|
version: '0'
|
|
422
422
|
requirements: []
|
|
423
|
-
rubygems_version: 3.
|
|
424
|
-
signing_key:
|
|
423
|
+
rubygems_version: 3.3.15
|
|
424
|
+
signing_key:
|
|
425
425
|
specification_version: 4
|
|
426
426
|
summary: Braintree Ruby Server SDK
|
|
427
427
|
test_files: []
|