braintree 2.90.0 → 2.91.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 +4 -4
- data/braintree.gemspec +5 -0
- data/lib/braintree/configuration.rb +39 -1
- data/lib/braintree/credit_card.rb +1 -0
- data/lib/braintree/error_codes.rb +8 -0
- data/lib/braintree/graphql_client.rb +28 -0
- data/lib/braintree/http.rb +21 -9
- data/lib/braintree/local_payment_completed.rb +20 -0
- data/lib/braintree/test/credit_card.rb +2 -0
- data/lib/braintree/transaction.rb +8 -0
- data/lib/braintree/transaction_gateway.rb +4 -0
- data/lib/braintree/util.rb +44 -3
- data/lib/braintree/validation_error.rb +10 -2
- data/lib/braintree/validation_error_collection.rb +2 -1
- data/lib/braintree/version.rb +1 -1
- data/lib/braintree/webhook_notification.rb +5 -1
- data/lib/braintree/webhook_testing_gateway.rb +34 -3
- data/lib/braintree.rb +3 -1
- data/spec/integration/braintree/credit_card_spec.rb +14 -0
- data/spec/integration/braintree/dispute_spec.rb +3 -0
- data/spec/integration/braintree/graphql_client_spec.rb +74 -0
- data/spec/integration/braintree/http_spec.rb +1 -1
- data/spec/integration/braintree/transaction_search_spec.rb +19 -0
- data/spec/integration/braintree/transaction_spec.rb +203 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/braintree/configuration_spec.rb +37 -0
- data/spec/unit/braintree/http_spec.rb +65 -0
- data/spec/unit/braintree/local_payment_completed_spec.rb +24 -0
- data/spec/unit/braintree/transaction_spec.rb +8 -0
- data/spec/unit/braintree/util_spec.rb +109 -0
- data/spec/unit/braintree/validation_error_collection_spec.rb +335 -132
- data/spec/unit/braintree/webhook_notification_spec.rb +31 -0
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 703d5a600446c3eccc5d310b70091319b9d426c2db3826851bbcd55fed478ecc
|
4
|
+
data.tar.gz: d98833b2c0937b365e18817b5bf5c0335695282e4aad32ecf08537fc5f36e3b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83411d93215207167d8aa5f3f52a2af58b0744f502c0ec64989dee900f87b415861563f11809e9f9f428c09ed63b7a4f47afb6a419708cfc78d5a3ae7ae3c847
|
7
|
+
data.tar.gz: bd72dec425b6f7164c5ca5f2560aacc5a62e3db20ea3b01afee70683fe964f888fd4e77f35139d7034e8dbc083a5bd15f5138844d01569b21614f675b64aed77
|
data/braintree.gemspec
CHANGED
@@ -14,5 +14,10 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.has_rdoc = false
|
15
15
|
s.files = Dir.glob ["README.rdoc", "LICENSE", "lib/**/*.{rb,crt}", "spec/**/*", "*.gemspec"]
|
16
16
|
s.add_dependency "builder", ">= 2.0.0"
|
17
|
+
s.metadata = {
|
18
|
+
"bug_tracker_uri" => "https://github.com/braintree/braintree_ruby/issues",
|
19
|
+
"changelog_uri" => "https://github.com/braintree/braintree_ruby/blob/master/CHANGELOG.md",
|
20
|
+
"source_code_uri" => "https://github.com/braintree/braintree_ruby",
|
21
|
+
}
|
17
22
|
end
|
18
23
|
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Braintree
|
2
2
|
class Configuration
|
3
|
-
API_VERSION = "
|
3
|
+
API_VERSION = "5" # :nodoc:
|
4
4
|
DEFAULT_ENDPOINT = "api" # :nodoc:
|
5
|
+
GRAPHQL_API_VERSION = "2018-09-10" # :nodoc:
|
5
6
|
|
6
7
|
READABLE_ATTRIBUTES = [
|
7
8
|
:merchant_id,
|
@@ -44,6 +45,7 @@ module Braintree
|
|
44
45
|
end
|
45
46
|
attr_reader *READABLE_ATTRIBUTES
|
46
47
|
attr_reader *NON_REQUIRED_READABLE_ATTRIBUTES
|
48
|
+
attr_writer *WRITABLE_ATTRIBUTES
|
47
49
|
|
48
50
|
def self.expectant_reader(*attributes) # :nodoc:
|
49
51
|
attributes.each do |attribute|
|
@@ -113,6 +115,8 @@ module Braintree
|
|
113
115
|
instance_variable_set "@#{attr}", options[attr]
|
114
116
|
end
|
115
117
|
|
118
|
+
@environment = @environment.to_sym if @environment
|
119
|
+
|
116
120
|
_check_for_mixed_credentials(options)
|
117
121
|
|
118
122
|
parser = Braintree::CredentialsParser.new
|
@@ -158,6 +162,10 @@ module Braintree
|
|
158
162
|
API_VERSION
|
159
163
|
end
|
160
164
|
|
165
|
+
def graphql_api_version # :nodoc:
|
166
|
+
GRAPHQL_API_VERSION
|
167
|
+
end
|
168
|
+
|
161
169
|
def base_merchant_path # :nodoc:
|
162
170
|
"/merchants/#{merchant_id}"
|
163
171
|
end
|
@@ -166,6 +174,10 @@ module Braintree
|
|
166
174
|
"#{protocol}://#{server}:#{port}"
|
167
175
|
end
|
168
176
|
|
177
|
+
def graphql_base_url
|
178
|
+
"#{protocol}://#{graphql_server}:#{graphql_port}/graphql"
|
179
|
+
end
|
180
|
+
|
169
181
|
def base_merchant_url # :nodoc:
|
170
182
|
"#{base_url}#{base_merchant_path}"
|
171
183
|
end
|
@@ -182,6 +194,10 @@ module Braintree
|
|
182
194
|
Http.new(self)
|
183
195
|
end
|
184
196
|
|
197
|
+
def graphql_client
|
198
|
+
GraphQLClient.new(self)
|
199
|
+
end
|
200
|
+
|
185
201
|
def logger
|
186
202
|
@logger ||= self.class._default_logger
|
187
203
|
end
|
@@ -195,6 +211,15 @@ module Braintree
|
|
195
211
|
end
|
196
212
|
end
|
197
213
|
|
214
|
+
def graphql_port # :nodoc:
|
215
|
+
case @environment
|
216
|
+
when :development, :integration
|
217
|
+
ENV['GRAPHQL_PORT'] || 8080
|
218
|
+
when :production, :qa, :sandbox
|
219
|
+
443
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
198
223
|
def protocol # :nodoc:
|
199
224
|
ssl? ? "https" : "http"
|
200
225
|
end
|
@@ -220,6 +245,19 @@ module Braintree
|
|
220
245
|
end
|
221
246
|
end
|
222
247
|
|
248
|
+
def graphql_server # :nodoc:
|
249
|
+
case @environment
|
250
|
+
when :development, :integration
|
251
|
+
ENV['GRAPHQL_HOST'] || "graphql.bt.local"
|
252
|
+
when :production
|
253
|
+
"payments.braintree-api.com"
|
254
|
+
when :qa
|
255
|
+
"payments-qa.dev.braintree-api.com"
|
256
|
+
when :sandbox
|
257
|
+
"payments.sandbox.braintree-api.com"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
223
261
|
def auth_url
|
224
262
|
case @environment
|
225
263
|
when :development, :integration
|
@@ -328,6 +328,7 @@ module Braintree
|
|
328
328
|
FinalAuthSubmitForSettlementForDifferentAmount = "95601"
|
329
329
|
HasAlreadyBeenRefunded = "91512"
|
330
330
|
IdealPaymentNotComplete = "815141"
|
331
|
+
PaymentInstrumentWithExternalVaultIsInvalid = "915176"
|
331
332
|
TooManyLineItems = "915157"
|
332
333
|
LineItemsExpected = "915158"
|
333
334
|
DiscountAmountFormatIsInvalid = "915159"
|
@@ -439,6 +440,13 @@ module Braintree
|
|
439
440
|
LodgingCheckOutDateIsInvalid = "93413"
|
440
441
|
end
|
441
442
|
end
|
443
|
+
|
444
|
+
module ExternalVault
|
445
|
+
StatusIsInvalid = "915175"
|
446
|
+
CardTypeIsInvalid = "915178"
|
447
|
+
StatusWithPreviousNetworkTransactionIdIsInvalid = "915177"
|
448
|
+
PreviousNetworkTransactionIdIsInvalid = "915179"
|
449
|
+
end
|
442
450
|
end
|
443
451
|
|
444
452
|
module TransactionLineItem
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Braintree
|
2
|
+
class GraphQLClient < Http # :nodoc:
|
3
|
+
|
4
|
+
def initialize(config)
|
5
|
+
@config = config
|
6
|
+
@graphql_headers = {
|
7
|
+
'Accept' => 'application/json',
|
8
|
+
'Braintree-Version' => @config.graphql_api_version,
|
9
|
+
'Content-Type' => 'application/json'
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def query(definition, variables = {}, operationName = nil)
|
14
|
+
graphql_connection = _setup_connection(@config.graphql_server, @config.graphql_port)
|
15
|
+
|
16
|
+
request = {}
|
17
|
+
request['query'] = definition
|
18
|
+
request['operationName'] = operationName if operationName
|
19
|
+
request['variables'] = variables
|
20
|
+
|
21
|
+
response = _http_do Net::HTTP::Post, @config.graphql_base_url, request.to_json, nil, graphql_connection, @graphql_headers
|
22
|
+
data = JSON.parse(response.body, :symbolize_names => true)
|
23
|
+
Util.raise_exception_for_graphql_error(data)
|
24
|
+
|
25
|
+
data
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/braintree/http.rb
CHANGED
@@ -67,19 +67,34 @@ module Braintree
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
def
|
70
|
+
def _setup_connection(server = @config.server, port = @config.port)
|
71
71
|
if @config.proxy_address
|
72
72
|
connection = Net::HTTP.new(
|
73
|
-
|
74
|
-
|
73
|
+
server,
|
74
|
+
port,
|
75
75
|
@config.proxy_address,
|
76
76
|
@config.proxy_port,
|
77
77
|
@config.proxy_user,
|
78
78
|
@config.proxy_pass
|
79
79
|
)
|
80
80
|
else
|
81
|
-
connection = Net::HTTP.new(
|
81
|
+
connection = Net::HTTP.new(server, port)
|
82
82
|
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def _compose_headers(header_overrides = {})
|
86
|
+
headers = {}
|
87
|
+
headers["Accept"] = "application/xml"
|
88
|
+
headers["User-Agent"] = @config.user_agent
|
89
|
+
headers["Accept-Encoding"] = "gzip"
|
90
|
+
headers["X-ApiVersion"] = @config.api_version
|
91
|
+
headers["Content-Type"] = "application/xml"
|
92
|
+
|
93
|
+
headers.merge(header_overrides)
|
94
|
+
end
|
95
|
+
|
96
|
+
def _http_do(http_verb, path, body = nil, file = nil, connection = nil, header_overrides = {})
|
97
|
+
connection ||= _setup_connection
|
83
98
|
|
84
99
|
connection.open_timeout = @config.http_open_timeout
|
85
100
|
connection.read_timeout = @config.http_read_timeout
|
@@ -90,12 +105,10 @@ module Braintree
|
|
90
105
|
connection.ca_file = @config.ca_file
|
91
106
|
connection.verify_callback = proc { |preverify_ok, ssl_context| _verify_ssl_certificate(preverify_ok, ssl_context) }
|
92
107
|
end
|
108
|
+
|
93
109
|
connection.start do |http|
|
94
110
|
request = http_verb.new(path)
|
95
|
-
request[
|
96
|
-
request["User-Agent"] = @config.user_agent
|
97
|
-
request["Accept-Encoding"] = "gzip"
|
98
|
-
request["X-ApiVersion"] = @config.api_version
|
111
|
+
_compose_headers(header_overrides).each { |header, value| request[header] = value }
|
99
112
|
if @config.client_credentials?
|
100
113
|
request.basic_auth @config.client_id, @config.client_secret
|
101
114
|
elsif @config.access_token
|
@@ -117,7 +130,6 @@ module Braintree
|
|
117
130
|
request.body = form_params.collect {|p| "--" + boundary + "#{LINE_FEED}" + p}.join("") + "--" + boundary + "--"
|
118
131
|
@config.logger.debug _format_and_sanitize_body_for_log(_build_xml(body))
|
119
132
|
else
|
120
|
-
request["Content-Type"] = "application/xml"
|
121
133
|
request.body = body
|
122
134
|
@config.logger.debug _format_and_sanitize_body_for_log(body)
|
123
135
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Braintree
|
2
|
+
class LocalPaymentCompleted
|
3
|
+
include BaseModule
|
4
|
+
|
5
|
+
attr_reader :payment_id
|
6
|
+
attr_reader :payer_id
|
7
|
+
|
8
|
+
def initialize(attributes) # :nodoc:
|
9
|
+
set_instance_variables_from_hash(attributes)
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
protected :new
|
14
|
+
end
|
15
|
+
|
16
|
+
def self._new(*args) # :nodoc:
|
17
|
+
self.new *args
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -21,6 +21,7 @@ module Braintree
|
|
21
21
|
CarteBlanches = %w[30569309025904] # :nodoc:
|
22
22
|
DinersClubs = %w[38520000023237] # :nodoc:
|
23
23
|
|
24
|
+
Discover = "6011111111111117"
|
24
25
|
Discovers = %w[6011111111111117 6011000990139424]
|
25
26
|
JCBs = %w[3530111333300000 3566002020360505] # :nodoc:
|
26
27
|
|
@@ -30,6 +31,7 @@ module Braintree
|
|
30
31
|
|
31
32
|
MasterCards = %w[5105105105105100 5555555555554444]
|
32
33
|
|
34
|
+
Elo = "5066991111111118"
|
33
35
|
Visa = "4012888888881881"
|
34
36
|
VisaInternational = "4009348888881881" # :nodoc:
|
35
37
|
VisaPrepaid = "4500600000000061"
|
@@ -69,6 +69,13 @@ module Braintree
|
|
69
69
|
All = constants.map { |c| const_get(c) }
|
70
70
|
end
|
71
71
|
|
72
|
+
module ExternalVault
|
73
|
+
module Status
|
74
|
+
WillVault = "will_vault"
|
75
|
+
Vaulted = "vaulted"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
72
79
|
attr_reader :add_ons
|
73
80
|
attr_reader :additional_processor_response # The raw response from the processor.
|
74
81
|
attr_reader :amex_express_checkout_details
|
@@ -102,6 +109,7 @@ module Braintree
|
|
102
109
|
attr_reader :ideal_payment_details
|
103
110
|
attr_reader :masterpass_card_details
|
104
111
|
attr_reader :merchant_account_id
|
112
|
+
attr_reader :network_transaction_id
|
105
113
|
attr_reader :order_id
|
106
114
|
attr_reader :partial_settlement_transaction_ids
|
107
115
|
attr_reader :payment_instrument_type
|
@@ -226,6 +226,10 @@ module Braintree
|
|
226
226
|
{:venmo => [:profile_id]}
|
227
227
|
]
|
228
228
|
},
|
229
|
+
{:external_vault => [
|
230
|
+
:status,
|
231
|
+
:previous_network_transaction_id,
|
232
|
+
]},
|
229
233
|
{:custom_fields => :_any_key_},
|
230
234
|
{:descriptor => [:name, :phone, :url]},
|
231
235
|
{:paypal_account => [:email, :token, :paypal_data, :payee_id, :payee_email]},
|
data/lib/braintree/util.rb
CHANGED
@@ -66,6 +66,37 @@ module Braintree
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
+
def self.raise_exception_for_graphql_error(response)
|
70
|
+
return if !response[:errors]
|
71
|
+
|
72
|
+
for error in response[:errors]
|
73
|
+
if error[:extensions] && error[:extensions][:errorClass]
|
74
|
+
case error[:extensions][:errorClass]
|
75
|
+
when "VALIDATION"
|
76
|
+
next # skip raising an error if it is a validation error
|
77
|
+
when "AUTHENTICATION"
|
78
|
+
raise AuthenticationError
|
79
|
+
when "AUTHORIZATION"
|
80
|
+
raise AuthorizationError, error[:message]
|
81
|
+
when "NOT_FOUND"
|
82
|
+
raise NotFoundError
|
83
|
+
when "UNSUPPORTED_CLIENT"
|
84
|
+
raise UpgradeRequiredError, "Please upgrade your client library."
|
85
|
+
when "RESOURCE_LIMIT"
|
86
|
+
raise TooManyRequestsError
|
87
|
+
when "INTERNAL"
|
88
|
+
raise ServerError
|
89
|
+
when "SERVICE_AVAILABILITY"
|
90
|
+
raise DownForMaintenanceError
|
91
|
+
else
|
92
|
+
raise UnexpectedError, "Unexpected Response: #{error[:message]}"
|
93
|
+
end
|
94
|
+
else
|
95
|
+
raise UnexpectedError, "Unexpected Response: #{error[:message]}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
69
100
|
def self.to_big_decimal(decimal)
|
70
101
|
case decimal
|
71
102
|
when BigDecimal, NilClass
|
@@ -82,15 +113,19 @@ module Braintree
|
|
82
113
|
end
|
83
114
|
|
84
115
|
def self.verify_keys(valid_keys, hash)
|
85
|
-
|
86
|
-
invalid_keys = _flatten_hash_keys(hash) - flattened_valid_keys
|
87
|
-
invalid_keys = _remove_wildcard_keys(flattened_valid_keys, invalid_keys)
|
116
|
+
invalid_keys = _get_invalid_keys(valid_keys, hash)
|
88
117
|
if invalid_keys.any?
|
89
118
|
sorted = invalid_keys.sort_by { |k| k.to_s }.join(", ")
|
90
119
|
raise ArgumentError, "invalid keys: #{sorted}"
|
91
120
|
end
|
92
121
|
end
|
93
122
|
|
123
|
+
def self.keys_valid?(valid_keys, hash)
|
124
|
+
invalid_keys = _get_invalid_keys(valid_keys, hash)
|
125
|
+
|
126
|
+
!invalid_keys.any?
|
127
|
+
end
|
128
|
+
|
94
129
|
def self._flatten_valid_keys(valid_keys, namespace = nil)
|
95
130
|
valid_keys.inject([]) do |result, key|
|
96
131
|
if key.is_a?(Hash)
|
@@ -138,6 +173,12 @@ module Braintree
|
|
138
173
|
end
|
139
174
|
end
|
140
175
|
|
176
|
+
def self._get_invalid_keys(valid_keys, hash)
|
177
|
+
flattened_valid_keys = _flatten_valid_keys(valid_keys)
|
178
|
+
keys = _flatten_hash_keys(hash) - flattened_valid_keys
|
179
|
+
keys = _remove_wildcard_keys(flattened_valid_keys, keys)
|
180
|
+
end
|
181
|
+
|
141
182
|
module IdEquality
|
142
183
|
def ==(other) # :nodoc:
|
143
184
|
return false unless other.is_a?(self.class)
|
@@ -6,8 +6,16 @@ module Braintree
|
|
6
6
|
attr_reader :code
|
7
7
|
attr_reader :message
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
|
9
|
+
def initialize(error_hash)
|
10
|
+
# parse GraphQL response objects
|
11
|
+
if (error_hash[:extensions] &&
|
12
|
+
error_hash[:extensions][:errorClass] &&
|
13
|
+
error_hash[:extensions][:errorClass] == "VALIDATION")
|
14
|
+
error_hash[:code] = error_hash[:extensions][:legacyCode].to_i
|
15
|
+
error_hash[:attribute] = error_hash[:path].last
|
16
|
+
end
|
17
|
+
|
18
|
+
set_instance_variables_from_hash error_hash
|
11
19
|
end
|
12
20
|
|
13
21
|
def inspect # :nodoc:
|
@@ -3,7 +3,8 @@ module Braintree
|
|
3
3
|
include Enumerable
|
4
4
|
|
5
5
|
def initialize(data) # :nodoc:
|
6
|
-
|
6
|
+
return if !data.is_a? Hash
|
7
|
+
@errors = (data[:errors] || {}).map { |hash| Braintree::ValidationError.new(hash) }
|
7
8
|
@nested = {}
|
8
9
|
data.keys.each do |key|
|
9
10
|
next if key == :errors
|
data/lib/braintree/version.rb
CHANGED
@@ -41,6 +41,8 @@ module Braintree
|
|
41
41
|
ConnectedMerchantPayPalStatusChanged = "connected_merchant_paypal_status_changed"
|
42
42
|
|
43
43
|
GrantedPaymentInstrumentUpdate = "granted_payment_instrument_update"
|
44
|
+
|
45
|
+
LocalPaymentCompleted = "local_payment_completed"
|
44
46
|
end
|
45
47
|
|
46
48
|
attr_reader :account_updater_daily_report
|
@@ -51,8 +53,9 @@ module Braintree
|
|
51
53
|
attr_reader :granted_payment_instrument_update
|
52
54
|
attr_reader :ideal_payment
|
53
55
|
attr_reader :kind
|
54
|
-
attr_reader :
|
56
|
+
attr_reader :local_payment_completed
|
55
57
|
attr_reader :oauth_access_revocation
|
58
|
+
attr_reader :partner_merchant
|
56
59
|
attr_reader :source_merchant_id
|
57
60
|
attr_reader :subscription
|
58
61
|
attr_reader :timestamp
|
@@ -82,6 +85,7 @@ module Braintree
|
|
82
85
|
@connected_merchant_status_transitioned = ConnectedMerchantStatusTransitioned._new(@subject[:connected_merchant_status_transitioned]) if @subject.has_key?(:connected_merchant_status_transitioned)
|
83
86
|
@connected_merchant_paypal_status_changed = ConnectedMerchantPayPalStatusChanged._new(@subject[:connected_merchant_paypal_status_changed]) if @subject.has_key?(:connected_merchant_paypal_status_changed)
|
84
87
|
@granted_payment_instrument_update = GrantedPaymentInstrumentUpdate._new(@subject[:granted_payment_instrument_update]) if @subject.has_key?(:granted_payment_instrument_update)
|
88
|
+
@local_payment_completed = LocalPaymentCompleted._new(@subject[:local_payment]) if @subject.has_key?(:local_payment)
|
85
89
|
end
|
86
90
|
|
87
91
|
def merchant_account
|
@@ -64,6 +64,8 @@ module Braintree
|
|
64
64
|
_disbursement_sample_xml(id)
|
65
65
|
when Braintree::WebhookNotification::Kind::SubscriptionChargedSuccessfully
|
66
66
|
_subscription_charged_successfully(id)
|
67
|
+
when Braintree::WebhookNotification::Kind::SubscriptionChargedUnsuccessfully
|
68
|
+
_subscription_charged_unsuccessfully(id)
|
67
69
|
when Braintree::WebhookNotification::Kind::AccountUpdaterDailyReport
|
68
70
|
_account_updater_daily_report_sample_xml(id)
|
69
71
|
when Braintree::WebhookNotification::Kind::ConnectedMerchantStatusTransitioned
|
@@ -76,6 +78,8 @@ module Braintree
|
|
76
78
|
_ideal_payment_failed_sample_xml(id)
|
77
79
|
when Braintree::WebhookNotification::Kind::GrantedPaymentInstrumentUpdate
|
78
80
|
_granted_payment_instrument_update_sample_xml(id)
|
81
|
+
when Braintree::WebhookNotification::Kind::LocalPaymentCompleted
|
82
|
+
_local_payment_completed_sample_xml(id)
|
79
83
|
else
|
80
84
|
_subscription_sample_xml(id)
|
81
85
|
end
|
@@ -95,6 +99,7 @@ module Braintree
|
|
95
99
|
<id>#{id}</id>
|
96
100
|
<transactions type="array">
|
97
101
|
<transaction>
|
102
|
+
<id>#{id}</id>
|
98
103
|
<status>submitted_for_settlement</status>
|
99
104
|
<amount>49.99</amount>
|
100
105
|
</transaction>
|
@@ -107,6 +112,26 @@ module Braintree
|
|
107
112
|
XML
|
108
113
|
end
|
109
114
|
|
115
|
+
def _subscription_charged_unsuccessfully(id)
|
116
|
+
|
117
|
+
<<-XML
|
118
|
+
<subscription>
|
119
|
+
<id>#{id}</id>
|
120
|
+
<transactions type="array">
|
121
|
+
<transaction>
|
122
|
+
<id>#{id}</id>
|
123
|
+
<status>failed</status>
|
124
|
+
<amount>49.99</amount>
|
125
|
+
</transaction>
|
126
|
+
</transactions>
|
127
|
+
<add_ons type="array">
|
128
|
+
</add_ons>
|
129
|
+
<discounts type="array">
|
130
|
+
</discounts>
|
131
|
+
</subscription>
|
132
|
+
XML
|
133
|
+
end
|
134
|
+
|
110
135
|
def _subscription_sample_xml(id)
|
111
136
|
|
112
137
|
<<-XML
|
@@ -589,7 +614,6 @@ module Braintree
|
|
589
614
|
end
|
590
615
|
|
591
616
|
def _ideal_payment_complete_sample_xml(id)
|
592
|
-
|
593
617
|
<<-XML
|
594
618
|
<ideal-payment>
|
595
619
|
<id>#{id}</id>
|
@@ -606,7 +630,6 @@ module Braintree
|
|
606
630
|
end
|
607
631
|
|
608
632
|
def _ideal_payment_failed_sample_xml(id)
|
609
|
-
|
610
633
|
<<-XML
|
611
634
|
<ideal-payment>
|
612
635
|
<id>#{id}</id>
|
@@ -623,7 +646,6 @@ module Braintree
|
|
623
646
|
end
|
624
647
|
|
625
648
|
def _granted_payment_instrument_update_sample_xml(id)
|
626
|
-
|
627
649
|
<<-XML
|
628
650
|
<granted-payment-instrument-update>
|
629
651
|
<grant-owner-merchant-id>vczo7jqrpwrsi2px</grant-owner-merchant-id>
|
@@ -641,5 +663,14 @@ module Braintree
|
|
641
663
|
</granted-payment-instrument-update>
|
642
664
|
XML
|
643
665
|
end
|
666
|
+
|
667
|
+
def _local_payment_completed_sample_xml(id)
|
668
|
+
<<-XML
|
669
|
+
<local-payment>
|
670
|
+
<payment-id>PAY-XYZ123</payment-id>
|
671
|
+
<payer-id>ABCPAYER</payer-id>
|
672
|
+
</local-payment>
|
673
|
+
XML
|
674
|
+
end
|
644
675
|
end
|
645
676
|
end
|
data/lib/braintree.rb
CHANGED
@@ -21,6 +21,7 @@ require "braintree/base_module"
|
|
21
21
|
require "braintree/modification"
|
22
22
|
|
23
23
|
require "braintree/util"
|
24
|
+
require "braintree/http"
|
24
25
|
|
25
26
|
require "braintree/account_updater_daily_report"
|
26
27
|
require "braintree/ach_mandate"
|
@@ -70,10 +71,11 @@ require "braintree/error_codes"
|
|
70
71
|
require "braintree/error_result"
|
71
72
|
require "braintree/errors"
|
72
73
|
require "braintree/gateway"
|
73
|
-
require "braintree/
|
74
|
+
require "braintree/graphql_client"
|
74
75
|
require "braintree/ideal_payment"
|
75
76
|
require "braintree/ideal_payment_gateway"
|
76
77
|
require "braintree/transaction/ideal_payment_details"
|
78
|
+
require "braintree/local_payment_completed"
|
77
79
|
require "braintree/merchant"
|
78
80
|
require "braintree/merchant_gateway"
|
79
81
|
require "braintree/merchant_account"
|
@@ -535,6 +535,20 @@ describe Braintree::CreditCard do
|
|
535
535
|
credit_card.expiration_date.should == "11/2099"
|
536
536
|
end
|
537
537
|
end
|
538
|
+
|
539
|
+
context "card_type" do
|
540
|
+
it "is set to Elo" do
|
541
|
+
customer = Braintree::Customer.create!
|
542
|
+
result = Braintree::CreditCard.create(
|
543
|
+
:customer_id => customer.id,
|
544
|
+
:number => Braintree::Test::CreditCardNumbers::Elo,
|
545
|
+
:expiration_date => "10/2020",
|
546
|
+
)
|
547
|
+
result.success?.should == true
|
548
|
+
credit_card = result.credit_card
|
549
|
+
credit_card.card_type.should == Braintree::CreditCard::CardType::Elo
|
550
|
+
end
|
551
|
+
end
|
538
552
|
end
|
539
553
|
|
540
554
|
describe "self.create!" do
|
@@ -34,6 +34,9 @@ describe Braintree::Dispute do
|
|
34
34
|
|
35
35
|
refreshed_dispute = Braintree::Dispute.find(dispute.id)
|
36
36
|
refreshed_dispute.status.should == Braintree::Dispute::Status::Accepted
|
37
|
+
|
38
|
+
dispute_from_transaction = Braintree::Transaction.find(dispute.transaction.id).disputes[0]
|
39
|
+
dispute_from_transaction.status.should == Braintree::Dispute::Status::Accepted
|
37
40
|
end
|
38
41
|
|
39
42
|
it "returns an error response if the dispute is not in open status" do
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe Braintree::GraphQLClient do
|
4
|
+
before :each do
|
5
|
+
@config = Braintree::Configuration.instantiate
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "initialize" do
|
9
|
+
it "assigns overriding graphql headers" do
|
10
|
+
expect(@config.graphql_client.instance_variable_get("@graphql_headers")).to be_kind_of(Hash)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "query" do
|
15
|
+
it "makes valid GraphQL queries when given a definition" do
|
16
|
+
definition = <<-GRAPHQL
|
17
|
+
query {
|
18
|
+
ping
|
19
|
+
}
|
20
|
+
GRAPHQL
|
21
|
+
|
22
|
+
response = Braintree::GraphQLClient.new(@config).query(definition)
|
23
|
+
|
24
|
+
expect(response[:data]).to eq({:ping=>"pong"})
|
25
|
+
end
|
26
|
+
|
27
|
+
it "makes valid GraphQL requests when given a definitiona and variable" do
|
28
|
+
definition = <<-GRAPHQL
|
29
|
+
mutation CreateClientToken($input: CreateClientTokenInput!) {
|
30
|
+
createClientToken(input: $input) {
|
31
|
+
clientMutationId
|
32
|
+
clientToken
|
33
|
+
}
|
34
|
+
}
|
35
|
+
GRAPHQL
|
36
|
+
|
37
|
+
variables = {
|
38
|
+
input: {
|
39
|
+
clientMutationId: "abc123",
|
40
|
+
clientToken: {
|
41
|
+
merchantAccountId: "ABC123"
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
response = Braintree::GraphQLClient.new(@config).query(definition, variables)
|
47
|
+
|
48
|
+
expect(response[:data][:createClientToken][:clientToken]).to be_a(String)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns results parsable into validation errors" do
|
52
|
+
definition = <<-GRAPHQL
|
53
|
+
query TransactionLevelFeeReport($date: Date!, $merchantAccountId: ID) {
|
54
|
+
report {
|
55
|
+
transactionLevelFees(date: $date, merchantAccountId: $merchantAccountId) {
|
56
|
+
url
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
GRAPHQL
|
61
|
+
|
62
|
+
variables = {
|
63
|
+
date: "2018-01-01",
|
64
|
+
merchantAccountId: "some_merchant"
|
65
|
+
}
|
66
|
+
|
67
|
+
response = Braintree::GraphQLClient.new(@config).query(definition, variables)
|
68
|
+
errors = Braintree::ValidationErrorCollection.new(response)
|
69
|
+
|
70
|
+
expect(errors.size).to eq(1)
|
71
|
+
expect(errors.first.message).to eq("Invalid merchant account id: some_merchant")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|