braintree 4.29.0 → 4.31.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 +5 -0
- data/lib/braintree/apple_pay_card.rb +1 -0
- data/lib/braintree/bank_account_instant_verification_gateway.rb +38 -0
- data/lib/braintree/bank_account_instant_verification_jwt.rb +23 -0
- data/lib/braintree/bank_account_instant_verification_jwt_request.rb +21 -0
- data/lib/braintree/dispute.rb +1 -0
- data/lib/braintree/error_codes.rb +2 -0
- data/lib/braintree/gateway.rb +4 -0
- data/lib/braintree/payment_method_gateway.rb +6 -0
- data/lib/braintree/successful_result.rb +1 -0
- data/lib/braintree/transaction/apple_pay_details.rb +1 -0
- data/lib/braintree/transaction.rb +3 -0
- data/lib/braintree/transaction_gateway.rb +29 -0
- data/lib/braintree/us_bank_account_verification.rb +3 -1
- data/lib/braintree/version.rb +1 -1
- data/lib/braintree/webhook_notification.rb +1 -0
- data/lib/braintree/webhook_testing_gateway.rb +16 -0
- data/lib/braintree.rb +3 -0
- data/spec/integration/braintree/bank_account_instant_verification_spec.rb +191 -0
- data/spec/integration/braintree/client_api/spec_helper.rb +81 -0
- data/spec/integration/braintree/dispute_spec.rb +13 -2
- data/spec/integration/braintree/payment_method_spec.rb +3 -0
- data/spec/integration/braintree/transaction_search_spec.rb +26 -24
- data/spec/integration/braintree/transaction_spec.rb +43 -3
- data/spec/integration/braintree/transaction_transfer_type_spec.rb +301 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/unit/braintree/apple_pay_card_spec.rb +2 -0
- data/spec/unit/braintree/bank_account_instant_verification_gateway_spec.rb +98 -0
- data/spec/unit/braintree/bank_account_instant_verification_jwt_request_spec.rb +71 -0
- data/spec/unit/braintree/dispute_spec.rb +6 -0
- data/spec/unit/braintree/transaction_ach_mandate_spec.rb +82 -0
- data/spec/unit/braintree/transaction_gateway_spec.rb +25 -0
- data/spec/unit/braintree/transaction_spec.rb +18 -0
- data/spec/unit/braintree/webhook_notification_spec.rb +17 -0
- metadata +11 -4
- data/lib/ssl/securetrust_ca.crt +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a1505b44cec85c55cc5237d0fa3d57165dfa809589893774fdecfc972147940
|
4
|
+
data.tar.gz: e92b0f87a02744e0df5db4173aa6a2e237dd5b7817932232e380a160d7df1450
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d5c303f50bd453a719fc0586593fcf9307fc8a1be02c5307487178bbf368d7e1467bf08ceda4e0b96c421a46f1d43d1f9c17af35206efcb22b5c3d0f0da9094
|
7
|
+
data.tar.gz: 287dadfccf55558b99069ffd42458b67085a68aabeb2d6575765e8f96c281c97158228bf99254a802d84b50e41fc90dc28b06d4c5984fb06e2563e28c108c286
|
@@ -84,6 +84,11 @@ module Braintree
|
|
84
84
|
def self._update_signature
|
85
85
|
_create_signature
|
86
86
|
end
|
87
|
+
|
88
|
+
def self._address_attributes
|
89
|
+
[:street_address, :extended_address, :locality, :region, :postal_code, :country_code_alpha2,
|
90
|
+
{:international_phone => [:country_code, :national_number]}]
|
91
|
+
end
|
87
92
|
end
|
88
93
|
end
|
89
94
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Braintree
|
2
|
+
class BankAccountInstantVerificationGateway
|
3
|
+
|
4
|
+
CREATE_JWT_MUTATION =
|
5
|
+
"mutation CreateBankAccountInstantVerificationJwt($input: CreateBankAccountInstantVerificationJwtInput!) { " +
|
6
|
+
" createBankAccountInstantVerificationJwt(input: $input) {" +
|
7
|
+
" jwt" +
|
8
|
+
" }" +
|
9
|
+
"}"
|
10
|
+
|
11
|
+
def initialize(gateway)
|
12
|
+
@gateway = gateway
|
13
|
+
@config = gateway.config
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_jwt(request)
|
17
|
+
variables = request.to_graphql_variables
|
18
|
+
response = @gateway.graphql_client.query(CREATE_JWT_MUTATION, variables)
|
19
|
+
errors = Braintree::GraphQLClient.get_validation_errors(response)
|
20
|
+
|
21
|
+
if errors
|
22
|
+
ErrorResult.new(@gateway, {errors: errors})
|
23
|
+
else
|
24
|
+
data = response.dig(:data, :createBankAccountInstantVerificationJwt)
|
25
|
+
|
26
|
+
if data.nil?
|
27
|
+
raise UnexpectedError, "expected :createBankAccountInstantVerificationJwt"
|
28
|
+
end
|
29
|
+
|
30
|
+
jwt_attrs = {
|
31
|
+
:jwt => data[:jwt]
|
32
|
+
}
|
33
|
+
|
34
|
+
SuccessfulResult.new(:bank_account_instant_verification_jwt => BankAccountInstantVerificationJwt._new(jwt_attrs))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Braintree
|
2
|
+
class BankAccountInstantVerificationJwt
|
3
|
+
include BaseModule
|
4
|
+
|
5
|
+
attr_reader :jwt
|
6
|
+
|
7
|
+
def initialize(attributes)
|
8
|
+
set_instance_variables_from_hash(attributes)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self._new(*args)
|
12
|
+
self.new(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def inspect
|
16
|
+
attr_order = [:jwt]
|
17
|
+
formatted_attrs = attr_order.map do |attr|
|
18
|
+
"#{attr}: #{send(attr).inspect}"
|
19
|
+
end
|
20
|
+
"#<#{self.class} #{formatted_attrs.join(', ')}>"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Braintree
|
2
|
+
class BankAccountInstantVerificationJwtRequest
|
3
|
+
include BaseModule
|
4
|
+
|
5
|
+
attr_accessor :business_name, :return_url, :cancel_url
|
6
|
+
|
7
|
+
def initialize(attributes = {})
|
8
|
+
set_instance_variables_from_hash(attributes)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_graphql_variables
|
12
|
+
variables = {:input => {}}
|
13
|
+
|
14
|
+
variables[:input][:businessName] = business_name if business_name
|
15
|
+
variables[:input][:returnUrl] = return_url if return_url
|
16
|
+
variables[:input][:cancelUrl] = cancel_url if cancel_url
|
17
|
+
|
18
|
+
variables
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/braintree/dispute.rb
CHANGED
@@ -459,6 +459,8 @@ module Braintree
|
|
459
459
|
TransactionIsNotEligibleForAdjustment = "915219"
|
460
460
|
TransactionMustBeInStateAuthorized = "915218"
|
461
461
|
TransactionSourceIsInvalid = "915133"
|
462
|
+
TransactionTransferDetailsAreMandatory = "97510"
|
463
|
+
TransactionTransferTypeIsInvalid = "97501"
|
462
464
|
TypeIsInvalid = "91523"
|
463
465
|
TypeIsRequired = "91524"
|
464
466
|
UnsupportedVoiceAuthorization = "91539"
|
data/lib/braintree/gateway.rb
CHANGED
@@ -23,6 +23,7 @@ module Braintree
|
|
23
23
|
attr_reader :subscription
|
24
24
|
attr_reader :supported_networks
|
25
25
|
attr_reader :transaction
|
26
|
+
attr_reader :bank_account_instant_verification_jwt
|
26
27
|
attr_reader :us_bank_account_verification
|
27
28
|
attr_reader :session_id
|
28
29
|
attr_reader :customer_recommendations
|
@@ -82,6 +82,8 @@ module Braintree
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
+
attr_reader :account_funding_transaction
|
86
|
+
attr_reader :ach_reject_reason
|
85
87
|
attr_reader :ach_return_code
|
86
88
|
attr_reader :ach_return_responses
|
87
89
|
attr_reader :acquirer_reference_number
|
@@ -171,6 +173,7 @@ module Braintree
|
|
171
173
|
attr_reader :tax_exempt
|
172
174
|
attr_reader :three_d_secure_info
|
173
175
|
attr_reader :type
|
176
|
+
attr_reader :upcoming_retry_date
|
174
177
|
attr_reader :updated_at
|
175
178
|
attr_reader :us_bank_account_details
|
176
179
|
attr_reader :venmo_account_details
|
@@ -280,6 +280,35 @@ module Braintree
|
|
280
280
|
:ds_transaction_id,
|
281
281
|
]
|
282
282
|
},
|
283
|
+
{
|
284
|
+
:transfer => [
|
285
|
+
:type,
|
286
|
+
{
|
287
|
+
:sender => [
|
288
|
+
:first_name,
|
289
|
+
:last_name,
|
290
|
+
:account_reference_number,
|
291
|
+
:tax_id,
|
292
|
+
{:address => AddressGateway._address_attributes}
|
293
|
+
]
|
294
|
+
},
|
295
|
+
{
|
296
|
+
:receiver => [
|
297
|
+
:first_name,
|
298
|
+
:last_name,
|
299
|
+
:account_reference_number,
|
300
|
+
:tax_id,
|
301
|
+
{:address => AddressGateway._address_attributes}
|
302
|
+
]
|
303
|
+
},
|
304
|
+
]
|
305
|
+
},
|
306
|
+
{
|
307
|
+
:us_bank_account => [
|
308
|
+
:ach_mandate_text,
|
309
|
+
:ach_mandate_accepted_at,
|
310
|
+
]
|
311
|
+
},
|
283
312
|
]
|
284
313
|
end
|
285
314
|
|
@@ -15,11 +15,12 @@ module Braintree
|
|
15
15
|
|
16
16
|
module VerificationMethod
|
17
17
|
IndependentCheck = "independent_check"
|
18
|
+
InstantVerificationAccountValidation = "instant_verification_account_validation"
|
18
19
|
NetworkCheck = "network_check"
|
19
20
|
TokenizedCheck = "tokenized_check"
|
20
21
|
MicroTransfers = "micro_transfers"
|
21
22
|
|
22
|
-
All = [IndependentCheck, NetworkCheck, TokenizedCheck, MicroTransfers]
|
23
|
+
All = [IndependentCheck, InstantVerificationAccountValidation, NetworkCheck, TokenizedCheck, MicroTransfers]
|
23
24
|
end
|
24
25
|
|
25
26
|
module VerificationAddOns
|
@@ -42,6 +43,7 @@ module Braintree
|
|
42
43
|
|
43
44
|
def initialize(attributes)
|
44
45
|
set_instance_variables_from_hash(attributes)
|
46
|
+
@us_bank_account = UsBankAccount._new(nil, attributes[:us_bank_account]) if attributes[:us_bank_account]
|
45
47
|
end
|
46
48
|
|
47
49
|
def inspect
|
data/lib/braintree/version.rb
CHANGED
@@ -57,6 +57,7 @@ module Braintree
|
|
57
57
|
SubscriptionWentPastDue = "subscription_went_past_due"
|
58
58
|
|
59
59
|
TransactionDisbursed = "transaction_disbursed"
|
60
|
+
TransactionRetried = "transaction_retried"
|
60
61
|
TransactionReviewed = "transaction_reviewed"
|
61
62
|
TransactionSettlementDeclined = "transaction_settlement_declined"
|
62
63
|
TransactionSettled = "transaction_settled"
|
@@ -60,6 +60,8 @@ module Braintree
|
|
60
60
|
_oauth_access_revoked_sample_xml(id)
|
61
61
|
when Braintree::WebhookNotification::Kind::TransactionDisbursed
|
62
62
|
_transaction_disbursed_sample_xml(id)
|
63
|
+
when Braintree::WebhookNotification::Kind::TransactionRetried
|
64
|
+
_transaction_retried_sample_xml(id)
|
63
65
|
when Braintree::WebhookNotification::Kind::TransactionReviewed
|
64
66
|
_transaction_reviewed_sample_xml(id)
|
65
67
|
when Braintree::WebhookNotification::Kind::TransactionSettled
|
@@ -269,6 +271,20 @@ module Braintree
|
|
269
271
|
XML
|
270
272
|
end
|
271
273
|
|
274
|
+
def _transaction_retried_sample_xml(id)
|
275
|
+
|
276
|
+
<<-XML
|
277
|
+
<transaction>
|
278
|
+
<id>#{id}</id>
|
279
|
+
<amount>100</amount>
|
280
|
+
<status>submitted_for_settlement</status>
|
281
|
+
<type>sale</type>
|
282
|
+
<currency-iso-code>USD</currency-iso-code>
|
283
|
+
<retried-transaction-id>original_txn_id</retried-transaction-id>
|
284
|
+
</transaction>
|
285
|
+
XML
|
286
|
+
end
|
287
|
+
|
272
288
|
def _transaction_reviewed_sample_xml(id)
|
273
289
|
|
274
290
|
<<-XML
|
data/lib/braintree.rb
CHANGED
@@ -35,6 +35,9 @@ require "braintree/apple_pay_card"
|
|
35
35
|
require "braintree/apple_pay_gateway"
|
36
36
|
require "braintree/apple_pay_options"
|
37
37
|
require "braintree/authorization_adjustment"
|
38
|
+
require "braintree/bank_account_instant_verification_gateway"
|
39
|
+
require "braintree/bank_account_instant_verification_jwt"
|
40
|
+
require "braintree/bank_account_instant_verification_jwt_request"
|
38
41
|
require "braintree/bin_data"
|
39
42
|
require "braintree/client_token"
|
40
43
|
require "braintree/client_token_gateway"
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/client_api/spec_helper")
|
3
|
+
|
4
|
+
describe Braintree::BankAccountInstantVerificationGateway do
|
5
|
+
before do
|
6
|
+
@gateway = Braintree::Gateway.new(
|
7
|
+
:environment => :development,
|
8
|
+
:merchant_id => "integration2_merchant_id",
|
9
|
+
:public_key => "integration2_public_key",
|
10
|
+
:private_key => "integration2_private_key",
|
11
|
+
)
|
12
|
+
|
13
|
+
@us_bank_gateway = Braintree::Gateway.new(
|
14
|
+
:environment => :development,
|
15
|
+
:merchant_id => "integration_merchant_id",
|
16
|
+
:public_key => "integration_public_key",
|
17
|
+
:private_key => "integration_private_key",
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "create_jwt" do
|
22
|
+
it "creates a jwt with valid request" do
|
23
|
+
request = Braintree::BankAccountInstantVerificationJwtRequest.new(
|
24
|
+
:business_name => "15Ladders",
|
25
|
+
:return_url => "https://example.com/success",
|
26
|
+
:cancel_url => "https://example.com/cancel",
|
27
|
+
)
|
28
|
+
|
29
|
+
result = @gateway.bank_account_instant_verification.create_jwt(request)
|
30
|
+
|
31
|
+
unless result.success?
|
32
|
+
puts "DEBUG: Result failed!"
|
33
|
+
puts "DEBUG: Errors: #{result.errors.inspect}" if result.respond_to?(:errors)
|
34
|
+
end
|
35
|
+
|
36
|
+
expect(result.success?).to eq(true)
|
37
|
+
expect(result.bank_account_instant_verification_jwt).to have_attributes(
|
38
|
+
jwt: a_string_matching(/.+/),
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "fails with invalid business name" do
|
43
|
+
request = Braintree::BankAccountInstantVerificationJwtRequest.new(
|
44
|
+
:business_name => "", # Empty business name should cause validation error
|
45
|
+
:return_url => "https://example.com/return",
|
46
|
+
:cancel_url => "https://example.com/cancel",
|
47
|
+
)
|
48
|
+
|
49
|
+
result = @gateway.bank_account_instant_verification.create_jwt(request)
|
50
|
+
|
51
|
+
expect(result.success?).to eq(false)
|
52
|
+
expect(result.errors).not_to be_nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it "fails with invalid URLs" do
|
56
|
+
request = Braintree::BankAccountInstantVerificationJwtRequest.new(
|
57
|
+
:business_name => "15Ladders",
|
58
|
+
:return_url => "not-a-valid-url",
|
59
|
+
:cancel_url => "also-not-valid",
|
60
|
+
)
|
61
|
+
|
62
|
+
result = @us_bank_gateway.bank_account_instant_verification.create_jwt(request)
|
63
|
+
|
64
|
+
expect(result.success?).to eq(false)
|
65
|
+
expect(result.errors).not_to be_nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "charge US bank with ACH mandate" do
|
70
|
+
it "creates transaction directly with nonce and provides ACH mandate at transaction time (instant verification)" do
|
71
|
+
nonce = generate_us_bank_account_nonce_via_open_banking
|
72
|
+
|
73
|
+
mandate_accepted_at = Time.now - 300 # 5 minutes ago
|
74
|
+
|
75
|
+
# Create transaction directly with nonce and provide ACH mandate at transaction time (instant verification)
|
76
|
+
transaction_request = {
|
77
|
+
:amount => "12.34",
|
78
|
+
:payment_method_nonce => nonce,
|
79
|
+
:merchant_account_id => SpecHelper::UsBankMerchantAccountId, # could it be?
|
80
|
+
:us_bank_account => {
|
81
|
+
:ach_mandate_text => "I authorize this transaction and future debits",
|
82
|
+
:ach_mandate_accepted_at => mandate_accepted_at
|
83
|
+
},
|
84
|
+
:options => {
|
85
|
+
:submit_for_settlement => true
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
transaction_result = @us_bank_gateway.transaction.sale(transaction_request)
|
90
|
+
|
91
|
+
expect(transaction_result.success?).to eq(true), "Expected transaction success but got failure with validation errors (see console output)"
|
92
|
+
transaction = transaction_result.transaction
|
93
|
+
|
94
|
+
expected_transaction = {
|
95
|
+
id: a_string_matching(/.+/),
|
96
|
+
amount: BigDecimal("12.34"),
|
97
|
+
us_bank_account_details: have_attributes(
|
98
|
+
ach_mandate: have_attributes(
|
99
|
+
text: "I authorize this transaction and future debits",
|
100
|
+
accepted_at: be_a(Time),
|
101
|
+
),
|
102
|
+
account_holder_name: "Dan Schulman",
|
103
|
+
last_4: "1234",
|
104
|
+
routing_number: "021000021",
|
105
|
+
account_type: "checking",
|
106
|
+
)
|
107
|
+
}
|
108
|
+
|
109
|
+
expect(transaction).to have_attributes(expected_transaction)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "Open Finance flow with INSTANT_VERIFICATION_ACCOUNT_VALIDATION" do
|
114
|
+
it "tokenizes bank account via Open Finance API, vaults with and charges" do
|
115
|
+
|
116
|
+
nonce = generate_us_bank_account_nonce_via_open_banking
|
117
|
+
|
118
|
+
customer_result = @us_bank_gateway.customer.create({})
|
119
|
+
expect(customer_result.success?).to eq(true)
|
120
|
+
customer = customer_result.customer
|
121
|
+
|
122
|
+
mandate_accepted_at = Time.now - 300
|
123
|
+
|
124
|
+
payment_method_request = {
|
125
|
+
:customer_id => customer.id,
|
126
|
+
:payment_method_nonce => nonce,
|
127
|
+
:us_bank_account => {
|
128
|
+
:ach_mandate_text => "I authorize this transaction and future debits",
|
129
|
+
:ach_mandate_accepted_at => mandate_accepted_at
|
130
|
+
},
|
131
|
+
:options => {
|
132
|
+
:verification_merchant_account_id => SpecHelper::UsBankMerchantAccountId,
|
133
|
+
:us_bank_account_verification_method => Braintree::UsBankAccountVerification::VerificationMethod::InstantVerificationAccountValidation
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
payment_method_result = @us_bank_gateway.payment_method.create(payment_method_request)
|
138
|
+
expect(payment_method_result.success?).to eq(true), "Expected payment method creation success but got failure with validation errors"
|
139
|
+
|
140
|
+
us_bank_account = payment_method_result.payment_method
|
141
|
+
|
142
|
+
expected_us_bank_account = {
|
143
|
+
verifications: a_collection_containing_exactly(
|
144
|
+
have_attributes(
|
145
|
+
verification_method: Braintree::UsBankAccountVerification::VerificationMethod::InstantVerificationAccountValidation,
|
146
|
+
status: "verified",
|
147
|
+
),
|
148
|
+
),
|
149
|
+
ach_mandate: have_attributes(
|
150
|
+
text: "I authorize this transaction and future debits",
|
151
|
+
accepted_at: be_a(Time),
|
152
|
+
)
|
153
|
+
}
|
154
|
+
|
155
|
+
expect(us_bank_account).to have_attributes(expected_us_bank_account)
|
156
|
+
|
157
|
+
verification = us_bank_account.verifications.first
|
158
|
+
expect(verification.verification_method).to eq(Braintree::UsBankAccountVerification::VerificationMethod::InstantVerificationAccountValidation)
|
159
|
+
|
160
|
+
transaction_request = {
|
161
|
+
:amount => "12.34",
|
162
|
+
:payment_method_token => us_bank_account.token,
|
163
|
+
:merchant_account_id => SpecHelper::UsBankMerchantAccountId,
|
164
|
+
:options => {
|
165
|
+
:submit_for_settlement => true
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
transaction_result = @us_bank_gateway.transaction.sale(transaction_request)
|
170
|
+
expect(transaction_result.success?).to eq(true), "Expected transaction success but got failure"
|
171
|
+
transaction = transaction_result.transaction
|
172
|
+
|
173
|
+
expected_transaction = {
|
174
|
+
id: a_string_matching(/.+/),
|
175
|
+
amount: BigDecimal("12.34"),
|
176
|
+
us_bank_account_details: have_attributes(
|
177
|
+
token: us_bank_account.token,
|
178
|
+
ach_mandate: have_attributes(
|
179
|
+
text: "I authorize this transaction and future debits",
|
180
|
+
accepted_at: be_a(Time),
|
181
|
+
),
|
182
|
+
last_4: "1234",
|
183
|
+
routing_number: "021000021",
|
184
|
+
account_type: "checking",
|
185
|
+
)
|
186
|
+
}
|
187
|
+
|
188
|
+
expect(transaction).to have_attributes(expected_transaction)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -147,6 +147,87 @@ def generate_invalid_us_bank_account_nonce
|
|
147
147
|
nonce + "_xxx"
|
148
148
|
end
|
149
149
|
|
150
|
+
def generate_us_bank_account_nonce_via_open_banking
|
151
|
+
|
152
|
+
config = Braintree::Configuration.new(
|
153
|
+
:environment => :development,
|
154
|
+
:merchant_id => "integration_merchant_id",
|
155
|
+
:public_key => "integration_public_key",
|
156
|
+
:private_key => "integration_private_key",
|
157
|
+
)
|
158
|
+
|
159
|
+
request_body = {
|
160
|
+
:account_details => {
|
161
|
+
:account_number => "567891234",
|
162
|
+
:account_type => "CHECKING",
|
163
|
+
:classification => "PERSONAL",
|
164
|
+
:tokenized_account => true,
|
165
|
+
:last_4 => "1234"
|
166
|
+
},
|
167
|
+
:institution_details => {
|
168
|
+
:bank_id => {
|
169
|
+
:bank_code => "021000021",
|
170
|
+
:country_code => "US"
|
171
|
+
}
|
172
|
+
},
|
173
|
+
:account_holders => [
|
174
|
+
{
|
175
|
+
:ownership => "PRIMARY",
|
176
|
+
:full_name => {
|
177
|
+
:name => "Dan Schulman"
|
178
|
+
},
|
179
|
+
:name => {
|
180
|
+
:given_name => "Dan",
|
181
|
+
:surname => "Schulman",
|
182
|
+
:full_name => "Dan Schulman"
|
183
|
+
}
|
184
|
+
}
|
185
|
+
]
|
186
|
+
}
|
187
|
+
|
188
|
+
graphql_base_url = config.graphql_base_url
|
189
|
+
atmosphere_base_url = graphql_base_url.gsub("/graphql", "")
|
190
|
+
url = "#{atmosphere_base_url}/v1/open-finance/tokenize-bank-account-details"
|
191
|
+
|
192
|
+
uri = URI.parse(url)
|
193
|
+
connection = Net::HTTP.new(uri.host, uri.port)
|
194
|
+
|
195
|
+
if uri.scheme == "https"
|
196
|
+
connection.use_ssl = true
|
197
|
+
connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
198
|
+
connection.ca_file = config.ca_file if config.ca_file
|
199
|
+
end
|
200
|
+
|
201
|
+
response = connection.start do |http|
|
202
|
+
request = Net::HTTP::Post.new(uri.path)
|
203
|
+
request["Content-Type"] = "application/json"
|
204
|
+
request["Accept"] = "application/json"
|
205
|
+
request["Braintree-Version"] = "2019-01-01"
|
206
|
+
request["User-Agent"] = "Braintree Ruby Library #{Braintree::Version::String}"
|
207
|
+
request["X-ApiVersion"] = config.api_version
|
208
|
+
|
209
|
+
# Basic auth like Node.js
|
210
|
+
auth_string = "#{config.public_key}:#{config.private_key}"
|
211
|
+
request["Authorization"] = "Basic #{Base64.strict_encode64(auth_string)}"
|
212
|
+
|
213
|
+
request.body = request_body.to_json
|
214
|
+
|
215
|
+
http.request(request)
|
216
|
+
end
|
217
|
+
|
218
|
+
if response.code.to_i != 200
|
219
|
+
raise "HTTP #{response.code}: #{response.body}"
|
220
|
+
end
|
221
|
+
|
222
|
+
result = JSON.parse(response.body)
|
223
|
+
|
224
|
+
unless result["tenant_token"]
|
225
|
+
raise "Open Banking tokenization failed: #{result.inspect}"
|
226
|
+
end
|
227
|
+
|
228
|
+
result["tenant_token"]
|
229
|
+
end
|
230
|
+
|
150
231
|
def _cosmos_post(token, url, payload)
|
151
232
|
uri = URI::parse(url)
|
152
233
|
connection = Net::HTTP.new(uri.host, uri.port)
|
@@ -32,8 +32,8 @@ describe Braintree::Dispute do
|
|
32
32
|
|
33
33
|
expect(result.success?).to eq(true)
|
34
34
|
|
35
|
-
|
36
|
-
expect(
|
35
|
+
updated_dispute = Braintree::Dispute.find(dispute.id)
|
36
|
+
expect(updated_dispute.status).to eq(Braintree::Dispute::Status::Accepted)
|
37
37
|
|
38
38
|
dispute_from_transaction = Braintree::Transaction.find(dispute.transaction.id).disputes[0]
|
39
39
|
expect(dispute_from_transaction.status).to eq(Braintree::Dispute::Status::Accepted)
|
@@ -99,6 +99,17 @@ describe Braintree::Dispute do
|
|
99
99
|
expect(result.evidence.category).to eq("GENERAL")
|
100
100
|
expect(result.evidence.url).to include("bt_logo.png")
|
101
101
|
end
|
102
|
+
|
103
|
+
it "reflects the updated remaining_file_evidence_storage" do
|
104
|
+
initial_storage = dispute.remaining_file_evidence_storage
|
105
|
+
expect(initial_storage).not_to be_nil
|
106
|
+
|
107
|
+
Braintree::Dispute.add_file_evidence(dispute.id, document_upload.id)
|
108
|
+
|
109
|
+
refreshed_dispute = Braintree::Dispute.find(dispute.id)
|
110
|
+
updated_storage = refreshed_dispute.remaining_file_evidence_storage
|
111
|
+
expect(updated_storage).to be < initial_storage
|
112
|
+
end
|
102
113
|
end
|
103
114
|
|
104
115
|
describe "self.add_text_evidence" do
|
@@ -108,6 +108,7 @@ describe Braintree::PaymentMethod do
|
|
108
108
|
expect(apple_pay_card.payroll).not_to be_nil
|
109
109
|
expect(apple_pay_card.prepaid).not_to be_nil
|
110
110
|
expect(apple_pay_card.product_id).not_to be_nil
|
111
|
+
expect(apple_pay_card.is_device_token).to eq(true)
|
111
112
|
end
|
112
113
|
|
113
114
|
it "creates a payment method from a fake apple pay mpan nonce" do
|
@@ -143,6 +144,7 @@ describe Braintree::PaymentMethod do
|
|
143
144
|
expect(apple_pay_card.prepaid).not_to be_nil
|
144
145
|
expect(apple_pay_card.product_id).not_to be_nil
|
145
146
|
expect(apple_pay_card.merchant_token_identifier).not_to be_nil
|
147
|
+
expect(apple_pay_card.is_device_token).not_to be_nil
|
146
148
|
expect(apple_pay_card.source_card_last4).not_to be_nil
|
147
149
|
end
|
148
150
|
|
@@ -1254,6 +1256,7 @@ describe Braintree::PaymentMethod do
|
|
1254
1256
|
expect(apple_pay_card.expiration_year.to_i).to be > 0
|
1255
1257
|
expect(apple_pay_card.source_description).to eq("Visa 2006")
|
1256
1258
|
expect(apple_pay_card.customer_id).to eq(customer.id)
|
1259
|
+
expect(apple_pay_card.is_device_token).to eq(false)
|
1257
1260
|
apple_pay_card.merchant_token_identifier == "DNITHE302308980427388297"
|
1258
1261
|
apple_pay_card.source_card_last4 == "2006"
|
1259
1262
|
end
|