solidus_braintree 2.0.0 → 3.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 (109) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +39 -8
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +8 -1
  5. data/CHANGELOG.md +37 -29
  6. data/Rakefile +6 -1
  7. data/app/assets/config/solidus_braintree_manifest.js +0 -1
  8. data/app/assets/javascripts/spree/backend/solidus_braintree.js +4 -4
  9. data/app/models/solidus_braintree/gateway.rb +4 -0
  10. data/app/models/solidus_braintree/response.rb +1 -1
  11. data/app/models/solidus_braintree/source.rb +5 -0
  12. data/bin/dummy-app +37 -0
  13. data/bin/rails-dummy-app +17 -0
  14. data/bin/rspec +11 -0
  15. data/bin/sandbox +20 -62
  16. data/db/migrate/20230210104310_add_device_data_to_braintree_sources.rb +5 -0
  17. data/lib/generators/solidus_braintree/install/install_generator.rb +134 -34
  18. data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/javascripts/spree/frontend/paypal_button.js +1 -1
  19. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/ajax.js +13 -0
  20. data/{app/assets/javascripts → lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend}/solidus_braintree/apple_pay_button.js +2 -2
  21. data/{app/assets/javascripts → lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend}/solidus_braintree/checkout.js +10 -5
  22. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/client.js +239 -0
  23. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/constants.js +89 -0
  24. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/frontend.js +15 -0
  25. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/hosted_form.js +48 -0
  26. data/{app/assets/javascripts → lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend}/solidus_braintree/paypal_button.js +2 -2
  27. data/{app/assets/javascripts → lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend}/solidus_braintree/paypal_messaging.js +1 -1
  28. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/promise.js +20 -0
  29. data/{app/assets/javascripts → lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend}/solidus_braintree/venmo_button.js +1 -1
  30. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree.js +1 -0
  31. data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/stylesheets/spree/frontend/solidus_braintree.scss +11 -0
  32. data/lib/{controllers/frontend → generators/solidus_braintree/install/templates/app/controllers}/solidus_braintree/checkouts_controller.rb +1 -1
  33. data/lib/{controllers/frontend → generators/solidus_braintree/install/templates/app/controllers}/solidus_braintree/transactions_controller.rb +3 -3
  34. data/lib/generators/solidus_braintree/install/templates/app/views/checkouts/existing_payment/_braintree.html.erb +2 -0
  35. data/lib/{views/frontend/spree/checkout → generators/solidus_braintree/install/templates/app/views/checkouts}/payment/_braintree.html.erb +1 -1
  36. data/lib/{views/frontend/solidus_braintree/payments/_payment.html.erb → generators/solidus_braintree/install/templates/app/views/payments/_braintree_payment_details.html.erb} +0 -3
  37. data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_apple_pay_button.html.erb +1 -1
  38. data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_braintree_head_scripts.html.erb +1 -1
  39. data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_braintree_hosted_fields.html.erb +1 -4
  40. data/lib/solidus_braintree/engine.rb +15 -10
  41. data/lib/solidus_braintree/version.rb +1 -1
  42. data/solidus_braintree.gemspec +3 -5
  43. data/spec/controllers/solidus_braintree/checkouts_controller_spec.rb +2 -2
  44. data/spec/controllers/solidus_braintree/client_tokens_controller_spec.rb +2 -2
  45. data/spec/controllers/solidus_braintree/configurations_controller_spec.rb +2 -2
  46. data/spec/controllers/solidus_braintree/transactions_controller_spec.rb +3 -3
  47. data/spec/fixtures/views/carts/_cart_footer.html.erb +18 -0
  48. data/spec/helpers/solidus_braintree/braintree_admin_helper_spec.rb +1 -1
  49. data/spec/helpers/solidus_braintree/braintree_checkout_helper_spec.rb +1 -1
  50. data/spec/models/solidus_braintree/address_spec.rb +1 -1
  51. data/spec/models/solidus_braintree/avs_result_spec.rb +1 -1
  52. data/spec/models/solidus_braintree/gateway_spec.rb +35 -3
  53. data/spec/models/solidus_braintree/response_spec.rb +1 -1
  54. data/spec/models/solidus_braintree/source_spec.rb +17 -1
  55. data/spec/models/solidus_braintree/transaction_address_spec.rb +2 -2
  56. data/spec/models/solidus_braintree/transaction_import_spec.rb +2 -2
  57. data/spec/models/solidus_braintree/transaction_spec.rb +2 -2
  58. data/spec/models/spree/store_spec.rb +2 -2
  59. data/spec/requests/spree/api/orders_controller_spec.rb +2 -2
  60. data/spec/solidus_braintree_helper.rb +7 -0
  61. data/{lib/solidus_braintree/testing_support → spec/support/solidus_braintree}/factories.rb +17 -15
  62. data/spec/support/{order_ready_for_payment.rb → solidus_braintree/order_ready_for_payment.rb} +9 -2
  63. data/spec/support/solidus_braintree/order_walkthrough.rb +87 -0
  64. data/spec/support/solidus_braintree/with_prepended_view_fixtures.rb +19 -0
  65. data/spec/{features → system}/backend/configuration_spec.rb +2 -2
  66. data/spec/{features → system}/backend/new_payment_spec.rb +3 -4
  67. data/spec/{features → system}/frontend/braintree_credit_card_checkout_spec.rb +23 -15
  68. data/spec/{features → system}/frontend/paypal_checkout_spec.rb +6 -3
  69. data/spec/{features → system}/frontend/venmo_checkout_spec.rb +8 -9
  70. metadata +88 -107
  71. data/app/assets/javascripts/solidus_braintree/frontend.js +0 -14
  72. data/app/assets/javascripts/spree/frontend/solidus_braintree.js +0 -1
  73. data/app/decorators/controllers/solidus_braintree/checkout_controller_decorator.rb +0 -11
  74. data/app/decorators/controllers/solidus_braintree/orders_controller_decorator.rb +0 -11
  75. data/app/overrides/spree/payments/payment/add_paypal_funding_source_to_payment.rb +0 -9
  76. data/app/views/spree/checkout/existing_payment/_braintree.html.erb +0 -10
  77. data/spec/fixtures/views/spree/orders/edit.html.erb +0 -50
  78. data/spec/spec_helper.rb +0 -32
  79. data/spec/support/views.rb +0 -1
  80. /data/app/assets/javascripts/{solidus_braintree → spree/backend/solidus_braintree}/client.js +0 -0
  81. /data/app/assets/javascripts/{solidus_braintree → spree/backend/solidus_braintree}/constants.js +0 -0
  82. /data/app/assets/javascripts/{solidus_braintree → spree/backend/solidus_braintree}/hosted_form.js +0 -0
  83. /data/app/assets/javascripts/{solidus_braintree → spree/backend/solidus_braintree}/promise.js +0 -0
  84. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_blue_button_280x48.svg +0 -0
  85. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_blue_button_320x48.svg +0 -0
  86. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_blue_button_375x48.svg +0 -0
  87. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_white_button_280x48.svg +0 -0
  88. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_white_button_320x48.svg +0 -0
  89. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_white_button_375x48.svg +0 -0
  90. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_blue_acceptance_mark.svg +0 -0
  91. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_blue_button_280x48.svg +0 -0
  92. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_blue_button_320x48.svg +0 -0
  93. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_blue_button_375x48.svg +0 -0
  94. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_blue_logo.svg +0 -0
  95. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_white_acceptance_mark.svg +0 -0
  96. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_white_button_280x48.svg +0 -0
  97. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_white_button_320x48.svg +0 -0
  98. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_white_button_375x48.svg +0 -0
  99. /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_white_logo.svg +0 -0
  100. /data/{app → lib/generators/solidus_braintree/install/templates/app}/helpers/solidus_braintree/braintree_checkout_helper.rb +0 -0
  101. /data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_braintree_errors.html.erb +0 -0
  102. /data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_paypal_cart_button.html.erb +0 -0
  103. /data/lib/{views/frontend → generators/solidus_braintree/install/templates/app/views}/spree/shared/_paypal_checkout_button.html.erb +0 -0
  104. /data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_paypal_messaging.html.erb +0 -0
  105. /data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_venmo_button.html.erb +0 -0
  106. /data/lib/generators/solidus_braintree/install/templates/{initializer.rb → config/initializers/solidus_braintree.rb} +0 -0
  107. /data/spec/support/{capybara.rb → solidus_braintree/capybara.rb} +0 -0
  108. /data/spec/support/{gateway_helpers.rb → solidus_braintree/gateway_helpers.rb} +0 -0
  109. /data/spec/support/{vcr.rb → solidus_braintree/vcr.rb} +0 -0
