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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/lib/braintree/client_token_gateway.rb +10 -1
  3. data/lib/braintree/credit_card_gateway.rb +9 -3
  4. data/lib/braintree/credit_card_verification_gateway.rb +3 -0
  5. data/lib/braintree/customer_gateway.rb +11 -3
  6. data/lib/braintree/error_codes.rb +12 -0
  7. data/lib/braintree/http.rb +4 -2
  8. data/lib/braintree/merchant_account_gateway.rb +2 -0
  9. data/lib/braintree/payment_method_gateway.rb +6 -1
  10. data/lib/braintree/payment_method_nonce_gateway.rb +4 -0
  11. data/lib/braintree/paypal_account_gateway.rb +6 -1
  12. data/lib/braintree/plan_gateway.rb +4 -0
  13. data/lib/braintree/sepa_direct_debit_account_gateway.rb +4 -0
  14. data/lib/braintree/subscription_gateway.rb +6 -0
  15. data/lib/braintree/testing_gateway.rb +4 -0
  16. data/lib/braintree/transaction.rb +14 -0
  17. data/lib/braintree/transaction_gateway.rb +39 -7
  18. data/lib/braintree/transaction_line_item_gateway.rb +3 -1
  19. data/lib/braintree/transaction_search.rb +1 -0
  20. data/lib/braintree/us_bank_account_gateway.rb +2 -0
  21. data/lib/braintree/us_bank_account_verification_gateway.rb +4 -0
  22. data/lib/braintree/version.rb +1 -1
  23. data/spec/integration/braintree/apple_pay_spec.rb +3 -1
  24. data/spec/integration/braintree/client_api/client_token_spec.rb +14 -0
  25. data/spec/integration/braintree/credit_card_spec.rb +31 -0
  26. data/spec/integration/braintree/credit_card_verification_spec.rb +54 -0
  27. data/spec/integration/braintree/customer_spec.rb +58 -0
  28. data/spec/integration/braintree/transaction_idempotency_spec.rb +30 -0
  29. data/spec/integration/braintree/transaction_search_spec.rb +95 -0
  30. data/spec/integration/braintree/transaction_spec.rb +211 -1
  31. data/spec/unit/braintree/client_token_spec.rb +72 -0
  32. data/spec/unit/braintree/credit_card_spec.rb +28 -2
  33. data/spec/unit/braintree/credit_card_verification_gateway_spec.rb +1 -0
  34. data/spec/unit/braintree/credit_card_verification_spec.rb +8 -0
  35. data/spec/unit/braintree/customer_spec.rb +28 -2
  36. data/spec/unit/braintree/http_spec.rb +44 -0
  37. data/spec/unit/braintree/merchant_account_spec.rb +11 -0
  38. data/spec/unit/braintree/package_tracking_spec.rb +2 -2
  39. data/spec/unit/braintree/payment_method_nonce_spec.rb +14 -0
  40. data/spec/unit/braintree/payment_method_spec.rb +20 -0
  41. data/spec/unit/braintree/paypal_account_spec.rb +20 -0
  42. data/spec/unit/braintree/plan_gateway_spec.rb +30 -0
  43. data/spec/unit/braintree/sepa_debit_account_spec.rb +14 -0
  44. data/spec/unit/braintree/subscription_spec.rb +20 -0
  45. data/spec/unit/braintree/test_transaction_spec.rb +18 -0
  46. data/spec/unit/braintree/transaction_gateway_spec.rb +24 -0
  47. data/spec/unit/braintree/transaction_line_item_spec.rb +11 -0
  48. data/spec/unit/braintree/transaction_search_spec.rb +25 -0
  49. data/spec/unit/braintree/transaction_spec.rb +68 -6
  50. data/spec/unit/braintree/us_bank_account_spec.rb +8 -0
  51. data/spec/unit/braintree/us_bank_account_verification_spec.rb +14 -0
  52. data/spec/unit/braintree/util_spec.rb +37 -0
  53. metadata +7 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a358a5cff7db74d5364a662ed1076dd786742d6d6f75b0f9c040fda06353a955
4
- data.tar.gz: b78e2a6f20ab1207515ea76f3e7aaa6a367283b10821b026c9f89498e2e8f35c
3
+ metadata.gz: 8ec866027a8aca5a627799053012f7e992155e64b4c318e1f8da68bf0a395a84
4
+ data.tar.gz: d4900837bac1f44acc8f0a9b976d75d6b1a60bde93df1a7cbdabf19bf623de2b
5
5
  SHA512:
