spree_stripe 1.7.0 → 1.8.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/app/controllers/spree_stripe/confirm_payments_controller.rb +52 -0
- data/app/helpers/spree_stripe/base_helper.rb +24 -2
- data/app/javascript/spree_stripe/controllers/stripe_button_controller.js +256 -338
- data/app/javascript/spree_stripe/controllers/stripe_controller.js +129 -206
- data/app/models/spree/payment_sessions/stripe.rb +1 -2
- data/app/models/spree_stripe/gateway/payment_intents.rb +0 -4
- data/app/models/spree_stripe/gateway/payment_sessions.rb +2 -2
- data/app/models/spree_stripe/order_decorator.rb +0 -27
- data/app/models/spree_stripe/shipment_decorator.rb +3 -3
- data/app/services/spree_stripe/create_payment_session.rb +18 -0
- data/app/services/spree_stripe/webhook_handlers/payment_intent_payment_failed.rb +4 -15
- data/app/services/spree_stripe/webhook_handlers/payment_intent_succeeded.rb +1 -7
- data/app/views/spree/checkout/payment/_spree_stripe.html.erb +58 -58
- data/app/views/spree_stripe/_quick_checkout.html.erb +9 -15
- data/config/locales/en.yml +3 -8
- data/config/routes.rb +3 -22
- data/db/migrate/20250310152812_setup_spree_stripe_models.rb +0 -17
- data/lib/spree_stripe/configuration.rb +0 -1
- data/lib/spree_stripe/engine.rb +0 -7
- data/lib/spree_stripe/version.rb +1 -1
- metadata +5 -44
- data/app/controllers/spree_stripe/payment_intents_controller.rb +0 -61
- data/app/jobs/spree_stripe/complete_order_job.rb +0 -8
- data/app/models/spree_stripe/payment_intent.rb +0 -81
- data/app/services/spree_stripe/create_payment_intent.rb +0 -40
- data/app/services/spree_stripe/create_setup_intent.rb +0 -20
- data/lib/spree_api_v2/spree/api/v2/platform/affirm_serializer.rb +0 -9
- data/lib/spree_api_v2/spree/api/v2/platform/after_pay_serializer.rb +0 -9
- data/lib/spree_api_v2/spree/api/v2/platform/alipay_serializer.rb +0 -9
- data/lib/spree_api_v2/spree/api/v2/platform/ideal_serializer.rb +0 -9
- data/lib/spree_api_v2/spree/api/v2/platform/klarna_serializer.rb +0 -9
- data/lib/spree_api_v2/spree/api/v2/platform/link_serializer.rb +0 -9
- data/lib/spree_api_v2/spree/api/v2/platform/przelewy24_serializer.rb +0 -9
- data/lib/spree_api_v2/spree/api/v2/platform/sepa_debit_serializer.rb +0 -9
- data/lib/spree_api_v2/spree/api/v2/storefront/stripe/base_controller.rb +0 -21
- data/lib/spree_api_v2/spree/api/v2/storefront/stripe/payment_intents_controller.rb +0 -86
- data/lib/spree_api_v2/spree/api/v2/storefront/stripe/setup_intents_controller.rb +0 -19
- data/lib/spree_api_v2/spree/v2/storefront/affirm_serializer.rb +0 -7
- data/lib/spree_api_v2/spree/v2/storefront/after_pay_serializer.rb +0 -7
- data/lib/spree_api_v2/spree/v2/storefront/alipay_serializer.rb +0 -7
- data/lib/spree_api_v2/spree/v2/storefront/ideal_serializer.rb +0 -7
- data/lib/spree_api_v2/spree/v2/storefront/klarna_serializer.rb +0 -7
- data/lib/spree_api_v2/spree/v2/storefront/link_serializer.rb +0 -7
- data/lib/spree_api_v2/spree/v2/storefront/payment_intent_serializer.rb +0 -15
- data/lib/spree_api_v2/spree/v2/storefront/przelewy24_serializer.rb +0 -7
- data/lib/spree_api_v2/spree/v2/storefront/sepa_debit_serializer.rb +0 -7
- data/lib/spree_api_v2/spree_stripe/v2/storefront/payment_method_serializer_decorator.rb +0 -17
- data/lib/spree_stripe/testing_support/factories/payment_intent_factory.rb +0 -24
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
>
|
|
14
|
-
|
|
1
|
+
<% if current_stripe_gateway.present? && current_stripe_payment_session.present? %>
|
|
2
|
+
<div
|
|
3
|
+
data-controller="checkout-stripe"
|
|
4
|
+
data-checkout-stripe-api-key-value="<%= current_stripe_gateway.try(:preferred_publishable_key) %>"
|
|
5
|
+
data-checkout-stripe-client-secret-value="<%= current_stripe_payment_session.client_secret %>"
|
|
6
|
+
data-checkout-stripe-cart-id-value="<%= stripe_cart_prefixed_id(@order) %>"
|
|
7
|
+
data-checkout-stripe-cart-token-value="<%= @order.token %>"
|
|
8
|
+
data-checkout-stripe-spree-api-key-value="<%= current_store_publishable_api_key %>"
|
|
9
|
+
data-checkout-stripe-order-email-value="<%= @order.email %>"
|
|
10
|
+
data-checkout-stripe-return-url-value="<%= spree.stripe_confirm_payment_url(@order.prefixed_id, session: current_stripe_payment_session.prefixed_id) %>"
|
|
11
|
+
data-checkout-stripe-color-primary-value="<%= hex_color_to_rgb(theme_setting(:primary_color)) %>"
|
|
12
|
+
data-checkout-stripe-color-text-value="<%= hex_color_to_rgb(theme_setting(:text_color)) %>"
|
|
13
|
+
>
|
|
14
|
+
<% payment_sources = checkout_payment_sources(payment_method) %>
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
<% if payment_sources.any? %>
|
|
17
|
+
<div id="existing_cards">
|
|
18
|
+
<div class="form-group">
|
|
19
|
+
<ul class="list-group mb-5 border rounded-md" data-controller="reveal">
|
|
20
|
+
<% payment_sources.each_with_index do |card, index| %>
|
|
21
|
+
<li class="p-0 m-0 border-b" id="<%= spree_dom_id(card) %>">
|
|
22
|
+
<div class="custom-control custom-radio px-5 py-4 flex items-center">
|
|
23
|
+
<label class="flex flex-row items-center cursor-pointer">
|
|
24
|
+
<%= radio_button_tag "order[existing_card]", card.gateway_payment_profile_id, index == 0, { data: { action: "checkout-stripe#initializeStripe reveal#hide", checkout_stripe_target: index == 0 ? "defaultCard" : nil }, class: "mr-5" } %>
|
|
25
|
+
<div class="flex space-x-4 items-center">
|
|
26
|
+
<%= payment_method_icon_tag(card.cc_type) %>
|
|
27
|
+
<span>****<%= card.last_digits %></span>
|
|
28
|
+
<span><%= card.month.to_s.rjust(2, '0') %>/<%= card.year %></span>
|
|
29
|
+
</div>
|
|
30
|
+
</label>
|
|
31
|
+
</div>
|
|
32
|
+
</li>
|
|
33
|
+
<% end %>
|
|
34
|
+
<li>
|
|
35
|
+
<div class="custom-control custom-radio px-5 py-4 flex items-center w-full">
|
|
36
|
+
<label class="flex flex-row items-center w-full pr-8">
|
|
37
|
+
<%= radio_button_tag "order[existing_card]", nil, false, { data: { action: "checkout-stripe#initializeStripe reveal#show" }, class: "mr-5" } %>
|
|
38
|
+
<div class="w-full flex flex-col items-start space-y-4 justify-center">
|
|
39
|
+
<span class="cursor-pointer">
|
|
40
|
+
<%= Spree.t(:add_new_credit_card) %>
|
|
41
|
+
</span>
|
|
42
|
+
<!-- Display a payment form -->
|
|
43
|
+
<div data-checkout-stripe-target="paymentElement" data-reveal-target="item" class="w-full hidden">
|
|
44
|
+
<!--Stripe.js injects the Payment Element-->
|
|
45
|
+
</div>
|
|
29
46
|
</div>
|
|
30
47
|
</label>
|
|
31
48
|
</div>
|
|
32
49
|
</li>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
</div>
|
|
47
|
-
</label>
|
|
48
|
-
</div>
|
|
49
|
-
</li>
|
|
50
|
-
</ul>
|
|
50
|
+
</ul>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
<% else %>
|
|
54
|
+
<div data-checkout-stripe-target="paymentElement" class="w-full"></div>
|
|
55
|
+
<% end %>
|
|
56
|
+
<div data-checkout-stripe-target="loading" class="p-6">
|
|
57
|
+
<div class="mx-auto flex justify-center lg:w-1/4">
|
|
58
|
+
<svg class="animate-spin h-5 w-5 mr-4 text-primary" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
59
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
60
|
+
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
61
|
+
</svg>
|
|
62
|
+
<%= Spree.t(:loading) %>...
|
|
51
63
|
</div>
|
|
52
|
-
</div>
|
|
53
|
-
<% else %>
|
|
54
|
-
<div data-checkout-stripe-target="paymentElement" class="w-full"></div>
|
|
55
|
-
<% end %>
|
|
56
|
-
<div data-checkout-stripe-target="messageContainer" class="hidden text-danger"></div>
|
|
57
|
-
<div data-checkout-stripe-target="loading" class="p-6">
|
|
58
|
-
<div class="mx-auto flex justify-center lg:w-1/4">
|
|
59
|
-
<svg class="animate-spin h-5 w-5 mr-4 text-primary" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
60
|
-
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
61
|
-
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
62
|
-
</svg>
|
|
63
|
-
<%= Spree.t(:loading) %>...
|
|
64
64
|
</div>
|
|
65
65
|
</div>
|
|
66
|
-
|
|
66
|
+
<% end %>
|
|
@@ -1,29 +1,23 @@
|
|
|
1
|
-
<% if quick_checkout_enabled?(@order) && current_stripe_gateway.present?
|
|
1
|
+
<% if quick_checkout_enabled?(@order) && current_stripe_gateway.present? %>
|
|
2
2
|
<div id="quick-checkout" class="<%= defined?(container_class) ? container_class : nil %>">
|
|
3
3
|
<%= tag.div class: 'w-full', data: {
|
|
4
4
|
controller: 'checkout-stripe-button',
|
|
5
5
|
checkout_stripe_button_target: 'container',
|
|
6
6
|
checkout_stripe_button_api_key_value: current_stripe_gateway.try(:preferred_publishable_key),
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
checkout_stripe_button_spree_api_key_value: current_store_publishable_api_key,
|
|
8
|
+
checkout_stripe_button_payment_method_id_value: current_stripe_gateway.prefixed_id,
|
|
9
|
+
checkout_stripe_button_cart_id_value: stripe_cart_prefixed_id(@order),
|
|
10
|
+
checkout_stripe_button_cart_token_value: @order.token,
|
|
11
|
+
checkout_stripe_button_confirm_payment_url_value: spree.stripe_confirm_payment_url(@order.prefixed_id),
|
|
9
12
|
checkout_stripe_button_currency_value: @order.currency.downcase,
|
|
10
|
-
checkout_stripe_button_amount_value: @order.
|
|
11
|
-
checkout_stripe_button_available_countries_value: available_countries_iso.as_json,
|
|
12
|
-
checkout_stripe_button_gift_card_code_value: @order.respond_to?(:gift_card) ? @order.gift_card&.code : nil,
|
|
13
|
-
checkout_stripe_button_gift_card_amount_value: @order.respond_to?(:gift_card_total) ? @order.gift_card_total : nil,
|
|
13
|
+
checkout_stripe_button_amount_value: Spree::Money.new(@order.total_minus_store_credits, currency: @order.currency).cents,
|
|
14
14
|
checkout_stripe_button_border_radius_value: theme_setting(:button_border_radius),
|
|
15
15
|
checkout_stripe_button_height_value: defined?(height) ? height : nil,
|
|
16
16
|
checkout_stripe_button_theme_value: defined?(theme) ? theme : nil,
|
|
17
17
|
checkout_stripe_button_max_rows_value: defined?(max_rows) ? max_rows : nil,
|
|
18
18
|
checkout_stripe_button_max_columns_value: defined?(max_columns) ? max_columns : nil,
|
|
19
19
|
checkout_stripe_button_button_width_value: defined?(button_width) ? button_width : nil,
|
|
20
|
-
|
|
21
|
-
checkout_stripe_button_checkout_advance_path_value: spree.advance_api_v2_storefront_checkout_path,
|
|
22
|
-
checkout_stripe_button_checkout_select_shipping_method_path_value: spree.select_shipping_method_api_v2_storefront_checkout_path,
|
|
23
|
-
checkout_stripe_button_checkout_validate_gift_card_data_path_value: respond_to?(:validate_gift_card_data_api_v2_storefront_checkout_path) ? spree.validate_gift_card_data_api_v2_storefront_checkout_path : nil,
|
|
24
|
-
checkout_stripe_button_checkout_validate_order_for_payment_path_value: spree.validate_order_for_payment_api_v2_storefront_checkout_path,
|
|
25
|
-
checkout_stripe_button_return_url_value: spree.stripe_payment_intent_url(current_stripe_payment_intent),
|
|
26
|
-
checkout_stripe_button_shipping_required_value: @order.respond_to?(:quick_checkout_require_address?) ? @order.quick_checkout_require_address? : true,
|
|
20
|
+
checkout_stripe_button_shipping_required_value: @order.quick_checkout_require_address?,
|
|
27
21
|
checkout_stripe_button_phone_required_value: Spree::Config[:address_requires_phone]
|
|
28
22
|
} do %>
|
|
29
23
|
<div id="payment-request-button"></div>
|
|
@@ -37,4 +31,4 @@
|
|
|
37
31
|
</div>
|
|
38
32
|
<% end %>
|
|
39
33
|
</div>
|
|
40
|
-
<% end%>
|
|
34
|
+
<% end %>
|
data/config/locales/en.yml
CHANGED
|
@@ -3,11 +3,6 @@ en:
|
|
|
3
3
|
spree:
|
|
4
4
|
bank_transfer: Bank Transfer
|
|
5
5
|
stripe:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
requires_action: Payment intent requires action
|
|
10
|
-
requires_capture: Payment intent requires capture
|
|
11
|
-
requires_confirmation: Payment intent requires confirmation
|
|
12
|
-
requires_payment_method: Payment intent requires payment method
|
|
13
|
-
succeeded: Payment intent succeeded
|
|
6
|
+
payment_could_not_be_processed: Your payment could not be processed. Please try again.
|
|
7
|
+
payment_session_errors:
|
|
8
|
+
zero_amount: Payment session amount must be greater than zero
|
data/config/routes.rb
CHANGED
|
@@ -1,30 +1,11 @@
|
|
|
1
1
|
Spree::Core::Engine.add_routes do
|
|
2
|
-
# Stripe payment
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
controller: '/spree_stripe/payment_intents'
|
|
2
|
+
# Stripe redirects here after payment confirmation. It completes the session + order server-side.
|
|
3
|
+
# Used by Rails storefront
|
|
4
|
+
get '/stripe/confirm_payment/:id', to: '/spree_stripe/confirm_payments#show', as: :stripe_confirm_payment
|
|
6
5
|
|
|
7
6
|
# Apple Pay domain verification certificate for Apple Pay
|
|
8
7
|
get '/.well-known/apple-developer-merchantid-domain-association' => '/spree_stripe/apple_pay_domain_verification#show'
|
|
9
8
|
|
|
10
9
|
# Stripe webhooks
|
|
11
10
|
mount StripeEvent::Engine, at: '/stripe'
|
|
12
|
-
|
|
13
|
-
# Storefront API (only when spree_legacy_api_v2 gem is available)
|
|
14
|
-
if defined?(SpreeLegacyApiV2::Engine)
|
|
15
|
-
namespace :api, defaults: { format: 'json' } do
|
|
16
|
-
namespace :v2 do
|
|
17
|
-
namespace :storefront do
|
|
18
|
-
namespace :stripe do
|
|
19
|
-
resources :setup_intents, only: %i[create]
|
|
20
|
-
resources :payment_intents, only: %i[show create update] do
|
|
21
|
-
member do
|
|
22
|
-
patch :confirm
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
11
|
end
|
|
@@ -1,22 +1,5 @@
|
|
|
1
1
|
class SetupSpreeStripeModels < ActiveRecord::Migration[7.2]
|
|
2
2
|
def change
|
|
3
|
-
create_table :spree_stripe_payment_intents do |t|
|
|
4
|
-
t.decimal :amount, precision: 10, scale: 2, default: '0.0', null: false
|
|
5
|
-
t.bigint :order_id, null: false
|
|
6
|
-
t.bigint :payment_method_id, null: false
|
|
7
|
-
t.string :stripe_id, null: false
|
|
8
|
-
t.string :client_secret, null: false
|
|
9
|
-
t.string :customer_id
|
|
10
|
-
t.string :ephemeral_key_secret
|
|
11
|
-
t.string :stripe_payment_method_id
|
|
12
|
-
|
|
13
|
-
t.timestamps
|
|
14
|
-
|
|
15
|
-
t.index ['order_id', 'stripe_id'], name: 'index_spree_stripe_payment_intents_on_order_id_and_stripe_id', unique: true
|
|
16
|
-
t.index ['order_id'], name: 'index_spree_stripe_payment_intents_on_order_id'
|
|
17
|
-
t.index ['payment_method_id'], name: 'index_spree_stripe_payment_intents_on_payment_method_id'
|
|
18
|
-
end
|
|
19
|
-
|
|
20
3
|
create_table :spree_stripe_webhook_keys do |t|
|
|
21
4
|
t.string :stripe_id, null: false
|
|
22
5
|
t.string :signing_secret, null: false
|
data/lib/spree_stripe/engine.rb
CHANGED
|
@@ -7,12 +7,6 @@ module SpreeStripe
|
|
|
7
7
|
# Add app/subscribers to autoload paths
|
|
8
8
|
config.paths.add 'app/subscribers', eager_load: true
|
|
9
9
|
|
|
10
|
-
# Only load API controllers and serializers when spree_legacy_api_v2 gem is available
|
|
11
|
-
if defined?(SpreeLegacyApiV2::Engine)
|
|
12
|
-
config.autoload_paths << root.join('lib', 'spree_api_v2')
|
|
13
|
-
config.eager_load_paths << root.join('lib', 'spree_api_v2')
|
|
14
|
-
end
|
|
15
|
-
|
|
16
10
|
# use rspec for tests
|
|
17
11
|
config.generators do |g|
|
|
18
12
|
g.test_framework :rspec
|
|
@@ -40,7 +34,6 @@ module SpreeStripe
|
|
|
40
34
|
|
|
41
35
|
def self.activate
|
|
42
36
|
glob_paths = [File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')]
|
|
43
|
-
glob_paths << File.join(File.dirname(__FILE__), '../../lib/spree_api_v2/**/*_decorator*.rb') if defined?(SpreeLegacyApiV2::Engine)
|
|
44
37
|
|
|
45
38
|
glob_paths.each do |glob_path|
|
|
46
39
|
Dir.glob(glob_path) do |c|
|
data/lib/spree_stripe/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_stripe
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vendo Connect Inc., Vendo Sp. z o.o.
|
|
@@ -85,20 +85,6 @@ dependencies:
|
|
|
85
85
|
- - ">="
|
|
86
86
|
- !ruby/object:Gem::Version
|
|
87
87
|
version: '0'
|
|
88
|
-
- !ruby/object:Gem::Dependency
|
|
89
|
-
name: jsonapi-rspec
|
|
90
|
-
requirement: !ruby/object:Gem::Requirement
|
|
91
|
-
requirements:
|
|
92
|
-
- - ">="
|
|
93
|
-
- !ruby/object:Gem::Version
|
|
94
|
-
version: '0'
|
|
95
|
-
type: :development
|
|
96
|
-
prerelease: false
|
|
97
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
98
|
-
requirements:
|
|
99
|
-
- - ">="
|
|
100
|
-
- !ruby/object:Gem::Version
|
|
101
|
-
version: '0'
|
|
102
88
|
- !ruby/object:Gem::Dependency
|
|
103
89
|
name: spree_dev_tools
|
|
104
90
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -167,7 +153,7 @@ files:
|
|
|
167
153
|
- app/assets/images/payment_icons/link.svg
|
|
168
154
|
- app/assets/images/payment_icons/sepadebit.svg
|
|
169
155
|
- app/controllers/spree_stripe/apple_pay_domain_verification_controller.rb
|
|
170
|
-
- app/controllers/spree_stripe/
|
|
156
|
+
- app/controllers/spree_stripe/confirm_payments_controller.rb
|
|
171
157
|
- app/controllers/spree_stripe/store_controller_decorator.rb
|
|
172
158
|
- app/controllers/stripe_event/webhook_controller_decorator.rb
|
|
173
159
|
- app/helpers/spree_stripe/base_helper.rb
|
|
@@ -178,7 +164,6 @@ files:
|
|
|
178
164
|
- app/jobs/spree_stripe/attach_customer_to_credit_card_job.rb
|
|
179
165
|
- app/jobs/spree_stripe/base_job.rb
|
|
180
166
|
- app/jobs/spree_stripe/complete_order_from_session_job.rb
|
|
181
|
-
- app/jobs/spree_stripe/complete_order_job.rb
|
|
182
167
|
- app/jobs/spree_stripe/create_tax_transaction_job.rb
|
|
183
168
|
- app/jobs/spree_stripe/create_webhook_endpoint_job.rb
|
|
184
169
|
- app/jobs/spree_stripe/register_domain_job.rb
|
|
@@ -196,7 +181,6 @@ files:
|
|
|
196
181
|
- app/models/spree_stripe/gateway_customer_decorator.rb
|
|
197
182
|
- app/models/spree_stripe/order_decorator.rb
|
|
198
183
|
- app/models/spree_stripe/payment_decorator.rb
|
|
199
|
-
- app/models/spree_stripe/payment_intent.rb
|
|
200
184
|
- app/models/spree_stripe/payment_method_decorator.rb
|
|
201
185
|
- app/models/spree_stripe/payment_methods_webhook_key.rb
|
|
202
186
|
- app/models/spree_stripe/payment_source_decorator.rb
|
|
@@ -220,8 +204,7 @@ files:
|
|
|
220
204
|
- app/services/spree_stripe/complete_order.rb
|
|
221
205
|
- app/services/spree_stripe/create_gateway_webhooks.rb
|
|
222
206
|
- app/services/spree_stripe/create_payment.rb
|
|
223
|
-
- app/services/spree_stripe/
|
|
224
|
-
- app/services/spree_stripe/create_setup_intent.rb
|
|
207
|
+
- app/services/spree_stripe/create_payment_session.rb
|
|
225
208
|
- app/services/spree_stripe/create_source.rb
|
|
226
209
|
- app/services/spree_stripe/register_domain.rb
|
|
227
210
|
- app/services/spree_stripe/update_customer.rb
|
|
@@ -245,27 +228,6 @@ files:
|
|
|
245
228
|
- config/routes.rb
|
|
246
229
|
- db/migrate/20250310152812_setup_spree_stripe_models.rb
|
|
247
230
|
- lib/generators/spree_stripe/install/install_generator.rb
|
|
248
|
-
- lib/spree_api_v2/spree/api/v2/platform/affirm_serializer.rb
|
|
249
|
-
- lib/spree_api_v2/spree/api/v2/platform/after_pay_serializer.rb
|
|
250
|
-
- lib/spree_api_v2/spree/api/v2/platform/alipay_serializer.rb
|
|
251
|
-
- lib/spree_api_v2/spree/api/v2/platform/ideal_serializer.rb
|
|
252
|
-
- lib/spree_api_v2/spree/api/v2/platform/klarna_serializer.rb
|
|
253
|
-
- lib/spree_api_v2/spree/api/v2/platform/link_serializer.rb
|
|
254
|
-
- lib/spree_api_v2/spree/api/v2/platform/przelewy24_serializer.rb
|
|
255
|
-
- lib/spree_api_v2/spree/api/v2/platform/sepa_debit_serializer.rb
|
|
256
|
-
- lib/spree_api_v2/spree/api/v2/storefront/stripe/base_controller.rb
|
|
257
|
-
- lib/spree_api_v2/spree/api/v2/storefront/stripe/payment_intents_controller.rb
|
|
258
|
-
- lib/spree_api_v2/spree/api/v2/storefront/stripe/setup_intents_controller.rb
|
|
259
|
-
- lib/spree_api_v2/spree/v2/storefront/affirm_serializer.rb
|
|
260
|
-
- lib/spree_api_v2/spree/v2/storefront/after_pay_serializer.rb
|
|
261
|
-
- lib/spree_api_v2/spree/v2/storefront/alipay_serializer.rb
|
|
262
|
-
- lib/spree_api_v2/spree/v2/storefront/ideal_serializer.rb
|
|
263
|
-
- lib/spree_api_v2/spree/v2/storefront/klarna_serializer.rb
|
|
264
|
-
- lib/spree_api_v2/spree/v2/storefront/link_serializer.rb
|
|
265
|
-
- lib/spree_api_v2/spree/v2/storefront/payment_intent_serializer.rb
|
|
266
|
-
- lib/spree_api_v2/spree/v2/storefront/przelewy24_serializer.rb
|
|
267
|
-
- lib/spree_api_v2/spree/v2/storefront/sepa_debit_serializer.rb
|
|
268
|
-
- lib/spree_api_v2/spree_stripe/v2/storefront/payment_method_serializer_decorator.rb
|
|
269
231
|
- lib/spree_stripe.rb
|
|
270
232
|
- lib/spree_stripe/configuration.rb
|
|
271
233
|
- lib/spree_stripe/engine.rb
|
|
@@ -276,7 +238,6 @@ files:
|
|
|
276
238
|
- lib/spree_stripe/testing_support/factories/ideal_payment_source_factory.rb
|
|
277
239
|
- lib/spree_stripe/testing_support/factories/klarna_payment_source_factory.rb
|
|
278
240
|
- lib/spree_stripe/testing_support/factories/link_payment_source_factory.rb
|
|
279
|
-
- lib/spree_stripe/testing_support/factories/payment_intent_factory.rb
|
|
280
241
|
- lib/spree_stripe/testing_support/factories/przelewy24_payment_source_factory.rb
|
|
281
242
|
- lib/spree_stripe/testing_support/factories/sepa_debit_payment_source_factory.rb
|
|
282
243
|
- lib/spree_stripe/testing_support/factories/stripe_payment_session_factory.rb
|
|
@@ -288,9 +249,9 @@ licenses:
|
|
|
288
249
|
- MIT
|
|
289
250
|
metadata:
|
|
290
251
|
bug_tracker_uri: https://github.com/spree/spree_stripe/issues
|
|
291
|
-
changelog_uri: https://github.com/spree/spree_stripe/releases/tag/v1.
|
|
252
|
+
changelog_uri: https://github.com/spree/spree_stripe/releases/tag/v1.8.0
|
|
292
253
|
documentation_uri: https://docs.spreecommerce.org/
|
|
293
|
-
source_code_uri: https://github.com/spree/spree_stripe/tree/v1.
|
|
254
|
+
source_code_uri: https://github.com/spree/spree_stripe/tree/v1.8.0
|
|
294
255
|
rdoc_options: []
|
|
295
256
|
require_paths:
|
|
296
257
|
- lib
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
# this is the endpoint that Stripe JS SDK will redirect customer to after payment
|
|
2
|
-
# it will handle the payment intent status and process the payment
|
|
3
|
-
module SpreeStripe
|
|
4
|
-
class PaymentIntentsController < defined?(Spree::StoreController) ? Spree::StoreController : Spree::BaseController
|
|
5
|
-
include Spree::CheckoutAnalyticsHelper if defined?(Spree::CheckoutAnalyticsHelper)
|
|
6
|
-
|
|
7
|
-
# GET /spree/payment_intents/:id
|
|
8
|
-
def show
|
|
9
|
-
# fetch the payment intent active record
|
|
10
|
-
@payment_intent_record = SpreeStripe::PaymentIntent.find(params[:id])
|
|
11
|
-
|
|
12
|
-
# fetch the stripe payment intent
|
|
13
|
-
@stripe_payment_intent = @payment_intent_record.stripe_payment_intent
|
|
14
|
-
|
|
15
|
-
@order = @payment_intent_record.order
|
|
16
|
-
|
|
17
|
-
# if somehow order was canceled, we need to redirect the customer to the cart
|
|
18
|
-
# this is a rare case, but we need to handle it
|
|
19
|
-
if @order.canceled?
|
|
20
|
-
flash[:error] = Spree.t(:order_canceled)
|
|
21
|
-
redirect_to spree.cart_path, status: :see_other
|
|
22
|
-
# if the order is already completed (race condition)
|
|
23
|
-
# we need to redirect the customer to the complete checkout page
|
|
24
|
-
# but we need to make sure not to set the session flag to indicate that the order was placed now
|
|
25
|
-
# because we don't know if the order was actually placed or not
|
|
26
|
-
elsif @order.completed?
|
|
27
|
-
redirect_to spree.checkout_complete_path(@order.token), status: :see_other
|
|
28
|
-
# if the payment intent is successful, we need to process the payment and complete the order
|
|
29
|
-
elsif @payment_intent_record.accepted?
|
|
30
|
-
@order = SpreeStripe::CompleteOrder.new(payment_intent: @payment_intent_record).call
|
|
31
|
-
|
|
32
|
-
# set the session flag to indicate that the order was placed now
|
|
33
|
-
track_checkout_completed if @order.completed? && defined?(track_checkout_completed)
|
|
34
|
-
|
|
35
|
-
# redirect the customer to the complete checkout page
|
|
36
|
-
redirect_to spree.checkout_complete_path(@order.token), status: :see_other
|
|
37
|
-
else
|
|
38
|
-
handle_failure(Spree.t("stripe.payment_intent_errors.#{@stripe_payment_intent.status}"))
|
|
39
|
-
end
|
|
40
|
-
rescue Spree::Core::GatewayError => e
|
|
41
|
-
handle_failure(e.message)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
private
|
|
45
|
-
|
|
46
|
-
def handle_failure(error_message)
|
|
47
|
-
flash[:error] = error_message
|
|
48
|
-
|
|
49
|
-
Rails.logger.error("Payment failed for order #{@order.id}: #{@stripe_payment_intent.status}")
|
|
50
|
-
|
|
51
|
-
# remove the payment intent record, so after returning to the checkout page, the customer can try again with a new payment intent
|
|
52
|
-
@payment_intent_record.destroy!
|
|
53
|
-
|
|
54
|
-
# this should be a rare race condition, but we need to handle it
|
|
55
|
-
payment = @order.payments.valid.find_by(response_code: @stripe_payment_intent.id)
|
|
56
|
-
payment.void! if payment.present?
|
|
57
|
-
|
|
58
|
-
redirect_to spree.checkout_path(@order.token), status: :see_other
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
module SpreeStripe
|
|
2
|
-
class PaymentIntent < Base
|
|
3
|
-
#
|
|
4
|
-
# Associations
|
|
5
|
-
#
|
|
6
|
-
belongs_to :order, class_name: 'Spree::Order', foreign_key: 'order_id'
|
|
7
|
-
belongs_to :payment_method, class_name: 'Spree::PaymentMethod', foreign_key: 'payment_method_id'
|
|
8
|
-
has_one :payment, class_name: 'Spree::Payment', foreign_key: 'response_code', primary_key: 'stripe_id'
|
|
9
|
-
|
|
10
|
-
#
|
|
11
|
-
# Validations
|
|
12
|
-
#
|
|
13
|
-
validates :order, :payment_method, :client_secret, presence: true
|
|
14
|
-
validates :stripe_id, presence: true, uniqueness: { scope: :order_id }
|
|
15
|
-
validates :amount, presence: true, numericality: { greater_than: 0 }
|
|
16
|
-
|
|
17
|
-
#
|
|
18
|
-
# Callbacks
|
|
19
|
-
#
|
|
20
|
-
before_validation :set_amount_from_order
|
|
21
|
-
after_update :update_stripe_payment_intent, if: :amount_or_stripe_payment_method_id_changed?
|
|
22
|
-
|
|
23
|
-
#
|
|
24
|
-
# Delegations
|
|
25
|
-
#
|
|
26
|
-
delegate :api_options, to: :payment_method
|
|
27
|
-
delegate :store, :currency, to: :order
|
|
28
|
-
|
|
29
|
-
def accepted?
|
|
30
|
-
payment_method.payment_intent_accepted?(stripe_payment_intent)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def successful?
|
|
34
|
-
stripe_payment_intent.status == 'succeeded'
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def charge_not_required?
|
|
38
|
-
payment_method.payment_intent_charge_not_required?(stripe_payment_intent)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def stripe_payment_intent
|
|
42
|
-
@stripe_payment_intent ||= payment_method.retrieve_payment_intent(stripe_id)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def stripe_charge
|
|
46
|
-
@stripe_charge ||= begin
|
|
47
|
-
latest_charge = stripe_payment_intent.latest_charge
|
|
48
|
-
latest_charge.present? ? payment_method.retrieve_charge(latest_charge) : nil
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# here we create a payment if it doesn't exist
|
|
53
|
-
# or we find it by the stripe_payment_intent_id
|
|
54
|
-
def find_or_create_payment!
|
|
55
|
-
return unless persisted?
|
|
56
|
-
return payment if payment.present?
|
|
57
|
-
|
|
58
|
-
SpreeStripe::CreatePayment.new(order: order, payment_intent: self, gateway: payment_method, amount: amount).call
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def set_amount_from_order
|
|
62
|
-
self.amount = order&.total_minus_store_credits if order.present? && (amount.nil? || amount.zero?)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def update_stripe_payment_intent
|
|
66
|
-
payment_method.update_payment_intent(stripe_id, amount_in_cents, order, stripe_payment_method_id)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def amount_or_stripe_payment_method_id_changed?
|
|
70
|
-
amount_previously_changed? || stripe_payment_method_id_previously_changed?
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def amount_in_cents
|
|
74
|
-
@amount_in_cents ||= money.cents
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def money
|
|
78
|
-
@money ||= Spree::Money.new(amount, currency: currency)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
module SpreeStripe
|
|
2
|
-
class CreatePaymentIntent
|
|
3
|
-
def call(order, gateway, stripe_payment_method_id: nil, off_session: false)
|
|
4
|
-
total = order.total_minus_store_credits
|
|
5
|
-
amount = Spree::Money.new(total).cents
|
|
6
|
-
|
|
7
|
-
return nil if amount.zero?
|
|
8
|
-
|
|
9
|
-
# lookup in database for existing payment intent
|
|
10
|
-
payment_intent = SpreeStripe::PaymentIntent.find_by(order: order, payment_method: gateway)
|
|
11
|
-
|
|
12
|
-
return payment_intent if payment_intent.present?
|
|
13
|
-
|
|
14
|
-
# response is a Spree::PaymentResponse object
|
|
15
|
-
response = gateway.create_payment_intent(
|
|
16
|
-
amount,
|
|
17
|
-
order,
|
|
18
|
-
payment_method_id: stripe_payment_method_id,
|
|
19
|
-
off_session: off_session
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
# we should only create a customer if the order was placed by a user
|
|
23
|
-
customer = gateway.fetch_or_create_customer(user: order.user) if order.user.present?
|
|
24
|
-
ephemeral_key_response = gateway.create_ephemeral_key(customer.profile_id) if customer.present?
|
|
25
|
-
ephemeral_key_secret = ephemeral_key_response&.params['secret'] if ephemeral_key_response.present?
|
|
26
|
-
|
|
27
|
-
# persist the payment intent
|
|
28
|
-
SpreeStripe::PaymentIntent.create!(
|
|
29
|
-
order: order,
|
|
30
|
-
payment_method: gateway,
|
|
31
|
-
amount: total,
|
|
32
|
-
stripe_id: response.authorization,
|
|
33
|
-
client_secret: response.params['client_secret'],
|
|
34
|
-
customer_id: customer&.profile_id,
|
|
35
|
-
stripe_payment_method_id: stripe_payment_method_id,
|
|
36
|
-
ephemeral_key_secret: ephemeral_key_secret
|
|
37
|
-
)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
module SpreeStripe
|
|
2
|
-
class CreateSetupIntent
|
|
3
|
-
prepend Spree::ServiceModule::Base
|
|
4
|
-
|
|
5
|
-
def call(gateway:, user:)
|
|
6
|
-
customer = gateway.fetch_or_create_customer(user: user)
|
|
7
|
-
|
|
8
|
-
ephemeral_key_response = gateway.create_ephemeral_key(customer.profile_id)
|
|
9
|
-
setup_intent = gateway.create_setup_intent(customer.profile_id)
|
|
10
|
-
|
|
11
|
-
success(
|
|
12
|
-
{
|
|
13
|
-
customer_id: customer.profile_id,
|
|
14
|
-
ephemeral_key_secret: ephemeral_key_response.params['secret'],
|
|
15
|
-
setup_intent_client_secret: setup_intent.params['client_secret']
|
|
16
|
-
}
|
|
17
|
-
)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|