braintree 4.30.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/lib/braintree/address_gateway.rb +5 -0
  3. data/lib/braintree/apple_pay_card.rb +1 -0
  4. data/lib/braintree/bank_account_instant_verification_gateway.rb +38 -0
  5. data/lib/braintree/bank_account_instant_verification_jwt.rb +23 -0
  6. data/lib/braintree/bank_account_instant_verification_jwt_request.rb +21 -0
  7. data/lib/braintree/error_codes.rb +2 -0
  8. data/lib/braintree/gateway.rb +4 -0
  9. data/lib/braintree/payment_method_gateway.rb +6 -0
  10. data/lib/braintree/successful_result.rb +1 -0
  11. data/lib/braintree/transaction/apple_pay_details.rb +1 -0
  12. data/lib/braintree/transaction.rb +1 -0
  13. data/lib/braintree/transaction_gateway.rb +24 -0
  14. data/lib/braintree/us_bank_account_verification.rb +3 -1
  15. data/lib/braintree/version.rb +1 -1
  16. data/lib/braintree.rb +3 -0
  17. data/spec/integration/braintree/bank_account_instant_verification_spec.rb +191 -0
  18. data/spec/integration/braintree/client_api/spec_helper.rb +81 -0
  19. data/spec/integration/braintree/payment_method_spec.rb +3 -0
  20. data/spec/integration/braintree/transaction_search_spec.rb +26 -24
  21. data/spec/integration/braintree/transaction_spec.rb +34 -3
  22. data/spec/integration/braintree/transaction_transfer_type_spec.rb +255 -0
  23. data/spec/spec_helper.rb +7 -0
  24. data/spec/unit/braintree/apple_pay_card_spec.rb +2 -0
  25. data/spec/unit/braintree/bank_account_instant_verification_gateway_spec.rb +98 -0
  26. data/spec/unit/braintree/bank_account_instant_verification_jwt_request_spec.rb +71 -0
  27. data/spec/unit/braintree/transaction_ach_mandate_spec.rb +82 -0
  28. data/spec/unit/braintree/transaction_gateway_spec.rb +20 -0
  29. data/spec/unit/braintree/transaction_spec.rb +10 -0
  30. metadata +13 -7
  31. data/lib/ssl/securetrust_ca.crt +0 -44
@@ -2214,6 +2214,37 @@ describe Braintree::Transaction do
2214
2214
  expect(apple_pay_details.commercial).not_to be_nil
2215
2215
  expect(apple_pay_details.payroll).not_to be_nil
2216
2216
  expect(apple_pay_details.product_id).not_to be_nil
2217
+ expect(apple_pay_details.is_device_token).to eq(true)
2218
+ end
2219
+
2220
+ it "can create a transaction with a fake apple pay mpan nonce" do
2221
+ result = Braintree::Transaction.create(
2222
+ :type => "sale",
2223
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
2224
+ :payment_method_nonce => Braintree::Test::Nonce::ApplePayMpan,
2225
+ )
2226
+ expect(result.success?).to eq(true)
2227
+ expect(result.transaction).not_to be_nil
2228
+ apple_pay_details = result.transaction.apple_pay_details
2229
+ expect(apple_pay_details).not_to be_nil
2230
+ expect(apple_pay_details.bin).not_to be_nil
2231
+ expect(apple_pay_details.card_type).to eq(Braintree::ApplePayCard::CardType::Visa)
2232
+ expect(apple_pay_details.payment_instrument_name).to eq("Visa 2006")
2233
+ expect(apple_pay_details.source_description).to eq("Visa 2006")
2234
+ expect(apple_pay_details.expiration_month.to_i).to be > 0
2235
+ expect(apple_pay_details.expiration_year.to_i).to be > 0
2236
+ expect(apple_pay_details.cardholder_name).not_to be_nil
2237
+ expect(apple_pay_details.image_url).not_to be_nil
2238
+ expect(apple_pay_details.token).to be_nil
2239
+ expect(apple_pay_details.prepaid).not_to be_nil
2240
+ expect(apple_pay_details.healthcare).not_to be_nil
2241
+ expect(apple_pay_details.debit).not_to be_nil
2242
+ expect(apple_pay_details.durbin_regulated).not_to be_nil
2243
+ expect(apple_pay_details.commercial).not_to be_nil
2244
+ expect(apple_pay_details.payroll).not_to be_nil
2245
+ expect(apple_pay_details.product_id).not_to be_nil
2246
+ expect(apple_pay_details.merchant_token_identifier).not_to be_nil
2247
+ expect(apple_pay_details.is_device_token).to eq(false)
2217
2248
  end
