solidus_paypal_braintree 0.4.0 → 1.0.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 (135) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +40 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +17 -0
  5. data/.gitignore +18 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +68 -0
  8. data/CHANGELOG.md +258 -0
  9. data/Gemfile +43 -0
  10. data/LICENSE +2 -2
  11. data/README.md +77 -23
  12. data/Rakefile +4 -25
  13. data/app/assets/javascripts/solidus_paypal_braintree/checkout.js +32 -3
  14. data/app/assets/javascripts/solidus_paypal_braintree/client.js +23 -4
  15. data/app/assets/javascripts/solidus_paypal_braintree/constants.js +19 -0
  16. data/app/assets/javascripts/solidus_paypal_braintree/frontend.js +1 -0
  17. data/app/assets/javascripts/solidus_paypal_braintree/hosted_form.js +15 -5
  18. data/app/assets/javascripts/solidus_paypal_braintree/paypal_button.js +47 -20
  19. data/app/assets/javascripts/solidus_paypal_braintree/paypal_messaging.js +22 -0
  20. data/app/decorators/controllers/solidus_paypal_braintree/admin_payments_controller_decorator.rb +11 -0
  21. data/app/decorators/controllers/solidus_paypal_braintree/checkout_controller_decorator.rb +11 -0
  22. data/app/decorators/controllers/solidus_paypal_braintree/client_tokens_controller.rb +41 -0
  23. data/app/decorators/controllers/solidus_paypal_braintree/orders_controller_decorator.rb +11 -0
  24. data/app/decorators/models/solidus_paypal_braintree/spree/store_decorator.rb +20 -0
  25. data/app/decorators/models/solidus_paypal_braintree/spree/user_decorator.rb +13 -0
  26. data/app/helpers/solidus_paypal_braintree/braintree_admin_helper.rb +23 -0
  27. data/app/helpers/solidus_paypal_braintree/braintree_checkout_helper.rb +46 -0
  28. data/app/models/application_record.rb +2 -0
  29. data/app/models/solidus_paypal_braintree/address.rb +30 -0
  30. data/app/models/solidus_paypal_braintree/configuration.rb +26 -3
  31. data/app/models/solidus_paypal_braintree/customer.rb +7 -3
  32. data/app/models/solidus_paypal_braintree/gateway.rb +52 -20
  33. data/app/models/solidus_paypal_braintree/response.rb +3 -2
  34. data/app/models/solidus_paypal_braintree/source.rb +21 -7
  35. data/app/models/solidus_paypal_braintree/transaction.rb +2 -0
  36. data/app/models/solidus_paypal_braintree/transaction_address.rb +30 -12
  37. data/app/models/solidus_paypal_braintree/transaction_import.rb +13 -9
  38. data/app/views/spree/api/payments/source_views/_paypal_braintree.json.jbuilder +3 -0
  39. data/app/views/spree/checkout/existing_payment/_paypal_braintree.html.erb +10 -0
  40. data/app/views/spree/shared/_apple_pay_button.html.erb +2 -2
  41. data/app/views/spree/shared/_braintree_errors.html.erb +11 -17
  42. data/app/views/spree/shared/_braintree_hosted_fields.html.erb +24 -9
  43. data/app/views/spree/shared/_paypal_braintree_head_scripts.html.erb +9 -6
  44. data/app/views/spree/shared/_paypal_cart_button.html.erb +16 -2
  45. data/app/views/spree/shared/_paypal_messaging.html.erb +13 -0
  46. data/bin/console +17 -0
  47. data/bin/rails +15 -0
  48. data/bin/setup +8 -0
  49. data/config/locales/en.yml +10 -0
  50. data/config/locales/it.yml +51 -8
  51. data/config/routes.rb +2 -0
  52. data/db/migrate/20160906201711_create_solidus_paypal_braintree_customers.rb +3 -1
  53. data/db/migrate/20161125172005_add_braintree_configuration_to_stores.rb +5 -7
  54. data/db/migrate/20170505193712_add_null_constraint_to_sources.rb +3 -1
  55. data/db/migrate/20190705115327_add_paypal_button_preferences_to_braintree_configurations.rb +5 -0
  56. data/db/migrate/20190911141712_add_3d_secure_to_braintree_configuration.rb +5 -0
  57. data/lib/controllers/backend/solidus_paypal_braintree/configurations_controller.rb +20 -5
  58. data/lib/controllers/frontend/solidus_paypal_braintree/checkouts_controller.rb +25 -21
  59. data/lib/controllers/frontend/solidus_paypal_braintree/transactions_controller.rb +55 -51
  60. data/lib/generators/solidus_paypal_braintree/install/install_generator.rb +7 -5
  61. data/lib/solidus_paypal_braintree.rb +4 -0
  62. data/lib/solidus_paypal_braintree/country_mapper.rb +4 -2
  63. data/lib/solidus_paypal_braintree/engine.rb +11 -11
  64. data/lib/solidus_paypal_braintree/factories.rb +8 -4
  65. data/lib/solidus_paypal_braintree/request_protection.rb +3 -0
  66. data/lib/solidus_paypal_braintree/version.rb +3 -1
  67. data/lib/views/backend/solidus_paypal_braintree/configurations/list.html.erb +30 -5
  68. data/lib/views/backend/spree/admin/payments/source_forms/_paypal_braintree.html.erb +2 -2
  69. data/lib/views/backend/spree/admin/payments/source_views/_paypal_braintree.html.erb +2 -2
  70. data/lib/views/backend_v1.2/spree/admin/payments/source_forms/_paypal_braintree.html.erb +2 -2
  71. data/lib/views/frontend/spree/checkout/payment/_paypal_braintree.html.erb +4 -2
  72. data/lib/views/frontend/spree/shared/_paypal_checkout_button.html.erb +30 -0
  73. data/solidus_paypal_braintree.gemspec +42 -0
  74. data/spec/controllers/solidus_paypal_braintree/checkouts_controller_spec.rb +99 -0
  75. data/spec/controllers/solidus_paypal_braintree/client_tokens_controller_spec.rb +55 -0
  76. data/spec/controllers/solidus_paypal_braintree/configurations_controller_spec.rb +73 -0
  77. data/spec/controllers/solidus_paypal_braintree/transactions_controller_spec.rb +183 -0
  78. data/spec/features/backend/configuration_spec.rb +23 -0
  79. data/spec/features/backend/new_payment_spec.rb +137 -0
  80. data/spec/features/frontend/braintree_credit_card_checkout_spec.rb +187 -0
  81. data/spec/features/frontend/paypal_checkout_spec.rb +166 -0
  82. data/spec/fixtures/cassettes/admin/invalid_credit_card.yml +63 -0
  83. data/spec/fixtures/cassettes/admin/resubmit_credit_card.yml +352 -0
  84. data/spec/fixtures/cassettes/admin/valid_credit_card.yml +412 -0
  85. data/spec/fixtures/cassettes/braintree/create_profile.yml +71 -0
  86. data/spec/fixtures/cassettes/braintree/generate_token.yml +63 -0
  87. data/spec/fixtures/cassettes/braintree/token.yml +63 -0
  88. data/spec/fixtures/cassettes/checkout/invalid_credit_card.yml +63 -0
  89. data/spec/fixtures/cassettes/checkout/resubmit_credit_card.yml +216 -0
  90. data/spec/fixtures/cassettes/checkout/update.yml +71 -0
  91. data/spec/fixtures/cassettes/checkout/valid_credit_card.yml +156 -0
  92. data/spec/fixtures/cassettes/gateway/authorize.yml +86 -0
  93. data/spec/fixtures/cassettes/gateway/authorize/credit_card/address.yml +86 -0
  94. data/spec/fixtures/cassettes/gateway/authorize/merchant_account/EUR.yml +154 -0
  95. data/spec/fixtures/cassettes/gateway/authorize/paypal/EUR.yml +90 -0
  96. data/spec/fixtures/cassettes/gateway/authorize/paypal/address.yml +90 -0
  97. data/spec/fixtures/cassettes/gateway/authorized_transaction.yml +73 -0
  98. data/spec/fixtures/cassettes/gateway/cancel/missing.yml +63 -0
  99. data/spec/fixtures/cassettes/gateway/cancel/refunds.yml +272 -0
  100. data/spec/fixtures/cassettes/gateway/cancel/void.yml +201 -0
  101. data/spec/fixtures/cassettes/gateway/capture.yml +141 -0
  102. data/spec/fixtures/cassettes/gateway/complete.yml +157 -0
  103. data/spec/fixtures/cassettes/gateway/credit.yml +208 -0
  104. data/spec/fixtures/cassettes/gateway/purchase.yml +87 -0
  105. data/spec/fixtures/cassettes/gateway/settled_transaction.yml +140 -0
  106. data/spec/fixtures/cassettes/gateway/void.yml +137 -0
  107. data/spec/fixtures/cassettes/source/card_type.yml +267 -0
  108. data/spec/fixtures/cassettes/source/last4.yml +267 -0
  109. data/spec/fixtures/cassettes/transaction/import/valid.yml +71 -0
  110. data/spec/fixtures/cassettes/transaction/import/valid/capture.yml +224 -0
  111. data/spec/fixtures/views/spree/orders/edit.html.erb +50 -0
  112. data/spec/helpers/solidus_paypal_braintree/braintree_admin_helper_spec.rb +17 -0
  113. data/spec/models/solidus_paypal_braintree/address_spec.rb +51 -0
  114. data/spec/models/solidus_paypal_braintree/avs_result_spec.rb +317 -0
  115. data/spec/models/solidus_paypal_braintree/gateway_spec.rb +692 -0
  116. data/spec/models/solidus_paypal_braintree/response_spec.rb +280 -0
  117. data/spec/models/solidus_paypal_braintree/source_spec.rb +360 -0
  118. data/spec/models/solidus_paypal_braintree/transaction_address_spec.rb +253 -0
  119. data/spec/models/solidus_paypal_braintree/transaction_import_spec.rb +283 -0
  120. data/spec/models/solidus_paypal_braintree/transaction_spec.rb +85 -0
  121. data/spec/models/spree/store_spec.rb +14 -0
  122. data/spec/requests/spree/api/orders_controller_spec.rb +36 -0
  123. data/spec/spec_helper.rb +26 -0
  124. data/spec/support/capybara.rb +7 -0
  125. data/spec/support/factories.rb +2 -0
  126. data/spec/support/gateway_helpers.rb +29 -0
  127. data/spec/support/order_ready_for_payment.rb +37 -0
  128. data/spec/support/vcr.rb +42 -0
  129. data/spec/support/views.rb +1 -0
  130. metadata +182 -194
  131. data/app/controllers/solidus_paypal_braintree/client_tokens_controller.rb +0 -22
  132. data/app/helpers/braintree_admin_helper.rb +0 -18
  133. data/app/models/spree/store_decorator.rb +0 -11
  134. data/app/views/spree/shared/_paypal_checkout_button.html.erb +0 -27
  135. data/config/initializers/braintree.rb +0 -1
