spree_braintree_vzero 3.5.1 → 3.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +11 -0
- data/.travis.yml +39 -46
- data/Appraisals +19 -28
- data/README.md +6 -4
- data/app/assets/images/backend-settle.svg +3 -0
- data/app/assets/javascripts/spree/frontend/spree_braintree_vzero.js +3 -1
- data/app/controllers/spree/admin/payments_controller_decorator.rb +9 -4
- data/app/controllers/spree/orders_controller_decorator.rb +2 -0
- data/app/helpers/spree/admin/payment_methods_helper.rb +11 -5
- data/app/helpers/spree/braintree_helper.rb +2 -2
- data/app/models/concerns/spree/gateway/braintree_vzero/legacy_rails_patch.rb +20 -0
- data/app/models/spree/address_decorator.rb +2 -2
- data/app/models/spree/braintree_vzero/order_decorator.rb +155 -0
- data/app/models/spree/gateway/braintree_vzero_base/utils.rb +50 -3
- data/app/models/spree/gateway/braintree_vzero_base.rb +4 -0
- data/app/models/spree/gateway/braintree_vzero_drop_in_ui.rb +3 -1
- data/app/models/spree/gateway/braintree_vzero_hosted_fields.rb +3 -1
- data/app/models/spree/log_entry_decorator.rb +52 -0
- data/app/models/spree/payment_processing_decorator.rb +12 -0
- data/app/models/spree/preferences/preferable_decorator.rb +1 -1
- data/app/overrides/spree/orders/edit.rb +1 -1
- data/app/views/spree/braintree_vzero/_paypal_checkout.html.erb +77 -59
- data/app/views/spree/checkout/payment/braintree_vzero/_non_three_d_secure.html.erb +178 -0
- data/app/views/spree/checkout/payment/braintree_vzero/_payment.html.erb +32 -13
- data/app/views/spree/checkout/payment/braintree_vzero/_three_d_secure.html.erb +54 -14
- data/config/initializers/prepend_helpers.rb +3 -1
- data/db/migrate/20160112153422_add_admin_payment_to_spree_braintree_checkout.rb +1 -1
- data/gemfiles/spree_3_7.gemfile +2 -0
- data/gemfiles/spree_4_0.gemfile +1 -0
- data/gemfiles/{spree_3_5.gemfile → spree_4_1.gemfile} +2 -5
- data/gemfiles/{spree_4_0_spree_auth_devise.gemfile → spree_4_2.gemfile} +2 -2
- data/gemfiles/spree_master.gemfile +1 -3
- data/lib/spree_braintree_vzero/engine.rb +3 -1
- data/lib/spree_braintree_vzero/version.rb +2 -2
- data/spec/controllers/spree/checkout_controller_spec.rb +1 -1
- data/spec/features/spree/admin/log_entries_spec.rb +18 -3
- data/spec/models/gateway/braintree_vzero_base_spec.rb +8 -5
- data/spec/models/spree/address_spec.rb +18 -0
- data/spec/support/vcr.rb +1 -1
- data/spec/vcr/Spree_Gateway_BraintreeVzeroBase/valid_credentials/_purchase/using_Vault/sends_address_data_when_address_is_new.yml +72 -0
- data/spree_braintree_vzero.gemspec +4 -5
- metadata +22 -49
- data/app/controllers/spree/user_sessions_controller_decorator.rb +0 -15
- data/app/models/spree/order_decorator.rb +0 -153
- data/gemfiles/spree_3_5_spree_auth_devise.gemfile +0 -13
- data/gemfiles/spree_3_7_spree_auth_devise.gemfile +0 -13
- data/gemfiles/spree_master_spree_auth_devise.gemfile +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09e02a4cf3c79e5be3e0964676effe42b4633d8aa4ed2b991b7f301c962f5545'
|
4
|
+
data.tar.gz: 646f04bc68b92b1347ab313ef428ab47171cab19d2db364f714ea57320750350
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1bb01d7427a967624664259f2cd13679b2c6678ef81b2265b81a8bc67af912dcdf3dea095764e1ad25f8c9646d89548b70c2b45aca8de31cd901749f64ed6eb3
|
7
|
+
data.tar.gz: d9ef517a4204b61b2eca65f4412ebd62e583c34e3a53517541ca4c8d48624203a96657ea571acca80fad2090793ddf188af6514d9e8d9323f7f7bda700126e7e
|
data/.travis.yml
CHANGED
@@ -1,5 +1,16 @@
|
|
1
|
-
|
2
|
-
dist:
|
1
|
+
os: linux
|
2
|
+
dist: bionic
|
3
|
+
|
4
|
+
addons:
|
5
|
+
apt:
|
6
|
+
sources:
|
7
|
+
- google-chrome
|
8
|
+
packages:
|
9
|
+
- google-chrome-stable
|
10
|
+
|
11
|
+
services:
|
12
|
+
- mysql
|
13
|
+
- postgresql
|
3
14
|
|
4
15
|
language: ruby
|
5
16
|
|
@@ -7,57 +18,39 @@ env:
|
|
7
18
|
- DB=postgres
|
8
19
|
- DB=mysql
|
9
20
|
|
21
|
+
rvm:
|
22
|
+
- 2.7
|
23
|
+
- 3.0
|
24
|
+
|
10
25
|
gemfile:
|
11
|
-
- gemfiles/spree_3_5.gemfile
|
12
|
-
- gemfiles/spree_3_5_spree_auth_devise.gemfile
|
13
26
|
- gemfiles/spree_3_7.gemfile
|
14
|
-
- gemfiles/spree_3_7_spree_auth_devise.gemfile
|
15
27
|
- gemfiles/spree_4_0.gemfile
|
16
|
-
- gemfiles/
|
28
|
+
- gemfiles/spree_4_1.gemfile
|
29
|
+
- gemfiles/spree_4_2.gemfile
|
17
30
|
- gemfiles/spree_master.gemfile
|
18
|
-
- gemfiles/spree_master_spree_auth_devise.gemfile
|
19
31
|
|
20
32
|
script:
|
21
33
|
- bundle exec rake test_app
|
22
34
|
- bundle exec rake spec
|
23
35
|
- bundle exec codeclimate-test-reporter
|
24
36
|
|
25
|
-
|
26
|
-
|
27
|
-
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
- rvm: 2.4.4
|
46
|
-
gemfile: gemfiles/spree_4_0_spree_auth_devise.gemfile
|
47
|
-
- rvm: 2.4.4
|
48
|
-
gemfile: gemfiles/spree_master.gemfile
|
49
|
-
- rvm: 2.4.4
|
50
|
-
gemfile: gemfiles/spree_master_spree_auth_devise.gemfile
|
51
|
-
- rvm: 2.5.1
|
52
|
-
gemfile: gemfiles/spree_3_5.gemfile
|
53
|
-
- rvm: 2.5.1
|
54
|
-
gemfile: gemfiles/spree_3_5_spree_auth_devise.gemfile
|
55
|
-
|
56
|
-
|
57
|
-
addons:
|
58
|
-
apt:
|
59
|
-
packages:
|
60
|
-
- mysql-server-5.6
|
61
|
-
- mysql-client-core-5.6
|
62
|
-
- mysql-client-5.6
|
63
|
-
postgresql: 9.4
|
37
|
+
jobs:
|
38
|
+
exclude:
|
39
|
+
- rvm: 3.0
|
40
|
+
gemfile: gemfiles/spree_3_7.gemfile
|
41
|
+
- rvm: 3.0
|
42
|
+
gemfile: gemfiles/spree_4_0.gemfile
|
43
|
+
- rvm: 3.0
|
44
|
+
gemfile: gemfiles/spree_4_1.gemfile
|
45
|
+
allow_failures:
|
46
|
+
- gemfile: gemfiles/spree_master.gemfile
|
47
|
+
|
48
|
+
before_install:
|
49
|
+
- mysql -u root -e "GRANT ALL ON *.* TO 'travis'@'%';"
|
50
|
+
|
51
|
+
before_script:
|
52
|
+
- CHROME_MAIN_VERSION=`google-chrome-stable --version | sed -E 's/(^Google Chrome |\.[0-9]+ )//g'`
|
53
|
+
- CHROMEDRIVER_VERSION=`curl -s "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_$CHROME_MAIN_VERSION"`
|
54
|
+
- curl "https://chromedriver.storage.googleapis.com/${CHROMEDRIVER_VERSION}/chromedriver_linux64.zip" -O
|
55
|
+
- unzip chromedriver_linux64.zip -d ~/bin
|
56
|
+
- nvm install 14
|
data/Appraisals
CHANGED
@@ -1,44 +1,35 @@
|
|
1
|
-
appraise 'spree-3-5' do
|
2
|
-
ENV['WITHOUT_SPREE_AUTH_DEVISE'] = 'true'
|
3
|
-
|
4
|
-
gem 'spree', '~> 3.5.0'
|
5
|
-
end
|
6
|
-
|
7
|
-
appraise 'spree-3-5-spree-auth-devise' do
|
8
|
-
gem 'spree', '~> 3.5.0'
|
9
|
-
gem 'spree_auth_devise', '~> 3.3.0'
|
10
|
-
end
|
11
|
-
|
12
1
|
appraise 'spree-3-7' do
|
13
|
-
|
14
|
-
|
2
|
+
gem 'sassc-rails'
|
15
3
|
gem 'spree', '~> 3.7.1'
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
gem '
|
20
|
-
gem 'spree_auth_devise', '~> 3.
|
4
|
+
gem 'pg'
|
5
|
+
gem 'mysql2'
|
6
|
+
gem 'webmock', '>= 2.3.1'
|
7
|
+
gem 'rails-controller-testing'
|
8
|
+
gem 'spree_auth_devise', '~> 3.5.2'
|
21
9
|
end
|
22
10
|
|
23
11
|
appraise 'spree-4-0' do
|
24
|
-
ENV['WITHOUT_SPREE_AUTH_DEVISE'] = 'true'
|
25
|
-
|
26
|
-
gem 'spree', '~> 4.0.0'
|
27
|
-
end
|
28
|
-
|
29
|
-
appraise 'spree-4-0-spree-auth-devise' do
|
30
12
|
gem 'spree', '~> 4.0.0'
|
13
|
+
gem 'pg'
|
14
|
+
gem 'mysql2'
|
15
|
+
gem 'webmock', '>= 2.3.1'
|
16
|
+
gem 'rails-controller-testing'
|
31
17
|
gem 'spree_auth_devise', '~> 4.0.0'
|
32
18
|
end
|
33
19
|
|
34
|
-
appraise 'spree-
|
35
|
-
|
20
|
+
appraise 'spree-4-1' do
|
21
|
+
gem 'spree', '~> 4.1.0'
|
22
|
+
gem 'spree_auth_devise', '~> 4.1.0'
|
23
|
+
gem 'rails-controller-testing'
|
24
|
+
end
|
36
25
|
|
37
|
-
|
26
|
+
appraise 'spree-4-2' do
|
27
|
+
gem 'spree', '~> 4.2.0'
|
28
|
+
gem 'spree_auth_devise', '~> 4.2.0'
|
38
29
|
gem 'rails-controller-testing'
|
39
30
|
end
|
40
31
|
|
41
|
-
appraise 'spree-master
|
32
|
+
appraise 'spree-master' do
|
42
33
|
gem 'spree', github: 'spree/spree', branch: 'master'
|
43
34
|
gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: 'master'
|
44
35
|
gem 'rails-controller-testing'
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
# Braintree
|
1
|
+
# Official Braintree + PayPal integration for Spree Commerce
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.
|
3
|
+
[![Build Status](https://travis-ci.com/spree-contrib/spree_braintree_vzero.svg?branch=master)](https://travis-ci.com/spree-contrib/spree_braintree_vzero) [![Code Climate](https://codeclimate.com/repos/560308aa6956801375000a4e/badges/9874199a656054d613cd/gpa.svg)](https://codeclimate.com/repos/560308aa6956801375000a4e/feed)
|
4
4
|
|
5
|
-
This is the official Braintree
|
5
|
+
This is the official Braintree + PayPal extension for [Spree Commerce](https://spreecommerce.org). It supports:
|
6
6
|
* [Braintree Hosted Fields](https://github.com/spree-contrib/spree_braintree_vzero/wiki/1.-Hosted-Fields) - style the credit card form to match your UI with full PCI compliance
|
7
7
|
* [PayPal Express Checkout](https://github.com/spree-contrib/spree_braintree_vzero/wiki/2.-PayPal-Express) - the fastest way for buyers to pay with PayPal - available on Spree for the first time
|
8
8
|
* [Braintree Drop-in UI](http://github.com/spree-contrib/spree_braintree_vzero/wiki/3.-Drop-in-UI) - start accepting payments ASAP
|
@@ -43,7 +43,9 @@ Behind-the-scenes, this extension uses [Braintree Ruby SDK](https://github.com/b
|
|
43
43
|
|
44
44
|
If your server was running, restart it so that it can find the assets properly.
|
45
45
|
|
46
|
+
## Documentation
|
46
47
|
|
48
|
+
See [wiki](https://github.com/spree-contrib/spree_braintree_vzero/wiki) for more detailed documentation.
|
47
49
|
|
48
50
|
## Heroku installation (optional)
|
49
51
|
|
@@ -64,7 +66,7 @@ pull request.
|
|
64
66
|
|
65
67
|
## License
|
66
68
|
|
67
|
-
Spree Braintree V.zero is copyright © 2015-
|
69
|
+
Spree Braintree V.zero is copyright © 2015-2021
|
68
70
|
[Spark Solutions Sp. z o.o.][spark]. It is free software,
|
69
71
|
and may be redistributed under the terms specified in the
|
70
72
|
[LICENCE](LICENSE) file.
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2">
|
2
|
+
<path fill="currentColor" d="M474.975 82.072c-5.79-5.77-15.123-5.77-20.874 0L173.92 362.589 58.76 247.27c-5.75-5.75-15.085-5.79-20.874 0-5.77 5.75-5.77 15.104 0 20.874l125.597 125.774c2.875 2.895 6.656 4.333 10.437 4.333 3.8 0 7.562-1.438 10.437-4.333l290.62-290.953c5.769-5.77 5.769-15.144 0-20.894z" fill-rule="nonzero" stroke="currentColor" stroke-width="24.024606"/>
|
3
|
+
</svg>
|
@@ -46,7 +46,8 @@ SpreeBraintreeVzero = {
|
|
46
46
|
}
|
47
47
|
}
|
48
48
|
|
49
|
-
$(document).ready(function() {
|
49
|
+
$(document).ready(function () {
|
50
|
+
var event = new Event('spreebraintree:ready');
|
50
51
|
paymentMethods = $('div[data-hook="checkout_payment_step"] input[type="radio"]').click(function (e) {
|
51
52
|
SpreeBraintreeVzero.setSaveAndContinueVisibility();
|
52
53
|
});
|
@@ -65,4 +66,5 @@ $(document).ready(function() {
|
|
65
66
|
SpreeBraintreeVzero.addDeviceData();
|
66
67
|
});
|
67
68
|
SpreeBraintreeVzero.setSaveAndContinueVisibility();
|
69
|
+
window.dispatchEvent(event);
|
68
70
|
})
|
@@ -1,6 +1,11 @@
|
|
1
1
|
module Spree
|
2
2
|
module Admin
|
3
3
|
module PaymentsControllerDecorator
|
4
|
+
def self.prepended(base)
|
5
|
+
base.include Spree::BraintreeHelper
|
6
|
+
base.helper_method [:asset_available?, :options_from_braintree_payments]
|
7
|
+
end
|
8
|
+
|
4
9
|
def create
|
5
10
|
invoke_callbacks(:create, :before)
|
6
11
|
@payment ||= @order.payments.build(object_params)
|
@@ -8,11 +13,11 @@ module Spree
|
|
8
13
|
if @payment.payment_method.source_required?
|
9
14
|
if params[:card].present? && params[:card] != 'new'
|
10
15
|
@payment.source = @payment.payment_method.payment_source_class.find_by_id(params[:card])
|
11
|
-
elsif @payment.payment_source.is_a?(Spree::Gateway::BraintreeVzeroBase)
|
12
|
-
@payment.braintree_token = params[:payment_method_token]
|
13
|
-
@payment.braintree_nonce = params[:payment_method_nonce]
|
14
|
-
@payment.source = Spree::BraintreeCheckout.create!(admin_payment: true)
|
15
16
|
end
|
17
|
+
elsif @payment.payment_source.is_a?(Spree::Gateway::BraintreeVzeroBase)
|
18
|
+
@payment.braintree_token = params[:payment_method_token]
|
19
|
+
@payment.braintree_nonce = params[:payment_method_nonce]
|
20
|
+
@payment.source = Spree::BraintreeCheckout.create!(admin_payment: true)
|
16
21
|
end
|
17
22
|
|
18
23
|
begin
|
@@ -7,6 +7,8 @@ module Spree
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def process_paypal_express
|
10
|
+
return false if current_order.blank?
|
11
|
+
|
10
12
|
if params[:paypal].blank? || params[:paypal][:payment_method_nonce].blank?
|
11
13
|
# when user goes back from checkout, paypal express payments should be invalidated to ensure standard checkout flow
|
12
14
|
current_order.invalidate_paypal_express_payments
|
@@ -84,11 +84,17 @@ module Spree
|
|
84
84
|
keys.reject { |k| k == :currency_merchant_accounts }.map do |key|
|
85
85
|
next unless object.has_preference?(key)
|
86
86
|
|
87
|
-
|
88
|
-
form
|
89
|
-
|
90
|
-
|
91
|
-
|
87
|
+
if object.preference_type(key) == :boolean
|
88
|
+
content_tag(:div, preference_field_for(form, "preferred_#{key}", type: object.preference_type(key)) +
|
89
|
+
form.label("preferred_#{key}", Spree.t(key), class: 'form-check-label'),
|
90
|
+
class: 'form-group form-check', id: [object.class.to_s.parameterize, 'preference', key].join('-'))
|
91
|
+
else
|
92
|
+
content_tag(:div, class: 'form-group', 'data-hook' => "preferred_#{key}") do
|
93
|
+
form.label("preferred_#{key}", Spree.t(key) + ': ') +
|
94
|
+
preference_field_for(form, "preferred_#{key}", type: object.preference_type(key),
|
95
|
+
values: object.send("preferred_#{key}_default").is_a?(Hash) ? object.send("preferred_#{key}_default")[:values] : nil,
|
96
|
+
selected: object.preferences[key])
|
97
|
+
end
|
92
98
|
end
|
93
99
|
end.join(' ').html_safe
|
94
100
|
end
|
@@ -6,14 +6,14 @@ module Spree
|
|
6
6
|
else
|
7
7
|
[]
|
8
8
|
end
|
9
|
-
additional_options + payment_methods.map do |method|
|
9
|
+
(additional_options + payment_methods.map do |method|
|
10
10
|
text = if method.is_a?(Braintree::CreditCard)
|
11
11
|
Spree.t('admin.vaulted_payments.credit_card', card_type: method.card_type, last_4: method.last_4)
|
12
12
|
elsif method.is_a?(Braintree::PayPalAccount)
|
13
13
|
Spree.t('admin.vaulted_payments.paypal', email: method.email)
|
14
14
|
end
|
15
15
|
"<option value='#{method.token}'>#{text}</option>"
|
16
|
-
end.join.html_safe
|
16
|
+
end).join.html_safe
|
17
17
|
end
|
18
18
|
|
19
19
|
def asset_available?(logical_path)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Spree
|
2
|
+
class Gateway
|
3
|
+
module BraintreeVzero
|
4
|
+
module LegacyRailsPatch
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
# https://github.com/spree-contrib/spree_braintree_vzero/issues/216
|
10
|
+
def method_name_for_attributes_after_save
|
11
|
+
Rails::VERSION::STRING >= '5.1' ? :saved_changes : :changes
|
12
|
+
end
|
13
|
+
|
14
|
+
def attributes_after_save
|
15
|
+
method(method_name_for_attributes_after_save).call
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -2,9 +2,9 @@ module Spree
|
|
2
2
|
module AddressDecorator
|
3
3
|
def self.prepended(base)
|
4
4
|
base.scope :vaulted_duplicates, ->(address) do
|
5
|
-
where.not(id: address.id).
|
5
|
+
base.where.not(id: address.id).
|
6
6
|
where.not(braintree_id: nil).
|
7
|
-
where(address.attributes.except('id', 'updated_at', 'created_at', 'braintree_id'))
|
7
|
+
where(address.attributes.except('id', 'updated_at', 'created_at', 'braintree_id', 'preferences'))
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module Spree
|
2
|
+
module BraintreeVzero
|
3
|
+
module OrderDecorator
|
4
|
+
def self.prepended(base)
|
5
|
+
base.state_machine.before_transition to: :complete, do: :process_paypal_express_payments
|
6
|
+
end
|
7
|
+
|
8
|
+
def save_paypal_address(type, address_hash)
|
9
|
+
return if address_hash.blank?
|
10
|
+
address = Spree::Address.new(prepare_address_hash(address_hash))
|
11
|
+
return unless address.save
|
12
|
+
|
13
|
+
update_column("#{type}_id", address.id)
|
14
|
+
end
|
15
|
+
|
16
|
+
def save_paypal_payment(options)
|
17
|
+
options[:source] = Spree::BraintreeCheckout.create!(options.slice(:paypal_email, :advanced_fraud_data))
|
18
|
+
payments.create(options.slice(:braintree_nonce, :payment_method_id, :source))
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_billing_address
|
22
|
+
return if bill_address_id
|
23
|
+
return unless ship_address_id
|
24
|
+
|
25
|
+
address = Spree::Address.create(shipping_address.attributes.except('id', 'updated_at', 'created_at', 'braintree_id'))
|
26
|
+
update_column(:bill_address_id, address.try(:id))
|
27
|
+
end
|
28
|
+
|
29
|
+
# override needed to add braintree source attribute
|
30
|
+
def update_from_params(params, permitted_params, request_env = {})
|
31
|
+
success = false
|
32
|
+
@updating_params = params
|
33
|
+
run_callbacks :updating_from_params do
|
34
|
+
# Set existing card after setting permitted parameters because
|
35
|
+
# rails would slice parameters containg ruby objects, apparently
|
36
|
+
existing_card_id = @updating_params[:order] ? @updating_params[:order].delete(:existing_card) : nil
|
37
|
+
|
38
|
+
attributes = @updating_params[:order] ? @updating_params[:order].permit(permitted_params).delete_if { |_k, v| v.nil? } : {}
|
39
|
+
payment_attributes = attributes[:payments_attributes].first if attributes[:payments_attributes].present?
|
40
|
+
|
41
|
+
if existing_card_id.present?
|
42
|
+
credit_card = Spree::CreditCard.find existing_card_id
|
43
|
+
if credit_card.user_id != user_id || credit_card.user_id.blank?
|
44
|
+
raise Spree::Core::GatewayError, Spree.t(:invalid_credit_card)
|
45
|
+
end
|
46
|
+
|
47
|
+
credit_card.verification_value = params[:cvc_confirm] if params[:cvc_confirm].present?
|
48
|
+
|
49
|
+
attributes[:payments_attributes].first[:source] = credit_card
|
50
|
+
attributes[:payments_attributes].first[:payment_method_id] = credit_card.payment_method_id
|
51
|
+
attributes[:payments_attributes].first.delete :source_attributes
|
52
|
+
end
|
53
|
+
|
54
|
+
if payment_attributes.present?
|
55
|
+
payment_attributes[:request_env] = request_env
|
56
|
+
|
57
|
+
if (token = payment_attributes[:braintree_token]).present?
|
58
|
+
payment_attributes[:source] = Spree::BraintreeCheckout.create_from_token(token, payment_attributes[:payment_method_id])
|
59
|
+
elsif payment_attributes[:braintree_nonce].present?
|
60
|
+
payment_attributes[:source] = Spree::BraintreeCheckout.create_from_params(params)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
success = update(attributes)
|
65
|
+
set_shipments_cost if shipments.any?
|
66
|
+
end
|
67
|
+
|
68
|
+
@updating_params = nil
|
69
|
+
success
|
70
|
+
end
|
71
|
+
|
72
|
+
def payment_required?
|
73
|
+
# default payment processing requires order to have state == payment
|
74
|
+
# so there is no need to divide this method for checkout steps and actual payment processing
|
75
|
+
return false if paid_with_paypal_express?
|
76
|
+
total.to_f > 0.0
|
77
|
+
end
|
78
|
+
|
79
|
+
def confirmation_required?
|
80
|
+
Spree::Config[:always_include_confirm_step] ||
|
81
|
+
payments.valid.map(&:payment_method).compact.any?(&:payment_profiles_supported?) ||
|
82
|
+
# setting payment_profiles_supported? for braintree gateways would require few additional changes in payments profiles system
|
83
|
+
braintree_confirmation_required? || state == 'confirm'
|
84
|
+
end
|
85
|
+
|
86
|
+
def paid_with_braintree?
|
87
|
+
payments.valid.map(&:payment_method).compact.any? { |p| p.is_a?(Spree::Gateway::BraintreeVzeroBase) }
|
88
|
+
end
|
89
|
+
|
90
|
+
def paid_with_paypal_express?
|
91
|
+
payments.valid.map(&:payment_method).compact.any? { |p| p.is_a?(Spree::Gateway::BraintreeVzeroPaypalExpress) }
|
92
|
+
end
|
93
|
+
|
94
|
+
def invalidate_paypal_express_payments
|
95
|
+
return unless paid_with_paypal_express?
|
96
|
+
|
97
|
+
payments.valid.each do |payment|
|
98
|
+
payment.invalidate! if payment.payment_method.is_a?(Spree::Gateway::BraintreeVzeroPaypalExpress)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def no_phone_number?
|
103
|
+
[ship_address, bill_address].each do |address|
|
104
|
+
return true if address.try(:phone).eql?(I18n.t('braintree.phone_number_placeholder'))
|
105
|
+
end
|
106
|
+
false
|
107
|
+
end
|
108
|
+
|
109
|
+
def remove_phone_number_placeholder
|
110
|
+
[ship_address, bill_address].each do |address|
|
111
|
+
address.update_column(:phone, nil) if address.try(:phone).eql?(I18n.t('braintree.phone_number_placeholder'))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def braintree_confirmation_required?
|
118
|
+
paid_with_braintree? && state.eql?('payment')
|
119
|
+
end
|
120
|
+
|
121
|
+
def prepare_address_hash(hash)
|
122
|
+
hash.delete_if { |e| hash[e].eql?('undefined') }
|
123
|
+
country_id = Spree::Country.find_by(iso: hash.delete(:country)).try(:id)
|
124
|
+
|
125
|
+
hash[:country_id] = country_id
|
126
|
+
state_param = hash.delete(:state)
|
127
|
+
state = Spree::State.where('spree_states.abbr = :abbr OR upper(spree_states.name) = :name',
|
128
|
+
abbr: state_param, name: state_param.upcase).find_by(country_id: country_id)
|
129
|
+
hash[:state_id] = state.try(:id)
|
130
|
+
hash[:phone] ||= I18n.t('braintree.phone_number_placeholder')
|
131
|
+
|
132
|
+
return hash if hash[:full_name].blank?
|
133
|
+
|
134
|
+
full_name = hash.delete(:full_name).split(' ')
|
135
|
+
hash[:lastname] = full_name.slice!(-1)
|
136
|
+
hash[:firstname] = full_name.join(' ')
|
137
|
+
hash
|
138
|
+
end
|
139
|
+
|
140
|
+
def process_paypal_express_payments
|
141
|
+
return unless paid_with_paypal_express?
|
142
|
+
|
143
|
+
if payments.valid.empty?
|
144
|
+
order.errors.add(:base, Spree.t(:no_payment_found))
|
145
|
+
false
|
146
|
+
else
|
147
|
+
payments.valid.last.update(amount: total)
|
148
|
+
process_payments!
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
::Spree::Order.prepend(Spree::BraintreeVzero::OrderDecorator)
|
@@ -39,7 +39,9 @@ module Spree
|
|
39
39
|
def order_data(identifier, amount)
|
40
40
|
identifier.merge(
|
41
41
|
amount: amount,
|
42
|
-
order_id: order.number
|
42
|
+
order_id: order.number,
|
43
|
+
line_items: collect_line_items,
|
44
|
+
shipping_amount: order_shipping
|
43
45
|
)
|
44
46
|
end
|
45
47
|
|
@@ -81,9 +83,11 @@ module Spree
|
|
81
83
|
|
82
84
|
def payment_in_vault(data = {})
|
83
85
|
store_ship_address = data['shipping_address_id'].blank?
|
84
|
-
|
86
|
+
|
87
|
+
case gateway.preferred_store_payments_in_vault.to_s
|
88
|
+
when 'store_only_on_success'
|
85
89
|
{ store_in_vault_on_success: true, store_shipping_address_in_vault: store_ship_address }
|
86
|
-
|
90
|
+
when 'store_all'
|
87
91
|
{ store_in_vault: true, store_shipping_address_in_vault: store_ship_address }
|
88
92
|
else
|
89
93
|
{ store_in_vault: false }
|
@@ -102,6 +106,49 @@ module Spree
|
|
102
106
|
'failed'
|
103
107
|
end
|
104
108
|
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
PAYPAL_MAX_LINEITEMS = 249
|
113
|
+
|
114
|
+
# Because of strange PayPal behaviour with accepting discounts
|
115
|
+
# the only solution to add needed discount (if it exist) to
|
116
|
+
# create a virtual Line Item with discount amount and with 'credit'
|
117
|
+
# and name it as 'discount' to be reflected in PayPal email to customer
|
118
|
+
#
|
119
|
+
def collect_line_items # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
120
|
+
items =
|
121
|
+
@order
|
122
|
+
.line_items
|
123
|
+
.reject { |li| li.price.zero? || li.quantity.zero? }
|
124
|
+
.map do |li|
|
125
|
+
{
|
126
|
+
name: li.name.truncate(127, omission: ''),
|
127
|
+
kind: 'debit',
|
128
|
+
quantity: li.quantity.to_s,
|
129
|
+
unit_amount: li.price.to_s,
|
130
|
+
unit_of_measure: 'unit',
|
131
|
+
product_code: li.sku,
|
132
|
+
total_amount: (li.price * li.quantity).to_s,
|
133
|
+
tax_amount: li.additional_tax_total.to_s
|
134
|
+
}
|
135
|
+
end.
|
136
|
+
take(PAYPAL_MAX_LINEITEMS - 1)
|
137
|
+
total = @order.adjustment_total.abs
|
138
|
+
return items if total.zero?
|
139
|
+
|
140
|
+
items.append({
|
141
|
+
name: 'discount',
|
142
|
+
kind: 'credit',
|
143
|
+
quantity: '1',
|
144
|
+
unit_amount: total.to_s,
|
145
|
+
total_amount: total.to_s
|
146
|
+
})
|
147
|
+
end
|
148
|
+
|
149
|
+
def order_shipping
|
150
|
+
@order.shipment_total.to_s
|
151
|
+
end
|
105
152
|
end
|
106
153
|
end
|
107
154
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Spree
|
2
2
|
class Gateway::BraintreeVzeroDropInUi < Spree::Gateway::BraintreeVzeroBase
|
3
|
+
include ::Spree::Gateway::BraintreeVzero::LegacyRailsPatch
|
4
|
+
|
3
5
|
preference :dropin_container, :string, default: 'payment-form'
|
4
6
|
preference :checkout_form_id, :string, default: 'checkout_form_payment'
|
5
7
|
preference :error_messages_container_id, :string, default: 'content'
|
@@ -7,7 +9,7 @@ module Spree
|
|
7
9
|
preference :'3dsecure', :boolean_select, default: false
|
8
10
|
|
9
11
|
after_save :disable_hosted_gateways, if: proc {
|
10
|
-
active? && (
|
12
|
+
active? && (attributes_after_save.keys & %w[active id]).any?
|
11
13
|
}
|
12
14
|
|
13
15
|
def method_type
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Spree
|
2
2
|
class Gateway::BraintreeVzeroHostedFields < Spree::Gateway::BraintreeVzeroBase
|
3
|
+
include ::Spree::Gateway::BraintreeVzero::LegacyRailsPatch
|
4
|
+
|
3
5
|
preference :checkout_form_id, :string, default: 'checkout_form_payment'
|
4
6
|
preference :error_messages_container_id, :string, default: 'content'
|
5
7
|
preference :number_selector, :string, default: '#hosted-fields-number'
|
@@ -12,7 +14,7 @@ module Spree
|
|
12
14
|
preference :'3dsecure', :boolean_select, default: false
|
13
15
|
|
14
16
|
after_save :disable_dropin_gateways, if: proc {
|
15
|
-
active? && (
|
17
|
+
active? && (attributes_after_save.keys & %w[active id]).any?
|
16
18
|
}
|
17
19
|
|
18
20
|
def method_type
|