2218
2249
 
2219
2250
  it "can create a vaulted transaction with a fake apple pay nonce" do
@@ -2304,9 +2335,9 @@ describe Braintree::Transaction do
2304
2335
  expect(google_pay_details).not_to be_nil
2305
2336
  expect(google_pay_details.card_type).to eq(Braintree::CreditCard::CardType::MasterCard)
2306
2337
  expect(google_pay_details.virtual_card_type).to eq(Braintree::CreditCard::CardType::MasterCard)
2307
- expect(google_pay_details.last_4).to eq("4444")
2308
- expect(google_pay_details.virtual_card_last_4).to eq("4444")
2309
- expect(google_pay_details.source_description).to eq("MasterCard 4444")
2338
+ expect(google_pay_details.last_4).to eq("0005")
2339
+ expect(google_pay_details.virtual_card_last_4).to eq("0005")
2340
+ expect(google_pay_details.source_description).to eq("MasterCard 0005")
2310
2341
  expect(google_pay_details.expiration_month.to_i).to be > 0
2311
2342
  expect(google_pay_details.expiration_year.to_i).to be > 0
2312
2343
  expect(google_pay_details.google_transaction_id).to eq("google_transaction_id")
@@ -42,5 +42,260 @@ describe Braintree::Transaction do
42
42
  result = Braintree::Transaction.sale(transaction_params)
43
43
  expect(result.success?).to eq(false)
44
44
  end
