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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/spree_stripe/confirm_payments_controller.rb +52 -0
  3. data/app/helpers/spree_stripe/base_helper.rb +24 -2
  4. data/app/javascript/spree_stripe/controllers/stripe_button_controller.js +256 -338
  5. data/app/javascript/spree_stripe/controllers/stripe_controller.js +129 -206
  6. data/app/models/spree/payment_sessions/stripe.rb +1 -2
  7. data/app/models/spree_stripe/gateway/payment_intents.rb +0 -4
  8. data/app/models/spree_stripe/gateway/payment_sessions.rb +2 -2
  9. data/app/models/spree_stripe/order_decorator.rb +0 -27
  10. data/app/models/spree_stripe/shipment_decorator.rb +3 -3
  11. data/app/services/spree_stripe/create_payment_session.rb +18 -0
  12. data/app/services/spree_stripe/webhook_handlers/payment_intent_payment_failed.rb +4 -15
  13. data/app/services/spree_stripe/webhook_handlers/payment_intent_succeeded.rb +1 -7
  14. data/app/views/spree/checkout/payment/_spree_stripe.html.erb +58 -58
  15. data/app/views/spree_stripe/_quick_checkout.html.erb +9 -15
  16. data/config/locales/en.yml +3 -8
  17. data/config/routes.rb +3 -22
  18. data/db/migrate/20250310152812_setup_spree_stripe_models.rb +0 -17
  19. data/lib/spree_stripe/configuration.rb +0 -1
  20. data/lib/spree_stripe/engine.rb +0 -7
  21. data/lib/spree_stripe/version.rb +1 -1
  22. metadata +5 -44
  23. data/app/controllers/spree_stripe/payment_intents_controller.rb +0 -61
  24. data/app/jobs/spree_stripe/complete_order_job.rb +0 -8
  25. data/app/models/spree_stripe/payment_intent.rb +0 -81
  26. data/app/services/spree_stripe/create_payment_intent.rb +0 -40
  27. data/app/services/spree_stripe/create_setup_intent.rb +0 -20
  28. data/lib/spree_api_v2/spree/api/v2/platform/affirm_serializer.rb +0 -9
  29. data/lib/spree_api_v2/spree/api/v2/platform/after_pay_serializer.rb +0 -9
  30. data/lib/spree_api_v2/spree/api/v2/platform/alipay_serializer.rb +0 -9
  31. data/lib/spree_api_v2/spree/api/v2/platform/ideal_serializer.rb +0 -9
  32. data/lib/spree_api_v2/spree/api/v2/platform/klarna_serializer.rb +0 -9
  33. data/lib/spree_api_v2/spree/api/v2/platform/link_serializer.rb +0 -9
  34. data/lib/spree_api_v2/spree/api/v2/platform/przelewy24_serializer.rb +0 -9
  35. data/lib/spree_api_v2/spree/api/v2/platform/sepa_debit_serializer.rb +0 -9
  36. data/lib/spree_api_v2/spree/api/v2/storefront/stripe/base_controller.rb +0 -21
  37. data/lib/spree_api_v2/spree/api/v2/storefront/stripe/payment_intents_controller.rb +0 -86
  38. data/lib/spree_api_v2/spree/api/v2/storefront/stripe/setup_intents_controller.rb +0 -19
  39. data/lib/spree_api_v2/spree/v2/storefront/affirm_serializer.rb +0 -7
  40. data/lib/spree_api_v2/spree/v2/storefront/after_pay_serializer.rb +0 -7
  41. data/lib/spree_api_v2/spree/v2/storefront/alipay_serializer.rb +0 -7
  42. data/lib/spree_api_v2/spree/v2/storefront/ideal_serializer.rb +0 -7
  43. data/lib/spree_api_v2/spree/v2/storefront/klarna_serializer.rb +0 -7
  44. data/lib/spree_api_v2/spree/v2/storefront/link_serializer.rb +0 -7
  45. data/lib/spree_api_v2/spree/v2/storefront/payment_intent_serializer.rb +0 -15
  46. data/lib/spree_api_v2/spree/v2/storefront/przelewy24_serializer.rb +0 -7
  47. data/lib/spree_api_v2/spree/v2/storefront/sepa_debit_serializer.rb +0 -7
  48. data/lib/spree_api_v2/spree_stripe/v2/storefront/payment_method_serializer_decorator.rb +0 -17
  49. data/lib/spree_stripe/testing_support/factories/payment_intent_factory.rb +0 -24