6
- metadata.gz: 7fbb0b0ca10ec35cd3e8e6d34476eaada51e465caf4aa25a00e6d61fdbafea147a25579ed012717f2b2fec3da184d823dd0756add7738d8e4bcf1a8abea1dd2d
7
- data.tar.gz: 7374cd696e006db551149f9363194c3a8ecafc7ec607b93b6a53f2eeb3eb2961e4b63bd68d20c2ea0f5262fab405597e924219b7e76fd514b0a398c367fa7403
6
+ metadata.gz: e6c03eb513ad06b6fcaabc57167e2398c5a1d36c82f6863f30dcb57e6f1a40a43142f2b8c4591eb594eb36e4fc0d6c4cf2b9a3b756c77450501d5d6c2baa6652
7
+ data.tar.gz: e4f00316d23efaf9bee33c0af67d05e7a013e7c4a32224f810a4c39a72135e0fd977c57077e816c4fddad6e8e6e95245e6f0eb2888c00f96dec25f8ecbe0e0e1
@@ -9,12 +9,21 @@ module Braintree
9
9
  end
10
10
 
11
11
  def generate(options={})
12
+ options = options.dup
13
+
12
14
  _validate_options(options)
13
15
 
14
16
  options[:version] ||= ClientToken::DEFAULT_VERSION
15
17
 
16
18
  Util.verify_keys(ClientTokenGateway._generate_signature, options)
17
19
 
20
+ if options.has_key?(:preferred_payment_method_token)
21
+ options[:payment_method_id] = options.delete(:preferred_payment_method_token)
22
+ options.delete("preferred_payment_method_token")
23
+ elsif options.has_key?("preferred_payment_method_token")
24
+ options[:payment_method_id] = options.delete("preferred_payment_method_token")
25
+ end
26
+
18
27
  params = {:client_token => options}
19
28
  result = @config.http.post("#{@config.base_merchant_path}/client_token", params)
20
29
 
@@ -27,7 +36,7 @@ module Braintree
27
36
 
28
37
  def self._generate_signature
29
38
  [
30
- :address_id, :customer_id, :proxy_merchant_id, :merchant_account_id,
39
+ :address_id, :customer_id, :merchant_account_id, :preferred_payment_method_token, :proxy_merchant_id,
31
40
  :version,
32
41
  {:domains => [:_any_key_]},
33
42
  {:options => [:fail_on_duplicate_payment_method, :fail_on_duplicate_payment_method_for_customer, :make_default, :verify_card]}
@@ -39,6 +39,8 @@ module Braintree
39
39
  end
40
40
 
41
41
  def delete(token)
42
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
43
+
42
44
  @config.http.delete("#{@config.base_merchant_path}/payment_methods/credit_card/#{token}")
43
45
  end
44
46
 
@@ -55,7 +57,8 @@ module Braintree
55
57
  end
56
58
 
57
59
  def find(token)
58
- raise ArgumentError if token.nil? || token.to_s.strip == ""
60
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
61
+
59
62
  response = @config.http.get("#{@config.base_merchant_path}/payment_methods/credit_card/#{token}")
60
63
  CreditCard._new(@gateway, response[:credit_card])
61
64
  rescue NotFoundError
@@ -63,7 +66,8 @@ module Braintree
63
66
  end
64
67
 
65
68
  def from_nonce(nonce)
66
- raise ArgumentError if nonce.nil? || nonce.to_s.strip == ""
69
+ raise ArgumentError, "nonce contains invalid characters" if Util.invalid_path_segment?(nonce)
70
+
67
71
  response = @config.http.get("#{@config.base_merchant_path}/payment_methods/from_nonce/#{nonce}")
68
72
  CreditCard._new(@gateway, response[:credit_card])
69
73
  rescue NotFoundError
@@ -71,6 +75,8 @@ module Braintree
71
75
  end
72
76
 
73
77
  def update(token, attributes)
78
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
79
+
74
80
  # NEXT_MAJOR_VERSION remove this check
75
81
  if attributes.has_key?(:venmo_sdk_payment_method_code) || attributes.has_key?(:venmo_sdk_session)
76
82
  warn "[DEPRECATED] The Venmo SDK integration is Unsupported. Please update your integration to use Pay with Venmo instead."
@@ -114,7 +120,7 @@ module Braintree
114
120
  :billing_address_id, :cardholder_name, :cvv, :expiration_date, :expiration_month,
115
121
  :expiration_year, :number, :token, :venmo_sdk_payment_method_code, # Deprecated
116
122
  :device_data, :payment_method_nonce,
117
- {:external_vault => [:network_transaction_id]},
123
+ {:external_vault => [:network_transaction_id, :mastercard_transaction_link_id]},
118
124
  {:options => options},
119
125
  {:billing_address => billing_address_params}
120
126
  ]
