braintree 4.40.0 → 4.42.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/client_token_gateway.rb +10 -1
- data/lib/braintree/credit_card_gateway.rb +9 -3
- data/lib/braintree/credit_card_verification_gateway.rb +3 -0
- data/lib/braintree/customer_gateway.rb +11 -3
- data/lib/braintree/error_codes.rb +12 -0
- data/lib/braintree/http.rb +4 -2
- data/lib/braintree/merchant_account_gateway.rb +2 -0
- data/lib/braintree/payment_method_gateway.rb +6 -1
- data/lib/braintree/payment_method_nonce_gateway.rb +4 -0
- data/lib/braintree/paypal_account_gateway.rb +6 -1
- data/lib/braintree/plan_gateway.rb +4 -0
- data/lib/braintree/sepa_direct_debit_account_gateway.rb +4 -0
- data/lib/braintree/subscription_gateway.rb +6 -0
- data/lib/braintree/testing_gateway.rb +4 -0
- data/lib/braintree/transaction.rb +14 -0
- data/lib/braintree/transaction_gateway.rb +39 -7
- data/lib/braintree/transaction_line_item_gateway.rb +3 -1
- data/lib/braintree/transaction_search.rb +1 -0
- data/lib/braintree/us_bank_account_gateway.rb +2 -0
- data/lib/braintree/us_bank_account_verification_gateway.rb +4 -0
- data/lib/braintree/version.rb +1 -1
- data/spec/integration/braintree/apple_pay_spec.rb +3 -1
- data/spec/integration/braintree/client_api/client_token_spec.rb +14 -0
- data/spec/integration/braintree/credit_card_spec.rb +31 -0
- data/spec/integration/braintree/credit_card_verification_spec.rb +54 -0
- data/spec/integration/braintree/customer_spec.rb +58 -0
- data/spec/integration/braintree/transaction_idempotency_spec.rb +30 -0
- data/spec/integration/braintree/transaction_search_spec.rb +95 -0
- data/spec/integration/braintree/transaction_spec.rb +211 -1
- data/spec/unit/braintree/client_token_spec.rb +72 -0
- data/spec/unit/braintree/credit_card_spec.rb +28 -2
- data/spec/unit/braintree/credit_card_verification_gateway_spec.rb +1 -0
- data/spec/unit/braintree/credit_card_verification_spec.rb +8 -0
- data/spec/unit/braintree/customer_spec.rb +28 -2
- data/spec/unit/braintree/http_spec.rb +44 -0
- data/spec/unit/braintree/merchant_account_spec.rb +11 -0
- data/spec/unit/braintree/package_tracking_spec.rb +2 -2
- data/spec/unit/braintree/payment_method_nonce_spec.rb +14 -0
- data/spec/unit/braintree/payment_method_spec.rb +20 -0
- data/spec/unit/braintree/paypal_account_spec.rb +20 -0
- data/spec/unit/braintree/plan_gateway_spec.rb +30 -0
- data/spec/unit/braintree/sepa_debit_account_spec.rb +14 -0
- data/spec/unit/braintree/subscription_spec.rb +20 -0
- data/spec/unit/braintree/test_transaction_spec.rb +18 -0
- data/spec/unit/braintree/transaction_gateway_spec.rb +24 -0
- data/spec/unit/braintree/transaction_line_item_spec.rb +11 -0
- data/spec/unit/braintree/transaction_search_spec.rb +25 -0
- data/spec/unit/braintree/transaction_spec.rb +68 -6
- data/spec/unit/braintree/us_bank_account_spec.rb +8 -0
- data/spec/unit/braintree/us_bank_account_verification_spec.rb +14 -0
- data/spec/unit/braintree/util_spec.rb +37 -0
- metadata +7 -3
|
@@ -529,6 +529,37 @@ describe Braintree::CreditCard do
|
|
|
529
529
|
expect(result.success?).to eq(true)
|
|
530
530
|
end
|
|
531
531
|
|
|
532
|
+
it "can set the mastercard transaction link identifier when creating a credit card" do
|
|
533
|
+
customer = Braintree::Customer.create!
|
|
534
|
+
|
|
535
|
+
result = Braintree::CreditCard.create(
|
|
536
|
+
:customer_id => customer.id,
|
|
537
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
|
538
|
+
:expiration_date => "05/2009",
|
|
539
|
+
:external_vault => {
|
|
540
|
+
:mastercard_transaction_link_id => "1234567890123456789012",
|
|
541
|
+
},
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
expect(result.success?).to eq(true)
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
it "rejects a mastercard transaction link identifier that is not 22 characters" do
|
|
548
|
+
customer = Braintree::Customer.create!
|
|
549
|
+
|
|
550
|
+
result = Braintree::CreditCard.create(
|
|
551
|
+
:customer_id => customer.id,
|
|
552
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
|
553
|
+
:expiration_date => "05/2009",
|
|
554
|
+
:external_vault => {
|
|
555
|
+
:mastercard_transaction_link_id => "1234567890123456789012123",
|
|
556
|
+
},
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
expect(result.success?).to eq(false)
|
|
560
|
+
expect(result.errors.for(:credit_card).for(:external_vault).on(:mastercard_transaction_link_id)[0].code).to eq(Braintree::ErrorCodes::CreditCard::ExternalVault::MastercardTransactionLinkIdIsInvalid)
|
|
561
|
+
end
|
|
562
|
+
|
|
532
563
|
context "card type indicators" do
|
|
533
564
|
it "sets the prepaid field if the card is prepaid" do
|
|
534
565
|
customer = Braintree::Customer.create!
|
|
@@ -147,6 +147,60 @@ describe Braintree::CreditCardVerification, "search" do
|
|
|
147
147
|
expect(result.credit_card_verification.network_transaction_id).not_to be_nil
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
+
it "creates a new verification with previous_mastercard_transaction_link_id" do
|
|
151
|
+
verification_params = {
|
|
152
|
+
:credit_card => {
|
|
153
|
+
:expiration_date => "05/2029",
|
|
154
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
|
155
|
+
},
|
|
156
|
+
:external_vault => {
|
|
157
|
+
:status => "vaulted",
|
|
158
|
+
:previous_mastercard_transaction_link_id => "1234567890123456789012",
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
result = Braintree::CreditCardVerification.create(verification_params)
|
|
163
|
+
|
|
164
|
+
expect(result).to be_success
|
|
165
|
+
expect(result.credit_card_verification.id).to match(/^\w{6,}$/)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "rejects non-vaulted status with previous_mastercard_transaction_link_id" do
|
|
169
|
+
verification_params = {
|
|
170
|
+
:credit_card => {
|
|
171
|
+
:expiration_date => "05/2029",
|
|
172
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
|
173
|
+
},
|
|
174
|
+
:external_vault => {
|
|
175
|
+
:status => "will_vault",
|
|
176
|
+
:previous_mastercard_transaction_link_id => "1234567890123456789012",
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
result = Braintree::CreditCardVerification.create(verification_params)
|
|
181
|
+
|
|
182
|
+
expect(result.success?).to eq(false)
|
|
183
|
+
expect(result.errors.for(:verification).for(:external_vault).on(:status)[0].code).to eq(Braintree::ErrorCodes::Verification::ExternalVault::StatusWithPreviousMastercardTransactionLinkIdIsInvalid)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "rejects previous_mastercard_transaction_link_id that is not 22 characters" do
|
|
187
|
+
verification_params = {
|
|
188
|
+
:credit_card => {
|
|
189
|
+
:expiration_date => "05/2029",
|
|
190
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
|
191
|
+
},
|
|
192
|
+
:external_vault => {
|
|
193
|
+
:status => "vaulted",
|
|
194
|
+
:previous_mastercard_transaction_link_id => "1234567890123456789012123",
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
result = Braintree::CreditCardVerification.create(verification_params)
|
|
199
|
+
|
|
200
|
+
expect(result.success?).to eq(false)
|
|
201
|
+
expect(result.errors.for(:verification).for(:external_vault).on(:previous_mastercard_transaction_link_id)[0].code).to eq(Braintree::ErrorCodes::Verification::ExternalVault::PreviousMastercardTransactionLinkIdIsInvalid)
|
|
202
|
+
end
|
|
203
|
+
|
|
150
204
|
it "creates a new verification from risk data param" do
|
|
151
205
|
verification_params = {
|
|
152
206
|
:credit_card => {
|
|
@@ -102,6 +102,21 @@ describe Braintree::Customer do
|
|
|
102
102
|
expect(result).to be_success
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
+
it "supports creation with a mastercard_transaction_link_id external_vault param" do
|
|
106
|
+
result = Braintree::Customer.create(
|
|
107
|
+
:credit_card => {
|
|
108
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
|
109
|
+
:expiration_date => "05/2010",
|
|
110
|
+
:cvv => "100",
|
|
111
|
+
:external_vault => {
|
|
112
|
+
:mastercard_transaction_link_id => "1234567890123456789012",
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
expect(result).to be_success
|
|
118
|
+
end
|
|
119
|
+
|
|
105
120
|
it "supports creation including risk data with customer_browser and customer_ip" do
|
|
106
121
|
result = Braintree::Customer.create(
|
|
107
122
|
:credit_card => {
|
|
@@ -2677,4 +2692,47 @@ describe Braintree::Customer do
|
|
|
2677
2692
|
end
|
|
2678
2693
|
end
|
|
2679
2694
|
|
|
2695
|
+
describe "path traversal" do
|
|
2696
|
+
it "self.update rejects a traversal customer_id and does not void the victim transaction" do
|
|
2697
|
+
transaction = Braintree::Transaction.sale!(
|
|
2698
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
|
2699
|
+
:credit_card => {
|
|
2700
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
2701
|
+
:expiration_date => "05/2009"
|
|
2702
|
+
},
|
|
2703
|
+
:options => {:submit_for_settlement => false},
|
|
2704
|
+
)
|
|
2705
|
+
traversal_id = "../transactions/#{transaction.id}/void"
|
|
2706
|
+
|
|
2707
|
+
expect do
|
|
2708
|
+
Braintree::Customer.update(traversal_id, :first_name => "HackerOne")
|
|
2709
|
+
end.to raise_error(ArgumentError, "customer_id contains invalid characters")
|
|
2710
|
+
|
|
2711
|
+
unaffected_transaction = Braintree::Transaction.find(transaction.id)
|
|
2712
|
+
expect(unaffected_transaction.status).to eq(Braintree::Transaction::Status::Authorized)
|
|
2713
|
+
end
|
|
2714
|
+
|
|
2715
|
+
it "self.delete rejects a traversal customer_id and does not delete the victim payment method" do
|
|
2716
|
+
create_result = Braintree::Customer.create(:first_name => "Victim")
|
|
2717
|
+
expect(create_result.success?).to eq(true)
|
|
2718
|
+
customer = create_result.customer
|
|
2719
|
+
|
|
2720
|
+
credit_card_result = Braintree::CreditCard.create(
|
|
2721
|
+
:customer_id => customer.id,
|
|
2722
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
2723
|
+
:expiration_date => "05/2009",
|
|
2724
|
+
)
|
|
2725
|
+
expect(credit_card_result.success?).to eq(true)
|
|
2726
|
+
token = credit_card_result.credit_card.token
|
|
2727
|
+
traversal_id = "../payment_methods/any/#{token}"
|
|
2728
|
+
|
|
2729
|
+
expect do
|
|
2730
|
+
Braintree::Customer.delete(traversal_id)
|
|
2731
|
+
end.to raise_error(ArgumentError, "customer_id contains invalid characters")
|
|
2732
|
+
|
|
2733
|
+
unaffected_credit_card = Braintree::CreditCard.find(token)
|
|
2734
|
+
expect(unaffected_credit_card.token).to eq(token)
|
|
2735
|
+
end
|
|
2736
|
+
end
|
|
2737
|
+
|
|
2680
2738
|
end
|
|
@@ -277,6 +277,36 @@ describe Braintree::Transaction, "idempotency" do
|
|
|
277
277
|
end
|
|
278
278
|
end
|
|
279
279
|
|
|
280
|
+
describe "reverse" do
|
|
281
|
+
it "returns original reverse on duplicate request with same api_request_key" do
|
|
282
|
+
api_request_key = "reverse-idempotency-key-#{rand(1000000)}"
|
|
283
|
+
|
|
284
|
+
sale_request = {
|
|
285
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
|
286
|
+
:credit_card => {
|
|
287
|
+
:number => "4111111111111111",
|
|
288
|
+
:expiration_date => "05/2035"
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
sale_result = Braintree::Transaction.sale(sale_request)
|
|
293
|
+
expect(sale_result).to be_success
|
|
294
|
+
transaction_id = sale_result.transaction.id
|
|
295
|
+
|
|
296
|
+
reverse_options = {
|
|
297
|
+
:api_request_key => api_request_key
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
reverse_result1 = Braintree::Transaction.reverse(transaction_id, reverse_options)
|
|
301
|
+
expect(reverse_result1).to be_success
|
|
302
|
+
|
|
303
|
+
reverse_result2 = Braintree::Transaction.reverse(transaction_id, reverse_options)
|
|
304
|
+
expect(reverse_result2).to be_success
|
|
305
|
+
expect(reverse_result1.transaction.id).to eq(reverse_result2.transaction.id)
|
|
306
|
+
expect(reverse_result2.transaction.status).to eq(Braintree::Transaction::Status::Voided)
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
280
310
|
describe "refund" do
|
|
281
311
|
it "returns original refund on duplicate request with same api_request_key" do
|
|
282
312
|
api_request_key = "refund-idempotency-key-#{rand(1000000)}"
|
|
@@ -257,6 +257,93 @@ describe Braintree::Transaction, "search" do
|
|
|
257
257
|
expect(collection.maximum_size).to eq(0)
|
|
258
258
|
end
|
|
259
259
|
|
|
260
|
+
it "searches on ach_type" do
|
|
261
|
+
same_day_transaction = Braintree::Transaction.find("sameday_ach_sameday_requested")
|
|
262
|
+
standard_transaction = Braintree::Transaction.find("standard_ach_standard_requested")
|
|
263
|
+
|
|
264
|
+
collection = Braintree::Transaction.search do |search|
|
|
265
|
+
search.id.is same_day_transaction.id
|
|
266
|
+
search.ach_type.is Braintree::Transaction::AchType::SameDay
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
expect(collection.maximum_size).to eq(1)
|
|
270
|
+
expect(collection.first.id).to eq(same_day_transaction.id)
|
|
271
|
+
|
|
272
|
+
collection = Braintree::Transaction.search do |search|
|
|
273
|
+
search.id.is same_day_transaction.id
|
|
274
|
+
search.ach_type.is Braintree::Transaction::AchType::Standard
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
expect(collection.maximum_size).to eq(0)
|
|
278
|
+
|
|
279
|
+
collection = Braintree::Transaction.search do |search|
|
|
280
|
+
search.id.is standard_transaction.id
|
|
281
|
+
search.ach_type.is Braintree::Transaction::AchType::Standard
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
expect(collection.maximum_size).to eq(1)
|
|
285
|
+
expect(collection.first.id).to eq(standard_transaction.id)
|
|
286
|
+
|
|
287
|
+
collection = Braintree::Transaction.search do |search|
|
|
288
|
+
search.id.is standard_transaction.id
|
|
289
|
+
search.ach_type.is Braintree::Transaction::AchType::SameDay
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
expect(collection.maximum_size).to eq(0)
|
|
293
|
+
|
|
294
|
+
collection = Braintree::Transaction.search do |search|
|
|
295
|
+
search.id.is same_day_transaction.id
|
|
296
|
+
search.ach_type.in [
|
|
297
|
+
Braintree::Transaction::AchType::SameDay,
|
|
298
|
+
Braintree::Transaction::AchType::Standard
|
|
299
|
+
]
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
expect(collection.maximum_size).to eq(1)
|
|
303
|
+
expect(collection.first.id).to eq(same_day_transaction.id)
|
|
304
|
+
|
|
305
|
+
collection = Braintree::Transaction.search do |search|
|
|
306
|
+
search.id.is standard_transaction.id
|
|
307
|
+
search.ach_type.in [
|
|
308
|
+
Braintree::Transaction::AchType::SameDay,
|
|
309
|
+
Braintree::Transaction::AchType::Standard
|
|
310
|
+
]
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
expect(collection.maximum_size).to eq(1)
|
|
314
|
+
expect(collection.first.id).to eq(standard_transaction.id)
|
|
315
|
+
|
|
316
|
+
divergent_transaction = Braintree::Transaction.find("standard_ach_sameday_requested")
|
|
317
|
+
expect(divergent_transaction.ach_type).to eq(Braintree::Transaction::AchType::Standard)
|
|
318
|
+
expect(divergent_transaction.requested_ach_type).to eq(Braintree::Transaction::AchType::SameDay)
|
|
319
|
+
|
|
320
|
+
collection = Braintree::Transaction.search do |search|
|
|
321
|
+
search.id.is divergent_transaction.id
|
|
322
|
+
search.ach_type.is Braintree::Transaction::AchType::Standard
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
expect(collection.maximum_size).to eq(1)
|
|
326
|
+
expect(collection.first.id).to eq(divergent_transaction.id)
|
|
327
|
+
|
|
328
|
+
collection = Braintree::Transaction.search do |search|
|
|
329
|
+
search.id.is divergent_transaction.id
|
|
330
|
+
search.ach_type.is Braintree::Transaction::AchType::SameDay
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
expect(collection.maximum_size).to eq(0)
|
|
334
|
+
|
|
335
|
+
collection = Braintree::Transaction.search do |search|
|
|
336
|
+
search.id.is divergent_transaction.id
|
|
337
|
+
search.ach_type.in [
|
|
338
|
+
Braintree::Transaction::AchType::SameDay,
|
|
339
|
+
Braintree::Transaction::AchType::Standard
|
|
340
|
+
]
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
expect(collection.maximum_size).to eq(1)
|
|
344
|
+
expect(collection.first.id).to eq(divergent_transaction.id)
|
|
345
|
+
end
|
|
346
|
+
|
|
260
347
|
it "searches on credit_card_customer_location" do
|
|
261
348
|
transaction = Braintree::Transaction.sale!(
|
|
262
349
|
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
|
@@ -661,6 +748,14 @@ describe Braintree::Transaction, "search" do
|
|
|
661
748
|
end
|
|
662
749
|
end.to raise_error(ArgumentError)
|
|
663
750
|
end
|
|
751
|
+
|
|
752
|
+
it "raises an exception on invalid ach_type" do
|
|
753
|
+
expect do
|
|
754
|
+
Braintree::Transaction.search do |search|
|
|
755
|
+
search.ach_type.is "invalid_ach_type"
|
|
756
|
+
end
|
|
757
|
+
end.to raise_error(ArgumentError)
|
|
758
|
+
end
|
|
664
759
|
end
|
|
665
760
|
|
|
666
761
|
context "range fields" do
|
|
@@ -5013,6 +5013,23 @@ describe Braintree::Transaction do
|
|
|
5013
5013
|
expect(result.transaction.network_transaction_id).not_to be_nil
|
|
5014
5014
|
end
|
|
5015
5015
|
|
|
5016
|
+
it "accepts previous_mastercard_transaction_link_id" do
|
|
5017
|
+
result = Braintree::Transaction.create(
|
|
5018
|
+
:type => "sale",
|
|
5019
|
+
:credit_card => {
|
|
5020
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
|
5021
|
+
:expiration_date => "05/2009"
|
|
5022
|
+
},
|
|
5023
|
+
:external_vault => {
|
|
5024
|
+
:status => Braintree::Transaction::ExternalVault::Status::Vaulted,
|
|
5025
|
+
:previous_mastercard_transaction_link_id => "1234567890123456789012",
|
|
5026
|
+
},
|
|
5027
|
+
:amount => "10.00",
|
|
5028
|
+
)
|
|
5029
|
+
expect(result.success?).to eq(true)
|
|
5030
|
+
expect(result.transaction.network_transaction_id).not_to be_nil
|
|
5031
|
+
end
|
|
5032
|
+
|
|
5016
5033
|
it "rejects non-vaulted status with previous_network_transaction_id" do
|
|
5017
5034
|
result = Braintree::Transaction.create(
|
|
5018
5035
|
:type => "sale",
|
|
@@ -5029,6 +5046,40 @@ describe Braintree::Transaction do
|
|
|
5029
5046
|
expect(result.success?).to eq(false)
|
|
5030
5047
|
expect(result.errors.for(:transaction).for(:external_vault).on(:status)[0].code).to eq(Braintree::ErrorCodes::Transaction::ExternalVault::StatusWithPreviousNetworkTransactionIdIsInvalid)
|
|
5031
5048
|
end
|
|
5049
|
+
|
|
5050
|
+
it "rejects non-vaulted status with previous_mastercard_transaction_link_id" do
|
|
5051
|
+
result = Braintree::Transaction.create(
|
|
5052
|
+
:type => "sale",
|
|
5053
|
+
:credit_card => {
|
|
5054
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
|
5055
|
+
:expiration_date => "05/2009"
|
|
5056
|
+
},
|
|
5057
|
+
:external_vault => {
|
|
5058
|
+
:status => Braintree::Transaction::ExternalVault::Status::WillVault,
|
|
5059
|
+
:previous_mastercard_transaction_link_id => "1234567890123456789012",
|
|
5060
|
+
},
|
|
5061
|
+
:amount => "10.00",
|
|
5062
|
+
)
|
|
5063
|
+
expect(result.success?).to eq(false)
|
|
5064
|
+
expect(result.errors.for(:transaction).for(:external_vault).on(:status)[0].code).to eq(Braintree::ErrorCodes::Transaction::ExternalVault::StatusWithPreviousMastercardTransactionLinkIdIsInvalid)
|
|
5065
|
+
end
|
|
5066
|
+
|
|
5067
|
+
it "rejects previous_mastercard_transaction_link_id that is not 22 characters" do
|
|
5068
|
+
result = Braintree::Transaction.create(
|
|
5069
|
+
:type => "sale",
|
|
5070
|
+
:credit_card => {
|
|
5071
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
|
5072
|
+
:expiration_date => "05/2009"
|
|
5073
|
+
},
|
|
5074
|
+
:external_vault => {
|
|
5075
|
+
:status => Braintree::Transaction::ExternalVault::Status::Vaulted,
|
|
5076
|
+
:previous_mastercard_transaction_link_id => "1234567890123456789012123",
|
|
5077
|
+
},
|
|
5078
|
+
:amount => "10.00",
|
|
5079
|
+
)
|
|
5080
|
+
expect(result.success?).to eq(false)
|
|
5081
|
+
expect(result.errors.for(:transaction).for(:external_vault).on(:previous_mastercard_transaction_link_id)[0].code).to eq(Braintree::ErrorCodes::Transaction::ExternalVault::PreviousMastercardTransactionLinkIdIsInvalid)
|
|
5082
|
+
end
|
|
5032
5083
|
end
|
|
5033
5084
|
|
|
5034
5085
|
context "Non-(Visa/Mastercard/Discover/AmEx) card types" do
|
|
@@ -5233,6 +5284,28 @@ describe Braintree::Transaction do
|
|
|
5233
5284
|
transaction = Braintree::Transaction.find(transaction.id)
|
|
5234
5285
|
expect(transaction.refund_ids.sort).to eq([transaction_1.id, transaction_2.id].sort)
|
|
5235
5286
|
end
|
|
5287
|
+
|
|
5288
|
+
it "allows partial refund with surcharge_amount" do
|
|
5289
|
+
transaction = Braintree::Transaction.sale!(
|
|
5290
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
|
5291
|
+
:surcharge_amount => "1.00",
|
|
5292
|
+
:credit_card => {
|
|
5293
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
5294
|
+
:expiration_date => "05/2009"
|
|
5295
|
+
},
|
|
5296
|
+
:options => {
|
|
5297
|
+
:submit_for_settlement => true
|
|
5298
|
+
},
|
|
5299
|
+
)
|
|
5300
|
+
config = Braintree::Configuration.instantiate
|
|
5301
|
+
config.http.put("#{config.base_merchant_path}/transactions/#{transaction.id}/settle")
|
|
5302
|
+
transaction = Braintree::Transaction.find(transaction.id)
|
|
5303
|
+
|
|
5304
|
+
result = Braintree::Transaction.refund(transaction.id, :amount => transaction.amount / 2, :surcharge_amount => "0.50")
|
|
5305
|
+
expect(result.success?).to eq(true)
|
|
5306
|
+
expect(result.transaction.type).to eq("credit")
|
|
5307
|
+
expect(result.transaction.surcharge_amount).to eq(BigDecimal("0.50"))
|
|
5308
|
+
end
|
|
5236
5309
|
end
|
|
5237
5310
|
|
|
5238
5311
|
it "returns a successful result if successful" do
|
|
@@ -5272,6 +5345,28 @@ describe Braintree::Transaction do
|
|
|
5272
5345
|
expect(result.success?).to eq(false)
|
|
5273
5346
|
expect(result.errors.for(:transaction).on(:base)[0].code).to eq(Braintree::ErrorCodes::Transaction::CannotRefundUnlessSettled)
|
|
5274
5347
|
end
|
|
5348
|
+
|
|
5349
|
+
it "accepts surcharge_amount field in refund" do
|
|
5350
|
+
transaction = Braintree::Transaction.sale!(
|
|
5351
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
|
5352
|
+
:surcharge_amount => "1.00",
|
|
5353
|
+
:credit_card => {
|
|
5354
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
5355
|
+
:expiration_date => "05/2009"
|
|
5356
|
+
},
|
|
5357
|
+
:options => {
|
|
5358
|
+
:submit_for_settlement => true
|
|
5359
|
+
},
|
|
5360
|
+
)
|
|
5361
|
+
config = Braintree::Configuration.instantiate
|
|
5362
|
+
config.http.put("#{config.base_merchant_path}/transactions/#{transaction.id}/settle")
|
|
5363
|
+
transaction = Braintree::Transaction.find(transaction.id)
|
|
5364
|
+
|
|
5365
|
+
result = Braintree::Transaction.refund(transaction.id, :surcharge_amount => "1.00")
|
|
5366
|
+
expect(result.success?).to eq(true)
|
|
5367
|
+
expect(result.transaction.type).to eq("credit")
|
|
5368
|
+
expect(result.transaction.surcharge_amount).to eq(BigDecimal("1.00"))
|
|
5369
|
+
end
|
|
5275
5370
|
end
|
|
5276
5371
|
|
|
5277
5372
|
describe "self.refund!" do
|
|
@@ -7295,6 +7390,85 @@ describe Braintree::Transaction do
|
|
|
7295
7390
|
end
|
|
7296
7391
|
end
|
|
7297
7392
|
|
|
7393
|
+
describe "self.reverse" do
|
|
7394
|
+
it "voids a voidable transaction" do
|
|
7395
|
+
transaction = Braintree::Transaction.sale!(
|
|
7396
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
|
7397
|
+
:credit_card => {
|
|
7398
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
7399
|
+
:expiration_date => "05/2009"
|
|
7400
|
+
},
|
|
7401
|
+
)
|
|
7402
|
+
|
|
7403
|
+
result = Braintree::Transaction.reverse(transaction.id)
|
|
7404
|
+
|
|
7405
|
+
expect(result.success?).to eq(true)
|
|
7406
|
+
expect(result.transaction.id).to eq(transaction.id)
|
|
7407
|
+
expect(result.transaction.status).to eq(Braintree::Transaction::Status::Voided)
|
|
7408
|
+
expect(result.transaction.refunded_transaction_id).to be_nil
|
|
7409
|
+
end
|
|
7410
|
+
|
|
7411
|
+
it "returns an error when reversing twice without an api request key" do
|
|
7412
|
+
transaction = Braintree::Transaction.sale!(
|
|
7413
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
|
7414
|
+
:credit_card => {
|
|
7415
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
7416
|
+
:expiration_date => "05/2009"
|
|
7417
|
+
},
|
|
7418
|
+
)
|
|
7419
|
+
|
|
7420
|
+
expect(Braintree::Transaction.reverse(transaction.id)).to be_success
|
|
7421
|
+
result = Braintree::Transaction.reverse(transaction.id)
|
|
7422
|
+
|
|
7423
|
+
expect(result.success?).to eq(false)
|
|
7424
|
+
expect(result.errors.for(:transaction).on(:base).first.code).to eq(
|
|
7425
|
+
Braintree::ErrorCodes::Transaction::CannotRefundUnlessSettled,
|
|
7426
|
+
)
|
|
7427
|
+
end
|
|
7428
|
+
|
|
7429
|
+
it "voids an explicitly created voidable refund" do
|
|
7430
|
+
transaction = Braintree::Transaction.sale!(
|
|
7431
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
|
7432
|
+
:credit_card => {
|
|
7433
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
7434
|
+
:expiration_date => "05/2009"
|
|
7435
|
+
},
|
|
7436
|
+
:options => {
|
|
7437
|
+
:submit_for_settlement => true
|
|
7438
|
+
},
|
|
7439
|
+
)
|
|
7440
|
+
Braintree::TestTransaction.settle(transaction.id)
|
|
7441
|
+
refund = Braintree::Transaction.refund!(transaction.id)
|
|
7442
|
+
|
|
7443
|
+
result = Braintree::Transaction.reverse(refund.id)
|
|
7444
|
+
|
|
7445
|
+
expect(result.success?).to eq(true)
|
|
7446
|
+
expect(result.transaction.id).to eq(refund.id)
|
|
7447
|
+
expect(result.transaction.status).to eq(Braintree::Transaction::Status::Voided)
|
|
7448
|
+
expect(result.transaction.refunded_transaction_id).to eq(transaction.id)
|
|
7449
|
+
end
|
|
7450
|
+
|
|
7451
|
+
it "refunds a settled transaction" do
|
|
7452
|
+
transaction = Braintree::Transaction.sale!(
|
|
7453
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
|
7454
|
+
:credit_card => {
|
|
7455
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
7456
|
+
:expiration_date => "05/2009"
|
|
7457
|
+
},
|
|
7458
|
+
:options => {
|
|
7459
|
+
:submit_for_settlement => true
|
|
7460
|
+
},
|
|
7461
|
+
)
|
|
7462
|
+
Braintree::TestTransaction.settle(transaction.id)
|
|
7463
|
+
|
|
7464
|
+
result = Braintree::Transaction.reverse(transaction.id)
|
|
7465
|
+
|
|
7466
|
+
expect(result.success?).to eq(true)
|
|
7467
|
+
expect(result.transaction.type).to eq(Braintree::Transaction::Type::Credit)
|
|
7468
|
+
expect(result.transaction.refunded_transaction_id).to eq(transaction.id)
|
|
7469
|
+
end
|
|
7470
|
+
end
|
|
7471
|
+
|
|
7298
7472
|
describe "self.void" do
|
|
7299
7473
|
it "returns a successful result if successful" do
|
|
7300
7474
|
transaction = Braintree::Transaction.sale!(
|
|
@@ -8179,7 +8353,7 @@ describe Braintree::Transaction do
|
|
|
8179
8353
|
end
|
|
8180
8354
|
|
|
8181
8355
|
context "Surcharge Amount" do
|
|
8182
|
-
it "accepts surcharge_amount field" do
|
|
8356
|
+
it "accepts surcharge_amount field for sale transactions" do
|
|
8183
8357
|
result = Braintree::Transaction.create(
|
|
8184
8358
|
:type => "sale",
|
|
8185
8359
|
:amount => "10.00",
|
|
@@ -8193,5 +8367,41 @@ describe Braintree::Transaction do
|
|
|
8193
8367
|
expect(result.success?).to eq(true)
|
|
8194
8368
|
expect(result.transaction.surcharge_amount).to eq(BigDecimal("1.00"))
|
|
8195
8369
|
end
|
|
8370
|
+
|
|
8371
|
+
it "accepts surcharge_amount field for blind credit" do
|
|
8372
|
+
result = Braintree::Transaction.create(
|
|
8373
|
+
:type => "credit",
|
|
8374
|
+
:amount => "10.00",
|
|
8375
|
+
:surcharge_amount => "1.00",
|
|
8376
|
+
:credit_card => {
|
|
8377
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
8378
|
+
:expiration_date => "05/2029"
|
|
8379
|
+
},
|
|
8380
|
+
)
|
|
8381
|
+
|
|
8382
|
+
expect(result.success?).to eq(true)
|
|
8383
|
+
expect(result.transaction.surcharge_amount).to eq(BigDecimal("1.00"))
|
|
8384
|
+
end
|
|
8385
|
+
end
|
|
8386
|
+
|
|
8387
|
+
describe "path traversal" do
|
|
8388
|
+
it "self.void rejects a traversal transaction_id and does not void the victim transaction" do
|
|
8389
|
+
victim_transaction = Braintree::Transaction.sale!(
|
|
8390
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
|
8391
|
+
:credit_card => {
|
|
8392
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
8393
|
+
:expiration_date => "05/2009"
|
|
8394
|
+
},
|
|
8395
|
+
:options => {:submit_for_settlement => false},
|
|
8396
|
+
)
|
|
8397
|
+
traversal_id = "../transactions/#{victim_transaction.id}"
|
|
8398
|
+
|
|
8399
|
+
expect do
|
|
8400
|
+
Braintree::Transaction.void(traversal_id)
|
|
8401
|
+
end.to raise_error(ArgumentError, "transaction_id contains invalid characters")
|
|
8402
|
+
|
|
8403
|
+
unaffected_transaction = Braintree::Transaction.find(victim_transaction.id)
|
|
8404
|
+
expect(unaffected_transaction.status).to eq(Braintree::Transaction::Status::Authorized)
|
|
8405
|
+
end
|
|
8196
8406
|
end
|
|
8197
8407
|
end
|
|
@@ -20,6 +20,78 @@ module Braintree
|
|
|
20
20
|
)
|
|
21
21
|
}.to raise_error(ArgumentError, /created_at, public_key/)
|
|
22
22
|
end
|
|
23
|
+
|
|
24
|
+
context "with preferred_payment_method_token" do
|
|
25
|
+
let(:config) { SpecHelper::TestMerchantConfig }
|
|
26
|
+
let(:gateway) { Gateway.new(config) }
|
|
27
|
+
let(:http) { double(:http) }
|
|
28
|
+
|
|
29
|
+
before do
|
|
30
|
+
allow(config).to receive(:http).and_return(http)
|
|
31
|
+
allow(Configuration).to receive(:gateway).and_return(gateway)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def expect_client_token_post(options)
|
|
35
|
+
expect(http).to receive(:post).with(
|
|
36
|
+
"#{config.base_merchant_path}/client_token",
|
|
37
|
+
:client_token => options,
|
|
38
|
+
).and_return(:client_token => {:value => "client-token"})
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "renames preferred_payment_method_token to payment_method_id" do
|
|
42
|
+
expect_client_token_post(
|
|
43
|
+
:payment_method_id => "a-pmt",
|
|
44
|
+
:version => ClientToken::DEFAULT_VERSION,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
client_token = Braintree::ClientToken.generate(
|
|
48
|
+
:preferred_payment_method_token => "a-pmt",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
expect(client_token).to eq("client-token")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "renames string preferred_payment_method_token to payment_method_id" do
|
|
55
|
+
expect_client_token_post(
|
|
56
|
+
:payment_method_id => "a-pmt",
|
|
57
|
+
:version => ClientToken::DEFAULT_VERSION,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
client_token = Braintree::ClientToken.generate(
|
|
61
|
+
"preferred_payment_method_token" => "a-pmt",
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
expect(client_token).to eq("client-token")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "renames preferred_payment_method_token when the value is nil" do
|
|
68
|
+
expect_client_token_post(
|
|
69
|
+
:payment_method_id => nil,
|
|
70
|
+
:version => ClientToken::DEFAULT_VERSION,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
client_token = Braintree::ClientToken.generate(
|
|
74
|
+
:preferred_payment_method_token => nil,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
expect(client_token).to eq("client-token")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "does not mutate the caller's options hash" do
|
|
81
|
+
options = {:preferred_payment_method_token => "a-pmt"}
|
|
82
|
+
expect(http).to receive(:post).twice.with(
|
|
83
|
+
"#{config.base_merchant_path}/client_token",
|
|
84
|
+
:client_token => {
|
|
85
|
+
:payment_method_id => "a-pmt",
|
|
86
|
+
:version => ClientToken::DEFAULT_VERSION,
|
|
87
|
+
},
|
|
88
|
+
).and_return(:client_token => {:value => "client-token"})
|
|
89
|
+
|
|
90
|
+
expect(Braintree::ClientToken.generate(options)).to eq("client-token")
|
|
91
|
+
expect(Braintree::ClientToken.generate(options)).to eq("client-token")
|
|
92
|
+
expect(options).to eq(:preferred_payment_method_token => "a-pmt")
|
|
93
|
+
end
|
|
94
|
+
end
|
|
23
95
|
end
|
|
24
96
|
|
|
25
97
|
context "adding credit_card options with no customer ID" do
|