45
+
46
+ it "should create a transaction with valid transfer types and merchant account id" do
47
+ SpecHelper::SdwoSupportedTransferTypes.each do |transfer_type|
48
+ transaction_params = {
49
+ :type => "sale",
50
+ :amount => "100.00",
51
+ :merchant_account_id => "card_processor_brl_sdwo",
52
+ :credit_card => {
53
+ :number => "4111111111111111",
54
+ :expiration_date => "06/2026",
55
+ :cvv => "123"
56
+ },
57
+ :descriptor => {
58
+ :name => "companynme12*product1",
59
+ :phone => "1232344444",
60
+ :url => "example.com",
61
+ },
62
+ :billing => {
63
+ :first_name => "Bob James",
64
+ :country_code_alpha2 => "CA",
65
+ :extended_address => "",
66
+ :locality => "Trois-Rivires",
67
+ :region => "QC",
68
+ :postal_code => "G8Y 156",
69
+ :street_address => "2346 Boul Lane",
70
+ },
71
+ :transfer => {
72
+ :type => transfer_type,
73
+ :sender => {
74
+ :first_name => "Alice",
75
+ :last_name => "Silva",
76
+ :account_reference_number => "1000012345",
77
+ :tax_id => "12345678900",
78
+ :address => {
79
+ :street_address => "Rua das Flores, 100",
80
+ :extended_address => "2B",
81
+ :locality => "São Paulo",
82
+ :region => "SP",
83
+ :postal_code => "01001-000",
84
+ :country_code_alpha2 => "BR",
85
+ :international_phone => {
86
+ :country_code => "55",
87
+ :national_number => "1234567890"
88
+ }
89
+ }
90
+ },
91
+ :receiver => {
92
+ :first_name => "Bob",
93
+ :last_name => "Souza",
94
+ :account_reference_number => "2000012345",
95
+ :tax_id => "98765432100",
96
+ :address => {
97
+ :street_address => "Avenida Brasil, 200",
98
+ :extended_address => "2B",
99
+ :locality => "Rio de Janeiro",
100
+ :region => "RJ",
101
+ :postal_code => "20040-002",
102
+ :country_code_alpha2 => "BR",
103
+ :international_phone => {
104
+ :country_code => "55",
105
+ :national_number => "9876543210"
106
+ }
107
+ }
108
+ }
109
+ },
110
+ :options => {
111
+ :store_in_vault_on_success => true,
112
+ }
113
+ }
114
+
115
+ result = Braintree::Transaction.sale(transaction_params)
116
+ expect(result.success?).to eq(true)
117
+ expect(result.transaction.status).to eq(Braintree::Transaction::Status::Authorized)
118
+ end
119
+ end
120
+
121
+ it "should fail when transfer details are not provided" do
122
+ transaction_params = {
123
+ :type => "sale",
124
+ :amount => "100.00",
125
+ :merchant_account_id => "card_processor_brl_sdwo",
126
+ :credit_card => {
127
+ :number => "4111111111111111",
128
+ :expiration_date => "06/2026",
129
+ :cvv => "123"
130
+ },
131
+ :descriptor => {
132
+ :name => "companynme12*product1",
133
+ :phone => "1232344444",
134
+ :url => "example.com",
135
+ },
136
+ :billing => {
137
+ :first_name => "Bob James",
138
+ :country_code_alpha2 => "CA",
139
+ :extended_address => "",
140
+ :locality => "Trois-Rivires",
141
+ :region => "QC",
142
+ :postal_code => "G8Y 156",
143
+ :street_address => "2346 Boul Lane",
144
+ },
145
+ :options => {
146
+ :store_in_vault_on_success => true,
147
+ }
148
+ }
149
+
150
+ result = Braintree::Transaction.sale(transaction_params)
151
+ expect(result.success?).to eq(false)
152
+ expect(result.errors.for(:transaction).first.code).to eq(Braintree::ErrorCodes::Transaction::TransactionTransferDetailsAreMandatory)
153
+ end
154
+
155
+ it "should fail on transaction with invalid transfer type" do
156
+ transaction_params = {
157
+ :type => "sale",
158
+ :amount => "100.00",
159
+ :merchant_account_id => "card_processor_brl_sdwo",
160
+ :credit_card => {
161
+ :number => "4111111111111111",
162
+ :expiration_date => "06/2026",
163
+ :cvv => "123"
164
+ },
165
+ :descriptor => {
166
+ :name => "companynme12*product1",
167
+ :phone => "1232344444",
168
+ :url => "example.com",
169
+ },
170
+ :billing => {
171
+ :first_name => "Bob James",
172
+ :country_code_alpha2 => "CA",
173
+ :extended_address => "",
174
+ :locality => "Trois-Rivires",
175
+ :region => "QC",
176
+ :postal_code => "G8Y 156",
177
+ :street_address => "2346 Boul Lane",
178
+ },
179
+ :transfer => {
180
+ :type => "invalid_transfer_type",
181
+ :sender => {
182
+ :first_name => "Alice",
183
+ :last_name => "Silva",
184
+ :account_reference_number => "1000012345",
185
+ :tax_id => "12345678900",
186
+ :address => {
187
+ :street_address => "Rua das Flores, 100",
188
+ :extended_address => "2B",
189
+ :locality => "São Paulo",
190
+ :region => "SP",
191
+ :postal_code => "01001-000",
192
+ :country_code_alpha2 => "BR",
193
+ :international_phone => {
194
+ :country_code => "55",
195
+ :national_number => "1234567890"
196
+ }
197
+ }
198
+ },
199
+ :receiver => {
200
+ :first_name => "Bob",
201
+ :last_name => "Souza",
202
+ :account_reference_number => "2000012345",
203
+ :tax_id => "98765432100",
204
+ :address => {
205
+ :street_address => "Avenida Brasil, 200",
206
+ :extended_address => "2B",
207
+ :locality => "Rio de Janeiro",
208
+ :region => "RJ",
209
+ :postal_code => "20040-002",
210
+ :country_code_alpha2 => "BR",
211
+ :international_phone => {
212
+ :country_code => "55",
213
+ :national_number => "9876543210"
214
+ }
215
+ }
216
+ }
217
+ },
218
+ :options => {
219
+ :store_in_vault_on_success => true,
220
+ }
221
+ }
222
+
223
+ result = Braintree::Transaction.sale(transaction_params)
224
+ expect(result.success?).to eq(false)
225
+ expect(result.errors.for(:account_funding_transaction).first.code).to eq(Braintree::ErrorCodes::Transaction::TransactionTransferTypeIsInvalid)
226
+ end
227
+
228
+ it "should create a transaction when transfer type is nil" do
229
+ transaction_params = {
230
+ :type => "sale",
231
+ :amount => "100.00",
232
+ :merchant_account_id => "card_processor_brl_sdwo",
233
+ :credit_card => {
234
+ :number => "4111111111111111",
235
+ :expiration_date => "06/2026",
236
+ :cvv => "123"
237
+ },
238
+ :descriptor => {
239
+ :name => "companynme12*product1",
240
+ :phone => "1232344444",
241
+ :url => "example.com",
242
+ },
243
+ :billing => {
244
+ :first_name => "Bob James",
245
+ :country_code_alpha2 => "CA",
246
+ :extended_address => "",
247
+ :locality => "Trois-Rivires",
248
+ :region => "QC",
249
+ :postal_code => "G8Y 156",
250
+ :street_address => "2346 Boul Lane",
251
+ },
252
+ :transfer => {
253
+ :type => nil,
254
+ :sender => {
255
+ :first_name => "Alice",
256
+ :last_name => "Silva",
257
+ :account_reference_number => "1000012345",
258
+ :tax_id => "12345678900",
259
+ :address => {
260
+ :street_address => "Rua das Flores, 100",
261
+ :extended_address => "2B",
262
+ :locality => "São Paulo",
263
+ :region => "SP",
264
+ :postal_code => "01001-000",
265
+ :country_code_alpha2 => "BR",
266
+ :international_phone => {
267
+ :country_code => "55",
268
+ :national_number => "1234567890"
269
+ }
270
+ }
271
+ },
272
+ :receiver => {
273
+ :first_name => "Bob",
274
+ :last_name => "Souza",
275
+ :account_reference_number => "2000012345",
276
+ :tax_id => "98765432100",
277
+ :address => {
278
+ :street_address => "Avenida Brasil, 200",
279
+ :extended_address => "2B",
280
+ :locality => "Rio de Janeiro",
281
+ :region => "RJ",
282
+ :postal_code => "20040-002",
283
+ :country_code_alpha2 => "BR",
284
+ :international_phone => {
285
+ :country_code => "55",
286
+ :national_number => "9876543210"
287
+ }
288
+ }
289
+ }
290
+ },
291
+ :options => {
292
+ :store_in_vault_on_success => true,
293
+ }
294
+ }
295
+
296
+ result = Braintree::Transaction.sale(transaction_params)
297
+ expect(result.success?).to eq(true)
298
+ expect(result.transaction.status).to eq(Braintree::Transaction::Status::Authorized)
299
+ end
45
300
  end
