braintree 2.99.0 → 2.104.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/lib/braintree/address_gateway.rb +2 -2
  3. data/lib/braintree/amex_express_checkout_card.rb +2 -0
  4. data/lib/braintree/android_pay_card.rb +5 -0
  5. data/lib/braintree/base_module.rb +4 -0
  6. data/lib/braintree/credit_card.rb +5 -1
  7. data/lib/braintree/credit_card_gateway.rb +14 -0
  8. data/lib/braintree/credit_card_verification.rb +2 -0
  9. data/lib/braintree/customer.rb +5 -2
  10. data/lib/braintree/dispute.rb +1 -0
  11. data/lib/braintree/dispute/transaction.rb +2 -0
  12. data/lib/braintree/error_codes.rb +76 -33
  13. data/lib/braintree/graphql_client.rb +7 -1
  14. data/lib/braintree/masterpass_card.rb +2 -0
  15. data/lib/braintree/payment_instrument_type.rb +2 -1
  16. data/lib/braintree/payment_method_gateway.rb +14 -0
  17. data/lib/braintree/payment_method_nonce.rb +2 -0
  18. data/lib/braintree/payment_method_nonce_gateway.rb +13 -2
  19. data/lib/braintree/payment_method_parser.rb +1 -0
  20. data/lib/braintree/risk_data.rb +4 -1
  21. data/lib/braintree/test/authentication_id.rb +21 -0
  22. data/lib/braintree/test/credit_card.rb +1 -0
  23. data/lib/braintree/test/nonce.rb +18 -0
  24. data/lib/braintree/three_d_secure_info.rb +2 -0
  25. data/lib/braintree/transaction.rb +15 -1
  26. data/lib/braintree/transaction/address_details.rb +11 -0
  27. data/lib/braintree/transaction/android_pay_details.rb +5 -0
  28. data/lib/braintree/transaction/apple_pay_details.rb +1 -0
  29. data/lib/braintree/transaction/masterpass_card_details.rb +2 -0
  30. data/lib/braintree/transaction/paypal_details.rb +2 -0
  31. data/lib/braintree/transaction_gateway.rb +12 -3
  32. data/lib/braintree/version.rb +1 -1
  33. data/lib/braintree/webhook_notification.rb +3 -0
  34. data/lib/braintree/webhook_testing_gateway.rb +243 -0
  35. data/spec/integration/braintree/client_api/spec_helper.rb +98 -46
  36. data/spec/integration/braintree/credit_card_spec.rb +135 -2
  37. data/spec/integration/braintree/credit_card_verification_spec.rb +2 -0
  38. data/spec/integration/braintree/customer_spec.rb +116 -0
  39. data/spec/integration/braintree/dispute_search_spec.rb +1 -1
  40. data/spec/integration/braintree/dispute_spec.rb +1 -0
  41. data/spec/integration/braintree/document_upload_spec.rb +12 -0
  42. data/spec/integration/braintree/merchant_spec.rb +2 -2
  43. data/spec/integration/braintree/payment_method_nonce_spec.rb +83 -2
  44. data/spec/integration/braintree/payment_method_spec.rb +113 -18
  45. data/spec/integration/braintree/paypal_account_spec.rb +1 -1
  46. data/spec/integration/braintree/transaction_spec.rb +437 -45
  47. data/spec/spec_helper.rb +1 -1
  48. data/spec/unit/braintree/credit_card_spec.rb +51 -3
  49. data/spec/unit/braintree/credit_card_verification_spec.rb +7 -0
  50. data/spec/unit/braintree/customer_spec.rb +28 -2
  51. data/spec/unit/braintree/dispute_spec.rb +3 -0
  52. data/spec/unit/braintree/three_d_secure_info_spec.rb +3 -1
  53. data/spec/unit/braintree/transaction/paypal_details_spec.rb +57 -0
  54. data/spec/unit/braintree/transaction_spec.rb +16 -2
  55. data/spec/unit/braintree/webhook_notification_spec.rb +48 -0
  56. metadata +5 -3
@@ -74,7 +74,7 @@ describe Braintree::Dispute, "search" do
74
74
  ]
75
75
  end
76
76
 
77
- expect(collection.disputes.count).to eq(2)
77
+ expect(collection.disputes.count).to be >= 2
78
78
  dispute = collection.disputes.first
79
79
  end
80
80
 
@@ -186,6 +186,7 @@ describe Braintree::Dispute do
186
186
  dispute.amount_disputed.should == 31.0
187
187
  dispute.amount_won.should == 0.0
188
188
  dispute.id.should == "open_dispute"
189
+ dispute.graphql_id.should_not be_nil
189
190
  dispute.status.should == Braintree::Dispute::Status::Open
190
191
  dispute.transaction.amount.should == 31.0
191
192
  dispute.transaction.id.should == "open_disputed_transaction"
@@ -46,6 +46,18 @@ describe Braintree::DocumentUploadGateway do
46
46
  end
47
47
  end
48
48
 
49
+ it "returns file is empty error with empty file" do
50
+ filename = "#{File.dirname(__FILE__)}/../../fixtures/files/empty_file.png"
51
+ begin
52
+ File.open(filename, "w+") {}
53
+ file = File.new(filename, "r")
54
+ response = Braintree::DocumentUpload.create({:kind => Braintree::DocumentUpload::Kind::EvidenceDocument, :file => file})
55
+ response.errors.for(:document_upload).first.code.should == Braintree::ErrorCodes::DocumentUpload::FileIsEmpty
56
+ ensure
57
+ File.delete(filename)
58
+ end
59
+ end
60
+
49
61
  it "returns file too long error with file over 50 pages" do
50
62
  filename = "#{File.dirname(__FILE__)}/../../fixtures/files/too_long.pdf"
51
63
  file = File.new(filename, "r")
@@ -305,7 +305,7 @@ describe Braintree::MerchantGateway do
305
305
  it "succeeds" do
306
306
  result = Braintree::Merchant.provision_raw_apple_pay
307
307
  result.should be_success
308
- result.supported_networks.should == ["visa", "mastercard", "amex", "discover"]
308
+ result.supported_networks.should == ["visa", "mastercard", "amex", "discover", "maestro"]
309
309
  end
310
310
 
311
311
  it "is repeatable" do
@@ -313,7 +313,7 @@ describe Braintree::MerchantGateway do
313
313
  result.should be_success