@@ -27,7 +27,7 @@ module SolidusPaypalBraintree
27
27
  transaction = result.transaction
28
28
  options = response_options(transaction).update(
29
29
  # For error responses we want to have the CVV code
30
- cvv_result: transaction.try!(:cvv_response_code)
30
+ cvv_result: transaction&.cvv_response_code
31
31
  )
32
32
  new(false, error_message(result), result.params, options)
33
33
  end
@@ -35,6 +35,7 @@ module SolidusPaypalBraintree
35
35
  def response_options(transaction)
36
36
  # Some error responses do not have a transaction
37
37
  return {} if transaction.nil?
38
+
38
39
  {
39
40
  authorization: transaction.id,
40
41
  avs_result: SolidusPaypalBraintree::AVSResult.build(transaction),
@@ -67,7 +68,7 @@ module SolidusPaypalBraintree
67
68
  when 'settlement_declined'
68
69
  I18n.t(transaction.processor_settlement_response_code,
69
70
  scope: 'solidus_paypal_braintree.processor_settlement_response_codes',
70
- default: "#{transaction.processor_settlement_response_text} (#{transaction.processor_settlement_response_code})")
71
+ default: "#{transaction.processor_settlement_response_text} (#{transaction.processor_settlement_response_code})") # rubocop:disable Layout/LineLength
71
72
  else
