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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +39 -8
- data/.gitignore +1 -0
- data/.rubocop.yml +8 -1
- data/CHANGELOG.md +37 -29
- data/Rakefile +6 -1
- data/app/assets/config/solidus_braintree_manifest.js +0 -1
- data/app/assets/javascripts/spree/backend/solidus_braintree.js +4 -4
- data/app/models/solidus_braintree/gateway.rb +4 -0
- data/app/models/solidus_braintree/response.rb +1 -1
- data/app/models/solidus_braintree/source.rb +5 -0
- data/bin/dummy-app +37 -0
- data/bin/rails-dummy-app +17 -0
- data/bin/rspec +11 -0
- data/bin/sandbox +20 -62
- data/db/migrate/20230210104310_add_device_data_to_braintree_sources.rb +5 -0
- data/lib/generators/solidus_braintree/install/install_generator.rb +134 -34
- data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/javascripts/spree/frontend/paypal_button.js +1 -1
- data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/ajax.js +13 -0
- data/{app/assets/javascripts → lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend}/solidus_braintree/apple_pay_button.js +2 -2
- data/{app/assets/javascripts → lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend}/solidus_braintree/checkout.js +10 -5
- data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/client.js +239 -0
- data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/constants.js +89 -0
- data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/frontend.js +15 -0
- data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/hosted_form.js +48 -0
- data/{app/assets/javascripts → lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend}/solidus_braintree/paypal_button.js +2 -2
- data/{app/assets/javascripts → lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend}/solidus_braintree/paypal_messaging.js +1 -1
- data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/promise.js +20 -0
- data/{app/assets/javascripts → lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend}/solidus_braintree/venmo_button.js +1 -1
- data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree.js +1 -0
- data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/stylesheets/spree/frontend/solidus_braintree.scss +11 -0
- data/lib/{controllers/frontend → generators/solidus_braintree/install/templates/app/controllers}/solidus_braintree/checkouts_controller.rb +1 -1
- data/lib/{controllers/frontend → generators/solidus_braintree/install/templates/app/controllers}/solidus_braintree/transactions_controller.rb +3 -3
- data/lib/generators/solidus_braintree/install/templates/app/views/checkouts/existing_payment/_braintree.html.erb +2 -0
- data/lib/{views/frontend/spree/checkout → generators/solidus_braintree/install/templates/app/views/checkouts}/payment/_braintree.html.erb +1 -1
- 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
- data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_apple_pay_button.html.erb +1 -1
- data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_braintree_head_scripts.html.erb +1 -1
- data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_braintree_hosted_fields.html.erb +1 -4
- data/lib/solidus_braintree/engine.rb +15 -10
- data/lib/solidus_braintree/version.rb +1 -1
- data/solidus_braintree.gemspec +3 -5
- data/spec/controllers/solidus_braintree/checkouts_controller_spec.rb +2 -2
- data/spec/controllers/solidus_braintree/client_tokens_controller_spec.rb +2 -2
- data/spec/controllers/solidus_braintree/configurations_controller_spec.rb +2 -2
- data/spec/controllers/solidus_braintree/transactions_controller_spec.rb +3 -3
- data/spec/fixtures/views/carts/_cart_footer.html.erb +18 -0
- data/spec/helpers/solidus_braintree/braintree_admin_helper_spec.rb +1 -1
- data/spec/helpers/solidus_braintree/braintree_checkout_helper_spec.rb +1 -1
- data/spec/models/solidus_braintree/address_spec.rb +1 -1
- data/spec/models/solidus_braintree/avs_result_spec.rb +1 -1
- data/spec/models/solidus_braintree/gateway_spec.rb +35 -3
- data/spec/models/solidus_braintree/response_spec.rb +1 -1
- data/spec/models/solidus_braintree/source_spec.rb +17 -1
- data/spec/models/solidus_braintree/transaction_address_spec.rb +2 -2
- data/spec/models/solidus_braintree/transaction_import_spec.rb +2 -2
- data/spec/models/solidus_braintree/transaction_spec.rb +2 -2
- data/spec/models/spree/store_spec.rb +2 -2
- data/spec/requests/spree/api/orders_controller_spec.rb +2 -2
- data/spec/solidus_braintree_helper.rb +7 -0
- data/{lib/solidus_braintree/testing_support → spec/support/solidus_braintree}/factories.rb +17 -15
- data/spec/support/{order_ready_for_payment.rb → solidus_braintree/order_ready_for_payment.rb} +9 -2
- data/spec/support/solidus_braintree/order_walkthrough.rb +87 -0
- data/spec/support/solidus_braintree/with_prepended_view_fixtures.rb +19 -0
- data/spec/{features → system}/backend/configuration_spec.rb +2 -2
- data/spec/{features → system}/backend/new_payment_spec.rb +3 -4
- data/spec/{features → system}/frontend/braintree_credit_card_checkout_spec.rb +23 -15
- data/spec/{features → system}/frontend/paypal_checkout_spec.rb +6 -3
- data/spec/{features → system}/frontend/venmo_checkout_spec.rb +8 -9
- metadata +88 -107
- data/app/assets/javascripts/solidus_braintree/frontend.js +0 -14
- data/app/assets/javascripts/spree/frontend/solidus_braintree.js +0 -1
- data/app/decorators/controllers/solidus_braintree/checkout_controller_decorator.rb +0 -11
- data/app/decorators/controllers/solidus_braintree/orders_controller_decorator.rb +0 -11
- data/app/overrides/spree/payments/payment/add_paypal_funding_source_to_payment.rb +0 -9
- data/app/views/spree/checkout/existing_payment/_braintree.html.erb +0 -10
- data/spec/fixtures/views/spree/orders/edit.html.erb +0 -50
- data/spec/spec_helper.rb +0 -32
- data/spec/support/views.rb +0 -1
- /data/app/assets/javascripts/{solidus_braintree → spree/backend/solidus_braintree}/client.js +0 -0
- /data/app/assets/javascripts/{solidus_braintree → spree/backend/solidus_braintree}/constants.js +0 -0
- /data/app/assets/javascripts/{solidus_braintree → spree/backend/solidus_braintree}/hosted_form.js +0 -0
- /data/app/assets/javascripts/{solidus_braintree → spree/backend/solidus_braintree}/promise.js +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_blue_button_280x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_blue_button_320x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_blue_button_375x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_white_button_280x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_white_button_320x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_active_white_button_375x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_blue_acceptance_mark.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_blue_button_280x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_blue_button_320x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_blue_button_375x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_blue_logo.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_white_acceptance_mark.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_white_button_280x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_white_button_320x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_white_button_375x48.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/assets/images/solidus_braintree/venmo/venmo_white_logo.svg +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/helpers/solidus_braintree/braintree_checkout_helper.rb +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_braintree_errors.html.erb +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_paypal_cart_button.html.erb +0 -0
- /data/lib/{views/frontend → generators/solidus_braintree/install/templates/app/views}/spree/shared/_paypal_checkout_button.html.erb +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_paypal_messaging.html.erb +0 -0
- /data/{app → lib/generators/solidus_braintree/install/templates/app}/views/spree/shared/_venmo_button.html.erb +0 -0
- /data/lib/generators/solidus_braintree/install/templates/{initializer.rb → config/initializers/solidus_braintree.rb} +0 -0
- /data/spec/support/{capybara.rb → solidus_braintree/capybara.rb} +0 -0
- /data/spec/support/{gateway_helpers.rb → solidus_braintree/gateway_helpers.rb} +0 -0
- /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::
|
|
6
|
-
|
|
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
|
|
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
|
-
|
|
49
|
+
directory 'config/initializers', 'config/initializers'
|
|
21
50
|
end
|
|
22
51
|
end
|
|
23
52
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
31
|
-
|
|
58
|
+
def mount_engine
|
|
59
|
+
gsub_file 'config/routes.rb',
|
|
60
|
+
"mount SolidusPaypalBraintree::Engine, at: '/solidus_paypal_braintree'\n", ''
|
|
32
61
|
|
|
33
|
-
|
|
62
|
+
route "mount SolidusBraintree::Engine, at: '/solidus_braintree'"
|
|
34
63
|
end
|
|
35
64
|
|
|
36
|
-
def
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
41
|
-
|
|
70
|
+
append_file 'vendor/assets/javascripts/spree/backend/all.js',
|
|
71
|
+
"//= require spree/backend/solidus_braintree\n"
|
|
42
72
|
|
|
43
|
-
|
|
44
|
-
|
|
73
|
+
gsub_file 'vendor/assets/stylesheets/spree/backend/all.css',
|
|
74
|
+
" *= require spree/backend/solidus_paypal_braintree\n", ''
|
|
45
75
|
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
51
|
-
|
|
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
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
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
|
-
|
|
66
|
-
|
|
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
|
-
|
|
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
|
|
@@ -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
|
-
|
|
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 = $("
|
|
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
|
+
};
|