314
314
  result = Braintree::Merchant.provision_raw_apple_pay
315
315
  result.should be_success
316
- result.supported_networks.should == ["visa", "mastercard", "amex", "discover"]
316
+ result.supported_networks.should == ["visa", "mastercard", "amex", "discover", "maestro"]
317
317
  end
318
318
  end
319
319
 
@@ -84,10 +84,14 @@ describe Braintree::PaymentMethodNonce do
84
84
  end
85
85
 
86
86
  it "return paypal details if details exist" do
87
- result = Braintree::PaymentMethodNonce.find("fake-google-pay-paypal-nonce")
88
-
87
+ result = Braintree::PaymentMethodNonce.find("fake-paypal-one-time-nonce")
89
88
  nonce = result.payment_method_nonce
90
89
 
90
+ nonce.details.fetch(:cobranded_card_label).should_not be_nil
91
+ nonce.details.fetch(:shipping_option_id).should_not be_nil
92
+ nonce.details.fetch(:billing_address).fetch(:recipient_name).should_not be_nil
93
+ nonce.details.fetch(:shipping_address).fetch(:recipient_name).should_not be_nil
94
+
91
95
  nonce.details.fetch(:payer_info).fetch(:first_name).should_not be_nil
92
96
  nonce.details.fetch(:payer_info).fetch(:last_name).should_not be_nil
93
97
  nonce.details.fetch(:payer_info).fetch(:email).should_not be_nil
@@ -235,5 +239,82 @@ describe Braintree::PaymentMethodNonce do
235
239
  Braintree::PaymentMethodNonce.find("not_a_nonce")
236
240
  end.to raise_error(Braintree::NotFoundError)
237
241
  end
242
+
243
+ context "authentication insights" do
244
+ let(:indian_payment_token) { "india_visa_credit" }
245
+ let(:european_payment_token) { "european_visa_credit" }
246
+ let(:indian_merchant_token) { "india_three_d_secure_merchant_account" }
247
+ let(:european_merchant_token) { "european_three_d_secure_merchant_account" }
248
+
249
+ describe "self.create" do
250
+ it "raises an exception if hash includes an invalid key" do
251
+ expect do
252
+ Braintree::PaymentMethodNonce.create("european_visa_credit", :invalid_key => "foo")
253
+ end.to raise_error(ArgumentError, "invalid keys: invalid_key")
254
+ end
255
+ end
256
+
257
+ context "regulation environments" do
258
+ it "can get unregulated" do
259
+ expect(
260
+ request_authentication_insights(european_merchant_token, indian_payment_token)[:regulation_environment]
261
+ ).to eq "unregulated"
262
+ end
263
+
264
+ it "can get psd2" do
265
+ expect(
266
+ request_authentication_insights(european_merchant_token, european_payment_token)[:regulation_environment]
267
+ ).to eq "psd2"
268
+ end
269
+
270
+ it "can get rbi" do
271
+ expect(
272
+ request_authentication_insights(indian_merchant_token, indian_payment_token)[:regulation_environment]
273
+ ).to eq "rbi"
274
+ end
275
+ end
276
+
277
+ context "sca_indicator" do
278
+ it "can get unavailable" do
279
+ expect(
280
+ request_authentication_insights(indian_merchant_token, indian_payment_token)[:sca_indicator]
281
+ ).to eq "unavailable"
282
+ end
283
+
284
+ it "can get sca_required" do
285
+ expect(
286
+ request_authentication_insights(indian_merchant_token, indian_payment_token, {amount: 2001})[:sca_indicator]
287
+ ).to eq "sca_required"
288
+ end
289
+
290
+ it "can get sca_optional" do
291
+ expect(
292
+ request_authentication_insights(indian_merchant_token, indian_payment_token, {amount: 2000, recurring_customer_consent: true, recurring_max_amount: 2000})[:sca_indicator]
293
+
294
+ ).to eq "sca_optional"
295
+ end
296
+ end
297
+
298
+ def request_authentication_insights(merchant_token, payment_method_token, options = {})
299
+ authentication_insight_options = {
300
+ amount: options[:amount],
301
+ recurring_customer_consent: options[:recurring_customer_consent],
302
+ recurring_max_amount: options[:recurring_max_amount],
303
+ }
304
+ nonce_request = {
305
+ merchant_account_id: merchant_token,
306
+ authentication_insight: true,
307
+ authentication_insight_options: authentication_insight_options,
308
+ }
309
+
310
+ result = Braintree::PaymentMethodNonce.create(
311
+ payment_method_token,
312
+ payment_method_nonce: nonce_request
313
+ )
314
+ result.should be_success
315
+
316
+ return result.payment_method_nonce.authentication_insight
317
+ end
318
+ end
238
319
  end
239
320
  end
@@ -121,6 +121,7 @@ describe Braintree::PaymentMethod do
121
121
  android_pay_card.expiration_year.to_i.should > 0
122
122
  android_pay_card.default.should == true
123
123
  android_pay_card.image_url.should =~ /android_pay/
124
+ android_pay_card.is_network_tokenized?.should == false
124
125
  android_pay_card.source_card_type.should == Braintree::CreditCard::CardType::Discover
125
126
  android_pay_card.source_card_last_4.should == "1111"
126
127
  android_pay_card.google_transaction_id.should == "google_transaction_id"
@@ -148,6 +149,7 @@ describe Braintree::PaymentMethod do
148
149
  android_pay_card.expiration_year.to_i.should > 0
149
150
  android_pay_card.default.should == true
150
151
  android_pay_card.image_url.should =~ /android_pay/
152
+ android_pay_card.is_network_tokenized?.should == true
151
153
  android_pay_card.source_card_type.should == Braintree::CreditCard::CardType::MasterCard
152
154
  android_pay_card.source_card_last_4.should == "4444"
153
155
  android_pay_card.google_transaction_id.should == "google_transaction_id"
@@ -298,6 +300,50 @@ describe Braintree::PaymentMethod do
298
300
  result.credit_card_verification.amount.should == BigDecimal("100.00")
299
301
  end
300
302
 
