braintree 2.101.0 → 2.102.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -56,93 +56,83 @@ def nonce_for_paypal_account(paypal_account_details)
56
56
  end
57
57
 
58
58
  def generate_non_plaid_us_bank_account_nonce(account_number="1000000000")
59
- definition = <<-GRAPHQL
60
- mutation TokenizeUsBankAccount($input: TokenizeUsBankAccountInput!) {
61
- tokenizeUsBankAccount(input: $input) {
62
- paymentMethod {
63
- id
64
- }
65
- }
66
- }
67
- GRAPHQL
68
- variables = {
69
- input: {
70
- usBankAccount: {
71
- achMandate: "cl mandate text",
72
- routingNumber: "021000021",
73
- accountNumber: account_number,
74
- accountType: "CHECKING",
75
- individualOwner: {
76
- firstName: "John",
77
- lastName: "Doe",
78
- },
79
- billingAddress: {
80
- streetAddress: "123 Ave",
81
- city: "San Francisco",
82
- state: "CA",
83
- zipCode: "94112"
84
- }
85
- }
59
+ raw_client_token = Braintree::ClientToken.generate
60
+ client_token = decode_client_token(raw_client_token)
61
+
62
+ url = client_token["braintree_api"]["url"] + "/tokens"
63
+ token = client_token["braintree_api"]["access_token"]
64
+ payload = {
65
+ :type => "us_bank_account",
66
+ :billing_address => {
67
+ :street_address => "123 Ave",
68
+ :region => "CA",
69
+ :locality => "San Francisco",
70
+ :postal_code => "94112"
71
+ },
72
+ :account_type => "checking",
73
+ :routing_number => "021000021",
74
+ :account_number => account_number,
75
+ :first_name => "John",
76
+ :last_name => "Doe",
77
+ :ownership_type => "personal",
78
+ :ach_mandate => {
79
+ :text => "cl mandate text"
86
80
  }
87
81
  }
88
- response = Braintree::GraphQLClient.new(Braintree::Configuration.instantiate).query(definition, variables)
89
82
 
90
- response[:data][:tokenizeUsBankAccount][:paymentMethod][:id]
83
+ json = _cosmos_post(token, url, payload)
84
+ json["data"]["id"]
91
85
  end
92
86
 
93
87
  def generate_valid_plaid_us_bank_account_nonce
94
88
  raw_client_token = Braintree::ClientToken.generate
95
89
  client_token = decode_client_token(raw_client_token)
96
90
 
97
- url = client_token["graphQL"]["url"]
98
- date = client_token["graphQL"]["date"]
99
- token = client_token["authorizationFingerprint"]
100
-
101
- definition = <<-GRAPHQL
102
- mutation TokenizeUsBankLogin($input: TokenizeUsBankLoginInput!) {
103
- tokenizeUsBankLogin(input: $input) {
104
- paymentMethod {
105
- id
106
- }
107
- }
108
- }
109
- GRAPHQL
110
- variables = {
111
- input: {
112
- usBankLogin: {
113
- achMandate: "cl mandate text",
114
- publicToken: "good",
115
- accountId: "plaid_account_id",
116
- accountType: "CHECKING",
117
- businessOwner: {
118
- businessName: "PayPal, Inc."
119
- },
120
- billingAddress: {
121
- streetAddress: "123 Ave",
122
- city: "San Francisco",
123
- state: "CA",
124
- zipCode: "94112"
125
- }
126
- }
91
+ url = client_token["braintree_api"]["url"] + "/tokens"
92
+ token = client_token["braintree_api"]["access_token"]
93
+ payload = {
94
+ :type => "plaid_public_token",
95
+ :public_token => "good",
96
+ :account_id => "plaid_account_id",
97
+ :ownership_type => "business",
98
+ :business_name => "PayPal, Inc.",
99
+ :billing_address => {
100
+ :street_address => "123 Ave",
101
+ :region => "CA",
102
+ :locality => "San Francisco",
103
+ :postal_code => "94112"
104
+ },
105
+ :ach_mandate => {
106
+ :text => "cl mandate text"
127
107
  }
128
108
  }
109
+
110
+ json = _cosmos_post(token, url, payload)
111
+ json["data"]["id"]
112
+ end
113
+
114
+ def generate_valid_ideal_payment_nonce(amount = Braintree::Test::TransactionAmounts::Authorize)
115
+ raw_client_token = Braintree::ClientToken.generate(:merchant_account_id => "ideal_merchant_account")
116
+ client_token = decode_client_token(raw_client_token)
117
+ client = ClientApiHttp.new(
118
+ Braintree::Configuration.instantiate,
119
+ :authorization_fingerprint => client_token["authorizationFingerprint"],
120
+ )
121
+ config = JSON.parse(client.get_configuration.body)
122
+
123
+ token = client_token["braintree_api"]["access_token"]
124
+ url = client_token["braintree_api"]["url"] + "/ideal-payments"
129
125
  payload = {
130
- query: definition,
131
- variables: variables
126
+ :issuer => "RABONL2U",
127
+ :order_id => SpecHelper::DefaultOrderId,
128
+ :amount => amount,
129
+ :currency => "EUR",
130
+ :redirect_url => "https://braintree-api.com",
131
+ :route_id => config["ideal"]["routeId"]
132
132
  }
133
- uri = URI::parse(url)
134
- connection = Net::HTTP.new(uri.host, uri.port)
135
- connection.use_ssl = false
136
- response = connection.start do |http|
137
- request = Net::HTTP::Post.new(uri.path)
138
- request["Content-Type"] = "application/json"
139
- request["Braintree-Version"] = date
140
- request["Authorization"] = "Bearer #{token}"
141
- request.body = payload.to_json
142
- http.request(request)
143
- end
144
133
 
145
- JSON.parse(response.body)[:data][:tokenizeUsBankLogin][:paymentMethod][:id]
134
+ json = _cosmos_post(token, url, payload)
135
+ json["data"]["id"]
146
136
  end
147
137
 
148
138
  def sample(arr)
@@ -156,6 +146,23 @@ def generate_invalid_us_bank_account_nonce
156
146
  nonce += "_xxx"
157
147
  end
158
148
 
149
+ def _cosmos_post(token, url, payload)
150
+ uri = URI::parse(url)
151
+ connection = Net::HTTP.new(uri.host, uri.port)
152
+ connection.use_ssl = true
153
+ connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
154
+ resp = connection.start do |http|
155
+ request = Net::HTTP::Post.new(uri.path)
156
+ request["Content-Type"] = "application/json"
157
+ request["Braintree-Version"] = "2016-10-07"
158
+ request["Authorization"] = "Bearer #{token}"
159
+ request.body = payload.to_json
160
+ http.request(request)
161
+ end
162
+
163
+ JSON.parse(resp.body)
164
+ end
165
+
159
166
  class ClientApiHttp
160
167
  attr_reader :config, :options
161
168
 
@@ -227,6 +227,49 @@ describe Braintree::CreditCard do
227
227
  result.success?.should == true
228
228
  end
229
229
 
230
+ it "validates presence of three_d_secure_version in 3ds pass thru params" do
231
+ customer = Braintree::Customer.create!
232
+ result = Braintree::CreditCard.create(
233
+ :customer_id => customer.id,
234
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
235
+ :three_d_secure_pass_thru => {
236
+ :eci_flag => '02',
237
+ :cavv => 'some_cavv',
238
+ :xid => 'some_xid',
239
+ :authentication_response => 'Y',
240
+ :directory_response => 'Y',
241
+ :cavv_algorithm => '2',
242
+ :ds_transaction_id => 'some_ds_transaction_id',
243
+ },
244
+ :options => {:verify_card => true}
245
+ )
246
+ expect(result).not_to be_success
247
+ error = result.errors.for(:verification).first
248
+ expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::ThreeDSecureVersionIsRequired)
249
+ expect(error.message).to eq("ThreeDSecureVersion is required.")
250
+ end
251
+
252
+ it "accepts three_d_secure pass thru params in the request" do
253
+ customer = Braintree::Customer.create!
254
+ result = Braintree::CreditCard.create(
255
+ :customer_id => customer.id,
256
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
257
+ :three_d_secure_pass_thru => {
258
+ :eci_flag => '02',
259
+ :cavv => 'some_cavv',
260
+ :xid => 'some_xid',
261
+ :three_d_secure_version => '1.0.2',
262
+ :authentication_response => 'Y',
263
+ :directory_response => 'Y',
264
+ :cavv_algorithm => '2',
265
+ :ds_transaction_id => 'some_ds_transaction_id',
266
+ },
267
+ :options => {:verify_card => true}
268
+ )
269
+ result.success?.should == true
270
+
271
+ end
272
+
230
273
  it "returns 3DS info on cc verification" do
231
274
  customer = Braintree::Customer.create!
232
275
  result = Braintree::CreditCard.create(
@@ -844,6 +887,62 @@ describe Braintree::CreditCard do
844
887
  updated_credit_card.cardholder_name.should == "New Holder"
845
888
  end
846
889
 
890
+ it "validates presence of three_d_secure_version in 3ds pass thru params" do
891
+ customer = Braintree::Customer.create!
892
+ credit_card = Braintree::CreditCard.create!(
893
+ :cardholder_name => "Original Holder",
894
+ :customer_id => customer.id,
895
+ :cvv => "123",
896
+ :number => Braintree::Test::CreditCardNumbers::Visa,
897
+ :expiration_date => "05/2012"
898
+ )
899
+ result = Braintree::CreditCard.update(credit_card.token,
900
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
901
+ :three_d_secure_pass_thru => {
902
+ :eci_flag => '02',
903
+ :cavv => 'some_cavv',
904
+ :xid => 'some_xid',
905
+ :authentication_response => 'Y',
906
+ :directory_response => 'Y',
907
+ :cavv_algorithm => '2',
908
+ :ds_transaction_id => 'some_ds_transaction_id',
909
+ },
910
+ :options => {:verify_card => true}
911
+ )
912
+ expect(result).not_to be_success
913
+ error = result.errors.for(:verification).first
914
+ expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::ThreeDSecureVersionIsRequired)
915
+ expect(error.message).to eq("ThreeDSecureVersion is required.")
916
+ end
917
+
918
+ it "accepts three_d_secure pass thru params in the request" do
919
+ customer = Braintree::Customer.create!
920
+ credit_card = Braintree::CreditCard.create!(
921
+ :cardholder_name => "Original Holder",
922
+ :customer_id => customer.id,
923
+ :cvv => "123",
924
+ :number => Braintree::Test::CreditCardNumbers::Visa,
925
+ :expiration_date => "05/2012"
926
+ )
927
+ result = Braintree::CreditCard.update(credit_card.token,
928
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
929
+ :three_d_secure_pass_thru => {
930
+ :eci_flag => '02',
931
+ :cavv => 'some_cavv',
932
+ :three_d_secure_version=> "2.1.0",
933
+ :xid => 'some_xid',
934
+ :authentication_response => 'Y',
935
+ :directory_response => 'Y',
936
+ :cavv_algorithm => '2',
937
+ :ds_transaction_id => 'some_ds_transaction_id',
938
+ },
939
+ :options => {:verify_card => true}
940
+ )
941
+
942
+ result.success?.should == true
943
+
944
+ end
945
+
847
946
  context "billing address" do
848
947
  it "creates a new billing address by default" do
849
948
  customer = Braintree::Customer.create!
@@ -1115,6 +1115,74 @@ describe Braintree::Customer do
1115
1115
  end
1116
1116
 
1117
1117
  describe "self.update" do
1118
+ it "updates the credit card with three_d_secure pass thru params" do
1119
+ customer = Braintree::Customer.create!(
1120
+ :first_name => "Joe",
1121
+ :last_name => "Cool"
1122
+ )
1123
+ result = Braintree::Customer.update(
1124
+ customer.id,
1125
+ :first_name => "Mr. Joe",
1126
+ :last_name => "Super Cool",
1127
+ :custom_fields => {
1128
+ :store_me => "a value"
1129
+ },
1130
+ :credit_card => {
1131
+ :number => 4111111111111111,
1132
+ :expiration_date => "05/2060",
1133
+ :three_d_secure_pass_thru => {
1134
+ :eci_flag => '02',
1135
+ :cavv => 'some_cavv',
1136
+ :xid => 'some_xid',
1137
+ :three_d_secure_version => '1.0.2',
1138
+ :authentication_response => 'Y',
1139
+ :directory_response => 'Y',
1140
+ :cavv_algorithm => '2',
1141
+ :ds_transaction_id => 'some_ds_transaction_id',
1142
+ },
1143
+ :options => {:verify_card => true},
1144
+ }
1145
+ )
1146
+ result.success?.should == true
1147
+ result.customer.id.should == customer.id
1148
+ result.customer.first_name.should == "Mr. Joe"
1149
+ result.customer.last_name.should == "Super Cool"
1150
+ result.customer.custom_fields[:store_me].should == "a value"
1151
+ end
1152
+
1153
+ it "validates the presence of three_d_secure_version while passing three_d_secure_pass_thru in update" do
1154
+ customer = Braintree::Customer.create!(
1155
+ :first_name => "Joe",
1156
+ :last_name => "Cool"
1157
+ )
1158
+ result = Braintree::Customer.update(
1159
+ customer.id,
1160
+ :first_name => "Mr. Joe",
1161
+ :last_name => "Super Cool",
1162
+ :custom_fields => {
1163
+ :store_me => "a value"
1164
+ },
1165
+ :credit_card => {
1166
+ :number => 4111111111111111,
1167
+ :expiration_date => "05/2060",
1168
+ :three_d_secure_pass_thru => {
1169
+ :eci_flag => '02',
1170
+ :cavv => 'some_cavv',
1171
+ :xid => 'some_xid',
1172
+ :authentication_response => 'Y',
1173
+ :directory_response => 'Y',
1174
+ :cavv_algorithm => '2',
1175
+ :ds_transaction_id => 'some_ds_transaction_id',
1176
+ },
1177
+ options: {:verify_card => true}
1178
+ }
1179
+ )
1180
+ expect(result).to_not be_success
1181
+ error = result.errors.for(:verification).first
1182
+ expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::ThreeDSecureVersionIsRequired)
1183
+ expect(error.message).to eq("ThreeDSecureVersion is required.")
1184
+ end
1185
+
1118
1186
  it "updates the customer with the given id if successful" do
1119
1187
  customer = Braintree::Customer.create!(
1120
1188
  :first_name => "Joe",
@@ -1312,6 +1380,51 @@ describe Braintree::Customer do
1312
1380
  result.success?.should == true
1313
1381
  end
1314
1382
 
1383
+ it "validates presence of three_d_secure_version in 3ds pass thru params" do
1384
+ result = Braintree::Customer.create(
1385
+ :payment_method_nonce => Braintree::Test::Nonce::ThreeDSecureVisaFullAuthentication,
1386
+ :credit_card => {
1387
+ :three_d_secure_pass_thru => {
1388
+ :eci_flag => '02',
1389
+ :cavv => 'some_cavv',
1390
+ :xid => 'some_xid',
1391
+ :three_d_secure_version => 'xx',
1392
+ :authentication_response => 'Y',
1393
+ :directory_response => 'Y',
1394
+ :cavv_algorithm => '2',
1395
+ :ds_transaction_id => 'some_ds_transaction_id',
1396
+ },
1397
+ :options => {:verify_card => true}
1398
+ }
1399
+ )
1400
+
1401
+ expect(result).not_to be_success
1402
+ error = result.errors.for(:verification).first
1403
+ expect(error.code).to eq(Braintree::ErrorCodes::Verification::ThreeDSecurePassThru::ThreeDSecureVersionIsInvalid)
1404
+ 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`).")
1405
+ end
1406
+
1407
+ it "accepts three_d_secure pass thru params in the request" do
1408
+ result = Braintree::Customer.create(
1409
+ :payment_method_nonce => Braintree::Test::Nonce::ThreeDSecureVisaFullAuthentication,
1410
+ :credit_card => {
1411
+ :three_d_secure_pass_thru => {
1412
+ :eci_flag => '02',
1413
+ :cavv => 'some_cavv',
1414
+ :xid => 'some_xid',
1415
+ :three_d_secure_version => '2.2.1',
1416
+ :authentication_response => 'Y',
1417
+ :directory_response => 'Y',
1418
+ :cavv_algorithm => '2',
1419
+ :ds_transaction_id => 'some_ds_transaction_id',
1420
+ },
1421
+ :options => {:verify_card => true}
1422
+ }
1423
+ )
1424
+
1425
+ expect(result).to be_success
1426
+ end
1427
+
1315
1428
  it "returns 3DS info on cc verification" do
1316
1429
  result = Braintree::Customer.create(
1317
1430
  :payment_method_nonce => Braintree::Test::Nonce::ThreeDSecureVisaFullAuthentication,
@@ -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")
@@ -239,5 +239,82 @@ describe Braintree::PaymentMethodNonce do
239
239
  Braintree::PaymentMethodNonce.find("not_a_nonce")
240
240
  end.to raise_error(Braintree::NotFoundError)
241
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
242
319
  end
243
320
  end