solidus_stripe 3.1.0 → 4.2.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/.gitignore +1 -0
- data/.rubocop.yml +5 -0
- data/CHANGELOG.md +58 -2
- data/Gemfile +7 -0
- data/LICENSE +2 -2
- data/README.md +26 -8
- data/Rakefile +1 -1
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-cart-page-checkout.js +42 -9
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-intents.js +3 -2
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-request-button-shared.js +56 -20
- data/app/controllers/solidus_stripe/intents_controller.rb +23 -18
- data/app/decorators/models/spree/refund_decorator.rb +9 -0
- data/app/models/solidus_stripe/address_from_params_service.rb +5 -2
- data/app/models/solidus_stripe/create_intents_payment_service.rb +113 -0
- data/app/models/spree/payment_method/stripe_credit_card.rb +16 -1
- data/bin/r +13 -0
- data/bin/rake +7 -0
- data/bin/sandbox +84 -0
- data/bin/sandbox_rails +18 -0
- data/bin/setup +1 -1
- data/config/routes.rb +4 -1
- data/lib/generators/solidus_stripe/install/install_generator.rb +7 -3
- data/lib/solidus_stripe/engine.rb +2 -2
- data/lib/solidus_stripe/factories.rb +4 -0
- data/lib/solidus_stripe/version.rb +1 -1
- data/lib/views/frontend/spree/checkout/payment/v3/_form_elements.html.erb +0 -1
- data/solidus_stripe.gemspec +34 -37
- data/spec/features/stripe_checkout_spec.rb +101 -48
- data/spec/models/solidus_stripe/address_from_params_service_spec.rb +19 -5
- data/spec/models/solidus_stripe/create_intents_payment_service_spec.rb +127 -0
- data/spec/models/spree/payment_method/stripe_credit_card_spec.rb +44 -1
- data/spec/spec_helper.rb +4 -1
- metadata +23 -16
- data/LICENSE.md +0 -26
- data/app/models/solidus_stripe/create_intents_order_service.rb +0 -70
@@ -4,7 +4,7 @@ module SolidusStripe
|
|
4
4
|
class AddressFromParamsService
|
5
5
|
attr_reader :address_params, :user
|
6
6
|
|
7
|
-
def initialize(address_params, user)
|
7
|
+
def initialize(address_params, user = nil)
|
8
8
|
@address_params, @user = address_params, user
|
9
9
|
end
|
10
10
|
|
@@ -43,7 +43,10 @@ module SolidusStripe
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def state
|
46
|
-
@state ||=
|
46
|
+
@state ||= begin
|
47
|
+
region = address_params[:region]
|
48
|
+
country.states.find_by(abbr: region) || country.states.find_by(name: region)
|
49
|
+
end
|
47
50
|
end
|
48
51
|
|
49
52
|
def default_attributes
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusStripe
|
4
|
+
class CreateIntentsPaymentService
|
5
|
+
attr_reader :intent_id, :stripe, :controller
|
6
|
+
|
7
|
+
delegate :request, :current_order, :params, to: :controller
|
8
|
+
|
9
|
+
def initialize(intent_id, stripe, controller)
|
10
|
+
@intent_id, @stripe, @controller = intent_id, stripe, controller
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
invalidate_previous_payment_intents_payments
|
15
|
+
if (payment = create_payment)
|
16
|
+
description = "Solidus Order ID: #{payment.gateway_order_identifier}"
|
17
|
+
stripe.update_intent(nil, intent_id, nil, description: description)
|
18
|
+
true
|
19
|
+
else
|
20
|
+
invalidate_current_payment_intent
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def intent
|
28
|
+
@intent ||= stripe.show_intent(intent_id, {})
|
29
|
+
end
|
30
|
+
|
31
|
+
def invalidate_current_payment_intent
|
32
|
+
stripe.cancel(intent_id)
|
33
|
+
end
|
34
|
+
|
35
|
+
def invalidate_previous_payment_intents_payments
|
36
|
+
if stripe.v3_intents?
|
37
|
+
current_order.payments.pending.where(payment_method: stripe).each(&:void_transaction!)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_payment
|
42
|
+
Spree::OrderUpdateAttributes.new(
|
43
|
+
current_order,
|
44
|
+
payment_params,
|
45
|
+
request_env: request.headers.env
|
46
|
+
).apply
|
47
|
+
|
48
|
+
created_payment = Spree::Payment.find_by(response_code: intent_id)
|
49
|
+
created_payment&.tap { |payment| payment.update!(state: :pending) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def payment_params
|
53
|
+
{
|
54
|
+
payments_attributes: [{
|
55
|
+
payment_method_id: stripe.id,
|
56
|
+
amount: current_order.total,
|
57
|
+
response_code: intent_id,
|
58
|
+
source_attributes: {
|
59
|
+
month: intent_card['exp_month'],
|
60
|
+
year: intent_card['exp_year'],
|
61
|
+
cc_type: intent_card['brand'],
|
62
|
+
last_digits: intent_card['last4'],
|
63
|
+
gateway_payment_profile_id: intent_customer_profile,
|
64
|
+
name: card_holder_name || address_full_name,
|
65
|
+
address_attributes: address_attributes
|
66
|
+
}
|
67
|
+
}]
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def intent_card
|
72
|
+
intent_data['payment_method_details']['card']
|
73
|
+
end
|
74
|
+
|
75
|
+
def intent_customer_profile
|
76
|
+
intent.params['payment_method']
|
77
|
+
end
|
78
|
+
|
79
|
+
def card_holder_name
|
80
|
+
(html_payment_source_data['name'] || intent_data['billing_details']['name']).presence
|
81
|
+
end
|
82
|
+
|
83
|
+
def intent_data
|
84
|
+
intent.params['charges']['data'][0]
|
85
|
+
end
|
86
|
+
|
87
|
+
def form_data
|
88
|
+
params[:form_data]
|
89
|
+
end
|
90
|
+
|
91
|
+
def html_payment_source_data
|
92
|
+
if form_data.is_a?(String)
|
93
|
+
data = Rack::Utils.parse_nested_query(form_data)
|
94
|
+
data['payment_source'][stripe.id.to_s]
|
95
|
+
else
|
96
|
+
{}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def address_attributes
|
101
|
+
html_payment_source_data['address_attributes'] || SolidusStripe::AddressFromParamsService.new(form_data).call.attributes
|
102
|
+
end
|
103
|
+
|
104
|
+
def address_full_name
|
105
|
+
current_order.bill_address&.full_name || form_data[:recipient]
|
106
|
+
end
|
107
|
+
|
108
|
+
def update_stripe_payment_description
|
109
|
+
description = "Solidus Order ID: #{payment.gateway_order_identifier}"
|
110
|
+
stripe.update_intent(nil, intent_id, nil, description: description)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -15,7 +15,7 @@ module Spree
|
|
15
15
|
'Visa' => 'visa'
|
16
16
|
}
|
17
17
|
|
18
|
-
delegate :create_intent, :update_intent, :confirm_intent, to: :gateway
|
18
|
+
delegate :create_intent, :update_intent, :confirm_intent, :show_intent, to: :gateway
|
19
19
|
|
20
20
|
def stripe_config(order)
|
21
21
|
{
|
@@ -81,6 +81,21 @@ module Spree
|
|
81
81
|
gateway.void(response_code, {})
|
82
82
|
end
|
83
83
|
|
84
|
+
def payment_intents_refund_reason
|
85
|
+
Spree::RefundReason.where(name: Spree::Payment::Cancellation::DEFAULT_REASON).first_or_create
|
86
|
+
end
|
87
|
+
|
88
|
+
def try_void(payment)
|
89
|
+
if v3_intents? && payment.completed?
|
90
|
+
payment.refunds.create!(
|
91
|
+
amount: payment.credit_allowed,
|
92
|
+
reason: payment_intents_refund_reason
|
93
|
+
).response
|
94
|
+
else
|
95
|
+
void(payment.response_code, nil, nil)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
84
99
|
def cancel(response_code)
|
85
100
|
gateway.void(response_code, {})
|
86
101
|
end
|
data/bin/r
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_stripe/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/rake
ADDED
data/bin/sandbox
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
case "$DB" in
|
6
|
+
postgres|postgresql)
|
7
|
+
RAILSDB="postgresql"
|
8
|
+
;;
|
9
|
+
mysql)
|
10
|
+
RAILSDB="mysql"
|
11
|
+
;;
|
12
|
+
sqlite|'')
|
13
|
+
RAILSDB="sqlite3"
|
14
|
+
;;
|
15
|
+
*)
|
16
|
+
echo "Invalid DB specified: $DB"
|
17
|
+
exit 1
|
18
|
+
;;
|
19
|
+
esac
|
20
|
+
|
21
|
+
if [ ! -z $SOLIDUS_BRANCH ]
|
22
|
+
then
|
23
|
+
BRANCH=$SOLIDUS_BRANCH
|
24
|
+
else
|
25
|
+
BRANCH="master"
|
26
|
+
fi
|
27
|
+
|
28
|
+
extension_name="solidus_stripe"
|
29
|
+
|
30
|
+
# Stay away from the bundler env of the containing extension.
|
31
|
+
function unbundled {
|
32
|
+
ruby -rbundler -e'b = proc {system *ARGV}; Bundler.respond_to?(:with_unbundled_env) ? Bundler.with_unbundled_env(&b) : Bundler.with_clean_env(&b)' -- $@
|
33
|
+
}
|
34
|
+
|
35
|
+
rm -rf ./sandbox
|
36
|
+
unbundled bundle exec rails new sandbox --database="$RAILSDB" \
|
37
|
+
--skip-bundle \
|
38
|
+
--skip-git \
|
39
|
+
--skip-keeps \
|
40
|
+
--skip-rc \
|
41
|
+
--skip-spring \
|
42
|
+
--skip-test \
|
43
|
+
--skip-javascript
|
44
|
+
|
45
|
+
if [ ! -d "sandbox" ]; then
|
46
|
+
echo 'sandbox rails application failed'
|
47
|
+
exit 1
|
48
|
+
fi
|
49
|
+
|
50
|
+
cd ./sandbox
|
51
|
+
cat <<RUBY >> Gemfile
|
52
|
+
gem 'solidus', github: 'solidusio/solidus', branch: '$BRANCH'
|
53
|
+
gem 'solidus_auth_devise', '>= 2.1.0'
|
54
|
+
gem 'rails-i18n'
|
55
|
+
gem 'solidus_i18n'
|
56
|
+
|
57
|
+
gem '$extension_name', path: '..'
|
58
|
+
|
59
|
+
group :test, :development do
|
60
|
+
platforms :mri do
|
61
|
+
gem 'pry-byebug'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
RUBY
|
65
|
+
|
66
|
+
unbundled bundle install --gemfile Gemfile
|
67
|
+
|
68
|
+
unbundled bundle exec rake db:drop db:create
|
69
|
+
|
70
|
+
unbundled bundle exec rails generate spree:install \
|
71
|
+
--auto-accept \
|
72
|
+
--user_class=Spree::User \
|
73
|
+
--enforce_available_locales=true \
|
74
|
+
--with-authentication=false \
|
75
|
+
$@
|
76
|
+
|
77
|
+
unbundled bundle exec rails generate solidus:auth:install
|
78
|
+
|
79
|
+
echo
|
80
|
+
echo "🚀 Sandbox app successfully created for $extension_name!"
|
81
|
+
echo "🚀 Using $RAILSDB and Solidus $BRANCH"
|
82
|
+
echo "🚀 Use 'export DB=[postgres|mysql|sqlite]' to control the DB adapter"
|
83
|
+
echo "🚀 Use 'export SOLIDUS_BRANCH=<BRANCH-NAME>' to control the Solidus version"
|
84
|
+
echo "🚀 This app is intended for test purposes."
|
data/bin/sandbox_rails
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
app_root = 'sandbox'
|
6
|
+
|
7
|
+
unless File.exist? "#{app_root}/bin/rails"
|
8
|
+
warn 'Creating the sandbox app...'
|
9
|
+
Dir.chdir "#{__dir__}/.." do
|
10
|
+
system "#{__dir__}/sandbox" or begin # rubocop:disable Style/AndOr
|
11
|
+
warn 'Automatic creation of the sandbox app failed'
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Dir.chdir app_root
|
18
|
+
exec 'bin/rails', *ARGV
|
data/bin/setup
CHANGED
data/config/routes.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
Spree::Core::Engine.routes.draw do
|
2
4
|
# route to a deprecated controller, will be removed in the future:
|
3
5
|
post '/stripe/confirm_payment', to: 'stripe#confirm_payment'
|
4
6
|
|
5
7
|
# payment intents routes:
|
6
|
-
post '/stripe/
|
8
|
+
post '/stripe/create_intent', to: '/solidus_stripe/intents#create_intent'
|
9
|
+
post '/stripe/create_payment', to: '/solidus_stripe/intents#create_payment'
|
7
10
|
|
8
11
|
# payment request routes:
|
9
12
|
post '/stripe/shipping_rates', to: '/solidus_stripe/payment_request#shipping_rates'
|
@@ -13,12 +13,16 @@ module SolidusStripe
|
|
13
13
|
run 'bundle exec rake railties:install:migrations FROM=solidus_stripe'
|
14
14
|
end
|
15
15
|
|
16
|
+
def add_migrations
|
17
|
+
run 'bin/rails railties:install:migrations FROM=solidus_stripe'
|
18
|
+
end
|
19
|
+
|
16
20
|
def run_migrations
|
17
|
-
run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
|
21
|
+
run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]')) # rubocop:disable Metrics/LineLength
|
18
22
|
if run_migrations
|
19
|
-
run '
|
23
|
+
run 'bin/rails db:migrate'
|
20
24
|
else
|
21
|
-
puts 'Skipping
|
25
|
+
puts 'Skipping bin/rails db:migrate, don\'t forget to run it!' # rubocop:disable Rails/Output
|
22
26
|
end
|
23
27
|
end
|
24
28
|
|
@@ -4,9 +4,9 @@ require 'spree/core'
|
|
4
4
|
|
5
5
|
module SolidusStripe
|
6
6
|
class Engine < Rails::Engine
|
7
|
-
include SolidusSupport::EngineExtensions
|
7
|
+
include SolidusSupport::EngineExtensions
|
8
8
|
|
9
|
-
isolate_namespace Spree
|
9
|
+
isolate_namespace ::Spree
|
10
10
|
|
11
11
|
engine_name 'solidus_stripe'
|
12
12
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
<div id="payment-request-button" data-stripe-config="<%= payment_method.stripe_config(current_order).to_json %>" data-v3-api="<%= stripe_v3_api %>"></div>
|
2
2
|
|
3
|
-
<%= image_tag 'credit_cards/credit_card.gif', id: 'credit-card-image' %>
|
4
3
|
<% param_prefix = "payment_source[#{payment_method.id}]" %>
|
5
4
|
|
6
5
|
<div class="field field-required">
|
data/solidus_stripe.gemspec
CHANGED
@@ -1,40 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
s.add_dependency "activemerchant", ">= 1.100" # includes "Stripe Payment Intents: Fix fallback for Store"
|
38
|
-
|
39
|
-
s.add_development_dependency 'solidus_dev_support'
|
3
|
+
require_relative 'lib/solidus_stripe/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'solidus_stripe'
|
7
|
+
spec.version = SolidusStripe::VERSION
|
8
|
+
spec.authors = ['Solidus Team']
|
9
|
+
spec.email = 'contact@solidus.io'
|
10
|
+
|
11
|
+
spec.summary = 'Stripe Payment Method for Solidus'
|
12
|
+
spec.description = 'Stripe Payment Method for Solidus'
|
13
|
+
spec.homepage = 'https://github.com/solidusio/solidus_stripe#readme'
|
14
|
+
spec.license = 'BSD-3'
|
15
|
+
|
16
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
17
|
+
spec.metadata['source_code_uri'] = 'https://github.com/solidusio/solidus_stripe'
|
18
|
+
spec.metadata['changelog_uri'] = 'https://github.com/solidusio/solidus_stripe/blob/master/CHANGELOG.md'
|
19
|
+
|
20
|
+
spec.required_ruby_version = Gem::Requirement.new('~> 2.4')
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
|
25
|
+
|
26
|
+
spec.files = files.grep_v(%r{^(test|spec|features)/})
|
27
|
+
spec.test_files = files.grep(%r{^(test|spec|features)/})
|
28
|
+
spec.bindir = "exe"
|
29
|
+
spec.executables = files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ["lib"]
|
31
|
+
|
32
|
+
spec.add_dependency 'solidus_core', ['>= 2.3', '< 3']
|
33
|
+
spec.add_dependency 'solidus_support', '~> 0.5'
|
34
|
+
spec.add_dependency 'activemerchant', '>= 1.100'
|
35
|
+
|
36
|
+
spec.add_development_dependency 'solidus_dev_support'
|
40
37
|
end
|