303
+ it "validates presence of three_d_secure_version in 3ds pass thru params" do
304
+ customer = Braintree::Customer.create!
305
+ result = Braintree::PaymentMethod.create(
306
+ :customer_id => customer.id,
307
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
308
+ :three_d_secure_pass_thru => {
309
+ :eci_flag => '02',
310
+ :cavv => 'some_cavv',
311
+ :xid => 'some_xid',
312
+ :three_d_secure_version => 'xx',
313
+ :authentication_response => 'Y',
314
+ :directory_response => 'Y',
315
+ :cavv_algorithm => '2',
316
+ :ds_transaction_id => 'some_ds_transaction_id',
317
+ },
318
+ :options => {:verify_card => true}
319
+ )
320
+ expect(result).not_to be_success
321
+ error = result.errors.for(:verification).first
322
+ expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::ThreeDSecureVersionIsInvalid)
323
+ expect(error.message).to eq("The version of 3D Secure authentication must be composed only of digits and separated by periods (e.g. `1.0.2`).")
324
+ end
325
+
326
+ it "accepts three_d_secure pass thru params in the request" do
327
+ customer = Braintree::Customer.create!
328
+ result = Braintree::PaymentMethod.create(
329
+ :customer_id => customer.id,
330
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
331
+ :three_d_secure_pass_thru => {
332
+ :eci_flag => '02',
333
+ :cavv => 'some_cavv',
334
+ :xid => 'some_xid',
335
+ :three_d_secure_version => '1.0.2',
336
+ :authentication_response => 'Y',
337
+ :directory_response => 'Y',
338
+ :cavv_algorithm => '2',
339
+ :ds_transaction_id => 'some_ds_transaction_id',
340
+ },
341
+ :options => {:verify_card => true}
342
+ )
343
+
344
+ expect(result).to be_success
345
+ end
346
+
301
347
  it "returns 3DS info on cc verification" do
302
348
  customer = Braintree::Customer.create.customer
303
349
  result = Braintree::PaymentMethod.create(
@@ -727,24 +773,6 @@ describe Braintree::PaymentMethod do
727
773
  found_paypal_account.payer_id.should_not be_nil
728
774
  end
729
775
 
730
- it "creates a billing agreement payment method from a refresh token without upgrading" do
731
- customer = Braintree::Customer.create.customer
732
- result = Braintree::PaymentMethod.create(
733
- :customer_id => customer.id,
734
- :paypal_refresh_token => "some_future_payment_token",
735
- :paypal_vault_without_upgrade => true,
736
- )
737
-
738
- result.should be_success
739
- result.payment_method.should be_a(Braintree::PayPalAccount)
740
- result.payment_method.billing_agreement_id.should be_nil
741
- token = result.payment_method.token
742
-
743
- found_paypal_account = Braintree::PayPalAccount.find(token)
744
- found_paypal_account.should_not be_nil
745
- found_paypal_account.billing_agreement_id.should be_nil
746
- end
747
-
748
776
  it "does not create a payment method from an unvalidated onetime paypal account nonce" do
749
777
  customer = Braintree::Customer.create.customer
750
778
  nonce = nonce_for_paypal_account(:access_token => "PAYPAL_ACCESS_TOKEN")
@@ -1017,6 +1045,7 @@ describe Braintree::PaymentMethod do
1017
1045
  android_pay_card.expiration_year.to_i.should > 0
1018
1046
  android_pay_card.default.should == true
1019
1047
  android_pay_card.image_url.should =~ /android_pay/
1048
+ android_pay_card.is_network_tokenized?.should == false
1020
1049
  android_pay_card.source_card_type.should == Braintree::CreditCard::CardType::Discover
1021
1050
  android_pay_card.source_card_last_4.should == "1111"
1022
1051
  android_pay_card.google_transaction_id.should == "google_transaction_id"
@@ -1044,6 +1073,7 @@ describe Braintree::PaymentMethod do
1044
1073
  android_pay_card.expiration_year.to_i.should > 0
1045
1074
  android_pay_card.default.should == true
1046
1075
  android_pay_card.image_url.should =~ /android_pay/
1076
+ android_pay_card.is_network_tokenized?.should == true
1047
1077
  android_pay_card.source_card_type.should == Braintree::CreditCard::CardType::MasterCard
1048
1078
  android_pay_card.source_card_last_4.should == "4444"
1049
1079
  android_pay_card.google_transaction_id.should == "google_transaction_id"
@@ -1183,6 +1213,71 @@ describe Braintree::PaymentMethod do
1183
1213
 
1184
1214
  describe "self.update" do
1185
1215
  context "credit cards" do
1216
+ it "throws validation error when passing invalid pass thru params" do
1217
+ customer = Braintree::Customer.create!
1218
+ credit_card = Braintree::CreditCard.create!(
1219
+ :customer_id => customer.id,
1220
+ :payment_method_nonce => Braintree::Test::Nonce::ThreeDSecureVisaFullAuthentication,
1221
+ :options => {:verify_card => true},
1222
+ )
1223
+
1224
+ update_result = Braintree::PaymentMethod.update(credit_card.token,
1225
+ :cardholder_name => "New Holder",
1226
+ :cvv => "456",
1227
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
1228
+ :expiration_date => "06/2013",
1229
+ :three_d_secure_pass_thru => {
1230
+ :eci_flag => '02',
1231
+ :cavv => 'some_cavv',
1232
+ :xid => 'some_xid',
1233
+ :three_d_secure_version => 'xx',
1234
+ :authentication_response => 'Y',
1235
+ :directory_response => 'Y',
1236
+ :cavv_algorithm => '2',
1237
+ :ds_transaction_id => 'some_ds_transaction_id',
1238
+ },
1239
+ :options => {:verify_card => true},
1240
+ )
1241
+ expect(update_result).to_not be_success
1242
+ error = update_result.errors.for(:verification).first
1243
+ expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::ThreeDSecureVersionIsInvalid)
1244
+ expect(error.message).to eq("The version of 3D Secure authentication must be composed only of digits and separated by periods (e.g. `1.0.2`).")
1245
+ end
1246
+
1247
+ it "updates the credit card with three_d_secure pass thru params" do
1248
+ customer = Braintree::Customer.create!
1249
+ credit_card = Braintree::CreditCard.create!(
1250
+ :customer_id => customer.id,
1251
+ :payment_method_nonce => Braintree::Test::Nonce::ThreeDSecureVisaFullAuthentication,
1252
+ :options => {:verify_card => true},
1253
+ )
1254
+
1255
+ update_result = Braintree::PaymentMethod.update(credit_card.token,
1256
+ :cardholder_name => "New Holder",
1257
+ :cvv => "456",
1258
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
1259
+ :expiration_date => "06/2013",
1260
+ :three_d_secure_pass_thru => {
1261
+ :eci_flag => '02',
1262
+ :cavv => 'some_cavv',
1263
+ :xid => 'some_xid',
1264
+ :three_d_secure_version => '1.0.2',
1265
+ :authentication_response => 'Y',
1266
+ :directory_response => 'Y',
1267
+ :cavv_algorithm => '2',
1268
+ :ds_transaction_id => 'some_ds_transaction_id',
1269
+ },
1270
+ :options => {:verify_card => true},
1271
+ )
1272
+ update_result.success?.should == true
1273
+ update_result.payment_method.should == credit_card
1274
+ updated_credit_card = update_result.payment_method
1275
+ updated_credit_card.cardholder_name.should == "New Holder"
1276
+ updated_credit_card.bin.should == Braintree::Test::CreditCardNumbers::MasterCard[0, 6]
1277
+ updated_credit_card.last_4.should == Braintree::Test::CreditCardNumbers::MasterCard[-4..-1]
1278
+ updated_credit_card.expiration_date.should == "06/2013"
1279
+ end
1280
+
1186
1281
  it "updates the credit card" do