@@ -8,6 +8,8 @@ module Braintree
8
8
 
9
9
  def find(id)
10
10
  raise ArgumentError if id.nil? || id.to_s.strip == ""
11
+ raise ArgumentError, "id contains invalid characters" if Util.invalid_path_segment?(id)
12
+
11
13
  response = @config.http.get("#{@config.base_merchant_path}/verifications/#{id}")
12
14
  CreditCardVerification._new(response[:verification])
13
15
  rescue NotFoundError
@@ -59,6 +61,7 @@ module Braintree
59
61
  ]},
60
62
  {:external_vault => [
61
63
  :previous_network_transaction_id,
64
+ :previous_mastercard_transaction_link_id,
62
65
  :status,
63
66
  ]},
64
67
  :intended_transaction_source,
@@ -23,15 +23,19 @@ module Braintree
23
23
  end
24
24
 
25
25
  def delete(customer_id)
26
+ raise ArgumentError, "customer_id contains invalid characters" if Util.invalid_path_segment?(customer_id)
27
+
26
28
  @config.http.delete("#{@config.base_merchant_path}/customers/#{customer_id}")
27
29
  SuccessfulResult.new
28
30
  end
29
31
 
30
32
  def find(customer_id, options = {})
31
- raise ArgumentError, "customer_id contains invalid characters" unless customer_id.to_s =~ /\A[\w-]+\z/
32
- raise ArgumentError, "customer_id cannot be blank" if customer_id.nil?|| customer_id.to_s.strip == ""
33
+ raise ArgumentError, "customer_id contains invalid characters" if Util.invalid_path_segment?(customer_id)
34
+
35
+ association_filter_id = options[:association_filter_id]
36
+ raise ArgumentError, "association_filter_id contains invalid characters" if association_filter_id && Util.invalid_path_segment?(association_filter_id)
33
37
 
34
- query_params = options[:association_filter_id].nil? ? "" : "?association_filter_id=#{options[:association_filter_id]}"
38
+ query_params = association_filter_id.nil? ? "" : "?association_filter_id=#{association_filter_id}"
35
39
  response = @config.http.get("#{@config.base_merchant_path}/customers/#{customer_id}#{query_params}")
36
40
  Customer._new(@gateway, response[:customer])
37
41
  rescue NotFoundError
@@ -47,11 +51,15 @@ module Braintree
47
51
  end
48
52
 
49
53
  def transactions(customer_id, options = {})
54
+ raise ArgumentError, "customer_id contains invalid characters" if Util.invalid_path_segment?(customer_id)
55
+
50
56
  response = @config.http.post("#{@config.base_merchant_path}/customers/#{customer_id}/transaction_ids")
51
57
  ResourceCollection.new(response) { |ids| _fetch_transactions(customer_id, ids) }
52
58
  end
53
59
 
54
60
  def update(customer_id, attributes)
61
+ raise ArgumentError, "customer_id contains invalid characters" if Util.invalid_path_segment?(customer_id)
62
+
55
63
  Util.verify_keys(CustomerGateway._update_signature, attributes)
56
64
  _do_update(:put, "/customers/#{customer_id}", :customer => attributes)
57
65
  end
@@ -120,6 +120,10 @@ module Braintree
120
120
  VerificationAccountTypeNotSupported = "91758"
121
121
  VerificationNotSupportedOnThisMerchantAccount = "91730"
122
122
 
123
+ module ExternalVault
124
+ MastercardTransactionLinkIdIsInvalid = "91767"
125
+ end
126
+
123
127
  module Options
124
128
  UpdateExistingTokenIsInvalid = "91723"
125
129
  UpdateExistingTokenNotAllowed = "91729"
@@ -367,6 +371,7 @@ module Braintree
367
371
  CannotRefundUnlessSettled = "91506"
368
372
  CannotRefundWithPendingMerchantAccount = "91559"
369
373
  CannotRefundWithSuspendedMerchantAccount = "91538"
374
+ CannotReverseAtThisTime = "915282"
370
375
  CannotSimulateTransactionSettlement = "91575"
371
376
  CannotSubmitForSettlement = "91507"
372
377
  CannotUpdateTransactionDetailsNotSubmittedForSettlement = "915129"
@@ -613,8 +618,10 @@ module Braintree
613
618
  end