@@ -1,66 +1,66 @@
1
- <div
2
- data-controller="checkout-stripe"
3
- data-checkout-stripe-payment-intent-value="<%= current_stripe_payment_intent.to_json %>"
4
- data-checkout-stripe-return-url-value="<%= spree.stripe_payment_intent_url(current_stripe_payment_intent) %>"
5
- data-checkout-stripe-api-key-value="<%= current_stripe_gateway.try(:preferred_publishable_key) %>"
6
- data-checkout-stripe-order-token-value="<%= @order.token %>"
7
- data-checkout-stripe-order-email-value="<%= @order.email %>"
8
- data-checkout-stripe-color-primary-value="<%= hex_color_to_rgb(theme_setting(:primary_color)) %>"
9
- data-checkout-stripe-color-text-value="<%= hex_color_to_rgb(theme_setting(:text_color)) %>"
10
- data-checkout-stripe-payment-intent-path-value="<%= spree.api_v2_storefront_stripe_payment_intent_path(current_stripe_payment_intent.id) %>"
11
- data-checkout-stripe-checkout-path-value="<%= spree.api_v2_storefront_checkout_path %>"
12
- data-checkout-stripe-checkout-validate-order-for-payment-path-value="<%= spree.validate_order_for_payment_api_v2_storefront_checkout_path %>"
13
- >
14
- <% payment_sources = checkout_payment_sources(payment_method) %>
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
- <% 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>
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
- <% 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>
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
- </div>
66
+ <% end %>
@@ -1,29 +1,23 @@
1
- <% if quick_checkout_enabled?(@order) && current_stripe_gateway.present? && current_stripe_payment_intent.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
- checkout_stripe_button_order_token_value: @order.token,
8
- checkout_stripe_button_client_secret_value: current_stripe_payment_intent.client_secret,
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.display_total_minus_store_credits.cents,
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
- checkout_stripe_button_checkout_path_value: spree.api_v2_storefront_checkout_path,
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 %>
@@ -3,11 +3,6 @@ en:
3
3
  spree:
4
4
  bank_transfer: Bank Transfer
5
5
  stripe:
6
- payment_intent_errors:
7
- canceled: Payment intent canceled
8
- processing: Payment intent processing
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 intents
3
- get '/stripe/payment_intents/:id', to: '/spree_stripe/payment_intents#show',
4
- as: :stripe_payment_intent,
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
@@ -6,7 +6,6 @@ module SpreeStripe
6
6
  payment_intent.succeeded
7
7
  setup_intent.succeeded
8
8
  ]
9
- preference :use_legacy_payment_intents, :boolean, default: false
10
9
  preference :use_legacy_webhook_handlers, :boolean, default: false
11
10
  end
12
11
  end
@@ -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|
@@ -1,5 +1,5 @@
1
1
  module SpreeStripe
2
- VERSION = '1.7.0'.freeze
2
+ VERSION = '1.8.0'.freeze
3
3
 
4
4
  def gem_version
5
5
  Gem::Version.new(VERSION)
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.7.0
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/payment_intents_controller.rb
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/create_payment_intent.rb
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.7.0
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.7.0
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,8 +0,0 @@
1
- module SpreeStripe
2
- class CompleteOrderJob < BaseJob
3
- def perform(payment_intent_id)
4
- payment_intent = SpreeStripe::PaymentIntent.find(payment_intent_id)
5
- SpreeStripe::CompleteOrder.new(payment_intent: payment_intent).call
6
- end
7
- end
8
- 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
@@ -1,9 +0,0 @@
1
- module Spree
2
- module Api
3
- module V2
4
- module Platform
5
- class AffirmSerializer < PaymentSourceSerializer; end
6
- end
7
- end
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- module Spree
2
- module Api
3
- module V2
4
- module Platform
5
- class AfterPaySerializer < PaymentSourceSerializer; end
6
- end
7
- end
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- module Spree
2
- module Api
3
- module V2
4
- module Platform
5
- class AlipaySerializer < PaymentSourceSerializer; end
6
- end
7
- end
8
- end
9
- end