1187
1282
  customer = Braintree::Customer.create!
1188
1283
  credit_card = Braintree::CreditCard.create!(
@@ -131,7 +131,7 @@ describe Braintree::PayPalAccount do
131
131
  )
132
132
 
133
133
  result.success?.should == false
134
- result.errors.first.code.should == "82902"
134
+ result.errors.map(&:code).should include("82902")
135
135
  end
136
136
  end
137
137
 
@@ -140,6 +140,31 @@ describe Braintree::Transaction do
140
140
  result.transaction.risk_data.should respond_to(:fraud_service_provider)
141
141
  end
142
142
  end
143
+
144
+ it "handles validation errors for invalid risk data attributes" do
145
+ with_advanced_fraud_integration_merchant do
146
+ result = Braintree::Transaction.create(
147
+ :type => "sale",
148
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
149
+ :credit_card => {
150
+ :number => Braintree::Test::CreditCardNumbers::Visa,
151
+ :expiration_date => "05/2009"
152
+ },
153
+ :risk_data => {
154
+ :customer_browser => "#{"1" * 300}",
155
+ :customer_device_id => "customer_device_id_0#{"1" * 300}",
156
+ :customer_ip => "192.168.0.1",
157
+ :customer_location_zip => "not-a-$#phone",
158
+ :customer_tenure => "20#{"0" * 500}"
159
+ }
160
+ )
161
+ result.success?.should == false
162
+ result.errors.for(:transaction).for(:risk_data).on(:customer_browser).map { |e| e.code }.should include Braintree::ErrorCodes::RiskData::CustomerBrowserIsTooLong
163
+ result.errors.for(:transaction).for(:risk_data).on(:customer_device_id).map { |e| e.code }.should include Braintree::ErrorCodes::RiskData::CustomerDeviceIdIsTooLong
164
+ result.errors.for(:transaction).for(:risk_data).on(:customer_location_zip).map { |e| e.code }.should include Braintree::ErrorCodes::RiskData::CustomerLocationZipInvalidCharacters
165
+ result.errors.for(:transaction).for(:risk_data).on(:customer_tenure).map { |e| e.code }.should include Braintree::ErrorCodes::RiskData::CustomerTenureIsTooLong
166
+ end
167
+ end
143
168
  end
144
169
 
145
170
  describe "card type indicators" do
@@ -419,6 +444,7 @@ describe Braintree::Transaction do
419
444
  result.transaction.credit_card_details.last_4.should == Braintree::Test::CreditCardNumbers::Visa[-4..-1]
420
445
  result.transaction.credit_card_details.expiration_date.should == "05/2009"
421
446
  result.transaction.credit_card_details.customer_location.should == "US"
447
+ result.transaction.retrieval_reference_number.should_not be_nil
422
448
  end
423
449
 
424
450
  it "returns a successful network response code if successful" do
@@ -498,7 +524,7 @@ describe Braintree::Transaction do
498
524
  result.success?.should == true
499
525
  end
500
526
 
501
- it "accepts additional security parameters: risk data with customer_browser and customer_ip" do
527
+ it "accepts additional security parameters: risk data" do
502
528
  result = Braintree::Transaction.create(
503
529
  :type => "sale",
504
530
  :amount => Braintree::Test::TransactionAmounts::Authorize,
@@ -508,7 +534,10 @@ describe Braintree::Transaction do
508
534
  },
509
535
  :risk_data => {
510
536
  :customer_browser => "IE6",
511
- :customer_ip => "192.168.0.1"
537
+ :customer_device_id => "customer_device_id_012",
538
+ :customer_ip => "192.168.0.1",
539
+ :customer_location_zip => "91244",
540
+ :customer_tenure => "20",
512
541
  }
513
542
  )
514
543
 
@@ -687,6 +716,68 @@ describe Braintree::Transaction do
687
716
  codes.should include(Braintree::ErrorCodes::Address::CountryCodeNumericIsNotAccepted)
688
717
  end
689
718
 
719
+ it "returns an error if provided product sku is invalid" do
720
+ result = Braintree::Transaction.sale(
721
+ :amount => "100",
722
+ :credit_card => {
723
+ :number => "5105105105105100",
724
+ :expiration_date => "05/2012"
725
+ },
726
+ :product_sku => "product$ku!",
727
+ )
728
+
729
+ result.success?.should == false
730
+ result.errors.for(:transaction).on(:product_sku).map { |e| e.code }.should include(Braintree::ErrorCodes::Transaction::ProductSkuIsInvalid)
731
+ end
732
+
733
+ it "returns an error if provided shipping phone number is invalid" do
734
+ result = Braintree::Transaction.sale(
735
+ :amount => "100",
736
+ :credit_card => {
737
+ :number => "5105105105105100",
738
+ :expiration_date => "05/2012"
739
+ },
740
+ :shipping => {
741
+ :phone_number => "123-234-3456=098765"
742
+ }
743
+ )
744
+
745
+ result.success?.should == false
746
+ result.errors.for(:transaction).for(:shipping).on(:phone_number).map { |e| e.code }.should include(Braintree::ErrorCodes::Transaction::ShippingPhoneNumberIsInvalid)
747
+ end
748
+
749
+ it "returns an error if provided shipping method is invalid" do
750
+ result = Braintree::Transaction.sale(
751
+ :amount => "100",
752
+ :credit_card => {
753
+ :number => "5105105105105100",
754
+ :expiration_date => "05/2012"
755
+ },
756
+ :shipping => {
757
+ :shipping_method => "urgent"
758
+ }
759
+ )
760
+
761
+ result.success?.should == false
762
+ result.errors.for(:transaction).for(:shipping).on(:shipping_method).map { |e| e.code }.should include(Braintree::ErrorCodes::Transaction::ShippingMethodIsInvalid)
763
+ end
764
+
765
+ it "returns an error if provided billing phone number is invalid" do
766
+ result = Braintree::Transaction.sale(
767
+ :amount => "100",
768
+ :credit_card => {
769
+ :number => "5105105105105100",
770
+ :expiration_date => "05/2012"
771
+ },
772
+ :billing => {
773
+ :phone_number => "123-234-3456=098765"
774
+ }
775
+ )
776
+
777
+ result.success?.should == false
778
+ result.errors.for(:transaction).for(:billing).on(:phone_number).map { |e| e.code }.should include(Braintree::ErrorCodes::Transaction::BillingPhoneNumberIsInvalid)
779
+ end
780
+
690
781
  context "gateway rejection reason" do