46
301
  end
data/spec/spec_helper.rb CHANGED
@@ -77,6 +77,13 @@ unless defined?(SPEC_HELPER_LOADED)
77
77
  :billing_day_of_month => 5
78
78
  }
79
79
 
80
+ SdwoSupportedTransferTypes = [
81
+ "account_to_account",
82
+ "boleto_ticket",
83
+ "person_to_person",
84
+ "wallet_transfer"
85
+ ]
86
+
80
87
  AddOnIncrease10 = "increase_10"
81
88
  AddOnIncrease20 = "increase_20"
82
89
  AddOnIncrease30 = "increase_30"
@@ -36,6 +36,7 @@ describe Braintree::ApplePayCard do
36
36
  :expired => false,
37
37
  :healthcare => "No",
38
38
  :image_url => nil,
39
+ :is_device_token => false,
39
40
  :issuing_bank => "Big Bad Bank",
40
41
  :last_4 => "9876",
41
42
  :merchant_token_identifier => "merchant-token-123",
@@ -93,6 +94,7 @@ describe Braintree::ApplePayCard do
93
94
  card = Braintree::ApplePayCard._new(:gateway, attributes)
94
95
 
95
96
  expect(card.merchant_token_identifier).to_not be_nil
97
+ expect(card.is_device_token).to_not be_nil
96
98
  expect(card.source_card_last4).to_not be_nil