@@ -1,12 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rails/generators/app_base'
4
+
3
5
  module SolidusBraintree
4
6
  module Generators
5
- class InstallGenerator < Rails::Generators::Base
6
- class_option :auto_run_migrations, type: :boolean, default: false
7
+ class InstallGenerator < Rails::Generators::AppBase
8
+ argument :app_path, type: :string, default: Rails.root
9
+
10
+ class_option :migrate, type: :boolean, default: true
11
+ class_option :backend, type: :boolean, default: true
12
+ class_option :frontend, type: :string, default: 'starter'
13
+
14
+ # This is only used to run all-specs during development and CI, regular installation limits
15
+ # installed specs to frontend, which are the ones related to code copied to the target application.
16
+ class_option :specs, type: :string, enum: %w[all frontend], default: 'frontend', hide: true
17
+
7
18
  source_root File.expand_path('templates', __dir__)
8
19
 
9
- def setup_initializer
20
+ def normalize_components_options
21
+ @components = {
22
+ backend: options[:backend],
23
+ starter_frontend: options[:frontend] == 'starter',
24
+ classic_frontend: options[:frontend] == 'classic',
25
+ }
26
+ end
27
+
28
+ def add_test_gems
29
+ gem_group :test do
30
+ ['vcr', 'webmock'].each do |gem_name|
31
+ gem gem_name unless Bundler.locked_gems.dependencies[gem_name]
32
+ end
33
+ end
34
+
35
+ bundle_command 'install'
36
+ end
37
+
38
+ def setup_initializers
10
39
  legacy_initializer_pathname =