691
782
  it "exposes the cvv gateway rejection reason" do
692
783
  old_merchant = Braintree::Configuration.merchant_id
@@ -804,16 +895,44 @@ describe Braintree::Transaction do
804
895
  end
805
896
 
806
897
  it "exposes the fraud gateway rejection reason" do
807
- result = Braintree::Transaction.sale(
808
- :amount => Braintree::Test::TransactionAmounts::Authorize,
809
- :credit_card => {
810
- :number => Braintree::Test::CreditCardNumbers::Fraud,
811
- :expiration_date => "05/2017",
812
- :cvv => "333"
813
- }
814
- )
815
- result.success?.should == false
816
- result.transaction.gateway_rejection_reason.should == Braintree::Transaction::GatewayRejectionReason::Fraud
898
+ with_advanced_fraud_integration_merchant do
899
+ result = Braintree::Transaction.sale(
900
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
901
+ :credit_card => {
902
+ :number => Braintree::Test::CreditCardNumbers::Fraud,
903
+ :expiration_date => "05/2017",
904
+ :cvv => "333"
905
+ }
906
+ )
907
+ result.success?.should == false
908
+ result.transaction.gateway_rejection_reason.should == Braintree::Transaction::GatewayRejectionReason::Fraud
909
+ end
910
+ end
911
+
912
+ it "exposes the risk_threshold gateway rejection reason (via test cc num)" do
913
+ with_advanced_fraud_integration_merchant do
914
+ result = Braintree::Transaction.sale(
915
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
916
+ :credit_card => {
917
+ :number => Braintree::Test::CreditCardNumbers::RiskThreshold,
918
+ :expiration_date => "05/2017",
919
+ :cvv => "333"
920
+ }
921
+ )
922
+ result.success?.should == false
923
+ result.transaction.gateway_rejection_reason.should == Braintree::Transaction::GatewayRejectionReason::RiskThreshold
924
+ end
925
+ end
926
+
927
+ it "exposes the risk_threshold gateway rejection reason (via test test nonce)" do
928
+ with_advanced_fraud_integration_merchant do
929
+ result = Braintree::Transaction.sale(
930
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
931
+ :payment_method_nonce => Braintree::Test::Nonce::GatewayRejectedRiskThresholds,
932
+ )
933
+ result.success?.should == false
934
+ result.transaction.gateway_rejection_reason.should == Braintree::Transaction::GatewayRejectionReason::RiskThreshold
935
+ end
817
936
  end
818
937
 
819
938
  it "exposes the token issuance gateway rejection reason" do
@@ -1645,6 +1764,7 @@ describe Braintree::Transaction do
1645
1764
  result.transaction.should_not be_nil
1646
1765
  apple_pay_details = result.transaction.apple_pay_details
1647
1766
  apple_pay_details.should_not be_nil
1767
+ apple_pay_details.bin.should_not be_nil
1648
1768
  apple_pay_details.card_type.should == Braintree::ApplePayCard::CardType::Visa
1649
1769
  apple_pay_details.payment_instrument_name.should == "Visa 8886"
1650
1770
  apple_pay_details.source_description.should == "Visa 8886"
@@ -1695,6 +1815,7 @@ describe Braintree::Transaction do
1695
1815
  result.transaction.should_not be_nil
1696
1816
  android_pay_details = result.transaction.android_pay_details
1697
1817
  android_pay_details.should_not be_nil
1818
+ android_pay_details.bin.should_not be_nil
1698
1819
  android_pay_details.card_type.should == Braintree::CreditCard::CardType::Discover
1699
1820
  android_pay_details.virtual_card_type.should == Braintree::CreditCard::CardType::Discover
1700
1821
  android_pay_details.last_4.should == "1117"
@@ -1704,6 +1825,7 @@ describe Braintree::Transaction do
1704
1825
  android_pay_details.expiration_year.to_i.should > 0
1705
1826
  android_pay_details.google_transaction_id.should == "google_transaction_id"
1706
1827
  android_pay_details.image_url.should_not be_nil
1828
+ android_pay_details.is_network_tokenized?.should == false
1707
1829
  android_pay_details.token.should be_nil
1708
1830
  android_pay_details.prepaid.should_not be_nil
1709
1831
  android_pay_details.healthcare.should_not be_nil
@@ -1735,6 +1857,7 @@ describe Braintree::Transaction do
1735
1857
  android_pay_details.expiration_year.to_i.should > 0
1736
1858
  android_pay_details.google_transaction_id.should == "google_transaction_id"
1737
1859
  android_pay_details.image_url.should_not be_nil
1860
+ android_pay_details.is_network_tokenized?.should == false
1738
1861
  android_pay_details.token.should_not be_nil
1739
1862
  end
1740
1863
 
@@ -1757,6 +1880,7 @@ describe Braintree::Transaction do
1757
1880
  android_pay_details.expiration_month.to_i.should > 0
1758
1881
  android_pay_details.expiration_year.to_i.should > 0
1759
1882
  android_pay_details.google_transaction_id.should == "google_transaction_id"
1883
+ android_pay_details.is_network_tokenized?.should == true
1760
1884
  end
1761
1885
 