72
73
  I18n.t(transaction.status,
73
74
  scope: 'solidus_paypal_braintree.transaction_statuses',
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SolidusPaypalBraintree
2
4
  class Source < SolidusSupport.payment_source_parent_class
3
5
  include RequestProtection
@@ -6,19 +8,25 @@ module SolidusPaypalBraintree
6
8
  APPLE_PAY = "ApplePayCard"
7
9
  CREDIT_CARD = "CreditCard"
8
10
 
9
- belongs_to :user, class_name: Spree::UserClassHandle.new
11
+ belongs_to :user, class_name: ::Spree::UserClassHandle.new, optional: true
10
12
  belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
11
- has_many :payments, as: :source, class_name: "Spree::Payment"
13
+ has_many :payments, as: :source, class_name: "Spree::Payment", dependent: :destroy
12
14
 
13
- belongs_to :customer, class_name: "SolidusPaypalBraintree::Customer"
15
+ belongs_to :customer, class_name: "SolidusPaypalBraintree::Customer", optional: true
14
16
 
15
17
  validates :payment_type, inclusion: [PAYPAL, APPLE_PAY, CREDIT_CARD]
16
18
 
17
19
  scope(:with_payment_profile, -> { joins(:customer) })
18
20
  scope(:credit_card, -> { where(payment_type: CREDIT_CARD) })
19
21
 
20
- delegate :last_4, :card_type, to: :braintree_payment_method, allow_nil: true
22
+ delegate :last_4, :card_type, :expiration_month, :expiration_year, :email,
23
+ to: :braintree_payment_method, allow_nil: true
24
+
25
+ # Aliases to match Spree::CreditCard's interface
21
26
  alias_method :last_digits, :last_4
27
+ alias_method :month, :expiration_month
28
+ alias_method :year, :expiration_year
29
+ alias_method :cc_type, :card_type
22
30
 
23
31
  # we are not currenctly supporting an "imported" flag
24
32
  def imported
@@ -35,6 +43,7 @@ module SolidusPaypalBraintree
35
43
 
36
44
  def can_void?(payment)
37
45
  return false unless payment.response_code
46
+
38
47
  transaction = protected_request do
39
48
  braintree_client.transaction.find(payment.response_code)
40
49
  end
@@ -60,7 +69,7 @@ module SolidusPaypalBraintree
60
69
  end
61
70
 
62
71
  def reusable?
63
- true
72
+ token.present?
64
73
  end
65
74
 
66
75
  def credit_card?
@@ -68,13 +77,18 @@ module SolidusPaypalBraintree
68
77
  end
69
78
 
70
79
  def display_number
71
- "XXXX-XXXX-XXXX-#{last_digits.to_s.rjust(4, 'X')}"
80
+ if paypal?
81
+ email
82
+ else
83
+ "XXXX-XXXX-XXXX-#{last_digits.to_s.rjust(4, 'X')}"
84
+ end
72
85
  end
73
86
 
74
87
  private
75
88
 
76
89
  def braintree_payment_method
77
- return unless braintree_client && credit_card?
90
+ return unless braintree_client
91
+
78
92
  @braintree_payment_method ||= protected_request do
79
93
  braintree_client.payment_method.find(token)
80
94
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model'
2
4
 
3
5
  module SolidusPaypalBraintree
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model'
2
4
 
3
5
  module SolidusPaypalBraintree
@@ -6,11 +8,11 @@ module SolidusPaypalBraintree
6
8
  include ActiveModel::Validations::Callbacks
7
9
  include SolidusPaypalBraintree::CountryMapper
8
10
 
9
- attr_accessor :country_code, :last_name, :first_name,
10
- :city, :zip, :state_code, :address_line_1, :address_line_2
11
+ attr_accessor :country_code, :name, :city, :zip, :state_code,
12
+ :address_line_1, :address_line_2, :first_name, :last_name
11
13
 
12
- validates :first_name, :last_name, :address_line_1, :city, :zip,
13
- :country_code, presence: true
14
+ validates :address_line_1, :city, :zip, :country_code, presence: true
15
+ validates :name, presence: true, unless: ->(address){ address.first_name.present? }
14
16
 
15
17
  before_validation do
16
18
  self.country_code = country_code.presence || "us"
@@ -29,25 +31,37 @@ module SolidusPaypalBraintree
29
31
  end
30
32
 
31
33
  def spree_country
32
- country_code && (@country ||= Spree::Country.find_by(iso: country_code.upcase))
34
+ country_code && (@country ||= ::Spree::Country.find_by(iso: country_code.upcase))
33
35
  end
34
36
 
35
37
  def spree_state
36
- spree_country && state_code && ( @state ||= spree_country.states.where(
37
- Spree::State.arel_table[:name].matches(state_code).or(
38
- Spree::State.arel_table[:abbr].matches(state_code)
38
+ spree_country && state_code && ( @state ||= spree_country.states.find_by(
39
+ ::Spree::State.arel_table[:name].matches(state_code).or(
40
+ ::Spree::State.arel_table[:abbr].matches(state_code)
39
41
  )
40
- ).first )
42
+ ))
41
43
  end
42
44
 
43
45
  def to_spree_address
44
- address = Spree::Address.new first_name: first_name,
45
- last_name: last_name,
46
+ address = ::Spree::Address.new(
46
47
  city: city,
47
48
  country: spree_country,
48
49
  address1: address_line_1,
49
50
  address2: address_line_2,
50
51
  zipcode: zip
52
+ )
53
+
54
+ if !first_name.nil?
55
+ ::Spree::Deprecation.warn("first_name and last_name are deprecated. Use name instead.", caller)
56
+ address.first_name = first_name
57
+ address.last_name = last_name || "(left blank)"
58
+ elsif address.respond_to? :name
59
+ address.name = name
60
+ else
61
+ first_name, last_name = split_name(name)
62
+ address.first_name = first_name
63
+ address.last_name = last_name || "(left blank)"
64
+ end
51
65
 
52
66
  if spree_state
53
67
  address.state = spree_state
@@ -57,9 +71,13 @@ module SolidusPaypalBraintree
57
71
  address
58
72
  end
59
73
 
74
+ def split_name(name)
75
+ name.strip.split(' ', 2)
76
+ end
77
+
60
78
  # Check to see if this address should match to a state model in the database
61
79
  def should_match_state_model?
62
- spree_country.try!(:states_required?)
80
+ spree_country&.states_required?
63
81
  end
64
82
  end
65
83
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model'
2
4
 
3
5
  module SolidusPaypalBraintree
@@ -25,19 +27,19 @@ module SolidusPaypalBraintree
25
27
  end
26
28
 
27
29
  def source
28
- SolidusPaypalBraintree::Source.new nonce: transaction.nonce,
30
+ SolidusPaypalBraintree::Source.new(
31
+ nonce: transaction.nonce,
29
32
  payment_type: transaction.payment_type,
30
33
  payment_method: transaction.payment_method,
31
34
  user: user
35
+ )
32
36
  end
33
37
 
34
- def user
35
- order.user
36
- end
38
+ delegate :user, to: :order
37
39
 
38
40
  def import!(end_state, restart_checkout: false)
39
41
  if valid?
40
- order.email = user.try!(:email) || transaction.email
42
+ order.email = user&.email || transaction.email
41
43
 
42
44
  if address
43
45
  order.shipping_address = order.billing_address = address
@@ -46,9 +48,11 @@ module SolidusPaypalBraintree
46
48
  order.instance_variable_set("@tax_zone", nil)
47
49
  end
48
50
 
49
- payment = order.payments.new source: source,
51
+ payment = order.payments.new(
52
+ source: source,
50
53
  payment_method: transaction.payment_method,
51
54
  amount: order.total
55
+ )
52
56
 
53
57
  order.save!
54
58
  order.restart_checkout_flow if restart_checkout
@@ -85,9 +89,9 @@ module SolidusPaypalBraintree
85
89
  payment_total = order.payments.where(state: %w[checkout pending]).sum(:amount)
86
90
  payment_difference = order.outstanding_balance - payment_total
87
91
 
88
- if payment_difference != 0
89
- payment.update!(amount: payment.amount + payment_difference)
90
- end
92
+ return unless payment_difference != 0
93
+
94
+ payment.update!(amount: payment.amount + payment_difference)
91
95
  end
92
96
  end
93
97
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ json.call(payment_source, :id, :token, :created_at)
@@ -0,0 +1,10 @@
1
+ <tr id="<%= dom_id(wallet_payment_source, 'spree')%>" class="<%= cycle('even', 'odd') %>">
2
+ <td>
3
+ <%= radio_button_tag "order[wallet_payment_source_id]",
4
+ wallet_payment_source.id,
5
+ default,
6
+ class: "existing-cc-radio" %>
7
+ </td>
8
+ <td><%= wallet_payment_source.payment_source.friendly_payment_type %></td>
9
+ <td><%= wallet_payment_source.payment_source.display_number %></td>
10
+ </tr>
@@ -11,8 +11,8 @@
11
11
  amount: "<%= current_order.total %>",
12
12
  shippingContact: {
13
13
  emailAddress: '<%= current_order.email %>',
14
- familyName: '<%= address.firstname %>',
15
- givenName: '<%= address.lastname %>',
14
+ givenName: '<%= address.firstname %>',
15
+ familyName: '<%= address.lastname %>',
16
16
  phoneNumber: '<%= address.phone %>',
17
17
  addressLines: ['<%= address.address1 %>','<%= address.address2 %>'],
18
18
  locality: '<%= address.city %>',
@@ -1,19 +1,13 @@
1
1
  <script type="text/javascript">
2
- BraintreeError = {
3
- HOSTED_FIELDS_FIELDS_EMPTY: "<%= I18n.t('solidus_paypal_braintree.errors.empty_fields')%>",
4
- HOSTED_FIELDS_FIELDS_INVALID: "<%= I18n.t('solidus_paypal_braintree.errors.invalid_fields')%>",
5
- HOSTED_FIELDS_FAILED_TOKENIZATION: "<%= I18n.t('solidus_paypal_braintree.errors.invalid_card')%>",
6
- HOSTED_FIELDS_TOKENIZATION_NETWORK_ERROR: "<%= I18n.t('solidus_paypal_braintree.errors.network_error')%>",
7
- HOSTED_FIELDS_FIELD_DUPLICATE_IFRAME: "<%= I18n.t('solidus_paypal_braintree.errors.duplicate_iframe')%>",
8
- HOSTED_FIELDS_TOKENIZATION_FAIL_ON_DUPLICATE: "<%= I18n.t('solidus_paypal_braintree.errors.fail_on_duplicate')%>",
9
- HOSTED_FIELDS_TOKENIZATION_CVV_VERIFICATION_FAILED: "<%= I18n.t('solidus_paypal_braintree.errors.cvv_verification_failed')%>",
10
-
11
- getErrorFromSlug: function(slug) {
12
- // Default error message
13
- error = "<%= I18n.t('solidus_paypal_braintree.errors.default_error')%>"
14
- if (slug in BraintreeError)
15
- error = BraintreeError[slug]
16
- return error
17
- }
18
- }
2
+ BraintreeError.DEFAULT = "<%= I18n.t('solidus_paypal_braintree.errors.default_error')%>"
3
+ BraintreeError.PAYPAL_POPUP_CLOSED = "<%= I18n.t('solidus_paypal_braintree.errors.paypal_popup_closed') %>"
4
+ BraintreeError.HOSTED_FIELDS_FIELDS_EMPTY = "<%= I18n.t('solidus_paypal_braintree.errors.empty_fields')%>"
5
+ BraintreeError.HOSTED_FIELDS_FIELDS_INVALID = "<%= I18n.t('solidus_paypal_braintree.errors.invalid_fields')%>"
6
+ BraintreeError.HOSTED_FIELDS_FAILED_TOKENIZATION = "<%= I18n.t('solidus_paypal_braintree.errors.invalid_card')%>"
7
+ BraintreeError.HOSTED_FIELDS_TOKENIZATION_NETWORK_ERROR = "<%= I18n.t('solidus_paypal_braintree.errors.network_error')%>"
8
+ BraintreeError.HOSTED_FIELDS_FIELD_DUPLICATE_IFRAME = "<%= I18n.t('solidus_paypal_braintree.errors.duplicate_iframe')%>"
9
+ BraintreeError.HOSTED_FIELDS_TOKENIZATION_FAIL_ON_DUPLICATE = "<%= I18n.t('solidus_paypal_braintree.errors.fail_on_duplicate')%>"
10
+ BraintreeError.HOSTED_FIELDS_TOKENIZATION_CVV_VERIFICATION_FAILED = "<%= I18n.t('solidus_paypal_braintree.errors.cvv_verification_failed')%>"
11
+ BraintreeError.THREEDS_AUTHENTICATION_FAILED = "<%= t('solidus_paypal_braintree.errors.threeds.authentication_failed') %>";
12
+ BraintreeError.THREEDS_CARDINAL_SDK_ERROR = "<%= t('solidus_paypal_braintree.errors.threeds.authentication_failed') %>";
19
13
  </script>
@@ -1,24 +1,30 @@
1
- <% prefix = "payment_source[#{id}]" %>
1
+ <% if defined?(id) && !defined?(payment_method) %>
2
+ <% payment_method = Spree::PaymentMethod.find(id) %>
3
+ <% Spree::Deprecation.warn(
4
+ "passing id to _braintree_hosted_fields.html.erb is deprecated. Please pass the payment_method directly.",
5
+ caller
6
+ ) %>
7
+ <% end %>
2
8
 
3
- <%= render partial: "spree/shared/braintree_errors" %>
9
+ <% prefix = "payment_source[#{payment_method.id}]" %>
4
10
 
5
11
  <div class="hosted-fields">
6
12
  <div class="field" data-hook="card_number">
7
- <%= label_tag "card_number#{id}", Spree::CreditCard.human_attribute_name(:number), class: "required" %>
8
- <div class="input" id="card_number<%= id %>"></div>
13
+ <%= label_tag "card_number#{payment_method.id}", Spree::CreditCard.human_attribute_name(:number), class: "required" %>
14
+ <div class="input" id="card_number<%= payment_method.id %>"></div>
9
15
  </div>
10
16
 
11
17
  <div class="field" data-hook="card_expiration">
12
- <%= label_tag "card_expiry#{id}", Spree::CreditCard.human_attribute_name(:expiration), class: "required" %>
13
- <div class="input" id="card_expiry<%= id %>"></div>
18
+ <%= label_tag "card_expiry#{payment_method.id}", Spree::CreditCard.human_attribute_name(:expiration), class: "required" %>
19
+ <div class="input" id="card_expiry<%= payment_method.id %>"></div>
14
20
  </div>
15
21
 
16
22
  <div class="field" data-hook="card_code">
17
- <%= label_tag "card_code#{id}", Spree::CreditCard.human_attribute_name(:card_code), class: "required" %>
18
- <div class="input" id="card_code<%= id %>"></div>
23
+ <%= label_tag "card_code#{payment_method.id}", Spree::CreditCard.human_attribute_name(:card_code), class: "required" %>
24
+ <div class="input" id="card_code<%= payment_method.id %>"></div>
19
25
 
20
26
  <a href="/content/cvv" class="info cvvLink" target="_blank">
21
- (<%= Spree.t(:what_is_this) %>)
27
+ (<%= I18n.t("spree.what_is_this") %>)
22
28
  </a>
23
29
  </div>
24
30
 
@@ -26,3 +32,12 @@
26
32
  <input type="hidden" name="<%= prefix %>[payment_type]" value="<%= SolidusPaypalBraintree::Source::CREDIT_CARD %>">
27
33
  <input type="hidden" id="payment_method_nonce" name="<%= prefix %>[nonce]">
28
34
  </div>
35
+
36
+
37
+ <script>
38
+ <% if current_store.braintree_configuration.three_d_secure? %>
39
+ var threeDSecureOptions = <%= raw braintree_3ds_options_for(current_order).to_json %>;
40
+ <% end -%>
41
+ var credit_card_fields_style = <%= raw payment_method.preferred_credit_card_fields_style.to_json %>
42
+ var placeholder_text = <%= raw payment_method.preferred_placeholder_text.to_json %>
43
+ </script>
@@ -1,18 +1,21 @@
1
1
  <% content_for :head do %>
2
- <script src="https://js.braintreegateway.com/web/3.34.0/js/client.min.js"></script>
3
- <script src="https://js.braintreegateway.com/web/3.34.0/js/data-collector.min.js"></script>
2
+ <script src="https://js.braintreegateway.com/web/3.67.0/js/client.min.js"></script>
3
+ <script src="https://js.braintreegateway.com/web/3.67.0/js/data-collector.min.js"></script>
4
4
 
5
5
  <% if current_store.braintree_configuration.paypal? %>
6
- <script src="https://js.braintreegateway.com/web/3.34.0/js/paypal-checkout.min.js"></script>
7
- <script src="https://www.paypalobjects.com/api/checkout.js" data-version-4></script>
6
+ <script src="https://js.braintreegateway.com/web/3.67.0/js/paypal-checkout.min.js"></script>
8
7
  <% end %>
9
8
 
10
9
  <% if current_store.braintree_configuration.credit_card? %>
11
- <script src="https://js.braintreegateway.com/web/3.34.0/js/hosted-fields.min.js"></script>
10
+ <script src="https://js.braintreegateway.com/web/3.67.0/js/hosted-fields.min.js"></script>
11
+
12
+ <% if current_store.braintree_configuration.three_d_secure? %>
13
+ <script src="https://js.braintreegateway.com/web/3.67.0/js/three-d-secure.min.js"></script>
14
+ <% end %>
12
15
  <% end %>
13
16
 
14
17
  <% if current_store.braintree_configuration.apple_pay? %>
15
- <script src="https://js.braintreegateway.com/web/3.34.0/js/apple-pay.min.js"></script>
18
+ <script src="https://js.braintreegateway.com/web/3.67.0/js/apple-pay.min.js"></script>
16
19
  <% end %>
17
20
 
18
21
  <%= javascript_include_tag "solidus_paypal_braintree/checkout" %>
@@ -1,12 +1,26 @@
1
1
  <%= render "spree/shared/paypal_braintree_head_scripts" %>
2
2
 
3
3
  <div id="paypal-button"></div>
4
+ <div data-pp-message data-pp-placement="payment" data-pp-amount="<%= current_order.total %>"></div>
4
5
 
5
6
  <script>
6
7
  var paypalOptions = {
7
- flow: 'vault',
8
+ flow: '<%= SolidusPaypalBraintree::Gateway.first.preferred_paypal_flow %>',
9
+ amount: '<%= current_order.total %>',
10
+ currency: '<%= current_order.currency %>',
8
11
  enableShippingAddress: true,
9
- environment: '<%= Rails.env.production? ? "production" : "sandbox" %>'
12
+ environment: '<%= Rails.env.production? ? "production" : "sandbox" %>',
13
+ locale: '<%= paypal_button_preference(:paypal_button_locale, store: current_store) %>',
14
+ style: {
15
+ color: '<%= paypal_button_preference(:paypal_button_color, store: current_store) %>',
16
+ shape: '<%= paypal_button_preference(:paypal_button_shape, store: current_store) %>',
17
+ label: '<%= paypal_button_preference(:paypal_button_label, store: current_store) %>',
18
+ layout: '<%= paypal_button_preference(:paypal_button_layout, store: current_store) %>',
19
+ <% if paypal_button_preference(:paypal_button_layout, store: current_store) == "horizontal" %>
20
+ tagline: '<%= paypal_button_preference(:paypal_button_tagline, store: current_store) %>',
21
+ <% end %>
22
+ messaging: '<%= paypal_button_preference(:paypal_button_messaging, store: current_store) %>'
23
+ }
10
24
  }
11
25
  var options = {
12
26
  restart_checkout: true
@@ -0,0 +1,13 @@
1
+ <%= render "spree/shared/paypal_braintree_head_scripts" %>
2
+
3
+ <div data-pp-message data-pp-placement="<%= options[:placement] %>" data-pp-amount="<%= options[:total] %>"></div>
4
+
5
+ <script>
6
+ var message = new SolidusPaypalBraintree.createPaypalMessaging(
7
+ {
8
+ currency: "<%= options[:currency] %>"
9
+ }
10
+ )
11
+
12
+ message.initialize();
13
+ </script>
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require "bundler/setup"
6
+ require "solidus_paypal_braintree"
7
+
8
+ # You can add fixtures and/or initialization code here to make experimenting
9
+ # with your gem easier. You can also use a different console, if you like.
10
+ $LOAD_PATH.unshift(*Dir["#{__dir__}/../app/*"])
11
+
12
+ # (If you use this, don't forget to add pry to your Gemfile!)
13
+ # require "pry"
14
+ # Pry.start
15
+
16
+ require "irb"
17
+ IRB.start(__FILE__)
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ app_root = 'spec/dummy'
6
+
7
+ unless File.exist? "#{app_root}/bin/rails"
8
+ system "bin/rake", app_root or begin
9
+ warn "Automatic creation of the dummy app failed"
10
+ exit 1
11
+ end
12
+ end
13
+
14
+ Dir.chdir app_root
15
+ exec 'bin/rails', *ARGV