11
40
  Pathname.new(destination_root).join('config/initializers/solidus_paypal_braintree.rb')
12
41
 
@@ -17,57 +46,128 @@ module SolidusBraintree
17
46
  "SolidusPaypalBraintree.configure do |config|\n",
18
47
  "SolidusBraintree.configure do |config|\n"
19
48
  else
20
- template 'initializer.rb', 'config/initializers/solidus_braintree.rb'
49
+ directory 'config/initializers', 'config/initializers'
21
50
  end
22
51
  end
23
52
 
24
- def setup_javascripts
25
- gsub_file 'vendor/assets/javascripts/spree/frontend/all.js',
26
- "//= require spree/frontend/solidus_paypal_braintree\n", ''
27
-
28
- append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/solidus_braintree\n"
53
+ def run_migrations
54
+ rake 'railties:install:migrations FROM=solidus_braintree'
55
+ run 'bin/rails db:migrate' if options[:migrate]
56
+ end
29
57
 
30
- gsub_file 'vendor/assets/javascripts/spree/backend/all.js',
31
- "//= require spree/backend/solidus_paypal_braintree\n", ''
58
+ def mount_engine
59
+ gsub_file 'config/routes.rb',
60
+ "mount SolidusPaypalBraintree::Engine, at: '/solidus_paypal_braintree'\n", ''
32
61
 
33
- append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/solidus_braintree\n"
62
+ route "mount SolidusBraintree::Engine, at: '/solidus_braintree'"
34
63
  end
35
64
 
36
- def setup_stylesheets
37
- gsub_file 'vendor/assets/stylesheets/spree/frontend/all.css',
38
- " *= require spree/frontend/solidus_paypal_braintree\n", ''
65
+ def install_solidus_backend_support
66
+ support_code_for(:backend) do
67
+ gsub_file 'vendor/assets/javascripts/spree/backend/all.js',
68
+ "//= require spree/backend/solidus_paypal_braintree\n", ''
39
69
 
40
- inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css',
41
- " *= require spree/frontend/solidus_braintree\n", before: %r{\*/}, verbose: true
70
+ append_file 'vendor/assets/javascripts/spree/backend/all.js',
71
+ "//= require spree/backend/solidus_braintree\n"
42
72
 
43
- gsub_file 'vendor/assets/stylesheets/spree/backend/all.css',
44
- " *= require spree/backend/solidus_paypal_braintree\n", ''
73
+ gsub_file 'vendor/assets/stylesheets/spree/backend/all.css',
74
+ " *= require spree/backend/solidus_paypal_braintree\n", ''
45
75
 
46
- inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css',
47
- " *= require spree/backend/solidus_braintree\n", before: %r{\*/}, verbose: true
76
+ inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css',
77
+ " *= require spree/backend/solidus_braintree\n", before: %r{\*/}, verbose: true
78
+ end
48
79
  end
49
80
 