614
619
 
615
620
  module ExternalVault
621
+ PreviousMastercardTransactionLinkIdIsInvalid = "915279"
616
622
  PreviousNetworkTransactionIdIsInvalid = "915179"
617
623
  StatusIsInvalid = "915175"
624
+ StatusWithPreviousMastercardTransactionLinkIdIsInvalid = "915278"
618
625
  StatusWithPreviousNetworkTransactionIdIsInvalid = "915177"
619
626
  end
620
627
  end
@@ -745,6 +752,11 @@ module Braintree
745
752
  end
746
753
 
747
754
  module Verification
755
+ module ExternalVault
756
+ PreviousMastercardTransactionLinkIdIsInvalid = "942206"
757
+ StatusWithPreviousMastercardTransactionLinkIdIsInvalid = "942205"
758
+ end
759
+
748
760
  module Options
749
761
  AccountTypeIsInvalid = "942184"
750
762
  AccountTypeNotSupported = "942185"
@@ -8,7 +8,8 @@ module Braintree
8
8
  end
9
9
 
10
10
  def delete(path, query_params = {})
11
- response = _http_do Net::HTTP::Delete, path
11
+ full_path = path + _build_query_string(query_params)
12
+ response = _http_do Net::HTTP::Delete, full_path
12
13
  if response.code.to_i == 200 || response.code.to_i == 204
13
14
  true
14
15
  elsif response.code.to_i == 422
@@ -19,7 +20,8 @@ module Braintree
19
20
  end
20
21
 
21
22
  def get(path, query_params = {})
22
- response = _http_do Net::HTTP::Get, path
23
+ full_path = path + _build_query_string(query_params)
24
+ response = _http_do Net::HTTP::Get, full_path
23
25
  if response.code.to_i == 200 || response.code.to_i == 422
24
26
  Xml.hash_from_xml(_body(response))
25
27
  else
@@ -22,6 +22,8 @@ module Braintree
22
22
 
23
23
  def find(merchant_account_id)
24
24
  raise ArgumentError if merchant_account_id.nil? || merchant_account_id.to_s.strip == ""
25
+ raise ArgumentError, "merchant_account_id contains invalid characters" if Util.invalid_path_segment?(merchant_account_id)
26
+
25
27
  response = @config.http.get("#{@config.base_merchant_path}/merchant_accounts/#{merchant_account_id}")
26
28
  MerchantAccount._new(@gateway, response[:merchant_account])
27
29
  rescue NotFoundError
@@ -33,6 +33,8 @@ module Braintree
33
33
  end
34
34
 
35
35
  def delete(token, options = {})
36
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
37
+
36
38
  Util.verify_keys(PaymentMethodGateway._delete_signature, options)
37
39
  query_param = "?" + Util.hash_to_query_string(options) if not options.empty?
38
40
  @config.http.delete("#{@config.base_merchant_path}/payment_methods/any/#{token}#{query_param}")
@@ -40,7 +42,8 @@ module Braintree
40
42
  end
41
43
 
42
44
  def find(token)
43
- raise ArgumentError if token.nil? || token.to_s.strip == ""
45
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
46
+
44
47
  response = @config.http.get("#{@config.base_merchant_path}/payment_methods/any/#{token}")
45
48
  if response.has_key?(:credit_card)
46
49
  CreditCard._new(@gateway, response[:credit_card])
@@ -64,6 +67,8 @@ module Braintree
64
67
  end
65
68
 
66
69
  def update(token, attributes)
70
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
71
+
67
72
  # NEXT_MAJOR_VERSION remove this check
68
73
  if attributes.has_key?(:venmo_sdk_payment_method_code) || attributes.has_key?(:venmo_sdk_session)
69
74
  warn "[DEPRECATED] The Venmo SDK integration is Unsupported. Please update your integration to use Pay with Venmo instead."
@@ -9,6 +9,8 @@ module Braintree
9
9
  end
10
10
 
11
11
  def create(payment_method_token, args = {payment_method_nonce: {}})
12
+ raise ArgumentError, "payment_method_token contains invalid characters" if Util.invalid_path_segment?(payment_method_token)
13
+
12
14
  Util.verify_keys(PaymentMethodNonceGateway._create_signature, args)
13
15
 
14
16
  response = @config.http.post("#{@config.base_merchant_path}/payment_methods/#{payment_method_token}/nonces", args)
@@ -30,6 +32,8 @@ module Braintree
30
32
  end
31
33
 
32
34
  def find(payment_method_nonce)