97
99
  end
98
100
  end
@@ -0,0 +1,98 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Braintree::BankAccountInstantVerificationGateway do
4
+ let(:gateway) { double("gateway") }
5
+ let(:config) { double("config") }
6
+ let(:graphql_client) { double("graphql_client") }
7
+ let(:bank_account_instant_verification_gateway) { Braintree::BankAccountInstantVerificationGateway.new(gateway) }
8
+
9
+ before do
10
+ allow(gateway).to receive(:config).and_return(config)
11
+ allow(gateway).to receive(:graphql_client).and_return(graphql_client)
12
+ end
13
+
14
+ describe "create_jwt" do
15
+ let(:request) do
16
+ Braintree::BankAccountInstantVerificationJwtRequest.new(
17
+ :business_name => "Test Business",
18
+ :return_url => "https://example.com/success",
19
+ :cancel_url => "https://example.com/cancel",
20
+ )
21
+ end
22
+
23
+ it "returns success result with valid response" do
24
+ mock_response = {
25
+ :data => {
26
+ :createBankAccountInstantVerificationJwt => {
27
+ :jwt => "test-jwt-token"
28
+ }
29
+ }
30
+ }
31
+
32
+ allow(graphql_client).to receive(:query).and_return(mock_response)
33
+
34
+ result = bank_account_instant_verification_gateway.create_jwt(request)
35
+
36
+ expect(result.success?).to eq(true)
37
+ expect(result.bank_account_instant_verification_jwt).not_to be_nil
38
+ expect(result.bank_account_instant_verification_jwt.jwt).to eq("test-jwt-token")
39
+ end
40
+
41
+ it "returns error result with validation errors" do
42
+ mock_response = {
43
+ :errors => [
44
+ {
45
+ :message => "Validation error",
46
+ :extensions => {}
47
+ }
48
+ ]
49
+ }
50
+
51
+ allow(graphql_client).to receive(:query).and_return(mock_response)
52
+
53
+ result = bank_account_instant_verification_gateway.create_jwt(request)
54
+
55
+ expect(result.success?).to eq(false)
56
+ expect(result.errors).not_to be_nil
57
+ end
58
+
59
+ it "calls GraphQL client with correct mutation" do
60
+ mock_response = {
61
+ :data => {
62
+ :createBankAccountInstantVerificationJwt => {
63
+ :jwt => "test-jwt-token"
64
+ }
65
+ }
66
+ }
67
+
68
+ expect(graphql_client).to receive(:query).with(
69
+ /mutation CreateBankAccountInstantVerificationJwt/,
70
+ {:input=>{:businessName=>"Test Business", :cancelUrl=>"https://example.com/cancel", :returnUrl=>"https://example.com/success"}},
71
+ ).and_return(mock_response)
72
+
73
+ bank_account_instant_verification_gateway.create_jwt(request)
74
+ end
75
+
76
+ it "works with minimal request" do
77
+ minimal_request = Braintree::BankAccountInstantVerificationJwtRequest.new(
78
+ :business_name => "Test Business",
79
+ :return_url => "https://example.com/success",
80
+ )
81
+
82
+ mock_response = {
83
+ :data => {
84
+ :createBankAccountInstantVerificationJwt => {
85
+ :jwt => "test-jwt-token"
86
+ }
87
+ }
88
+ }
89
+
90
+ allow(graphql_client).to receive(:query).and_return(mock_response)
91
+
92
+ result = bank_account_instant_verification_gateway.create_jwt(minimal_request)
93
+
94
+ expect(result.success?).to eq(true)
95
+ expect(result.bank_account_instant_verification_jwt.jwt).to eq("test-jwt-token")
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,71 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Braintree::BankAccountInstantVerificationJwtRequest do
4
+ describe "to_graphql_variables" do
5
+ it "includes all fields when present" do
6
+ request = Braintree::BankAccountInstantVerificationJwtRequest.new(
7
+ :business_name => "Test Business",
8
+ :return_url => "https://example.com/success",
9
+ :cancel_url => "https://example.com/cancel",
10
+ )
11
+
12
+ variables = request.to_graphql_variables
13
+
14
+ expect(variables).not_to be_nil
15
+ expect(variables).to have_key(:input)
16
+
17
+ input = variables[:input]
18
+
19
+ expect(input[:businessName]).to eq("Test Business")
20
+ expect(input[:returnUrl]).to eq("https://example.com/success")
21
+ expect(input[:cancelUrl]).to eq("https://example.com/cancel")
22
+ end
23
+
24
+ it "only includes non-null fields" do
25
+ request = Braintree::BankAccountInstantVerificationJwtRequest.new(
26
+ :business_name => "Test Business",
27
+ :return_url => "https://example.com/success",
28
+ )
29
+
30
+ variables = request.to_graphql_variables
31
+
32
+ input = variables[:input]
33
+
34
+ expect(input[:businessName]).to eq("Test Business")
35
+ expect(input[:returnUrl]).to eq("https://example.com/success")
36
+ expect(input).not_to have_key(:cancelUrl)
37
+ end
38
+
39
+ it "handles empty request" do
40
+ request = Braintree::BankAccountInstantVerificationJwtRequest.new
41
+
42
+ variables = request.to_graphql_variables
43
+
44
+ expect(variables).to eq({:input => {}})
45
+ end
46
+ end
47
+
48
+ describe "attribute accessors" do
49
+ it "allows setting and getting all attributes and initializes with hash of attributes" do
50
+ request = Braintree::BankAccountInstantVerificationJwtRequest.new(
51
+ :business_name => "Test Business",
52
+ :return_url => "https://example.com/success",
53
+ :cancel_url => "https://example.com/cancel",
54
+ )
55
+
56
+ expect(request.business_name).to eq("Test Business")
57
+ expect(request.return_url).to eq("https://example.com/success")
58
+ expect(request.cancel_url).to eq("https://example.com/cancel")
59
+
60
+ new_request = Braintree::BankAccountInstantVerificationJwtRequest.new
61
+
62
+ new_request.business_name = "Updated Business"
63
+ new_request.return_url = "https://example.com/updated"
64
+ new_request.cancel_url = "https://example.com/updated-cancel"
65
+
66
+ expect(new_request.business_name).to eq("Updated Business")
67
+ expect(new_request.return_url).to eq("https://example.com/updated")
68
+ expect(new_request.cancel_url).to eq("https://example.com/updated-cancel")
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe "Transaction ACH Mandate" do
4
+ describe "transaction request handling" do
5
+ let(:gateway) { Braintree::Gateway.new(:environment => :sandbox, :merchant_id => "test", :public_key => "test", :private_key => "test") }
6
+ let(:transaction_gateway) { gateway.transaction }
7
+
8
+ it "processes us_bank_account ACH mandate fields" do
9
+ mandate_time = Time.now
10
+
11
+ # Mock the HTTP response for transaction creation
12
+ allow(gateway.config.http).to receive(:post).and_return({
13
+ :transaction => {
14
+ :id => "test_transaction_id",
15
+ :amount => "100.00",
16
+ :status => "authorized",
17
+ :us_bank_account => {
18
+ :token => "test_token",
19
+ :ach_mandate => {
20
+ :text => "I authorize this ACH debit",
21
+ :accepted_at => mandate_time.iso8601
22
+ }
23
+ }
24
+ }
25
+ })
26
+
27
+ transaction_attributes = {
28
+ :amount => "100.00",
29
+ :payment_method_token => "test_token",
30
+ :us_bank_account => {
31
+ :ach_mandate_text => "I authorize this ACH debit",
32
+ :ach_mandate_accepted_at => mandate_time
33
+ }
34
+ }
35
+
36
+ # This should not raise an error due to signature validation
37
+ expect {
38
+ Braintree::Util.verify_keys(Braintree::TransactionGateway._create_signature, transaction_attributes)
39
+ }.not_to raise_error
40
+ end
41
+
42
+ it "allows ACH mandate text only" do
43
+ transaction_attributes = {
44
+ :amount => "50.00",
45
+ :payment_method_token => "test_token",
46
+ :us_bank_account => {
47
+ :ach_mandate_text => "I authorize this ACH debit"
48
+ }
49
+ }
50
+
51
+ expect {
52
+ Braintree::Util.verify_keys(Braintree::TransactionGateway._create_signature, transaction_attributes)
53
+ }.not_to raise_error
54
+ end
55
+
56
+ it "allows ACH mandate accepted_at only" do
57
+ transaction_attributes = {
58
+ :amount => "50.00",
59
+ :payment_method_token => "test_token",
60
+ :us_bank_account => {
61
+ :ach_mandate_accepted_at => Time.now
62
+ }
63
+ }
64
+
65
+ expect {
66
+ Braintree::Util.verify_keys(Braintree::TransactionGateway._create_signature, transaction_attributes)
67
+ }.not_to raise_error
68
+ end
69
+
70
+ it "allows empty us_bank_account hash" do
71
+ transaction_attributes = {
72
+ :amount => "50.00",
73
+ :payment_method_token => "test_token",
74
+ :us_bank_account => {}
75
+ }
76
+
77
+ expect {
78
+ Braintree::Util.verify_keys(Braintree::TransactionGateway._create_signature, transaction_attributes)
79
+ }.not_to raise_error
80
+ end
81
+ end
82
+ end
@@ -132,6 +132,26 @@ describe Braintree::TransactionGateway do
132
132
  {
133
133
  :transfer => [
134
134
  :type,
135
+ {:sender => [
136
+ :first_name,
137
+ :last_name,
138
+ :account_reference_number,
139
+ :tax_id,
140
+ :address => Braintree::AddressGateway._address_attributes
141
+ ]},
142
+ {:receiver => [
143
+ :first_name,
144
+ :last_name,
145
+ :account_reference_number,
146
+ :tax_id,
147
+ :address => Braintree::AddressGateway._address_attributes
148
+ ]},
149
+ ]
150
+ },
151
+ {
152
+ :us_bank_account => [
153
+ :ach_mandate_text,
154
+ :ach_mandate_accepted_at,
135
155
  ]
136
156
  },
137
157
  ])
@@ -317,6 +317,16 @@ describe Braintree::Transaction do
317
317
  expect(transaction.ach_return_code).to eq("R01")
318
318
  end
319
319
 
320
+ it "accepts ach_reject_reason" do
321
+ transaction = Braintree::Transaction._new(
322
+ :gateway,
323
+ :ach_return_code => "RJCT",
324
+ :ach_reject_reason => "some reject reason",
325
+ )
326
+ expect(transaction.ach_return_code).to eq("RJCT")
327
+ expect(transaction.ach_reject_reason).to eq("some reject reason")
328
+ end
329
+
320
330
  it "accepts network_response code and network_response_text" do
321
331
  transaction = Braintree::Transaction._new(
322
332
  :gateway,