50
- def add_migrations
51
- rake 'railties:install:migrations FROM=solidus_braintree'
81
+ def install_solidus_starter_frontend_support
82
+ support_code_for(:starter_frontend) do
83
+ directory 'app', 'app'
84
+
85
+ inject_into_file 'vendor/assets/javascripts/spree/frontend/all.js',
86
+ "//= require jquery3\n",
87
+ before: '//= require rails-ujs',
88
+ verbose: true
89
+
90
+ gsub_file 'vendor/assets/javascripts/spree/frontend/all.js',
91
+ "//= require spree/frontend/solidus_paypal_braintree\n", ''
92
+
93
+ append_file 'app/assets/javascripts/solidus_starter_frontend.js',
94
+ "//= require spree/frontend/solidus_braintree\n"
95
+
96
+ gsub_file 'vendor/assets/stylesheets/spree/frontend/all.css',
97
+ " *= require spree/frontend/solidus_paypal_braintree\n", ''
98
+
99
+ inject_into_file 'app/assets/stylesheets/solidus_starter_frontend.css',
100
+ " *= require spree/frontend/solidus_braintree\n", before: %r{\*/}, verbose: true
101
+
102
+ inject_into_class 'app/controllers/checkouts_controller.rb',
103
+ 'CheckoutsController',
104
+ " helper SolidusBraintree::BraintreeCheckoutHelper\n\n",
105
+ verbose: true
106
+
107
+ inject_into_class 'app/controllers/carts_controller.rb',
108
+ 'CartsController',
109
+ " helper SolidusBraintree::BraintreeCheckoutHelper\n\n",
110
+ verbose: true
111
+
112
+ inject_into_file 'app/views/orders/_payment_info.html.erb',
113
+ " <li><%= render 'payments/braintree_payment_details', payment: payment %></li>\n",
114
+ after: "<li><%= payment.payment_method.name %></li>\n",
115
+ verbose: true
116
+
117
+ spec_paths =
118
+ case options[:specs]
119
+ when 'all' then %w[spec]
120
+ when 'frontend'
121
+ %w[
122
+ spec/solidus_braintree_helper.rb
123
+ spec/system/frontend
124
+ spec/support
125
+ spec/fixtures
126
+ ]
127
+ end
128
+
129
+ spec_paths.each do |path|
130
+ if engine.root.join(path).directory?
131
+ directory engine.root.join(path), path
132
+ else
133
+ template engine.root.join(path), path
134
+ end
135
+ end
136
+ end
52
137
  end
53
138
 
54
- def mount_engine
55
- gsub_file 'config/routes.rb',
56
- "mount SolidusPaypalBraintree::Engine, at: '/solidus_paypal_braintree'\n", ''
57
-
58
- route "mount SolidusBraintree::Engine, at: '/solidus_braintree'"
139
+ def alert_no_classic_frontend_support
140
+ support_code_for(:classic_frontend) do
141
+ message = <<~TEXT
142
+ For solidus_frontend compatibility, please use version 2.x.
143
+ The new version of this extension only supports Solidus Starter Frontend.
144
+ No frontend code has been copied to your application.
145
+ TEXT
146
+ say_status :error, set_color(message.tr("\n", ' '), :red), :red
147
+ end
59
148
  end
60
149
 
61
- def run_migrations
62
- run_migrations = options[:auto_run_migrations] ||
63
- ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
150
+ private
64
151
 
65
- if run_migrations
66
- rake 'db:migrate'
152
+ def support_code_for(component_name, &block)
153
+ if @components[component_name]
154
+ say_status :install, "[#{engine.engine_name}] solidus_#{component_name}", :blue
155
+ shell.indent(&block)
67
156
  else
68
- puts 'Skipping bin/rails db:migrate, don\'t forget to run it!' # rubocop:disable Rails/Output
157
+ say_status :skip, "[#{engine.engine_name}] solidus_#{component_name}", :blue
69
158
  end
70
159
  end
160
+
161
+ def engine
162
+ SolidusBraintree::Engine
163
+ end
164
+
165
+ def bundle_command(command, env = {})
166
+ # Make `bundle install` less verbose by skipping the "Using ..." messages
167
+ super(command, env.reverse_merge('BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES' => 'true'))
168
+ ensure
169
+ Bundler.reset_paths!
170
+ end
71
171
  end
72
172
  end
73
173
  end
@@ -1,4 +1,4 @@
1
- //= require solidus_braintree/paypal_button
1
+ //= require spree/frontend/solidus_braintree/paypal_button
2
2
 
3
3
  // This is the PayPal button on the cart page