35
+ raise ArgumentError, "payment_method_nonce contains invalid characters" if Util.invalid_path_segment?(payment_method_nonce)
36
+
33
37
  response = @config.http.get("#{@config.base_merchant_path}/payment_method_nonces/#{payment_method_nonce}")
34
38
  payment_method_nonce = PaymentMethodNonce._new(@gateway, response.fetch(:payment_method_nonce))
35
39
  SuccessfulResult.new(:payment_method_nonce => payment_method_nonce)
@@ -7,7 +7,8 @@ module Braintree
7
7
  end
8
8
 
9
9
  def find(token)
10
- raise ArgumentError if token.nil? || token.to_s.strip == ""
10
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
11
+
11
12
  response = @config.http.get("#{@config.base_merchant_path}/payment_methods/paypal_account/#{token}")
12
13
  PayPalAccount._new(@gateway, response[:paypal_account])
13
14
  rescue NotFoundError
@@ -20,11 +21,15 @@ module Braintree
20
21
  end
21
22
 
22
23
  def update(token, attributes)
24
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
25
+
23
26
  Util.verify_keys(PayPalAccountGateway._update_signature, attributes)
24
27
  _do_update(:put, "/payment_methods/paypal_account/#{token}", :paypal_account => attributes)
25
28
  end
26
29
 
27
30
  def delete(token)
31
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
32
+
28
33
  @config.http.delete("#{@config.base_merchant_path}/payment_methods/paypal_account/#{token}")
29
34
  end
30
35
 
@@ -27,6 +27,8 @@ module Braintree
27
27
 
28
28
  def find(id)
29
29
  raise ArgumentError if id.nil? || id.to_s.strip == ""
30
+ raise ArgumentError, "id contains invalid characters" if Util.invalid_path_segment?(id)
31
+
30
32
  response = @config.http.get("#{@config.base_merchant_path}/plans/#{id}")
31
33
  Plan._new(@gateway, response[:plan])
32
34
  rescue NotFoundError
@@ -34,6 +36,8 @@ module Braintree
34
36
  end
35
37
 
36
38
  def update(plan_id, attributes)
39
+ raise ArgumentError, "plan_id contains invalid characters" if Util.invalid_path_segment?(plan_id)
40
+
37
41
  Util.verify_keys(PlanGateway._update_signature, attributes)
38
42
  response = @config.http.put("#{@config.base_merchant_path}/plans/#{plan_id}", :plan => attributes)
39
43
  if response[:plan]
@@ -8,6 +8,8 @@ module Braintree
8
8
 
9
9
  def find(token)
10
10
  raise ArgumentError if token.nil? || token.to_s.strip == ""
11
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
12
+
11
13
  response = @config.http.get("#{@config.base_merchant_path}/payment_methods/sepa_debit_account/#{token}")
12
14
  SepaDirectDebitAccount._new(@gateway, response[:sepa_debit_account])
13
15
  rescue NotFoundError
@@ -16,6 +18,8 @@ module Braintree
16
18
 
17
19
  def delete(token)
18
20
  raise ArgumentError if token.nil? || token.to_s.strip == ""
21
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
22
+
19
23
  @config.http.delete("#{@config.base_merchant_path}/payment_methods/sepa_debit_account/#{token}")
20
24
  SuccessfulResult.new
21
25
  rescue NotFoundError
@@ -9,6 +9,8 @@ module Braintree
9
9
  end
10
10
 
11
11
  def cancel(subscription_id)
12
+ raise ArgumentError, "subscription_id contains invalid characters" if Util.invalid_path_segment?(subscription_id)
13
+
12
14
  response = @config.http.put("#{@config.base_merchant_path}/subscriptions/#{subscription_id}/cancel")
13
15
  if response[:subscription]
14
16
  SuccessfulResult.new(:subscription => Subscription._new(@gateway, response[:subscription]))
@@ -36,6 +38,8 @@ module Braintree
36
38
 
37
39
  def find(id)
38
40
  raise ArgumentError if id.nil? || id.to_s.strip == ""
41
+ raise ArgumentError, "id contains invalid characters" if Util.invalid_path_segment?(id)
42
+
39
43
  response = @config.http.get("#{@config.base_merchant_path}/subscriptions/#{id}")
40
44
  Subscription._new(@gateway, response[:subscription])
41
45
  rescue NotFoundError
@@ -55,6 +59,8 @@ module Braintree
55
59
  end
56
60
 
57
61
  def update(subscription_id, attributes)
