braintree 4.39.0 → 4.40.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/lib/braintree/address_gateway.rb +13 -3
- data/lib/braintree/credit_card_gateway.rb +1 -0
- data/lib/braintree/credit_card_verification_gateway.rb +1 -0
- data/lib/braintree/dispute_gateway.rb +7 -7
- data/lib/braintree/error_codes.rb +11 -0
- data/lib/braintree/payment_method_gateway.rb +1 -0
- data/lib/braintree/three_d_secure_pass_thru.rb +11 -0
- data/lib/braintree/transaction_gateway.rb +1 -0
- data/lib/braintree/util.rb +5 -0
- data/lib/braintree/version.rb +1 -1
- data/lib/braintree.rb +1 -0
- data/spec/integration/braintree/advanced_search_spec.rb +4 -7
- data/spec/integration/braintree/braintree_gateway_spec.rb +1 -2
- data/spec/integration/braintree/credit_card_spec.rb +94 -2
- data/spec/integration/braintree/credit_card_verification_spec.rb +33 -0
- data/spec/integration/braintree/customer_spec.rb +153 -5
- data/spec/integration/braintree/http_spec.rb +1 -1
- data/spec/integration/braintree/payment_method_spec.rb +77 -7
- data/spec/integration/braintree/samsung_pay_card_spec.rb +1 -1
- data/spec/integration/braintree/transaction_search_spec.rb +18 -13
- data/spec/integration/braintree/transaction_spec.rb +116 -16
- data/spec/unit/braintree/address_spec.rb +32 -0
- data/spec/unit/braintree/credit_card_spec.rb +2 -0
- data/spec/unit/braintree/customer_spec.rb +2 -0
- data/spec/unit/braintree/dispute_spec.rb +38 -0
- data/spec/unit/braintree/transaction_gateway_spec.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a358a5cff7db74d5364a662ed1076dd786742d6d6f75b0f9c040fda06353a955
|
|
4
|
+
data.tar.gz: b78e2a6f20ab1207515ea76f3e7aaa6a367283b10821b026c9f89498e2e8f35c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7fbb0b0ca10ec35cd3e8e6d34476eaada51e465caf4aa25a00e6d61fdbafea147a25579ed012717f2b2fec3da184d823dd0756add7738d8e4bcf1a8abea1dd2d
|
|
7
|
+
data.tar.gz: 7374cd696e006db551149f9363194c3a8ecafc7ec607b93b6a53f2eeb3eb2961e4b63bd68d20c2ea0f5262fab405597e924219b7e76fd514b0a398c367fa7403
|
|
@@ -13,7 +13,7 @@ module Braintree
|
|
|
13
13
|
unless attributes[:customer_id]
|
|
14
14
|
raise ArgumentError, "Expected hash to contain a :customer_id"
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
if Util.invalid_path_segment?(attributes[:customer_id])
|
|
17
17
|
raise ArgumentError, ":customer_id contains invalid characters"
|
|
18
18
|
end
|
|
19
19
|
response = @config.http.post("#{@config.base_merchant_path}/customers/#{attributes.delete(:customer_id)}/addresses", :address => attributes)
|
|
@@ -32,13 +32,14 @@ module Braintree
|
|
|
32
32
|
|
|
33
33
|
def delete(customer_or_customer_id, address_id)
|
|
34
34
|
customer_id = _determine_customer_id(customer_or_customer_id)
|
|
35
|
+
address_id = _determine_address_id(address_id)
|
|
35
36
|
@config.http.delete("#{@config.base_merchant_path}/customers/#{customer_id}/addresses/#{address_id}")
|
|
36
37
|
SuccessfulResult.new
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
def find(customer_or_customer_id, address_id)
|
|
40
41
|
customer_id = _determine_customer_id(customer_or_customer_id)
|
|
41
|
-
|
|
42
|
+
address_id = _determine_address_id(address_id)
|
|
42
43
|
response = @config.http.get("#{@config.base_merchant_path}/customers/#{customer_id}/addresses/#{address_id}")
|
|
43
44
|
Address._new(@gateway, response[:address])
|
|
44
45
|
rescue NotFoundError
|
|
@@ -48,6 +49,7 @@ module Braintree
|
|
|
48
49
|
def update(customer_or_customer_id, address_id, attributes)
|
|
49
50
|
Util.verify_keys(AddressGateway._update_signature, attributes)
|
|
50
51
|
customer_id = _determine_customer_id(customer_or_customer_id)
|
|
52
|
+
address_id = _determine_address_id(address_id)
|
|
51
53
|
response = @config.http.put("#{@config.base_merchant_path}/customers/#{customer_id}/addresses/#{address_id}", :address => attributes)
|
|
52
54
|
if response[:address]
|
|
53
55
|
SuccessfulResult.new(:address => Address._new(@gateway, response[:address]))
|
|
@@ -64,12 +66,20 @@ module Braintree
|
|
|
64
66
|
|
|
65
67
|
def _determine_customer_id(customer_or_customer_id)
|
|
66
68
|
customer_id = customer_or_customer_id.is_a?(Customer) ? customer_or_customer_id.id : customer_or_customer_id
|
|
67
|
-
|
|
69
|
+
if Util.invalid_path_segment?(customer_id)
|
|
68
70
|
raise ArgumentError, "customer_id contains invalid characters"
|
|
69
71
|
end
|
|
70
72
|
customer_id
|
|
71
73
|
end
|
|
72
74
|
|
|
75
|
+
def _determine_address_id(address_id)
|
|
76
|
+
address_id = address_id.to_s
|
|
77
|
+
if Util.invalid_path_segment?(address_id)
|
|
78
|
+
raise ArgumentError, "address_id contains invalid characters"
|
|
79
|
+
end
|
|
80
|
+
address_id
|
|
81
|
+
end
|
|
82
|
+
|
|
73
83
|
def self._create_signature
|
|
74
84
|
_shared_signature + [:customer_id]
|
|
75
85
|
end
|
|
@@ -7,7 +7,7 @@ module Braintree
|
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def accept(dispute_id)
|
|
10
|
-
raise ArgumentError, "dispute_id contains invalid characters"
|
|
10
|
+
raise ArgumentError, "dispute_id contains invalid characters" if Util.invalid_path_segment?(dispute_id)
|
|
11
11
|
raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
|
|
12
12
|
|
|
13
13
|
response = @config.http.put("#{@config.base_merchant_path}/disputes/#{dispute_id}/accept")
|
|
@@ -21,7 +21,7 @@ module Braintree
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def add_file_evidence(dispute_id, document_id_or_request)
|
|
24
|
-
raise ArgumentError, "dispute_id contains invalid characters"
|
|
24
|
+
raise ArgumentError, "dispute_id contains invalid characters" if Util.invalid_path_segment?(dispute_id)
|
|
25
25
|
raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
|
|
26
26
|
raise ArgumentError, "document_id_or_request cannot be blank" if document_id_or_request.nil?
|
|
27
27
|
|
|
@@ -51,7 +51,7 @@ module Braintree
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def add_text_evidence(dispute_id, content_or_request)
|
|
54
|
-
raise ArgumentError, "dispute_id contains invalid characters"
|
|
54
|
+
raise ArgumentError, "dispute_id contains invalid characters" if Util.invalid_path_segment?(dispute_id)
|
|
55
55
|
raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
|
|
56
56
|
raise ArgumentError, "content_or_request cannot be blank" if content_or_request.nil?
|
|
57
57
|
|
|
@@ -84,7 +84,7 @@ module Braintree
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def finalize(dispute_id)
|
|
87
|
-
raise ArgumentError, "dispute_id contains invalid characters"
|
|
87
|
+
raise ArgumentError, "dispute_id contains invalid characters" if Util.invalid_path_segment?(dispute_id)
|
|
88
88
|
raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
|
|
89
89
|
|
|
90
90
|
response = @config.http.put("#{@config.base_merchant_path}/disputes/#{dispute_id}/finalize")
|
|
@@ -98,7 +98,7 @@ module Braintree
|
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
def find(dispute_id)
|
|
101
|
-
raise ArgumentError, "dispute_id contains invalid characters"
|
|
101
|
+
raise ArgumentError, "dispute_id contains invalid characters" if Util.invalid_path_segment?(dispute_id)
|
|
102
102
|
raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
|
|
103
103
|
response = @config.http.get("#{@config.base_merchant_path}/disputes/#{dispute_id}")
|
|
104
104
|
Dispute._new(response[:dispute])
|
|
@@ -107,9 +107,9 @@ module Braintree
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
def remove_evidence(dispute_id, evidence_id)
|
|
110
|
-
raise ArgumentError, "dispute_id contains invalid characters"
|
|
110
|
+
raise ArgumentError, "dispute_id contains invalid characters" if Util.invalid_path_segment?(dispute_id)
|
|
111
111
|
raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
|
|
112
|
-
raise ArgumentError, "evidence_id contains invalid characters"
|
|
112
|
+
raise ArgumentError, "evidence_id contains invalid characters" if Util.invalid_path_segment?(evidence_id)
|
|
113
113
|
raise ArgumentError, "evidence_id cannot be blank" if evidence_id.nil? || evidence_id.to_s.strip == ""
|
|
114
114
|
|
|
115
115
|
response = @config.http.delete("#{@config.base_merchant_path}/disputes/#{dispute_id}/evidence/#{evidence_id}")
|
|
@@ -216,6 +216,8 @@ module Braintree
|
|
|
216
216
|
CannotVaultOneTimeUsePayPalAccount = "82902"
|
|
217
217
|
ConsentCodeOrAccessTokenIsRequired = "82901"
|
|
218
218
|
CustomerIdIsRequiredForVaulting = "82905"
|
|
219
|
+
EmailFormatIsInvalid = "92963"
|
|
220
|
+
EmailIsTooLong = "92964"
|
|
219
221
|
IncompletePayPalAccount = "82901"
|
|
220
222
|
InvalidFundingSourceSelection = "92913"
|
|
221
223
|
InvalidParamsForPayPalAccountUpdate = "92915"
|
|
@@ -472,6 +474,10 @@ module Braintree
|
|
|
472
474
|
ThreeDSecureEciFlagIsInvalid = "915114"
|
|
473
475
|
ThreeDSecureEciFlagIsRequired = "915113"
|
|
474
476
|
ThreeDSecureMerchantAccountDoesNotSupportCardType = "915131"
|
|
477
|
+
ThreeDSecureNetworkDoesNotMatchPaymentInstrument = "915139"
|
|
478
|
+
ThreeDSecureNetworkDoesNotSupportCurrency = "915239"
|
|
479
|
+
ThreeDSecureNetworkDoesNotSupportMerchantAccountCurrency = "915243"
|
|
480
|
+
ThreeDSecureNetworkIsInvalid = "915128"
|
|
475
481
|
ThreeDSecureThreeDSecureVersionIsInvalid = "915119"
|
|
476
482
|
ThreeDSecureTokenIsInvalid = "91568"
|
|
477
483
|
ThreeDSecureTransactionDataDoesntMatchVerify = "91570"
|
|
@@ -502,6 +508,7 @@ module Braintree
|
|
|
502
508
|
|
|
503
509
|
|
|
504
510
|
module Options
|
|
511
|
+
SubmitForSettlementIsNotSupportedForNetwork = "915261"
|
|
505
512
|
SubmitForSettlementIsRequiredForCloning = "91544"
|
|
506
513
|
SubmitForSettlementIsRequiredForPayPalUnilateral = "91582"
|
|
507
514
|
VaultIsDisabled = "91525"
|
|
@@ -768,6 +775,10 @@ module Braintree
|
|
|
768
775
|
DirectoryResponseIsInvalid = "942121"
|
|
769
776
|
EciFlagIsInvalid = "942114"
|
|
770
777
|
EciFlagIsRequired = "942113"
|
|
778
|
+
NetworkDoesNotMatchPaymentInstrument = "942139"
|
|
779
|
+
NetworkDoesNotSupportCurrency = "942129"
|
|
780
|
+
NetworkDoesNotSupportMerchantAccountCurrency = "942130"
|
|
781
|
+
NetworkIsInvalid = "942128"
|
|
771
782
|
ThreeDSecureVersionIsInvalid = "942119"
|
|
772
783
|
ThreeDSecureVersionIsRequired = "942117"
|
|
773
784
|
end
|
data/lib/braintree/util.rb
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
module Braintree
|
|
2
2
|
module Util
|
|
3
|
+
# Allowlist of the characters that make up a Braintree id/token.
|
|
4
|
+
def self.invalid_path_segment?(value)
|
|
5
|
+
!value.to_s.match?(/\A[A-Za-z0-9_-]+\z/)
|
|
6
|
+
end
|
|
7
|
+
|
|
3
8
|
def self.extract_attribute_as_array(hash, attribute)
|
|
4
9
|
raise UnexpectedError.new("Unprocessable entity due to an invalid request") if hash.nil?
|
|
5
10
|
value = hash.has_key?(attribute) ? hash.delete(attribute) : []
|
data/lib/braintree/version.rb
CHANGED
data/lib/braintree.rb
CHANGED
|
@@ -138,6 +138,7 @@ require "braintree/risk_data/liability_shift"
|
|
|
138
138
|
require "braintree/facilitated_details"
|
|
139
139
|
require "braintree/facilitator_details"
|
|
140
140
|
require "braintree/three_d_secure_info"
|
|
141
|
+
require "braintree/three_d_secure_pass_thru"
|
|
141
142
|
require "braintree/settlement_batch_summary"
|
|
142
143
|
require "braintree/settlement_batch_summary_gateway"
|
|
143
144
|
require "braintree/resource_collection"
|
|
@@ -33,8 +33,7 @@ describe Braintree::AdvancedSearch do
|
|
|
33
33
|
expect(collection).not_to include(subscription2)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
xit "is_not" do
|
|
36
|
+
it "is_not" do
|
|
38
37
|
id = rand(36**8).to_s(36)
|
|
39
38
|
subscription1 = Braintree::Subscription.create(
|
|
40
39
|
:payment_method_token => @credit_card.token,
|
|
@@ -81,8 +80,7 @@ describe Braintree::AdvancedSearch do
|
|
|
81
80
|
expect(collection).not_to include(subscription2)
|
|
82
81
|
end
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
xit "ends_with" do
|
|
83
|
+
it "ends_with" do
|
|
86
84
|
id = rand(36**8).to_s(36)
|
|
87
85
|
subscription1 = Braintree::Subscription.create(
|
|
88
86
|
:payment_method_token => @credit_card.token,
|
|
@@ -177,8 +175,7 @@ describe Braintree::AdvancedSearch do
|
|
|
177
175
|
expect(collection).not_to include(subscription2)
|
|
178
176
|
end
|
|
179
177
|
|
|
180
|
-
|
|
181
|
-
xit "returns only matching results given an argument list" do
|
|
178
|
+
it "returns only matching results given an argument list" do
|
|
182
179
|
subscription1 = Braintree::Subscription.create(
|
|
183
180
|
:payment_method_token => @credit_card.token,
|
|
184
181
|
:plan_id => SpecHelper::TriallessPlan[:id],
|
|
@@ -265,7 +262,7 @@ describe Braintree::AdvancedSearch do
|
|
|
265
262
|
|
|
266
263
|
context "multiple_value_or_text_field" do
|
|
267
264
|
describe "in" do
|
|
268
|
-
|
|
265
|
+
it "works for the in operator(temporarily disabling until more stable CI)" do
|
|
269
266
|
Braintree::Subscription.create(
|
|
270
267
|
:payment_method_token => @credit_card.token,
|
|
271
268
|
:plan_id => SpecHelper::TriallessPlan[:id],
|
|
@@ -12,8 +12,7 @@ describe Braintree::Gateway do
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
describe "query" do
|
|
15
|
-
|
|
16
|
-
xit "makes valid GraphQL queries when given a definition" do
|
|
15
|
+
it "makes valid GraphQL mutation queries for tokenizeCreditCard" do
|
|
17
16
|
definition = <<-GRAPHQL
|
|
18
17
|
mutation ExampleServerSideSingleUseToken($input: TokenizeCreditCardInput!) {
|
|
19
18
|
tokenizeCreditCard(input: $input) {
|
|
@@ -312,6 +312,99 @@ describe Braintree::CreditCard do
|
|
|
312
312
|
expect(result.success?).to eq(true)
|
|
313
313
|
end
|
|
314
314
|
|
|
315
|
+
it "accepts a three_d_secure_pass_thru network specified in the request" do
|
|
316
|
+
customer = Braintree::Customer.create!
|
|
317
|
+
result = Braintree::CreditCard.create(
|
|
318
|
+
:customer_id => customer.id,
|
|
319
|
+
:payment_method_nonce => Braintree::Test::Nonce::TransactableVisa,
|
|
320
|
+
:three_d_secure_pass_thru => {
|
|
321
|
+
:eci_flag => "05",
|
|
322
|
+
:cavv => "some_cavv",
|
|
323
|
+
:xid => "some_xid",
|
|
324
|
+
:three_d_secure_version => "2.2.0",
|
|
325
|
+
:authentication_response => "Y",
|
|
326
|
+
:directory_response => "Y",
|
|
327
|
+
:cavv_algorithm => "2",
|
|
328
|
+
:ds_transaction_id => "some_ds_transaction_id",
|
|
329
|
+
:network => Braintree::ThreeDSecurePassThru::Network::Visa,
|
|
330
|
+
},
|
|
331
|
+
:options => {:verify_card => true},
|
|
332
|
+
)
|
|
333
|
+
expect(result.success?).to eq(true)
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
it "rejects invalid network value in 3ds pass thru params" do
|
|
337
|
+
customer = Braintree::Customer.create!
|
|
338
|
+
result = Braintree::CreditCard.create(
|
|
339
|
+
:customer_id => customer.id,
|
|
340
|
+
:payment_method_nonce => Braintree::Test::Nonce::Transactable,
|
|
341
|
+
:three_d_secure_pass_thru => {
|
|
342
|
+
:eci_flag => "05",
|
|
343
|
+
:cavv => "some_cavv",
|
|
344
|
+
:xid => "some_xid",
|
|
345
|
+
:three_d_secure_version => "2.2.0",
|
|
346
|
+
:authentication_response => "Y",
|
|
347
|
+
:directory_response => "Y",
|
|
348
|
+
:cavv_algorithm => "2",
|
|
349
|
+
:ds_transaction_id => "some_ds_transaction_id",
|
|
350
|
+
:network => "DISCOVER",
|
|
351
|
+
},
|
|
352
|
+
:options => {:verify_card => true},
|
|
353
|
+
)
|
|
354
|
+
expect(result).not_to be_success
|
|
355
|
+
error = result.errors.for(:verification).first
|
|
356
|
+
expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::NetworkIsInvalid)
|
|
357
|
+
expect(error.message).to eq("Network is invalid. Supported networks are eftpos, Visa, and Mastercard.")
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
it "rejects request where 3ds pass thru network does not match the payment instrument (VISA nonce, Mastercard network)" do
|
|
361
|
+
customer = Braintree::Customer.create!
|
|
362
|
+
result = Braintree::CreditCard.create(
|
|
363
|
+
:customer_id => customer.id,
|
|
364
|
+
:payment_method_nonce => Braintree::Test::Nonce::TransactableVisa,
|
|
365
|
+
:three_d_secure_pass_thru => {
|
|
366
|
+
:eci_flag => "05",
|
|
367
|
+
:cavv => "some_cavv",
|
|
368
|
+
:xid => "some_xid",
|
|
369
|
+
:three_d_secure_version => "2.2.0",
|
|
370
|
+
:authentication_response => "Y",
|
|
371
|
+
:directory_response => "Y",
|
|
372
|
+
:cavv_algorithm => "2",
|
|
373
|
+
:ds_transaction_id => "some_ds_transaction_id",
|
|
374
|
+
:network => Braintree::ThreeDSecurePassThru::Network::MasterCard,
|
|
375
|
+
},
|
|
376
|
+
:options => {:verify_card => true},
|
|
377
|
+
)
|
|
378
|
+
expect(result).not_to be_success
|
|
379
|
+
error = result.errors.for(:verification).first
|
|
380
|
+
expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::NetworkDoesNotMatchPaymentInstrument)
|
|
381
|
+
expect(error.message).to eq("Network does not match the payment instrument.")
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
it "rejects request where 3ds pass thru network does not support the merchant account currency" do
|
|
385
|
+
customer = Braintree::Customer.create!
|
|
386
|
+
result = Braintree::CreditCard.create(
|
|
387
|
+
:customer_id => customer.id,
|
|
388
|
+
:payment_method_nonce => Braintree::Test::Nonce::TransactableVisa,
|
|
389
|
+
:three_d_secure_pass_thru => {
|
|
390
|
+
:eci_flag => "05",
|
|
391
|
+
:cavv => "some_cavv",
|
|
392
|
+
:xid => "some_xid",
|
|
393
|
+
:three_d_secure_version => "2.2.0",
|
|
394
|
+
:authentication_response => "Y",
|
|
395
|
+
:directory_response => "Y",
|
|
396
|
+
:cavv_algorithm => "2",
|
|
397
|
+
:ds_transaction_id => "some_ds_transaction_id",
|
|
398
|
+
:network => Braintree::ThreeDSecurePassThru::Network::Eftpos,
|
|
399
|
+
},
|
|
400
|
+
:options => {:verify_card => true},
|
|
401
|
+
)
|
|
402
|
+
expect(result).not_to be_success
|
|
403
|
+
error = result.errors.for(:verification).first
|
|
404
|
+
expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::NetworkDoesNotSupportMerchantAccountCurrency)
|
|
405
|
+
expect(error.message).to eq("Network does not support the currency of the merchant account.")
|
|
406
|
+
end
|
|
407
|
+
|
|
315
408
|
it "returns 3DS info on cc verification" do
|
|
316
409
|
customer = Braintree::Customer.create!
|
|
317
410
|
result = Braintree::CreditCard.create(
|
|
@@ -1263,8 +1356,7 @@ describe Braintree::CreditCard do
|
|
|
1263
1356
|
end
|
|
1264
1357
|
|
|
1265
1358
|
describe "self.expiring_between" do
|
|
1266
|
-
|
|
1267
|
-
xit "finds payment methods expiring between the given dates" do
|
|
1359
|
+
it "finds payment methods expiring between the given dates" do
|
|
1268
1360
|
next_year = Time.now.year + 1
|
|
1269
1361
|
collection = Braintree::CreditCard.expiring_between(Time.mktime(next_year, 1), Time.mktime(next_year, 12))
|
|
1270
1362
|
expect(collection.maximum_size).to be > 0
|
|
@@ -630,5 +630,38 @@ describe Braintree::CreditCardVerification, "search" do
|
|
|
630
630
|
expect(result.credit_card_verification.processor_response_type).to eq(Braintree::ProcessorResponseTypes::Approved)
|
|
631
631
|
expect(result.credit_card_verification.network_transaction_id).not_to be_nil
|
|
632
632
|
end
|
|
633
|
+
|
|
634
|
+
it "can create a verification with a three_d_secure_pass_thru network specified" do
|
|
635
|
+
verification_params = {
|
|
636
|
+
:credit_card => {
|
|
637
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
638
|
+
:expiration_date => "12/12",
|
|
639
|
+
},
|
|
640
|
+
:options => {
|
|
641
|
+
:amount => "10.00",
|
|
642
|
+
},
|
|
643
|
+
:three_d_secure_pass_thru => {
|
|
644
|
+
:eci_flag => "05",
|
|
645
|
+
:cavv => "some_cavv",
|
|
646
|
+
:xid => "some_xid",
|
|
647
|
+
:three_d_secure_version => "2.2.0",
|
|
648
|
+
:authentication_response => "Y",
|
|
649
|
+
:directory_response => "Y",
|
|
650
|
+
:cavv_algorithm => "2",
|
|
651
|
+
:ds_transaction_id => "some_ds_id",
|
|
652
|
+
:network => Braintree::ThreeDSecurePassThru::Network::Visa,
|
|
653
|
+
},
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
result = Braintree::CreditCardVerification.create(verification_params)
|
|
657
|
+
|
|
658
|
+
expect(result).to be_success
|
|
659
|
+
expect(result.credit_card_verification.id).to match(/^\w{6,}$/)
|
|
660
|
+
expect(result.credit_card_verification.status).to eq(Braintree::CreditCardVerification::Status::Verified)
|
|
661
|
+
expect(result.credit_card_verification.processor_response_code).to eq("1000")
|
|
662
|
+
expect(result.credit_card_verification.processor_response_text).to eq("Approved")
|
|
663
|
+
expect(result.credit_card_verification.processor_response_type).to eq(Braintree::ProcessorResponseTypes::Approved)
|
|
664
|
+
expect(result.credit_card_verification.network_transaction_id).not_to be_nil
|
|
665
|
+
end
|
|
633
666
|
end
|
|
634
667
|
end
|
|
@@ -4,8 +4,7 @@ require File.expand_path(File.dirname(__FILE__) + "/client_api/spec_helper")
|
|
|
4
4
|
|
|
5
5
|
describe Braintree::Customer do
|
|
6
6
|
describe "self.all" do
|
|
7
|
-
|
|
8
|
-
xit "gets more than a page of customers" do
|
|
7
|
+
it "gets more than a page of customers" do
|
|
9
8
|
customers = Braintree::Customer.all
|
|
10
9
|
expect(customers.maximum_size).to be > 100
|
|
11
10
|
|
|
@@ -1242,7 +1241,7 @@ describe Braintree::Customer do
|
|
|
1242
1241
|
expect(apple_pay_card.expiration_year).not_to be_nil
|
|
1243
1242
|
expect(apple_pay_card.healthcare).not_to be_nil
|
|
1244
1243
|
expect(apple_pay_card.issuing_bank).not_to be_nil
|
|
1245
|
-
expect(apple_pay_card.payment_instrument_name).to
|
|
1244
|
+
expect(apple_pay_card.payment_instrument_name).to match(/\AAmEx \d{4,5}\z/)
|
|
1246
1245
|
expect(apple_pay_card.payroll).not_to be_nil
|
|
1247
1246
|
expect(apple_pay_card.prepaid).not_to be_nil
|
|
1248
1247
|
expect(apple_pay_card.prepaid_reloadable).not_to be_nil
|
|
@@ -1326,7 +1325,7 @@ describe Braintree::Customer do
|
|
|
1326
1325
|
expect(venmo_account.username).not_to be_nil
|
|
1327
1326
|
end
|
|
1328
1327
|
|
|
1329
|
-
|
|
1328
|
+
it "returns associated us bank accounts" do
|
|
1330
1329
|
result = Braintree::Customer.create(
|
|
1331
1330
|
:payment_method_nonce => generate_non_plaid_us_bank_account_nonce,
|
|
1332
1331
|
:credit_card => {
|
|
@@ -1693,7 +1692,8 @@ describe Braintree::Customer do
|
|
|
1693
1692
|
|
|
1694
1693
|
apple_pay_card = result.customer.payment_methods.find { |pm| pm.is_a?(Braintree::ApplePayCard) }
|
|
1695
1694
|
expect(apple_pay_card).not_to be_nil
|
|
1696
|
-
expect(apple_pay_card.
|
|
1695
|
+
expect(apple_pay_card.card_type).to eq(Braintree::ApplePayCard::CardType::Visa)
|
|
1696
|
+
expect(apple_pay_card.last_4).to match(/\A\d{4}\z/)
|
|
1697
1697
|
expect(apple_pay_card.cardholder_name).to eq("Updated Joe Cardholder")
|
|
1698
1698
|
|
|
1699
1699
|
verification = apple_pay_card.verification
|
|
@@ -2084,6 +2084,154 @@ describe Braintree::Customer do
|
|
|
2084
2084
|
expect(result).to be_success
|
|
2085
2085
|
end
|
|
2086
2086
|
|
|
2087
|
+
it "accepts a three_d_secure_pass_thru network specified on customer create" do
|
|
2088
|
+
result = Braintree::Customer.create(
|
|
2089
|
+
:payment_method_nonce => Braintree::Test::Nonce::TransactableVisa,
|
|
2090
|
+
:credit_card => {
|
|
2091
|
+
:three_d_secure_pass_thru => {
|
|
2092
|
+
:eci_flag => "05",
|
|
2093
|
+
:cavv => "some_cavv",
|
|
2094
|
+
:xid => "some_xid",
|
|
2095
|
+
:three_d_secure_version => "2.2.0",
|
|
2096
|
+
:authentication_response => "Y",
|
|
2097
|
+
:directory_response => "Y",
|
|
2098
|
+
:cavv_algorithm => "2",
|
|
2099
|
+
:ds_transaction_id => "some_ds_transaction_id",
|
|
2100
|
+
:network => Braintree::ThreeDSecurePassThru::Network::Visa,
|
|
2101
|
+
},
|
|
2102
|
+
:options => {:verify_card => true},
|
|
2103
|
+
},
|
|
2104
|
+
)
|
|
2105
|
+
expect(result).to be_success
|
|
2106
|
+
end
|
|
2107
|
+
|
|
2108
|
+
it "rejects invalid network value in 3ds pass thru params on customer create" do
|
|
2109
|
+
result = Braintree::Customer.create(
|
|
2110
|
+
:payment_method_nonce => Braintree::Test::Nonce::Transactable,
|
|
2111
|
+
:credit_card => {
|
|
2112
|
+
:three_d_secure_pass_thru => {
|
|
2113
|
+
:eci_flag => "05",
|
|
2114
|
+
:cavv => "some_cavv",
|
|
2115
|
+
:xid => "some_xid",
|
|
2116
|
+
:three_d_secure_version => "2.2.0",
|
|
2117
|
+
:authentication_response => "Y",
|
|
2118
|
+
:directory_response => "Y",
|
|
2119
|
+
:cavv_algorithm => "2",
|
|
2120
|
+
:ds_transaction_id => "some_ds_transaction_id",
|
|
2121
|
+
:network => "DISCOVER",
|
|
2122
|
+
},
|
|
2123
|
+
:options => {:verify_card => true},
|
|
2124
|
+
},
|
|
2125
|
+
)
|
|
2126
|
+
expect(result).not_to be_success
|
|
2127
|
+
error = result.errors.for(:verification).first
|
|
2128
|
+
expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::NetworkIsInvalid)
|
|
2129
|
+
expect(error.message).to eq("Network is invalid. Supported networks are eftpos, Visa, and Mastercard.")
|
|
2130
|
+
end
|
|
2131
|
+
|
|
2132
|
+
it "rejects request where 3ds pass thru network does not match the payment instrument on customer create (VISA nonce, Mastercard network)" do
|
|
2133
|
+
result = Braintree::Customer.create(
|
|
2134
|
+
:payment_method_nonce => Braintree::Test::Nonce::TransactableVisa,
|
|
2135
|
+
:credit_card => {
|
|
2136
|
+
:three_d_secure_pass_thru => {
|
|
2137
|
+
:eci_flag => "05",
|
|
2138
|
+
:cavv => "some_cavv",
|
|
2139
|
+
:xid => "some_xid",
|
|
2140
|
+
:three_d_secure_version => "2.2.0",
|
|
2141
|
+
:authentication_response => "Y",
|
|
2142
|
+
:directory_response => "Y",
|
|
2143
|
+
:cavv_algorithm => "2",
|
|
2144
|
+
:ds_transaction_id => "some_ds_transaction_id",
|
|
2145
|
+
:network => Braintree::ThreeDSecurePassThru::Network::MasterCard,
|
|
2146
|
+
},
|
|
2147
|
+
:options => {:verify_card => true},
|
|
2148
|
+
},
|
|
2149
|
+
)
|
|
2150
|
+
expect(result).not_to be_success
|
|
2151
|
+
error = result.errors.for(:verification).first
|
|
2152
|
+
expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::NetworkDoesNotMatchPaymentInstrument)
|
|
2153
|
+
expect(error.message).to eq("Network does not match the payment instrument.")
|
|
2154
|
+
end
|
|
2155
|
+
|
|
2156
|
+
it "accepts a three_d_secure_pass_thru network specified on customer update" do
|
|
2157
|
+
customer = Braintree::Customer.create!
|
|
2158
|
+
result = Braintree::Customer.update(
|
|
2159
|
+
customer.id,
|
|
2160
|
+
:credit_card => {
|
|
2161
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
2162
|
+
:expiration_date => "05/2009",
|
|
2163
|
+
:three_d_secure_pass_thru => {
|
|
2164
|
+
:eci_flag => "05",
|
|
2165
|
+
:cavv => "some_cavv",
|
|
2166
|
+
:xid => "some_xid",
|
|
2167
|
+
:three_d_secure_version => "2.2.0",
|
|
2168
|
+
:authentication_response => "Y",
|
|
2169
|
+
:directory_response => "Y",
|
|
2170
|
+
:cavv_algorithm => "2",
|
|
2171
|
+
:ds_transaction_id => "some_ds_transaction_id",
|
|
2172
|
+
:network => Braintree::ThreeDSecurePassThru::Network::Visa,
|
|
2173
|
+
},
|
|
2174
|
+
:options => {:verify_card => true}
|
|
2175
|
+
},
|
|
2176
|
+
)
|
|
2177
|
+
|
|
2178
|
+
expect(result).to be_success
|
|
2179
|
+
end
|
|
2180
|
+
|
|
2181
|
+
it "rejects invalid network value in 3ds pass thru params on customer update" do
|
|
2182
|
+
customer = Braintree::Customer.create!
|
|
2183
|
+
result = Braintree::Customer.update(
|
|
2184
|
+
customer.id,
|
|
2185
|
+
:credit_card => {
|
|
2186
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
2187
|
+
:expiration_date => "05/2009",
|
|
2188
|
+
:three_d_secure_pass_thru => {
|
|
2189
|
+
:eci_flag => "05",
|
|
2190
|
+
:cavv => "some_cavv",
|
|
2191
|
+
:xid => "some_xid",
|
|
2192
|
+
:three_d_secure_version => "2.2.0",
|
|
2193
|
+
:authentication_response => "Y",
|
|
2194
|
+
:directory_response => "Y",
|
|
2195
|
+
:cavv_algorithm => "2",
|
|
2196
|
+
:ds_transaction_id => "some_ds_transaction_id",
|
|
2197
|
+
:network => "DISCOVER",
|
|
2198
|
+
},
|
|
2199
|
+
:options => {:verify_card => true}
|
|
2200
|
+
},
|
|
2201
|
+
)
|
|
2202
|
+
expect(result).not_to be_success
|
|
2203
|
+
error = result.errors.for(:verification).first
|
|
2204
|
+
expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::NetworkIsInvalid)
|
|
2205
|
+
expect(error.message).to eq("Network is invalid. Supported networks are eftpos, Visa, and Mastercard.")
|
|
2206
|
+
end
|
|
2207
|
+
|
|
2208
|
+
it "rejects request where 3ds pass thru network does not match the payment instrument on customer update (VISA card, Mastercard network)" do
|
|
2209
|
+
customer = Braintree::Customer.create!
|
|
2210
|
+
result = Braintree::Customer.update(
|
|
2211
|
+
customer.id,
|
|
2212
|
+
:credit_card => {
|
|
2213
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
2214
|
+
:expiration_date => "05/2009",
|
|
2215
|
+
:three_d_secure_pass_thru => {
|
|
2216
|
+
:eci_flag => "05",
|
|
2217
|
+
:cavv => "some_cavv",
|
|
2218
|
+
:xid => "some_xid",
|
|
2219
|
+
:three_d_secure_version => "2.2.0",
|
|
2220
|
+
:authentication_response => "Y",
|
|
2221
|
+
:directory_response => "Y",
|
|
2222
|
+
:cavv_algorithm => "2",
|
|
2223
|
+
:ds_transaction_id => "some_ds_transaction_id",
|
|
2224
|
+
:network => Braintree::ThreeDSecurePassThru::Network::MasterCard,
|
|
2225
|
+
},
|
|
2226
|
+
:options => {:verify_card => true}
|
|
2227
|
+
},
|
|
2228
|
+
)
|
|
2229
|
+
expect(result).not_to be_success
|
|
2230
|
+
error = result.errors.for(:verification).first
|
|
2231
|
+
expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::NetworkDoesNotMatchPaymentInstrument)
|
|
2232
|
+
expect(error.message).to eq("Network does not match the payment instrument.")
|
|
2233
|
+
end
|
|
2234
|
+
|
|
2087
2235
|
it "returns 3DS info on cc verification" do
|
|
2088
2236
|
result = Braintree::Customer.create(
|
|
2089
2237
|
:payment_method_nonce => Braintree::Test::Nonce::ThreeDSecureVisaFullAuthentication,
|
|
@@ -97,7 +97,7 @@ describe Braintree::Http do
|
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
describe "ssl_version" do
|
|
100
|
-
|
|
100
|
+
it "causes failed requests to sandbox with incompatible SSL version" do
|
|
101
101
|
begin
|
|
102
102
|
original_env = Braintree::Configuration.environment
|
|
103
103
|
Braintree::Configuration.environment = :sandbox
|