4
4
  $(document).ready(function() {
@@ -0,0 +1,13 @@
1
+ SolidusBraintree.ajax = function(url, options) {
2
+ if (typeof url === "object") {
3
+ options = url;
4
+ url = undefined;
5
+ }
6
+ options = options || {};
7
+ options = $.extend(options, {
8
+ headers: {
9
+ 'Authorization': 'Bearer '
10
+ }
11
+ });
12
+ return $.ajax(url, options);
13
+ };
@@ -1,4 +1,4 @@
1
- //= require solidus_braintree/constants
1
+ //= require spree/frontend/solidus_braintree/constants
2
2
  /**
3
3
  * Constructor for Apple Pay button object
4
4
  * @constructor
@@ -94,7 +94,7 @@ SolidusBraintree.ApplepayButton.prototype.tokenize = function (session, payment)
94
94
  };
95
95
 
96
96
  SolidusBraintree.ApplepayButton.prototype._createTransaction = function (session, payment, payload) {
97
- Spree.ajax({
97
+ SolidusBraintree.ajax({
98
98
  data: this._transactionParams(payload, payment.shippingContact),
99
99
  dataType: 'json',
100
100
  type: 'POST',
@@ -1,4 +1,4 @@
1
- //= require solidus_braintree/frontend
1
+ //= require spree/frontend/solidus_braintree/frontend
2
2
 
3
3
  $(function() {
4
4
  /* This provides a default error handler for Braintree. Since we prevent
@@ -40,9 +40,9 @@ $(function() {
40
40
  $paymentForm.on("submit",function(event) {
41
41
  var $field = $(hostedField);
42
42
 
43
- if ($field.is(":visible") && !$field.data("submitting")) {
43
+ if ($field.is(":visible") && $field.is(":enabled") && !$field.data("submitting")) {
44
44
  var $nonce = $("#payment_method_nonce", $field);
45
-
45
+ var $deviceData = $("#device_data", $field);
46
46
  if ($nonce.length > 0 && $nonce.val() === "") {
47
47
  var client = braintreeForm._merchantConfigurationOptions._solidusClient;
48
48
 
@@ -56,6 +56,10 @@ $(function() {
56
56
  }
57
57
 
58
58
  $nonce.val(payload.nonce);
59
+
60
+ if (client._dataCollectorInstance) {
61
+ $deviceData.val(client._dataCollectorInstance.deviceData);
62
+ }
59
63
 
60
64
  if (!client.useThreeDSecure) {
61
65
  $paymentForm.submit();
@@ -84,7 +88,7 @@ $(function() {
84
88
 
85
89
  var $paymentForm = $("#checkout_form_payment");
86
90
  var $hostedFields = $("[data-braintree-hosted-fields]");
87
- var $submitButton = $("input[type='submit']", $paymentForm);
91
+ var $submitButton = $("[type='submit']", $paymentForm);
88
92
 
89
93
  // If we're not using hosted fields, the form doesn't need to wait.
90
94
  if ($hostedFields.length > 0) {
@@ -93,8 +97,9 @@ $(function() {
93
97
  var fieldPromises = $hostedFields.map(function(index, field) {
94
98
  var $this = $(this);
95
99
  var id = $this.data("id");
100
+ var useDataCollector = $this.data("use-data-collector");
96
101
 
97
- var braintreeForm = new SolidusBraintree.createHostedForm(id);
102
+ var braintreeForm = new SolidusBraintree.createHostedForm(id, useDataCollector);
98
103
 
99
104
  var formInitializationSuccess = function(formObject) {
100
105
  addFormHook(formObject, field);
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Braintree client interface
3
+ * @external "braintree.Client"
4
+ * @see {@link https://braintree.github.io/braintree-web/current/Client.html|Braintree Client Docs}
5
+ **/
6
+
7
+ /**
8
+ * Braintree paypal interface
9
+ * @external "braintree.PayPal"
10
+ * @see {@link https://braintree.github.io/braintree-web/current/PayPal.html|Braintree Paypal Docs}
11
+ **/
12
+
13
+ /**
14
+ * Braintree paypal interface
15
+ * @external "braintree.ApplePay"
16
+ * @see {@link https://braintree.github.io/braintree-web/current/ApplePay.html|Braintree Apple Pay Docs}
17
+ **/
18
+
19
+ /**
20
+ * Braintree dataCollector interface
21
+ * @external "braintree.DataCollector"
22
+ * @see {@link https://braintree.github.io/braintree-web/current/DataCollector.html|Braintree DataCollector Docs}
23
+ **/
24
+
25
+ /**
26
+ * jQuery.Deferred interface
27
+ *
28
+ * We use this for our promises because ES6 promises are non standard, and because jquery 1/2
29
+ * promises do not play nicely with them.
30
+ * @external "jQuery.Deferred"
31
+ * @see {@link https://api.jquery.com/category/deferred-object/|jQuery Deferred Documentation}
32
+ **/
33
+
34
+ /**
35
+ * Represents a wrapper around the braintree js library.
36
+ *
37
+ * This class is responsible for fetching tokens from a solidus store and using them
38
+ * to manage a braintree client. It takes a number of options as capabilities for the client
39
+ * depending on if you want to use use the data collector or paypal.
40
+ *
41
+ * We use this class mostly to hide the token operations for users.
42
+ *
43
+ * After creating the class, a call should be made to initialize before using it.
44
+ * @see initialize
45
+ *
46
+ * @constructor
47
+ * @param {Object} config Initalization options for the client
48
+ * @param {Boolean} config.useDataCollector Use data collector capabilities for the braintree client
49
+ * @param {Boolean} config.usePaypal Use Paypal capabilities for the braintree client
50
+ * @param {requestCallback} config.readyCallback A callback to be invoked when the client is ready to go.
51
+ * @param {Number} config.paymentMethodId A number indicating a specific payment method to be preferrred.
52
+ *
53
+ **/
54
+ SolidusBraintree.Client = function(config) {
55
+ this.paymentMethodId = config.paymentMethodId;
56
+ this.readyCallback = config.readyCallback;
57
+ this.useDataCollector = config.useDataCollector;
58
+ this.usePaypal = config.usePaypal;
59
+ this.useApplepay = config.useApplepay;
60
+ this.useVenmo = config.useVenmo;
61
+ this.flow = config.flow;
62
+ this.venmoNewTabSupported = config.newBrowserTabSupported
63
+ this.useThreeDSecure = config.useThreeDSecure;
64
+
65
+ this._braintreeInstance = null;
66
+ this._dataCollectorInstance = null;
67
+ this._paypalInstance = null;
68
+ this._venmoInstance = null;
69
+ this._threeDSecureInstance = null;
70
+ };
71
+
72
+ /**
73
+ * Fetches a client token from the backend and initializes the braintree client.
74
+ * @returns {external:"jQuery.Deferred"} Promise to be invoked after initialization is complete
75
+ **/
76
+ SolidusBraintree.Client.prototype.initialize = function() {
77
+ var initializationPromise = this._fetchToken().
78
+ then(this._createBraintreeInstance.bind(this));
79
+
80
+ if (this.useDataCollector) {
81
+ initializationPromise = initializationPromise.then(this._createDataCollector.bind(this));
82
+ }
83
+
84
+ if (this.usePaypal) {
85
+ initializationPromise = initializationPromise.then(this._createPaypal.bind(this));
86
+ }
87
+
88
+ if (this.useApplepay) {
89
+ initializationPromise = initializationPromise.then(this._createApplepay.bind(this));
90
+ }
91
+
92
+ if (this.useVenmo) {
93
+ initializationPromise = initializationPromise.then(this._createVenmo.bind(this));
94
+ }
95
+
96
+ if (this.useThreeDSecure) {
97
+ initializationPromise = initializationPromise.then(this._createThreeDSecure.bind(this));
98
+ }
99
+
100
+ return initializationPromise.then(this._invokeReadyCallback.bind(this));
101
+ };
102
+
103
+ /**
104
+ * Returns the braintree client instance
105
+ * @returns {external:"braintree.Client"} The braintree client that was initialized by this class
106
+ **/
107
+ SolidusBraintree.Client.prototype.getBraintreeInstance = function() {
108
+ return this._braintreeInstance;
109
+ };
110
+
111
+ /**
112
+ * Returns the braintree paypal instance
113
+ * @returns {external:"braintree.PayPal"} The braintree paypal that was initialized by this class
114
+ **/
115
+ SolidusBraintree.Client.prototype.getPaypalInstance = function() {
116
+ return this._paypalInstance;
117
+ };
118
+
119
+ /**
120
+ * Returns the braintree Apple Pay instance
121
+ * @returns {external:"braintree.ApplePay"} The Braintree Apple Pay that was initialized by this class
122
+ **/
123
+ SolidusBraintree.Client.prototype.getApplepayInstance = function() {
124
+ return this._applepayInstance;
125
+ };
126
+
127
+ /**
128
+ * Returns the braintree Venmo instance
129
+ * @returns {external:"braintree.Venmo"} The Braintree Venmo that was initialized by this class
130
+ **/
131
+ SolidusBraintree.Client.prototype.getVenmoInstance = function() {
132
+ return this._venmoInstance;
133
+ };
134
+
135
+ /**
136
+ * Returns the braintree dataCollector instance
137
+ * @returns {external:"braintree.DataCollector"} The braintree dataCollector that was initialized by this class
138
+ **/
139
+ SolidusBraintree.Client.prototype.getDataCollectorInstance = function() {
140
+ return this._dataCollectorInstance;
141
+ };
142
+
143
+
144
+ SolidusBraintree.Client.prototype._fetchToken = function() {
145
+ var payload = {
146
+ dataType: 'json',
147
+ type: 'POST',
148
+ url: SolidusBraintree.config.paths.clientTokens,
149
+ error: function(xhr) {
150
+ console.error("Error fetching braintree token");
151
+ }
152
+ };
153
+
154
+ if (this.paymentMethodId) {
155
+ payload.data = {
156
+ payment_method_id: this.paymentMethodId
157
+ };
158
+ }
159
+
160
+ return SolidusBraintree.ajax(payload);
161
+ };
162
+
163
+ SolidusBraintree.Client.prototype._createBraintreeInstance = function(tokenResponse) {
164
+ this.paymentMethodId = tokenResponse.payment_method_id;
165
+
166
+ return SolidusBraintree.PromiseShim.convertBraintreePromise(braintree.client.create, [{
167
+ authorization: tokenResponse.client_token
168
+ }]).then(function (clientInstance) {
169
+ this._braintreeInstance = clientInstance;
170
+ return clientInstance;
171
+ }.bind(this));
172
+ };
173
+
174
+ SolidusBraintree.Client.prototype._invokeReadyCallback = function() {
175
+ if(this.readyCallback) {
176
+ this.readyCallback(this._braintreeInstance);
177
+ }
178
+
179
+ return this;
180
+ };
181
+
182
+ SolidusBraintree.Client.prototype._createDataCollector = function() {
183
+ return SolidusBraintree.PromiseShim.convertBraintreePromise(braintree.dataCollector.create, [{
184
+ client: this._braintreeInstance,
185
+ paypal: !!this.usePaypal
186
+ }]).then(function (dataCollectorInstance) {
187
+ this._dataCollectorInstance = dataCollectorInstance;
188
+ return dataCollectorInstance;
189
+ }.bind(this));
190
+ };
191
+
192
+ SolidusBraintree.Client.prototype._createPaypal = function() {
193
+ return SolidusBraintree.PromiseShim.convertBraintreePromise(braintree.paypalCheckout.create, [{
194
+ client: this._braintreeInstance
195
+ }]).then(function (paypalInstance) {
196
+ this._paypalInstance = paypalInstance;
197
+ return paypalInstance;
198
+ }.bind(this), function(error) {
199
+ console.error(error.name + ':', error.message);
200
+ });
201
+ };
202
+
203
+ SolidusBraintree.Client.prototype._createApplepay = function() {
204
+ return SolidusBraintree.PromiseShim.convertBraintreePromise(braintree.applePay.create, [{
205
+ client: this._braintreeInstance
206
+ }]).then(function (applePayInstance) {
207
+ this._applepayInstance = applePayInstance;
208
+ return applePayInstance;
209
+ }.bind(this));
210
+ };
211
+
212
+ SolidusBraintree.Client.prototype._createVenmo = function() {
213
+ return SolidusBraintree.PromiseShim.convertBraintreePromise(braintree.venmo.create, [{
214
+ client: this._braintreeInstance,
215
+ allowDesktop: true,
216
+ paymentMethodUsage: this.flow === 'vault' ? 'multi_use' : 'single_use',
217
+ allowNewBrowserTab: this.venmoNewTabSupported
218
+ }]).then(function (venmoInstance) {
219
+ // Verify browser support before proceeding.
220
+ if (!venmoInstance.isBrowserSupported()) {
221
+ console.log('Browser does not support Venmo');
222
+ return;
223
+ }
224
+
225
+ this._venmoInstance = venmoInstance;
226
+ return venmoInstance;
227
+ }.bind(this));
228
+ };
229
+
230
+ SolidusBraintree.Client.prototype._createThreeDSecure = function() {
231
+ return SolidusBraintree.PromiseShim.convertBraintreePromise(braintree.threeDSecure.create, [{
232
+ client: this._braintreeInstance,
233
+ version: 2
234
+ }]).then(function (threeDSecureInstance) {
235
+ this._threeDSecureInstance = threeDSecureInstance;
236
+ }.bind(this), function(error) {
237
+ console.log(error);
238
+ });
239
+ };
@@ -0,0 +1,89 @@
1
+ SolidusBraintree = {
2
+ APPLE_PAY_API_VERSION: 1,
3
+
4
+ config: {
5
+ paths: {
6
+ clientTokens: Solidus.pathFor('solidus_braintree/client_token'),
7
+ transactions: Solidus.pathFor('solidus_braintree/transactions')
8
+ },
9
+
10
+ // Override to provide your own error messages.
11
+ braintreeErrorHandle: function(braintreeError) {
12
+ BraintreeError.getErrorFromSlug(braintreeError.code);
13
+ SolidusBraintree.showError(error);
14
+ },
15
+
16
+ classes: {
17
+ hostedForm: function() {
18
+ return SolidusBraintree.HostedForm;
19
+ },
20
+
21
+ client: function() {
22
+ return SolidusBraintree.Client;
23
+ },
24
+
25
+ paypalButton: function() {
26
+ return SolidusBraintree.PaypalButton;
27
+ },
28
+
29
+ paypalMessaging: function() {
30
+ return SolidusBraintree.PaypalMessaging;
31
+ },
32
+
33
+ applepayButton: function() {
34
+ return SolidusBraintree.ApplepayButton;
35
+ },
36
+
37
+ venmoButton: function() {
38
+ return SolidusBraintree.VenmoButton;
39
+ }
40
+ }
41
+ },
42
+
43
+ showError: function(error) {
44
+ var $contentContainer = $("main");
45
+ var $flash = $("<div class='flash error'>" + error + "</div>");
46
+ $contentContainer.before($flash);
47
+ $flash.show().delay(5000).fadeOut(500);
48
+ },
49
+
50
+ createHostedForm: function() {
51
+ return SolidusBraintree._factory(SolidusBraintree.config.classes.hostedForm(), arguments);
52
+ },
53
+
54
+ createClient: function() {
55
+ return SolidusBraintree._factory(SolidusBraintree.config.classes.client(), arguments);
56
+ },
57
+
58
+ createPaypalButton: function() {
59
+ return SolidusBraintree._factory(SolidusBraintree.config.classes.paypalButton(), arguments);
60
+ },
61
+
62
+ createPaypalMessaging: function() {
63
+ return SolidusBraintree._factory(SolidusBraintree.config.classes.paypalMessaging(), arguments);
64
+ },
65
+
66
+ createApplePayButton: function() {
67
+ return SolidusBraintree._factory(SolidusBraintree.config.classes.applepayButton(), arguments);
68
+ },
69
+
70
+ createVenmoButton: function() {
71
+ return SolidusBraintree._factory(SolidusBraintree.config.classes.venmoButton(), arguments);
72
+ },
73
+
74
+ _factory: function(klass, args) {
75
+ var normalizedArgs = Array.prototype.slice.call(args);
76
+ return new (Function.prototype.bind.apply(klass, [null].concat(normalizedArgs)));
77
+ }
78
+ };
79
+
80
+ BraintreeError = {
81
+ DEFAULT: "Something bad happened!",
82
+
83
+ getErrorFromSlug: function(slug) {
84
+ error = BraintreeError.DEFAULT
85
+ if (slug in BraintreeError)
86
+ error = BraintreeError[slug]
87
+ return error
88
+ }
89
+ }
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into including all the files listed below.
2
+ // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
3
+ // be included in the compiled file accessible from http://example.com/assets/application.js
4
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5
+ // the compiled file.
6
+ //
7
+ //= require spree/frontend/solidus_braintree/constants
8
+ //= require spree/frontend/solidus_braintree/ajax
9
+ //= require spree/frontend/solidus_braintree/promise
10
+ //= require spree/frontend/solidus_braintree/client
11
+ //= require spree/frontend/solidus_braintree/hosted_form
12
+ //= require spree/frontend/solidus_braintree/paypal_button
13
+ //= require spree/frontend/solidus_braintree/paypal_messaging
14
+ //= require spree/frontend/solidus_braintree/apple_pay_button
15
+ //= require spree/frontend/solidus_braintree/venmo_button
@@ -0,0 +1,48 @@
1
+ SolidusBraintree.HostedForm = function(paymentMethodId, useDataCollector) {
2
+ this.paymentMethodId = paymentMethodId;
3
+ this.useDataCollector = useDataCollector;
4
+ this.client = null;
5
+ };
6
+
7
+ SolidusBraintree.HostedForm.prototype.initialize = function() {
8
+ this.client = SolidusBraintree.createClient({
9
+ paymentMethodId: this.paymentMethodId,
10
+ useThreeDSecure: (typeof(window.threeDSecureOptions) !== 'undefined'),
11
+ useDataCollector: this.useDataCollector,
12
+ });
13
+
14
+ return this.client.initialize().
15
+ then(this._createHostedFields.bind(this));
16
+ };
17
+
18
+ SolidusBraintree.HostedForm.prototype._createHostedFields = function () {
19
+ if (!this.client) {
20
+ throw new Error("Client not initialized, please call initialize first!");
21
+ }
22
+
23
+ var opts = {
24
+ _solidusClient: this.client,
25
+ client: this.client.getBraintreeInstance(),
26
+
27
+ fields: {
28
+ number: {
29
+ selector: "#card_number" + this.paymentMethodId,
30
+ placeholder: placeholder_text["number"]
31
+ },
32
+
33
+ cvv: {
34
+ selector: "#card_code" + this.paymentMethodId,
35
+ placeholder: placeholder_text["cvv"]
36
+ },
37
+
38
+ expirationDate: {
39
+ selector: "#card_expiry" + this.paymentMethodId,
40
+ placeholder: placeholder_text["expirationDate"]
41
+ }
42
+ },
43
+
44
+ styles: credit_card_fields_style
45
+ };
46
+
47
+ return SolidusBraintree.PromiseShim.convertBraintreePromise(braintree.hostedFields.create, [opts]);
48
+ };