braintree 2.101.0 → 2.102.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.
@@ -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