solidus_braintree 1.2.0 โ 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +47 -0
- data/.gem_release.yml +5 -0
- data/.github/stale.yml +1 -0
- data/.github_changelog_generator +2 -0
- data/.gitignore +20 -10
- data/.rspec +1 -1
- data/.rubocop.yml +79 -0
- data/CHANGELOG.md +178 -18
- data/Gemfile +35 -17
- data/LICENSE +26 -0
- data/README.md +389 -24
- data/Rakefile +4 -19
- data/app/assets/config/solidus_braintree_manifest.js +1 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_280x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_320x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_375x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_280x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_320x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_375x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_blue_acceptance_mark.svg +15 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_280x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_320x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_375x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_blue_logo.svg +18 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_white_acceptance_mark.svg +20 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_white_button_280x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_white_button_320x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_white_button_375x48.svg +19 -0
- data/app/assets/images/solidus_braintree/venmo/venmo_white_logo.svg +18 -0
- data/app/assets/javascripts/solidus_braintree/apple_pay_button.js +179 -0
- data/app/assets/javascripts/solidus_braintree/checkout.js +108 -0
- data/app/assets/javascripts/solidus_braintree/client.js +239 -0
- data/app/assets/javascripts/solidus_braintree/constants.js +89 -0
- data/app/assets/javascripts/solidus_braintree/frontend.js +14 -0
- data/app/assets/javascripts/solidus_braintree/hosted_form.js +46 -0
- data/app/assets/javascripts/solidus_braintree/paypal_button.js +178 -0
- data/app/assets/javascripts/solidus_braintree/paypal_messaging.js +22 -0
- data/app/assets/javascripts/solidus_braintree/promise.js +20 -0
- data/app/assets/javascripts/solidus_braintree/venmo_button.js +86 -0
- data/app/assets/javascripts/spree/backend/solidus_braintree.js +96 -0
- data/app/assets/javascripts/spree/frontend/paypal_button.js +34 -0
- data/app/assets/javascripts/spree/frontend/solidus_braintree.js +1 -0
- data/app/assets/stylesheets/spree/backend/solidus_braintree.scss +28 -0
- data/app/assets/stylesheets/spree/frontend/solidus_braintree.scss +51 -0
- data/app/decorators/controllers/solidus_braintree/admin_payments_controller_decorator.rb +11 -0
- data/app/decorators/controllers/solidus_braintree/checkout_controller_decorator.rb +11 -0
- data/app/decorators/controllers/solidus_braintree/client_tokens_controller.rb +41 -0
- data/app/decorators/controllers/solidus_braintree/orders_controller_decorator.rb +11 -0
- data/app/decorators/models/solidus_braintree/spree/store_decorator.rb +20 -0
- data/app/decorators/models/solidus_braintree/spree/user_decorator.rb +13 -0
- data/app/helpers/solidus_braintree/braintree_admin_helper.rb +23 -0
- data/app/helpers/solidus_braintree/braintree_checkout_helper.rb +60 -0
- data/app/models/application_record.rb +5 -0
- data/app/models/solidus_braintree/address.rb +64 -0
- data/app/models/solidus_braintree/avs_result.rb +69 -0
- data/app/models/solidus_braintree/configuration.rb +39 -0
- data/app/models/solidus_braintree/customer.rb +8 -0
- data/app/models/solidus_braintree/gateway.rb +433 -0
- data/app/models/solidus_braintree/response.rb +80 -0
- data/app/models/solidus_braintree/source.rb +135 -0
- data/app/models/solidus_braintree/transaction.rb +31 -0
- data/app/models/solidus_braintree/transaction_address.rb +88 -0
- data/app/models/solidus_braintree/transaction_import.rb +98 -0
- data/app/overrides/spree/payments/payment/add_paypal_funding_source_to_payment.rb +9 -0
- data/app/views/spree/api/payments/source_views/_braintree.json.jbuilder +3 -0
- data/app/views/spree/checkout/existing_payment/_braintree.html.erb +10 -0
- data/app/views/spree/shared/_apple_pay_button.html.erb +27 -0
- data/app/views/spree/shared/_braintree_errors.html.erb +16 -0
- data/app/views/spree/shared/_braintree_head_scripts.html.erb +26 -0
- data/app/views/spree/shared/_braintree_hosted_fields.html.erb +43 -0
- data/app/views/spree/shared/_paypal_cart_button.html.erb +38 -0
- data/app/views/spree/shared/_paypal_messaging.html.erb +13 -0
- data/app/views/spree/shared/_venmo_button.html.erb +33 -0
- data/bin/console +4 -1
- data/bin/rails +5 -5
- data/bin/rails-engine +13 -0
- data/bin/rails-sandbox +16 -0
- data/bin/rake +7 -0
- data/bin/sandbox +103 -0
- data/bin/setup +5 -4
- data/config/locales/en.yml +94 -2
- data/config/locales/it.yml +56 -0
- data/config/routes.rb +12 -3
- data/db/migrate/20160830061749_create_solidus_paypal_braintree_sources.rb +16 -0
- data/db/migrate/20160906201711_create_solidus_paypal_braintree_customers.rb +13 -0
- data/db/migrate/20161114231422_create_solidus_paypal_braintree_configurations.rb +11 -0
- data/db/migrate/20161125172005_add_braintree_configuration_to_stores.rb +7 -0
- data/db/migrate/20170203191030_add_credit_card_to_braintree_configuration.rb +6 -0
- data/db/migrate/20170505193712_add_null_constraint_to_sources.rb +38 -0
- data/db/migrate/20170508085402_add_not_null_constraint_to_sources_payment_type.rb +14 -0
- data/db/migrate/20190705115327_add_paypal_button_preferences_to_braintree_configurations.rb +5 -0
- data/db/migrate/20190911141712_add_3d_secure_to_braintree_configuration.rb +5 -0
- data/db/migrate/20211222170950_add_paypal_funding_source_to_solidus_paypal_braintree_sources.rb +5 -0
- data/db/migrate/20220104150301_add_venmo_to_braintree_configuration.rb +5 -0
- data/db/migrate/20230109080950_rename_solidus_paypal_braintree_source_type.rb +31 -0
- data/lib/controllers/backend/solidus_braintree/configurations_controller.rb +48 -0
- data/lib/controllers/frontend/solidus_braintree/checkouts_controller.rb +31 -0
- data/lib/controllers/frontend/solidus_braintree/transactions_controller.rb +67 -0
- data/lib/generators/solidus_braintree/install/install_generator.rb +54 -18
- data/lib/generators/solidus_braintree/install/templates/initializer.rb +6 -0
- data/lib/solidus_braintree/country_mapper.rb +37 -0
- data/lib/solidus_braintree/engine.rb +55 -10
- data/lib/solidus_braintree/extension_configuration.rb +23 -0
- data/lib/solidus_braintree/request_protection.rb +21 -0
- data/lib/solidus_braintree/testing_support/factories.rb +53 -0
- data/lib/solidus_braintree/version.rb +3 -1
- data/lib/solidus_braintree.rb +14 -2
- data/lib/solidus_paypal_braintree.rb +6 -0
- data/lib/views/backend/solidus_braintree/configurations/list.html.erb +63 -0
- data/lib/views/backend/spree/admin/payments/source_forms/_braintree.html.erb +16 -0
- data/lib/views/backend/spree/admin/payments/source_views/_braintree.html.erb +39 -0
- data/lib/views/backend/spree/admin/shared/preference_fields/_preference_select.html.erb +13 -0
- data/lib/views/backend_v1.2/spree/admin/payments/source_forms/_braintree.html.erb +16 -0
- data/lib/views/backend_v2.4/spree/admin/shared/preference_fields/_hash.html.erb +12 -0
- data/lib/views/frontend/solidus_braintree/payments/_payment.html.erb +12 -0
- data/lib/views/frontend/spree/checkout/payment/_braintree.html.erb +23 -0
- data/lib/views/frontend/spree/shared/_paypal_checkout_button.html.erb +32 -0
- data/solidus_braintree.gemspec +39 -38
- data/spec/controllers/solidus_braintree/checkouts_controller_spec.rb +99 -0
- data/spec/controllers/solidus_braintree/client_tokens_controller_spec.rb +55 -0
- data/spec/controllers/solidus_braintree/configurations_controller_spec.rb +73 -0
- data/spec/controllers/solidus_braintree/transactions_controller_spec.rb +183 -0
- data/spec/features/backend/configuration_spec.rb +23 -0
- data/spec/features/backend/new_payment_spec.rb +137 -0
- data/spec/features/frontend/braintree_credit_card_checkout_spec.rb +191 -0
- data/spec/features/frontend/paypal_checkout_spec.rb +166 -0
- data/spec/features/frontend/venmo_checkout_spec.rb +194 -0
- data/spec/fixtures/cassettes/admin/invalid_credit_card.yml +63 -0
- data/spec/fixtures/cassettes/admin/resubmit_credit_card.yml +352 -0
- data/spec/fixtures/cassettes/admin/valid_credit_card.yml +412 -0
- data/spec/fixtures/cassettes/braintree/create_profile.yml +71 -0
- data/spec/fixtures/cassettes/braintree/generate_token.yml +63 -0
- data/spec/fixtures/cassettes/braintree/token.yml +63 -0
- data/spec/fixtures/cassettes/checkout/invalid_credit_card.yml +63 -0
- data/spec/fixtures/cassettes/checkout/resubmit_credit_card.yml +216 -0
- data/spec/fixtures/cassettes/checkout/update.yml +71 -0
- data/spec/fixtures/cassettes/checkout/valid_credit_card.yml +171 -0
- data/spec/fixtures/cassettes/checkout/valid_venmo_transaction.yml +599 -0
- data/spec/fixtures/cassettes/gateway/authorize/credit_card/address.yml +86 -0
- data/spec/fixtures/cassettes/gateway/authorize/merchant_account/EUR.yml +154 -0
- data/spec/fixtures/cassettes/gateway/authorize/paypal/EUR.yml +90 -0
- data/spec/fixtures/cassettes/gateway/authorize/paypal/address.yml +90 -0
- data/spec/fixtures/cassettes/gateway/authorize.yml +86 -0
- data/spec/fixtures/cassettes/gateway/authorized_transaction.yml +73 -0
- data/spec/fixtures/cassettes/gateway/cancel/missing.yml +63 -0
- data/spec/fixtures/cassettes/gateway/cancel/refunds.yml +272 -0
- data/spec/fixtures/cassettes/gateway/cancel/void.yml +201 -0
- data/spec/fixtures/cassettes/gateway/capture.yml +141 -0
- data/spec/fixtures/cassettes/gateway/complete.yml +157 -0
- data/spec/fixtures/cassettes/gateway/credit.yml +208 -0
- data/spec/fixtures/cassettes/gateway/customer.yml +79 -0
- data/spec/fixtures/cassettes/gateway/purchase.yml +87 -0
- data/spec/fixtures/cassettes/gateway/settled_transaction.yml +140 -0
- data/spec/fixtures/cassettes/gateway/void.yml +137 -0
- data/spec/fixtures/cassettes/source/bin.yml +295 -0
- data/spec/fixtures/cassettes/source/card_type.yml +267 -0
- data/spec/fixtures/cassettes/source/last4.yml +267 -0
- data/spec/fixtures/cassettes/transaction/import/valid/capture.yml +224 -0
- data/spec/fixtures/cassettes/transaction/import/valid.yml +71 -0
- data/spec/fixtures/views/spree/orders/edit.html.erb +50 -0
- data/spec/helpers/solidus_braintree/braintree_admin_helper_spec.rb +17 -0
- data/spec/helpers/solidus_braintree/braintree_checkout_helper_spec.rb +70 -0
- data/spec/models/solidus_braintree/address_spec.rb +71 -0
- data/spec/models/solidus_braintree/avs_result_spec.rb +317 -0
- data/spec/models/solidus_braintree/gateway_spec.rb +742 -0
- data/spec/models/solidus_braintree/response_spec.rb +280 -0
- data/spec/models/solidus_braintree/source_spec.rb +539 -0
- data/spec/models/solidus_braintree/transaction_address_spec.rb +235 -0
- data/spec/models/solidus_braintree/transaction_import_spec.rb +302 -0
- data/spec/models/solidus_braintree/transaction_spec.rb +86 -0
- data/spec/models/spree/store_spec.rb +14 -0
- data/spec/requests/spree/api/orders_controller_spec.rb +36 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/capybara.rb +7 -0
- data/spec/support/gateway_helpers.rb +29 -0
- data/spec/support/order_ready_for_payment.rb +37 -0
- data/spec/support/vcr.rb +42 -0
- data/spec/support/views.rb +1 -0
- metadata +281 -228
- data/.travis.yml +0 -41
- data/LICENSE.txt +0 -21
- data/app/controllers/spree/api/braintree_client_token_controller.rb +0 -13
- data/app/helpers/braintree_view_helpers.rb +0 -20
- data/app/models/concerns/solidus_braintree/add_name_validation_concern.rb +0 -8
- data/app/models/concerns/solidus_braintree/inject_device_data_concern.rb +0 -18
- data/app/models/concerns/solidus_braintree/payment_braintree_nonce_concern.rb +0 -8
- data/app/models/concerns/solidus_braintree/permitted_attributes_concern.rb +0 -11
- data/app/models/concerns/solidus_braintree/skip_require_card_numbers_concern.rb +0 -14
- data/app/models/concerns/solidus_braintree/use_data_field_concern.rb +0 -23
- data/app/models/credit_card_decorator.rb +0 -3
- data/app/models/payment_decorator.rb +0 -2
- data/app/models/permitted_attributes_decorator.rb +0 -1
- data/app/models/solidus/gateway/braintree_gateway.rb +0 -306
- data/app/overrides/spree/checkout/_confirm/braintree_security.html.erb.deface +0 -9
- data/app/views/spree/admin/payments/source_forms/_braintree.html.erb +0 -38
- data/app/views/spree/admin/payments/source_views/_braintree.html.erb +0 -30
- data/app/views/spree/checkout/payment/_braintree.html.erb +0 -55
- data/app/views/spree/checkout/payment/_braintree_initialization.html.erb +0 -12
- data/config/initializers/braintree.rb +0 -1
- data/db/migrate/20150910170527_add_data_to_credit_card.rb +0 -5
- data/db/migrate/20160426221931_add_braintree_device_data_to_order.rb +0 -5
- data/lib/assets/javascripts/spree/backend/braintree/solidus_braintree.js +0 -59
- data/lib/assets/javascripts/spree/frontend/braintree/solidus_braintree.js +0 -144
- data/lib/assets/javascripts/vendor/braintree.js +0 -8
- data/lib/assets/stylesheets/spree/frontend/solidus_braintree.scss +0 -26
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
require 'solidus_braintree/country_mapper'
|
5
|
+
|
6
|
+
module SolidusBraintree
|
7
|
+
class TransactionAddress
|
8
|
+
include ActiveModel::Model
|
9
|
+
include ActiveModel::Validations::Callbacks
|
10
|
+
include SolidusBraintree::CountryMapper
|
11
|
+
|
12
|
+
attr_accessor :country_code, :name, :city, :zip, :state_code,
|
13
|
+
:address_line_1, :address_line_2, :first_name, :last_name
|
14
|
+
|
15
|
+
validates :address_line_1, :city, :zip, :country_code, presence: true
|
16
|
+
validates :name, presence: true, unless: ->(address){ address.first_name.present? }
|
17
|
+
|
18
|
+
before_validation do
|
19
|
+
self.country_code = country_code.presence || "us"
|
20
|
+
end
|
21
|
+
|
22
|
+
validates :spree_country, presence: true
|
23
|
+
validates :state_code, :spree_state, presence: true, if: :should_match_state_model?
|
24
|
+
|
25
|
+
def initialize(attributes = {})
|
26
|
+
country_name = attributes.delete(:country_name) || ""
|
27
|
+
if attributes[:country_code].blank?
|
28
|
+
attributes[:country_code] = iso_from_name(country_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
super(attributes)
|
32
|
+
end
|
33
|
+
|
34
|
+
def spree_country
|
35
|
+
country_code && (@country ||= ::Spree::Country.find_by(iso: country_code.upcase))
|
36
|
+
end
|
37
|
+
|
38
|
+
def spree_state
|
39
|
+
spree_country && state_code && ( @state ||= spree_country.states.find_by(
|
40
|
+
::Spree::State.arel_table[:name].matches(state_code).or(
|
41
|
+
::Spree::State.arel_table[:abbr].matches(state_code)
|
42
|
+
)
|
43
|
+
))
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_spree_address
|
47
|
+
address = ::Spree::Address.new(
|
48
|
+
city: city,
|
49
|
+
country: spree_country,
|
50
|
+
address1: address_line_1,
|
51
|
+
address2: address_line_2,
|
52
|
+
zipcode: zip
|
53
|
+
)
|
54
|
+
|
55
|
+
if SolidusSupport.combined_first_and_last_name_in_address?
|
56
|
+
address.name = begin
|
57
|
+
if first_name.nil?
|
58
|
+
name
|
59
|
+
else
|
60
|
+
[first_name, last_name].join(" ")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
else
|
64
|
+
::Spree::Deprecation.warn("first_name and last_name are deprecated. Use name instead.", caller)
|
65
|
+
if first_name.nil?
|
66
|
+
first, last = SolidusBraintree::Address.split_name(name)
|
67
|
+
address.firstname = first
|
68
|
+
address.lastname = last || "(left blank)"
|
69
|
+
else
|
70
|
+
address.firstname = first_name
|
71
|
+
address.lastname = last_name || "(left blank)"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
if spree_state
|
76
|
+
address.state = spree_state
|
77
|
+
else
|
78
|
+
address.state_name = state_code
|
79
|
+
end
|
80
|
+
address
|
81
|
+
end
|
82
|
+
|
83
|
+
# Check to see if this address should match to a state model in the database
|
84
|
+
def should_match_state_model?
|
85
|
+
spree_country&.states_required?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
|
5
|
+
module SolidusBraintree
|
6
|
+
class TransactionImport
|
7
|
+
class InvalidImportError < StandardError; end
|
8
|
+
|
9
|
+
include ActiveModel::Model
|
10
|
+
|
11
|
+
validate do
|
12
|
+
errors.add("Address", "is invalid") if address&.invalid?
|
13
|
+
|
14
|
+
if transaction.invalid?
|
15
|
+
transaction.errors.each do |error|
|
16
|
+
errors.add(error.attribute, error.message)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
errors.none?
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :transaction, :order
|
23
|
+
|
24
|
+
def initialize(order, transaction)
|
25
|
+
@order = order
|
26
|
+
@transaction = transaction
|
27
|
+
end
|
28
|
+
|
29
|
+
def source
|
30
|
+
SolidusBraintree::Source.new(
|
31
|
+
nonce: transaction.nonce,
|
32
|
+
payment_type: transaction.payment_type,
|
33
|
+
payment_method: transaction.payment_method,
|
34
|
+
paypal_funding_source: transaction.paypal_funding_source,
|
35
|
+
user: user
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
delegate :user, to: :order
|
40
|
+
|
41
|
+
def import!(end_state, restart_checkout: false)
|
42
|
+
if valid?
|
43
|
+
order.email = user&.email || transaction.email
|
44
|
+
|
45
|
+
if address
|
46
|
+
order.shipping_address = order.billing_address = address
|
47
|
+
# work around a bug in most solidus versions
|
48
|
+
# about tax zone cachine between address changes
|
49
|
+
order.instance_variable_set(:@tax_zone, nil)
|
50
|
+
end
|
51
|
+
|
52
|
+
payment = order.payments.new(
|
53
|
+
source: source,
|
54
|
+
payment_method: transaction.payment_method,
|
55
|
+
amount: order.total
|
56
|
+
)
|
57
|
+
|
58
|
+
order.save!
|
59
|
+
order.restart_checkout_flow if restart_checkout
|
60
|
+
advance_order(payment, end_state)
|
61
|
+
else
|
62
|
+
raise InvalidImportError,
|
63
|
+
"Validation failed: #{errors.full_messages.join(', ')}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def address
|
68
|
+
transaction.address && transaction.address.to_spree_address.tap do |address|
|
69
|
+
address.phone = transaction.phone
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def state_before_current?(state)
|
74
|
+
steps = order.checkout_steps
|
75
|
+
steps.index(state) < (steps.index(order.state) || 0)
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
def advance_order(payment, end_state)
|
81
|
+
return if state_before_current?(end_state)
|
82
|
+
|
83
|
+
until order.state == end_state
|
84
|
+
order.next!
|
85
|
+
update_payment_total(payment) if order.payment?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def update_payment_total(payment)
|
90
|
+
payment_total = order.payments.where(state: %w[checkout pending]).sum(:amount)
|
91
|
+
payment_difference = order.outstanding_balance - payment_total
|
92
|
+
|
93
|
+
return unless payment_difference != 0
|
94
|
+
|
95
|
+
payment.update!(amount: payment.amount + payment_difference)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Deface::Override.new(
|
4
|
+
name: "payments/payment/add_paypal_funding_source_to_payment",
|
5
|
+
virtual_path: "spree/payments/_payment",
|
6
|
+
original: "0b5b5ae53626059cb3a202ef95d10827dd399925",
|
7
|
+
insert_after: "erb[loud]:contains('content_tag(:span, payment.payment_method.name)')",
|
8
|
+
partial: "solidus_braintree/payments/payment"
|
9
|
+
)
|
@@ -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>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<% address = current_order.ship_address %>
|
2
|
+
|
3
|
+
<button id="apple-pay-button" class="apple-pay-button"></button>
|
4
|
+
|
5
|
+
<script>
|
6
|
+
var applePayButtonElement = document.getElementById('apple-pay-button');
|
7
|
+
var applePayOptions = {
|
8
|
+
paymentMethodId: <%= id %>,
|
9
|
+
storeName: "<%= current_store.name %>",
|
10
|
+
orderEmail: "<%= current_order.email %>",
|
11
|
+
amount: "<%= current_order.total %>",
|
12
|
+
shippingContact: {
|
13
|
+
emailAddress: '<%= current_order.email %>',
|
14
|
+
givenName: '<%= address.firstname %>',
|
15
|
+
familyName: '<%= address.lastname %>',
|
16
|
+
phoneNumber: '<%= address.phone %>',
|
17
|
+
addressLines: ['<%= address.address1 %>','<%= address.address2 %>'],
|
18
|
+
locality: '<%= address.city %>',
|
19
|
+
administrativeArea: '<%= address.state.name %>',
|
20
|
+
postalCode: '<%= address.zipcode %>',
|
21
|
+
country: '<%= address.country.name %>',
|
22
|
+
countryCode: '<%= address.country.iso %>'
|
23
|
+
}
|
24
|
+
};
|
25
|
+
var button = new SolidusBraintree.createApplePayButton(applePayButtonElement, applePayOptions);
|
26
|
+
button.initialize();
|
27
|
+
</script>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<script type="text/javascript">
|
2
|
+
BraintreeError.DEFAULT = "<%= I18n.t('solidus_braintree.errors.default_error')%>"
|
3
|
+
BraintreeError.PAYPAL_POPUP_CLOSED = "<%= I18n.t('solidus_braintree.errors.paypal_popup_closed') %>"
|
4
|
+
BraintreeError.HOSTED_FIELDS_FIELDS_EMPTY = "<%= I18n.t('solidus_braintree.errors.empty_fields')%>"
|
5
|
+
BraintreeError.HOSTED_FIELDS_FIELDS_INVALID = "<%= I18n.t('solidus_braintree.errors.invalid_fields')%>"
|
6
|
+
BraintreeError.HOSTED_FIELDS_FAILED_TOKENIZATION = "<%= I18n.t('solidus_braintree.errors.invalid_card')%>"
|
7
|
+
BraintreeError.HOSTED_FIELDS_TOKENIZATION_NETWORK_ERROR = "<%= I18n.t('solidus_braintree.errors.network_error')%>"
|
8
|
+
BraintreeError.HOSTED_FIELDS_FIELD_DUPLICATE_IFRAME = "<%= I18n.t('solidus_braintree.errors.duplicate_iframe')%>"
|
9
|
+
BraintreeError.HOSTED_FIELDS_TOKENIZATION_FAIL_ON_DUPLICATE = "<%= I18n.t('solidus_braintree.errors.fail_on_duplicate')%>"
|
10
|
+
BraintreeError.HOSTED_FIELDS_TOKENIZATION_CVV_VERIFICATION_FAILED = "<%= I18n.t('solidus_braintree.errors.cvv_verification_failed')%>"
|
11
|
+
BraintreeError.THREEDS_AUTHENTICATION_FAILED = "<%= t('solidus_braintree.errors.threeds.authentication_failed') %>";
|
12
|
+
BraintreeError.THREEDS_CARDINAL_SDK_ERROR = "<%= t('solidus_braintree.errors.threeds.authentication_failed') %>";
|
13
|
+
BraintreeError.VENMO_CANCELED = "<%= t('solidus_braintree.errors.venmo.canceled') %>";
|
14
|
+
BraintreeError.VENMO_DESKTOP_CANCELED = "<%= t('solidus_braintree.errors.venmo.desktop_canceled') %>";
|
15
|
+
BraintreeError.VENMO_APP_CANCELED = "<%= t('solidus_braintree.errors.venmo.app_canceled') %>";
|
16
|
+
</script>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<% content_for :head do %>
|
2
|
+
<script src="https://js.braintreegateway.com/web/3.84.0/js/client.min.js"></script>
|
3
|
+
<script src="https://js.braintreegateway.com/web/3.84.0/js/data-collector.min.js"></script>
|
4
|
+
|
5
|
+
<% if current_store.braintree_configuration.paypal? %>
|
6
|
+
<script src="https://js.braintreegateway.com/web/3.84.0/js/paypal-checkout.min.js"></script>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% if current_store.braintree_configuration.credit_card? %>
|
10
|
+
<script src="https://js.braintreegateway.com/web/3.84.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.84.0/js/three-d-secure.min.js"></script>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<% if current_store.braintree_configuration.apple_pay? %>
|
18
|
+
<script src="https://js.braintreegateway.com/web/3.84.0/js/apple-pay.min.js"></script>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<% if current_store.braintree_configuration.venmo? %>
|
22
|
+
<script src="https://js.braintreegateway.com/web/3.84.0/js/venmo.min.js"></script>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<%= javascript_include_tag "solidus_braintree/checkout" %>
|
26
|
+
<% end %>
|
@@ -0,0 +1,43 @@
|
|
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 %>
|
8
|
+
|
9
|
+
<% prefix = "payment_source[#{payment_method.id}]" %>
|
10
|
+
|
11
|
+
<div class="hosted-fields">
|
12
|
+
<div class="field" data-hook="card_number">
|
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>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div class="field" data-hook="card_expiration">
|
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>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<div class="field" data-hook="card_code">
|
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>
|
25
|
+
|
26
|
+
<a href="/content/cvv" class="info cvvLink" target="_blank">
|
27
|
+
(<%= I18n.t("spree.what_is_this") %>)
|
28
|
+
</a>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
<div class="clear"></div>
|
32
|
+
<input type="hidden" name="<%= prefix %>[payment_type]" value="<%= SolidusBraintree::Source::CREDIT_CARD %>">
|
33
|
+
<input type="hidden" id="payment_method_nonce" name="<%= prefix %>[nonce]">
|
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>
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<%= render "spree/shared/braintree_head_scripts" %>
|
2
|
+
|
3
|
+
<div id="paypal-button"></div>
|
4
|
+
<div data-pp-message data-pp-placement="payment" data-pp-amount="<%= current_order.total %>"></div>
|
5
|
+
|
6
|
+
<script>
|
7
|
+
var paypalOptions = {
|
8
|
+
flow: '<%= SolidusBraintree::Gateway.first.preferred_paypal_flow %>',
|
9
|
+
amount: '<%= current_order.total %>',
|
10
|
+
currency: '<%= current_order.currency %>',
|
11
|
+
enableShippingAddress: true,
|
12
|
+
buyerCountry: '<%= SolidusBraintree::Gateway.first.preferred_force_buyer_country %>',
|
13
|
+
environment: '<%= Rails.env.production? ? "production" : "sandbox" %>',
|
14
|
+
locale: '<%= paypal_button_preference(:paypal_button_locale, store: current_store) %>',
|
15
|
+
useDataCollector: <%= SolidusBraintree::Gateway.first.preferred_use_data_collector %>,
|
16
|
+
style: {
|
17
|
+
color: '<%= paypal_button_preference(:paypal_button_color, store: current_store) %>',
|
18
|
+
shape: '<%= paypal_button_preference(:paypal_button_shape, store: current_store) %>',
|
19
|
+
label: '<%= paypal_button_preference(:paypal_button_label, store: current_store) %>',
|
20
|
+
layout: '<%= paypal_button_preference(:paypal_button_layout, store: current_store) %>',
|
21
|
+
<% if paypal_button_preference(:paypal_button_layout, store: current_store) == "horizontal" %>
|
22
|
+
tagline: '<%= paypal_button_preference(:paypal_button_tagline, store: current_store) %>',
|
23
|
+
<% end %>
|
24
|
+
messaging: '<%= paypal_button_preference(:paypal_button_messaging, store: current_store) %>'
|
25
|
+
}
|
26
|
+
}
|
27
|
+
var options = {
|
28
|
+
restart_checkout: true
|
29
|
+
}
|
30
|
+
|
31
|
+
var button = new SolidusBraintree.createPaypalButton(
|
32
|
+
document.querySelector("#paypal-button"),
|
33
|
+
paypalOptions,
|
34
|
+
options
|
35
|
+
)
|
36
|
+
|
37
|
+
button.initialize();
|
38
|
+
</script>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= render "spree/shared/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 SolidusBraintree.createPaypalMessaging(
|
7
|
+
{
|
8
|
+
currency: "<%= options[:currency] %>"
|
9
|
+
}
|
10
|
+
)
|
11
|
+
|
12
|
+
message.initialize();
|
13
|
+
</script>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<%= button_tag '', id: 'venmo-button', class: 'venmo-button', type: 'button' %>
|
2
|
+
|
3
|
+
<% store = Spree::Store.default %>
|
4
|
+
<% style = venmo_button_style(store) %>
|
5
|
+
|
6
|
+
<style>
|
7
|
+
.venmo-button {
|
8
|
+
width: <%= style[:width] %>px;
|
9
|
+
background-image: url('<%= venmo_button_asset_url(style)%>');
|
10
|
+
}
|
11
|
+
.venmo-button:active, .venmo-button:hover {
|
12
|
+
background-color: transparent !important;
|
13
|
+
background-image: url('<%= venmo_button_asset_url(style, active: true)%>') !important;
|
14
|
+
}
|
15
|
+
</style>
|
16
|
+
|
17
|
+
<% prefix = "payment_source[#{payment_method.id}]" %>
|
18
|
+
|
19
|
+
<div class="venmo-fields">
|
20
|
+
<div class="clear"></div>
|
21
|
+
<input disabled type="hidden" name="<%= prefix %>[payment_type]" value="<%= SolidusBraintree::Source::VENMO %>">
|
22
|
+
<input disabled type="hidden" id="venmo_payment_method_nonce" name="<%= prefix %>[nonce]">
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<script>
|
26
|
+
var venmoButtonElement = document.getElementById('venmo-button');
|
27
|
+
var venmoOptions = {
|
28
|
+
newBrowserTabSupported: <%= SolidusBraintree::Gateway.first.preferred_venmo_new_tab_support %>,
|
29
|
+
flow: '<%= SolidusBraintree::Gateway.first.preferred_paypal_flow %>'
|
30
|
+
};
|
31
|
+
var button = new SolidusBraintree.createVenmoButton(venmoButtonElement, venmoOptions);
|
32
|
+
button.initialize();
|
33
|
+
</script>
|
data/bin/console
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
3
5
|
require "bundler/setup"
|
4
6
|
require "solidus_braintree"
|
5
7
|
|
6
8
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
9
|
# with your gem easier. You can also use a different console, if you like.
|
10
|
+
$LOAD_PATH.unshift(*Dir["#{__dir__}/../app/*"])
|
8
11
|
|
9
12
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
13
|
# require "pry"
|
11
14
|
# Pry.start
|
12
15
|
|
13
16
|
require "irb"
|
14
|
-
IRB.start
|
17
|
+
IRB.start(__FILE__)
|
data/bin/rails
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
if %w[g generate].include? ARGV.first
|
4
|
+
exec "#{__dir__}/rails-engine", *ARGV
|
5
|
+
else
|
6
|
+
exec "#{__dir__}/rails-sandbox", *ARGV
|
7
|
+
end
|
data/bin/rails-engine
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails gems
|
3
|
+
# installed from the root of your application.
|
4
|
+
|
5
|
+
ENGINE_ROOT = File.expand_path('..', __dir__)
|
6
|
+
ENGINE_PATH = File.expand_path('../lib/solidus_braintree/engine', __dir__)
|
7
|
+
|
8
|
+
# Set up gems listed in the Gemfile.
|
9
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
10
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
11
|
+
|
12
|
+
require 'rails/all'
|
13
|
+
require 'rails/engine/commands'
|
data/bin/rails-sandbox
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
app_root = 'sandbox'
|
4
|
+
|
5
|
+
unless File.exist? "#{app_root}/bin/rails"
|
6
|
+
warn 'Creating the sandbox app...'
|
7
|
+
Dir.chdir "#{__dir__}/.." do
|
8
|
+
system "#{__dir__}/sandbox" or begin
|
9
|
+
warn 'Automatic creation of the sandbox app failed'
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Dir.chdir app_root
|
16
|
+
exec 'bin/rails', *ARGV
|
data/bin/rake
ADDED
data/bin/sandbox
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
if [ -n "$DEBUG" ]
|
5
|
+
then
|
6
|
+
set -x
|
7
|
+
fi
|
8
|
+
|
9
|
+
case "$DB" in
|
10
|
+
postgres|postgresql)
|
11
|
+
RAILSDB="postgresql"
|
12
|
+
;;
|
13
|
+
mysql)
|
14
|
+
RAILSDB="mysql"
|
15
|
+
;;
|
16
|
+
sqlite3|sqlite)
|
17
|
+
RAILSDB="sqlite3"
|
18
|
+
;;
|
19
|
+
'')
|
20
|
+
echo "~~> Use 'export DB=[postgres|mysql|sqlite]' to control the DB adapter"
|
21
|
+
RAILSDB="sqlite3"
|
22
|
+
;;
|
23
|
+
*)
|
24
|
+
echo "Invalid value specified for the Solidus sandbox: DB=\"$DB\"."
|
25
|
+
echo "Please use 'postgres', 'mysql', or 'sqlite' instead."
|
26
|
+
exit 1
|
27
|
+
;;
|
28
|
+
esac
|
29
|
+
echo "~~> Using $RAILSDB as the database engine"
|
30
|
+
|
31
|
+
if [ -z "$SOLIDUS_BRANCH" ]
|
32
|
+
then
|
33
|
+
echo "~~> Use 'export SOLIDUS_BRANCH=[master|v3.2|...]' to control the Solidus branch"
|
34
|
+
SOLIDUS_BRANCH="master"
|
35
|
+
fi
|
36
|
+
echo "~~> Using branch $SOLIDUS_BRANCH of solidus"
|
37
|
+
|
38
|
+
if [ -z "$SOLIDUS_FRONTEND" ]
|
39
|
+
then
|
40
|
+
echo "~~> Use 'export SOLIDUS_FRONTEND=[solidus_frontend|solidus_starter_frontend]' to control the Solidus frontend"
|
41
|
+
SOLIDUS_FRONTEND="solidus_frontend"
|
42
|
+
fi
|
43
|
+
echo "~~> Using branch $SOLIDUS_FRONTEND as the solidus frontend"
|
44
|
+
|
45
|
+
extension_name="solidus_braintree"
|
46
|
+
|
47
|
+
# Stay away from the bundler env of the containing extension.
|
48
|
+
function unbundled {
|
49
|
+
ruby -rbundler -e'b = proc {system *ARGV}; Bundler.respond_to?(:with_unbundled_env) ? Bundler.with_unbundled_env(&b) : Bundler.with_clean_env(&b)' -- $@
|
50
|
+
}
|
51
|
+
|
52
|
+
rm -rf ./sandbox
|
53
|
+
unbundled bundle exec rails new sandbox --database="$RAILSDB" \
|
54
|
+
--skip-bundle \
|
55
|
+
--skip-git \
|
56
|
+
--skip-keeps \
|
57
|
+
--skip-rc \
|
58
|
+
--skip-spring \
|
59
|
+
--skip-test \
|
60
|
+
--skip-javascript
|
61
|
+
|
62
|
+
if [ ! -d "sandbox" ]; then
|
63
|
+
echo 'sandbox rails application failed'
|
64
|
+
exit 1
|
65
|
+
fi
|
66
|
+
|
67
|
+
cd ./sandbox
|
68
|
+
cat <<RUBY >> Gemfile
|
69
|
+
gem 'solidus', github: 'solidusio/solidus', branch: '$SOLIDUS_BRANCH'
|
70
|
+
gem 'rails-i18n'
|
71
|
+
gem 'solidus_i18n'
|
72
|
+
|
73
|
+
# This Braintree extension contains a user decorator, so the user class must be loaded first.
|
74
|
+
gem "solidus_auth_devise", "~> 2.5"
|
75
|
+
gem '$extension_name', path: '..'
|
76
|
+
|
77
|
+
group :test, :development do
|
78
|
+
platforms :mri do
|
79
|
+
gem 'pry-byebug'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
RUBY
|
83
|
+
|
84
|
+
unbundled bundle install --gemfile Gemfile
|
85
|
+
|
86
|
+
unbundled bundle exec rake db:drop db:create
|
87
|
+
|
88
|
+
# Still request "devise". Solidus will skip installing it again but will include its seeds.
|
89
|
+
unbundled bundle exec rails generate solidus:install \
|
90
|
+
--auto-accept \
|
91
|
+
--user_class=Spree::User \
|
92
|
+
--enforce_available_locales=true \
|
93
|
+
--authentication="devise" \
|
94
|
+
--payment-method=none \
|
95
|
+
--frontend=${SOLIDUS_FRONTEND} \
|
96
|
+
$@
|
97
|
+
|
98
|
+
unbundled bundle exec rails generate solidus:auth:install --auto-run-migrations
|
99
|
+
unbundled bundle exec rails generate ${extension_name}:install --auto-run-migrations
|
100
|
+
|
101
|
+
echo
|
102
|
+
echo "๐ Sandbox app successfully created for $extension_name!"
|
103
|
+
echo "๐งช This app is intended for test purposes."
|
data/bin/setup
CHANGED