62
+ raise ArgumentError, "subscription_id contains invalid characters" if Util.invalid_path_segment?(subscription_id)
63
+
58
64
  Util.verify_keys(SubscriptionGateway._update_signature, attributes)
59
65
  response = @config.http.put("#{@config.base_merchant_path}/subscriptions/#{subscription_id}", :subscription => attributes)
60
66
  if response[:subscription]
@@ -10,6 +10,7 @@ module Braintree
10
10
 
11
11
  def settle(transaction_id)
12
12
  check_environment
13
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
13
14
 
14
15
  response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/settle")
15
16
  @transaction_gateway._handle_transaction_response(response)
@@ -17,6 +18,7 @@ module Braintree
17
18
 
18
19
  def settlement_confirm(transaction_id)
19
20
  check_environment
21
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
20
22
 
21
23
  response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/settlement_confirm")
22
24
  @transaction_gateway._handle_transaction_response(response)
@@ -24,6 +26,7 @@ module Braintree
24
26
 
25
27
  def settlement_decline(transaction_id)
26
28
  check_environment
29
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
27
30
 
28
31
  response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/settlement_decline")
29
32
  @transaction_gateway._handle_transaction_response(response)
@@ -31,6 +34,7 @@ module Braintree
31
34
 
32
35
  def settlement_pending(transaction_id)
33
36
  check_environment
37
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
34
38
 
35
39
  response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/settlement_pending")
36
40
  @transaction_gateway._handle_transaction_response(response)
@@ -3,6 +3,12 @@ module Braintree
3
3
  include BaseModule
4
4
  include Braintree::Util::IdEquality
5
5
 
6
+ module AchType
7
+ SameDay = "same_day"
8
+ Standard = "standard"
9
+ All = constants.map { |c| const_get(c) }
10
+ end
11
+
6
12
  module CreatedUsing
7
13
  FullInformation = "full_information"
8
14
  Token = "token"
@@ -241,6 +247,14 @@ module Braintree
241
247
  Configuration.gateway.transaction.refund!(*args)
242
248
  end
243
249
 
250
+ def self.reverse(*args)
251
+ Configuration.gateway.transaction.reverse(*args)
252
+ end
253
+
254
+ def self.reverse!(*args)
255
+ Configuration.gateway.transaction.reverse!(*args)
256
+ end
257
+
244
258
  def self.sale(*args)
245
259
  Configuration.gateway.transaction.sale(*args)
246
260
  end
@@ -22,7 +22,7 @@ module Braintree
22
22
  end
23
23
 
24
24
  def cancel_release(transaction_id)
25
- raise ArgumentError, "transaction_id is invalid" unless transaction_id =~ /\A[0-9a-z]+\z/
25
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
26
26
  response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/cancel_release")
27
27
  _handle_transaction_response(response)
28
28
  end
@@ -42,6 +42,8 @@ module Braintree
42
42
  end
43
43
 
44
44
  def clone_transaction(transaction_id, attributes)
45
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
46
+
45
47
  Util.verify_keys(TransactionGateway._clone_signature, attributes)
46
48
  _do_create "/transactions/#{transaction_id}/clone", :transaction_clone => attributes
47
49
  end
@@ -59,7 +61,9 @@ module Braintree
59
61
  end
60
62
 
61
63
  def find(id)
62
- raise ArgumentError, "id can not be empty" if id.nil? || id.strip.to_s == ""
64
+ raise ArgumentError, "id can not be empty" if id.nil? || id.to_s.strip == ""
65
+ raise ArgumentError, "id contains invalid characters" if Util.invalid_path_segment?(id)
66
+
63
67
  response = @config.http.get("#{@config.base_merchant_path}/transactions/#{id}")
64
68
  Transaction._new(@gateway, response[:transaction])
65
69
  rescue NotFoundError
@@ -67,6 +71,8 @@ module Braintree
67
71
  end
68
72
 
69
73
  def refund(transaction_id, amount_or_options = nil)
74
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
75
+
70
76
  options = if amount_or_options.is_a?(Hash)
71
77
  amount_or_options
72
78
  else
@@ -94,6 +100,22 @@ module Braintree
94
100
  _do_create "/transactions", :transaction => attributes
95
101
  end
96
102
 
103
+ def reverse(transaction_id, options = {})
104
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
105
+
106
+ Util.verify_keys(TransactionGateway._reverse_signature, options)
107
+ transaction_params = options.empty? ? nil : options
108
+ response = @config.http.post(
109
+ "#{@config.base_merchant_path}/transactions/#{transaction_id}/reverse",
110
+ transaction_params ? {:transaction => transaction_params} : nil,
111
+ )
112
+ _handle_transaction_response(response)
113
+ end
114
+
115
+ def reverse!(*args)
116
+ return_object_or_raise(:transaction) { reverse(*args) }
117
+ end
118
+
97
119
  def sale(attributes)