1762
1886
  it "can create a transaction with a fake amex express checkout card nonce" do
@@ -2083,6 +2207,7 @@ describe Braintree::Transaction do
2083
2207
 
2084
2208
  result = Braintree::Transaction.create(
2085
2209
  :type => "sale",
2210
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2086
2211
  :amount => Braintree::Test::TransactionAmounts::Authorize,
2087
2212
  :credit_card => {
2088
2213
  :number => Braintree::Test::CreditCardNumbers::Visa,
@@ -2119,7 +2244,8 @@ describe Braintree::Transaction do
2119
2244
  result.transaction.gateway_rejection_reason.should == Braintree::Transaction::GatewayRejectionReason::ThreeDSecure
2120
2245
  end
2121
2246
 
2122
- it "can create a transaction without a three_d_secure token" do
2247
+
2248
+ it "can create a transaction without a three_d_secure_authentication_id" do
2123
2249
  result = Braintree::Transaction.create(
2124
2250
  :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2125
2251
  :type => "sale",
@@ -2132,41 +2258,174 @@ describe Braintree::Transaction do
2132
2258
  result.success?.should == true
2133
2259
  end
2134
2260
 
2135
- it "returns an error if sent a nil three_d_secure token" do
2136
- result = Braintree::Transaction.create(
2137
- :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2138
- :type => "sale",
2139
- :amount => Braintree::Test::TransactionAmounts::Authorize,
2140
- :credit_card => {
2261
+ context "with three_d_secure_authentication_id" do
2262
+ it "can create a transaction with a three_d_secure_authentication_id" do
2263
+ three_d_secure_authentication_id = SpecHelper.create_3ds_verification(
2264
+ SpecHelper::ThreeDSecureMerchantAccountId,
2141
2265
  :number => Braintree::Test::CreditCardNumbers::Visa,
2142
- :expiration_date => "12/12",
2143
- },
2144
- :three_d_secure_token => nil
2145
- )
2146
- result.success?.should == false
2147
- result.errors.for(:transaction).on(:three_d_secure_token)[0].code.should == Braintree::ErrorCodes::Transaction::ThreeDSecureTokenIsInvalid
2266
+ :expiration_month => "12",
2267
+ :expiration_year => "2022"
2268
+ )
2269
+
2270
+ result = Braintree::Transaction.create(
2271
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2272
+ :type => "sale",
2273
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
2274
+ :credit_card => {
2275
+ :number => Braintree::Test::CreditCardNumbers::Visa,
2276
+ :expiration_date => "12/22",
2277
+ },
2278
+ :three_d_secure_authentication_id => three_d_secure_authentication_id
2279
+ )
2280
+
2281
+ result.success?.should == true
2282
+ end
2283
+ it "returns an error if sent a nil three_d_secure_authentication_id" do
2284
+ result = Braintree::Transaction.create(
2285
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2286
+ :type => "sale",
2287
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
2288
+ :credit_card => {
2289
+ :number => Braintree::Test::CreditCardNumbers::Visa,
2290
+ :expiration_date => "12/12",
2291
+ },
2292
+ :three_d_secure_authentication_id => nil
2293
+ )
2294
+ result.success?.should == false
2295
+ result.errors.for(:transaction).on(:three_d_secure_authentication_id)[0].code.should == Braintree::ErrorCodes::Transaction::ThreeDSecureAuthenticationIdIsInvalid
2296
+ end
2297
+ it "returns an error if merchant_account in the payment_method does not match with 3ds data" do
2298
+ three_d_secure_authentication_id = SpecHelper.create_3ds_verification(
2299
+ SpecHelper::ThreeDSecureMerchantAccountId,
2300
+ :number => Braintree::Test::CreditCardNumbers::Visa,
2301
+ :expiration_month => "12",
2302
+ :expiration_year => "2012"
2303
+ )
2304
+
2305
+ result = Braintree::Transaction.create(
2306
+ :type => "sale",
2307
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
2308
+ :credit_card => {
2309
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
2310
+ :expiration_date => "12/12",
2311
+ },
2312
+ :three_d_secure_authentication_id => three_d_secure_authentication_id
2313
+ )
2314
+ result.success?.should == false
2315
+ result.errors.for(:transaction).on(:three_d_secure_authentication_id)[0].code.should == Braintree::ErrorCodes::Transaction::ThreeDSecureTransactionPaymentMethodDoesntMatchThreeDSecureAuthenticationPaymentMethod
2316
+ end
2317
+ it "returns an error if 3ds lookup data does not match txn data" do
2318
+ three_d_secure_authentication_id = SpecHelper.create_3ds_verification(
2319
+ SpecHelper::ThreeDSecureMerchantAccountId,
2320
+ :number => Braintree::Test::CreditCardNumbers::Visa,
2321
+ :expiration_month => "12",
2322
+ :expiration_year => "2012"
2323
+ )
2324
+
2325
+ result = Braintree::Transaction.create(
2326
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2327
+ :type => "sale",
2328
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
2329
+ :credit_card => {
2330
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
2331
+ :expiration_date => "12/12",
2332
+ },
2333
+ :three_d_secure_authentication_id => three_d_secure_authentication_id
2334
+ )
2335
+ result.success?.should == false
2336
+ result.errors.for(:transaction).on(:three_d_secure_authentication_id)[0].code.should == Braintree::ErrorCodes::Transaction::ThreeDSecureTransactionPaymentMethodDoesntMatchThreeDSecureAuthenticationPaymentMethod
2337
+ end
2338
+ it "returns an error if three_d_secure_authentication_id is supplied with three_d_secure_pass_thru" do
2339
+ three_d_secure_authentication_id = SpecHelper.create_3ds_verification(
2340
+ SpecHelper::ThreeDSecureMerchantAccountId,
2341
+ :number => Braintree::Test::CreditCardNumbers::Visa,
2342
+ :expiration_month => "12",
2343
+ :expiration_year => "2012"
2344
+ )
2345
+ result = Braintree::Transaction.create(
2346
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2347
+ :type => "sale",
2348
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
2349
+ :credit_card => {
2350
+ :number => Braintree::Test::CreditCardNumbers::Visa,
2351
+ :expiration_date => "12/12",
2352
+ },
2353
+ :three_d_secure_authentication_id => three_d_secure_authentication_id,
2354
+ :three_d_secure_pass_thru => {
2355
+ :eci_flag => "02",
2356
+ :cavv => "some_cavv",
2357
+ :xid => "some_xid",
2358
+ :three_d_secure_version => "1.0.2",
2359
+ :authentication_response => "Y",
2360
+ :directory_response => "Y",
2361
+ :cavv_algorithm => "2",
2362
+ :ds_transaction_id => "some_ds_id",
2363
+ }
2364
+ )
2365
+ result.success?.should == false
2366
+ result.errors.for(:transaction).on(:three_d_secure_authentication_id)[0].code.should == Braintree::ErrorCodes::Transaction::ThreeDSecureAuthenticationIdWithThreeDSecurePassThruIsInvalid
2367
+ end
2148
2368
  end
2149
2369
 
2150
- it "returns an error if 3ds lookup data does not match txn data" do
2151
- three_d_secure_token = SpecHelper.create_3ds_verification(
2152
- SpecHelper::ThreeDSecureMerchantAccountId,
2153
- :number => Braintree::Test::CreditCardNumbers::Visa,
2154
- :expiration_month => "12",
2155
- :expiration_year => "2012"
2156
- )
2370
+ context "with three_d_secure_token" do
2371
+ it "can create a transaction with a three_d_secure token" do
2372
+ three_d_secure_token = SpecHelper.create_3ds_verification(
2373
+ SpecHelper::ThreeDSecureMerchantAccountId,
2374
+ :number => Braintree::Test::CreditCardNumbers::Visa,
2375
+ :expiration_month => "12",
2376
+ :expiration_year => "2012"
2377
+ )
2157
2378
 
2158
- result = Braintree::Transaction.create(
2159
- :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2160
- :type => "sale",
2161
- :amount => Braintree::Test::TransactionAmounts::Authorize,
2162
- :credit_card => {
2163
- :number => Braintree::Test::CreditCardNumbers::MasterCard,
2164
- :expiration_date => "12/12",
2165
- },
2166
- :three_d_secure_token => three_d_secure_token
2167
- )
2168
- result.success?.should == false
2169
- result.errors.for(:transaction).on(:three_d_secure_token)[0].code.should == Braintree::ErrorCodes::Transaction::ThreeDSecureTransactionDataDoesntMatchVerify
2379
+ result = Braintree::Transaction.create(
2380
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2381
+ :type => "sale",
2382
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
2383
+ :credit_card => {
2384
+ :number => Braintree::Test::CreditCardNumbers::Visa,
2385
+ :expiration_date => "12/12",
2386
+ },
2387
+ :three_d_secure_token => three_d_secure_token
2388
+ )
2389
+
2390
+ result.success?.should == true
2391
+ end
2392
+
2393
+ it "returns an error if sent a nil three_d_secure token" do
2394
+ result = Braintree::Transaction.create(
2395
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2396
+ :type => "sale",
2397
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
2398
+ :credit_card => {
2399
+ :number => Braintree::Test::CreditCardNumbers::Visa,
2400
+ :expiration_date => "12/12",
2401
+ },
2402
+ :three_d_secure_token => nil
2403
+ )
2404
+ result.success?.should == false
2405
+ result.errors.for(:transaction).on(:three_d_secure_token)[0].code.should == Braintree::ErrorCodes::Transaction::ThreeDSecureTokenIsInvalid
2406
+ end
2407
+
2408
+ it "returns an error if 3ds lookup data does not match txn data" do
2409
+ three_d_secure_token = SpecHelper.create_3ds_verification(
2410
+ SpecHelper::ThreeDSecureMerchantAccountId,
2411
+ :number => Braintree::Test::CreditCardNumbers::Visa,
2412
+ :expiration_month => "12",
2413
+ :expiration_year => "2012"
2414
+ )
2415
+
2416
+ result = Braintree::Transaction.create(
2417
+ :merchant_account_id => SpecHelper::ThreeDSecureMerchantAccountId,
2418
+ :type => "sale",
2419
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
2420
+ :credit_card => {
2421
+ :number => Braintree::Test::CreditCardNumbers::MasterCard,
2422
+ :expiration_date => "12/12",
2423
+ },
2424
+ :three_d_secure_token => three_d_secure_token
2425
+ )
2426
+ result.success?.should == false
2427
+ result.errors.for(:transaction).on(:three_d_secure_token)[0].code.should == Braintree::ErrorCodes::Transaction::ThreeDSecureTransactionDataDoesntMatchVerify
2428
+ end
2170
2429
  end
2171
2430
 
2172
2431
  it "can create a transaction with a three_d_secure_pass_thru" do
@@ -2630,6 +2889,36 @@ describe Braintree::Transaction do
2630
2889
  result.success?.should == false
2631
2890
  result.errors.for(:transaction).on(:base)[0].code.should == Braintree::ErrorCodes::Transaction::CannotRefundUnlessSettled
2632
2891
  end
2892
+
2893
+ it "handles soft declined refund authorizations" do
2894
+ transaction = Braintree::Transaction.sale!(
2895
+ :amount => "9000.00",
2896
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2897
+ :options => {
2898
+ :submit_for_settlement => true
2899
+ }
2900
+ )
2901
+ config = Braintree::Configuration.instantiate
2902
+ response = config.http.put("#{config.base_merchant_path}/transactions/#{transaction.id}/settle")
2903
+ result = Braintree::Transaction.refund(transaction.id, :amount => "2046.00")
2904
+ result.success?.should == false
2905
+ result.errors.for(:transaction).on(:base)[0].code.should == Braintree::ErrorCodes::Transaction::RefundAuthSoftDeclined
2906
+ end
2907
+
2908
+ it "handles hard declined refund authorizations" do
2909
+ transaction = Braintree::Transaction.sale!(
2910
+ :amount => "9000.00",
2911
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2912
+ :options => {
2913
+ :submit_for_settlement => true
2914
+ }
2915
+ )
2916
+ config = Braintree::Configuration.instantiate
2917
+ response = config.http.put("#{config.base_merchant_path}/transactions/#{transaction.id}/settle")
2918
+ result = Braintree::Transaction.refund(transaction.id, :amount => "2009.00")
2919
+ result.success?.should == false
2920
+ result.errors.for(:transaction).on(:base)[0].code.should == Braintree::ErrorCodes::Transaction::RefundAuthHardDeclined
2921
+ end
2633
2922
  end
2634
2923
 
2635
2924
  context "handling errors" do
@@ -4365,6 +4654,7 @@ describe Braintree::Transaction do
4365
4654
  result = Braintree::Transaction.sale(
4366
4655
  :amount => "100.00",
4367
4656
  :order_id => "123",
4657
+ :product_sku => "productsku01",
4368
4658
  :channel => "MyShoppingCartProvider",
4369
4659
  :credit_card => {
4370
4660
  :cardholder_name => "The Cardholder",
@@ -4389,6 +4679,7 @@ describe Braintree::Transaction do
4389
4679
  :extended_address => "Suite 403",
4390
4680
  :locality => "Chicago",
4391
4681
  :region => "IL",
4682
+ :phone_number => "122-555-1237",
4392
4683
  :postal_code => "60622",
4393
4684
  :country_name => "United States of America"
4394
4685
  },
@@ -4400,8 +4691,10 @@ describe Braintree::Transaction do
4400
4691
  :extended_address => "Apt 2F",
4401
4692
  :locality => "Bartlett",
4402
4693
  :region => "IL",
4694
+ :phone_number => "122-555-1236",
4403
4695
  :postal_code => "60103",
4404
- :country_name => "United States of America"
4696
+ :country_name => "United States of America",
4697
+ :shipping_method => Braintree::Transaction::AddressDetails::ShippingMethod::Electronic
4405
4698
  }
4406
4699
  )
4407
4700
  result.success?.should == true
@@ -5086,6 +5379,71 @@ describe Braintree::Transaction do
5086
5379
  result.errors.for(:transaction).on(:amount)[0].code.should == Braintree::ErrorCodes::Transaction::SettlementAmountIsLessThanServiceFeeAmount
5087
5380
  end
5088
5381
  end
5382
+
5383
+ it "succeeds when level 2 data is provided" do
5384
+ result = Braintree::Transaction.sale(
5385
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
5386
+ :merchant_account_id => SpecHelper::FakeAmexDirectMerchantAccountId,
5387
+ :credit_card => {
5388
+ :number => Braintree::Test::CreditCardNumbers::AmexPayWithPoints::Success,
5389
+ :expiration_date => "05/2009"
5390
+ },
5391
+ :options => {
5392
+ :amex_rewards => {
5393
+ :request_id => "ABC123",
5394
+ :points => "1000",
5395
+ :currency_amount => "10.00",
5396
+ :currency_iso_code => "USD"
5397
+ }
5398
+ }
5399
+ )
5400
+ result.success?.should == true
5401
+
5402
+ result = Braintree::Transaction.submit_for_settlement(result.transaction.id, nil, :tax_amount => "2.00", :tax_exempt => false, :purchase_order_number => "0Rd3r#")
5403
+ result.success?.should == true
5404
+ result.transaction.status.should == Braintree::Transaction::Status::SubmittedForSettlement
5405
+ end
5406
+
5407
+ it "succeeds when level 3 data is provided" do
5408
+ result = Braintree::Transaction.sale(
5409
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
5410
+ :merchant_account_id => SpecHelper::FakeAmexDirectMerchantAccountId,
5411
+ :credit_card => {
5412
+ :number => Braintree::Test::CreditCardNumbers::AmexPayWithPoints::Success,
5413
+ :expiration_date => "05/2009"
5414
+ },
5415
+ :options => {
5416
+ :amex_rewards => {
5417
+ :request_id => "ABC123",
5418
+ :points => "1000",
5419
+ :currency_amount => "10.00",
5420
+ :currency_iso_code => "USD"
5421
+ }
5422
+ }
5423
+ )
5424
+ result.success?.should == true
5425
+
5426
+ result = Braintree::Transaction.submit_for_settlement(
5427
+ result.transaction.id,
5428
+ nil,
5429
+ :discount_amount => "2.00",
5430
+ :shipping_amount => "1.23",
5431
+ :ships_from_postal_code => "90210",
5432
+ :line_items => [
5433
+ {
5434
+ :quantity => 1,
5435
+ :unit_amount => 1,
5436
+ :name => "New line item",
5437
+ :kind => "debit",
5438
+ :total_amount => "18.00",
5439
+ :discount_amount => "12.00",
5440
+ :tax_amount => "0",
5441
+ },
5442
+ ]
5443
+ )
5444
+ result.success?.should == true
5445
+ result.transaction.status.should == Braintree::Transaction::Status::SubmittedForSettlement
5446
+ end
5089
5447
  end
5090
5448
 
5091
5449
  describe "self.submit_for_settlement!" do
@@ -5882,6 +6240,7 @@ describe Braintree::Transaction do
5882
6240
  created_transaction = result.transaction
5883
6241
  found_transaction = Braintree::Transaction.find(created_transaction.id)
5884
6242
  found_transaction.should == created_transaction
6243
+ found_transaction.graphql_id.should_not be_nil
5885
6244
  end
5886
6245
 
5887
6246
  it "finds the vaulted transaction with the given id" do
@@ -6802,4 +7161,37 @@ describe Braintree::Transaction do
6802
7161
  details.refund_id.should_not be_nil
6803
7162
  end
6804
7163
  end
7164
+
7165
+ describe "card on file network tokenization" do
7166
+ it "creates a transaction with a vaulted, tokenized credit card" do
7167
+ result = Braintree::Transaction.sale(
7168
+ :amount => "112.44",
7169
+ :payment_method_token => "network_tokenized_credit_card",
7170
+ )
7171
+ result.success?.should == true
7172
+ transaction = result.transaction
7173
+
7174
+ transaction.amount.should == BigDecimal("112.44")
7175
+ transaction.processed_with_network_token?.should == true
7176
+ end
7177
+
7178
+ it "creates a transaction with a vaulted, non-tokenized credit card" do
7179
+ customer = Braintree::Customer.create!
7180
+ result = Braintree::PaymentMethod.create(
7181
+ :payment_method_nonce => Braintree::Test::Nonce::TransactableVisa,
7182
+ :customer_id => customer.id
7183
+ )
7184
+ payment_method_token = result.payment_method.token
7185
+
7186
+ result = Braintree::Transaction.sale(
7187
+ :amount => "112.44",
7188
+ :payment_method_token => payment_method_token,
7189
+ )
7190
+ result.success?.should == true
7191
+ transaction = result.transaction
7192
+
7193
+ transaction.amount.should == BigDecimal("112.44")
7194
+ transaction.processed_with_network_token?.should == false
7195
+ end
7196
+ end
6805
7197
  end