98
120
  create(attributes.merge(:type => "sale"))
99
121
  end
@@ -103,7 +125,7 @@ module Braintree
103
125
  end
104
126
 
105
127
  def package_tracking(transaction_id, package_tracking_request)
106
- raise ArgumentError, "transaction_id is invalid" unless transaction_id =~ /\A[0-9a-z]+\z/
128
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
107
129
  Util.verify_keys(TransactionGateway._package_tracking_request_signature, package_tracking_request)
108
130
  _do_create "/transactions/#{transaction_id}/shipments", :shipment => package_tracking_request
109
131
  end
@@ -126,7 +148,7 @@ module Braintree
126
148
  end
127
149
 
128
150
  def submit_for_settlement(transaction_id, amount = nil, options = {})
129
- raise ArgumentError, "transaction_id is invalid" unless transaction_id =~ /\A[0-9a-z]+\z/
151
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
130
152
  Util.verify_keys(TransactionGateway._submit_for_settlement_signature, options)
131
153
  transaction_params = {:amount => amount}.merge(options)
132
154
  response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/submit_for_settlement", :transaction => transaction_params)
@@ -138,7 +160,7 @@ module Braintree
138
160
  end
139
161
 
140
162
  def adjust_authorization(transaction_id, amount)
141
- raise ArgumentError, "transaction_id is invalid" unless transaction_id =~ /\A[0-9a-z]+\z/
163
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
142
164
  Util.verify_keys(TransactionGateway._adjust_authorization_signature, {})
143
165
  transaction_params = {:amount => amount}
144
166
  response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/adjust_authorization", :transaction => transaction_params)
@@ -150,14 +172,14 @@ module Braintree
150
172
  end
151
173
 
152
174
  def update_details(transaction_id, options = {})
153
- raise ArgumentError, "transaction_id is invalid" unless transaction_id =~ /\A[0-9a-z]+\z/
175
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
154
176
  Util.verify_keys(TransactionGateway._update_details_signature, options)
155
177
  response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/update_details", :transaction => options)
156
178
  _handle_transaction_response(response)
157
179
  end
158
180
 
159
181
  def submit_for_partial_settlement(authorized_transaction_id, amount = nil, options = {})
160
- raise ArgumentError, "authorized_transaction_id is invalid" unless authorized_transaction_id =~ /\A[0-9a-z]+\z/
182
+ raise ArgumentError, "authorized_transaction_id contains invalid characters" if Util.invalid_path_segment?(authorized_transaction_id)
161
183
  Util.verify_keys(TransactionGateway._submit_for_partial_settlement_signature, options)
162
184
  transaction_params = {:amount => amount}.merge(options)
163
185
  response = @config.http.post("#{@config.base_merchant_path}/transactions/#{authorized_transaction_id}/submit_for_partial_settlement", :transaction => transaction_params)
@@ -169,6 +191,8 @@ module Braintree
169
191
  end
170
192
 
171
193
  def void(transaction_id, options = {})
194
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
195
+
172
196
  transaction_params = options.empty? ? nil : options
173
197
  response = @config.http.put(
174
198
  "#{@config.base_merchant_path}/transactions/#{transaction_id}/void",
@@ -218,6 +242,7 @@ module Braintree
218
242
  {:external_vault => [
219
243
  :status,
220
244
  :previous_network_transaction_id,
245
+ :previous_mastercard_transaction_link_id,
221
246
  ]},
222
247
  {:google_pay_card => [:number, :cryptogram, :google_transaction_id, :expiration_month, :expiration_year, :source_card_type, :source_card_last_four, :eci_indicator]},
223
248
  {:industry => [
@@ -382,6 +407,13 @@ module Braintree
382
407
  :api_request_key,
383
408
  :merchant_account_id,
384
409
  :order_id,
410
+ :surcharge_amount,
411
+ ]
412
+ end
413
+
414
+ def self._reverse_signature
415
+ [
416
+ :api_request_key,
385
417
  ]
386
418
  end
387
419
 
@@ -7,7 +7,9 @@ module Braintree
7
7
  end
8
8
 
9
9
  def find_all(transaction_id)
10
- raise ArgumentError, "transaction_id cannot be blank" if transaction_id.nil? || transaction_id.strip.to_s == ""
10
+ raise ArgumentError, "transaction_id cannot be blank" if transaction_id.nil? || transaction_id.to_s.strip == ""
11
+ raise ArgumentError, "transaction_id contains invalid characters" if Util.invalid_path_segment?(transaction_id)
12
+
11
13
  response = @config.http.get("#{@config.base_merchant_path}/transactions/#{transaction_id}/line_items")
12
14
  response[:line_items].map do |line_item_params|
13
15
  TransactionLineItem._new(@gateway, line_item_params)
@@ -46,6 +46,7 @@ module Braintree
46
46
  equality_fields :credit_card_expiration_date
47
47
  partial_match_fields :credit_card_number
48
48
 
49
+ multiple_value_field :ach_type, :allows => Transaction::AchType::All
49
50
  multiple_value_field :created_using, :allows => [
50
51
  Transaction::CreatedUsing::FullInformation,
51
52
  Transaction::CreatedUsing::Token
@@ -8,6 +8,8 @@ module Braintree
8
8
 
9
9
  def find(token)
10
10
  raise ArgumentError if token.nil? || token.to_s.strip == ""
11
+ raise ArgumentError, "token contains invalid characters" if Util.invalid_path_segment?(token)
12
+
11
13
  response = @config.http.get("#{@config.base_merchant_path}/payment_methods/us_bank_account/#{token}")
12
14
  UsBankAccount._new(@gateway, response[:us_bank_account])
13
15
  rescue NotFoundError
@@ -8,6 +8,8 @@ module Braintree
8
8
 
9
9
  def confirm_micro_transfer_amounts(id, deposit_amounts)
10
10
  raise ArgumentError if id.nil? || id.to_s.strip == "" || !deposit_amounts.kind_of?(Array)
11
+ raise ArgumentError, "id contains invalid characters" if Util.invalid_path_segment?(id)
12
+
11
13
  response = @config.http.put(
12
14
  "#{@config.base_merchant_path}/us_bank_account_verifications/#{id}/confirm_micro_transfer_amounts",
13
15
  :us_bank_account_verification => {
@@ -27,6 +29,8 @@ module Braintree
27
29
 
28
30
  def find(id)
29
31
  raise ArgumentError if id.nil? || id.to_s.strip == ""
32
+ raise ArgumentError, "id contains invalid characters" if Util.invalid_path_segment?(id)
33
+
30
34
  response = @config.http.get("#{@config.base_merchant_path}/us_bank_account_verifications/#{id}")
31
35
  UsBankAccountVerification._new(response[:us_bank_account_verification])
32
36
  rescue NotFoundError
@@ -1,7 +1,7 @@
1
1
  module Braintree
2
2
  module Version
3
3
  Major = 4
4
- Minor = 40
4
+ Minor = 42
5
5
  Tiny = 0
6
6
 
7
7
  String = "#{Major}.#{Minor}.#{Tiny}"
@@ -56,7 +56,9 @@ describe Braintree::ApplePayGateway do
56
56
  it "returns stubbed registered domains" do
57
57
  result = @gateway.apple_pay.registered_domains
58
58
  expect(result).to be_success
59
- expect(result.apple_pay_options.domains).to eq(["www.example.com"])
59
+ domains = result.apple_pay_options.domains
60
+ expect(domains).not_to be_empty
61
+ expect(domains).to all(be_a(String).and(satisfy { |domain| !domain.empty? }))
60
62
  end
61
63
  end
62
64
  end
@@ -378,6 +378,20 @@ describe Braintree::ClientToken do
378
378
  end
379
379
  end
380
380
 
381
+ it "can pass preferred_payment_method_token" do
382
+ result = Braintree::Customer.create
383
+ raw_client_token = Braintree::ClientToken.generate(
384
+ :customer_id => result.customer.id,
385
+ :preferred_payment_method_token => "a-pmt",
386
+ )
387
+ client_token = decode_client_token(raw_client_token)
388
+
389
+ expect(client_token["paymentMethodIdJwt"]).not_to be_nil
390
+ jwt_segment = client_token["paymentMethodIdJwt"].split(".")[1]
391
+ jwt_payload = JSON.parse(Base64.urlsafe_decode64(jwt_segment + "=" * ((4 - jwt_segment.length % 4) % 4)))
392
+ expect(jwt_payload["pmid"]).to eq("a-pmt")
393
+ end
394
+
381
395
  it "can pass merchant_account_id" do
382
396
  merchant_account_id = SpecHelper::NonDefaultMerchantAccountId
383
397