spree_stripe 1.0.2

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 (100) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +14 -0
  3. data/README.md +132 -0
  4. data/Rakefile +21 -0
  5. data/app/assets/config/spree_stripe_manifest.js +3 -0
  6. data/app/controllers/spree/api/v2/storefront/stripe/base_controller.rb +21 -0
  7. data/app/controllers/spree/api/v2/storefront/stripe/payment_intents_controller.rb +61 -0
  8. data/app/controllers/spree/api/v2/storefront/stripe/setup_intents_controller.rb +19 -0
  9. data/app/controllers/spree_stripe/apple_pay_domain_verification_controller.rb +11 -0
  10. data/app/controllers/spree_stripe/payment_intents_controller.rb +61 -0
  11. data/app/controllers/spree_stripe/store_controller_decorator.rb +9 -0
  12. data/app/controllers/stripe_event/webhook_controller_decorator.rb +17 -0
  13. data/app/helpers/spree_stripe/base_helper.rb +13 -0
  14. data/app/javascript/spree_stripe/application.js +18 -0
  15. data/app/javascript/spree_stripe/controllers/stripe_button_controller.js +452 -0
  16. data/app/javascript/spree_stripe/controllers/stripe_controller.js +311 -0
  17. data/app/jobs/spree_stripe/base_job.rb +5 -0
  18. data/app/jobs/spree_stripe/complete_order_job.rb +8 -0
  19. data/app/jobs/spree_stripe/create_webhook_endpoint_job.rb +7 -0
  20. data/app/jobs/spree_stripe/register_domain_job.rb +20 -0
  21. data/app/models/spree_stripe/base.rb +6 -0
  22. data/app/models/spree_stripe/credit_card_decorator.rb +13 -0
  23. data/app/models/spree_stripe/custom_domain_decorator.rb +18 -0
  24. data/app/models/spree_stripe/gateway.rb +366 -0
  25. data/app/models/spree_stripe/order_decorator.rb +19 -0
  26. data/app/models/spree_stripe/payment_decorator.rb +46 -0
  27. data/app/models/spree_stripe/payment_intent.rb +66 -0
  28. data/app/models/spree_stripe/payment_method_decorator.rb +18 -0
  29. data/app/models/spree_stripe/payment_methods_webhook_key.rb +8 -0
  30. data/app/models/spree_stripe/payment_source_decorator.rb +9 -0
  31. data/app/models/spree_stripe/payment_sources/affirm.rb +9 -0
  32. data/app/models/spree_stripe/payment_sources/after_pay.rb +13 -0
  33. data/app/models/spree_stripe/payment_sources/alipay.rb +9 -0
  34. data/app/models/spree_stripe/payment_sources/ideal.rb +15 -0
  35. data/app/models/spree_stripe/payment_sources/klarna.rb +9 -0
  36. data/app/models/spree_stripe/payment_sources/link.rb +13 -0
  37. data/app/models/spree_stripe/payment_sources/przelewy24.rb +11 -0
  38. data/app/models/spree_stripe/payment_sources/sepa_debit.rb +13 -0
  39. data/app/models/spree_stripe/store_decorator.rb +24 -0
  40. data/app/models/spree_stripe/webhook_key.rb +14 -0
  41. data/app/presenters/spree_stripe/customer_presenter.rb +35 -0
  42. data/app/presenters/spree_stripe/payment_intent_presenter.rb +103 -0
  43. data/app/serializers/spree/api/v2/platform/affirm_serializer.rb +9 -0
  44. data/app/serializers/spree/api/v2/platform/after_pay_serializer.rb +9 -0
  45. data/app/serializers/spree/api/v2/platform/alipay_serializer.rb +9 -0
  46. data/app/serializers/spree/api/v2/platform/ideal_serializer.rb +9 -0
  47. data/app/serializers/spree/api/v2/platform/klarna_serializer.rb +9 -0
  48. data/app/serializers/spree/api/v2/platform/link_serializer.rb +9 -0
  49. data/app/serializers/spree/api/v2/platform/przelewy24_serializer.rb +9 -0
  50. data/app/serializers/spree/api/v2/platform/sepa_debit_serializer.rb +9 -0
  51. data/app/serializers/spree/v2/storefront/affirm_serializer.rb +7 -0
  52. data/app/serializers/spree/v2/storefront/after_pay_serializer.rb +7 -0
  53. data/app/serializers/spree/v2/storefront/alipay_serializer.rb +7 -0
  54. data/app/serializers/spree/v2/storefront/ideal_serializer.rb +7 -0
  55. data/app/serializers/spree/v2/storefront/klarna_serializer.rb +7 -0
  56. data/app/serializers/spree/v2/storefront/link_serializer.rb +7 -0
  57. data/app/serializers/spree/v2/storefront/payment_intent_serializer.rb +11 -0
  58. data/app/serializers/spree/v2/storefront/przelewy24_serializer.rb +7 -0
  59. data/app/serializers/spree/v2/storefront/sepa_debit_serializer.rb +7 -0
  60. data/app/services/spree_stripe/complete_order.rb +99 -0
  61. data/app/services/spree_stripe/create_gateway_webhooks.rb +55 -0
  62. data/app/services/spree_stripe/create_payment.rb +43 -0
  63. data/app/services/spree_stripe/create_payment_intent.rb +40 -0
  64. data/app/services/spree_stripe/create_setup_intent.rb +20 -0
  65. data/app/services/spree_stripe/create_source.rb +87 -0
  66. data/app/services/spree_stripe/register_domain.rb +22 -0
  67. data/app/services/spree_stripe/webhook_handlers/payment_intent_payment_failed.rb +18 -0
  68. data/app/services/spree_stripe/webhook_handlers/payment_intent_succeeded.rb +13 -0
  69. data/app/services/spree_stripe/webhook_handlers/setup_intent_succeeded.rb +34 -0
  70. data/app/views/spree/admin/payment_methods/configuration_guides/_spree_stripe.html.erb +0 -0
  71. data/app/views/spree/admin/payment_methods/custom_form_fields/_spree_stripe.html.erb +47 -0
  72. data/app/views/spree/admin/payment_methods/descriptions/_spree_stripe.html.erb +15 -0
  73. data/app/views/spree/checkout/payment/_spree_stripe.html.erb +63 -0
  74. data/app/views/spree_stripe/_head.html.erb +2 -0
  75. data/app/views/spree_stripe/_quick_checkout.html.erb +34 -0
  76. data/config/importmap.rb +8 -0
  77. data/config/initializers/spree.rb +8 -0
  78. data/config/initializers/stripe.rb +14 -0
  79. data/config/locales/en.yml +5 -0
  80. data/config/routes.rb +24 -0
  81. data/db/migrate/20250310152812_setup_spree_stripe_models.rb +41 -0
  82. data/lib/generators/spree_stripe/install/install_generator.rb +20 -0
  83. data/lib/spree_stripe/configuration.rb +5 -0
  84. data/lib/spree_stripe/engine.rb +36 -0
  85. data/lib/spree_stripe/factories.rb +3 -0
  86. data/lib/spree_stripe/testing_support/factories/after_pay_payment_source_factory.rb +6 -0
  87. data/lib/spree_stripe/testing_support/factories/alipay_payment_source_factory.rb +6 -0
  88. data/lib/spree_stripe/testing_support/factories/gateway_factory.rb +23 -0
  89. data/lib/spree_stripe/testing_support/factories/ideal_payment_source_factory.rb +6 -0
  90. data/lib/spree_stripe/testing_support/factories/klarna_payment_source_factory.rb +6 -0
  91. data/lib/spree_stripe/testing_support/factories/link_payment_source_factory.rb +6 -0
  92. data/lib/spree_stripe/testing_support/factories/payment_intent_factory.rb +24 -0
  93. data/lib/spree_stripe/testing_support/factories/payment_source_factory.rb +8 -0
  94. data/lib/spree_stripe/testing_support/factories/przelewy24_payment_source_factory.rb +6 -0
  95. data/lib/spree_stripe/testing_support/factories/sepa_debit_payment_source_factory.rb +6 -0
  96. data/lib/spree_stripe/testing_support/factories/webhook_key_factory.rb +23 -0
  97. data/lib/spree_stripe/version.rb +7 -0
  98. data/lib/spree_stripe.rb +14 -0
  99. data/vendor/javascript/@stripe--stripe-js--dist--pure.esm.js.js +4 -0
  100. metadata +295 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b9ff8503fd4b39888f48c4be858858eb6050eb4949171f498f5f8d1eb5c4b1e2
4
+ data.tar.gz: 72f161cfc29653e564f12b759954221f6d9c5c4e8803a9f6a148925952da2906
5
+ SHA512:
6
+ metadata.gz: 5ea0227d2b1461807f37babce54421d410f7f582e057821ed845c5a73b4eeb35bb6f1ca74999066852fedc07d1317b6ea6b7d1cee7547b482ccd04020546cb0a
7
+ data.tar.gz: 5b09ba2480311dcff8609d18471e757e49543ef517eaccce70b89816846504407159db6420f964082c0a23647a265fdea1ac08c3bb459bdae87d8ff8f1a6373b
data/LICENSE.md ADDED
@@ -0,0 +1,14 @@
1
+ # LICENSE
2
+
3
+ Copyright (c) 2025 Vendo Connect Inc.
4
+ All rights reserved.
5
+
6
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7
+
8
+ This program is distributed in the hope that it will be useful,
9
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ GNU Affero General Public License for more details.
12
+
13
+ You should have received a copy of the GNU Affero General Public License
14
+ along with this program. If not, see [https://www.gnu.org/licenses/](https://www.gnu.org/licenses/).
data/README.md ADDED
@@ -0,0 +1,132 @@
1
+ <p align="center">
2
+ <a href="https://spreecommerce.org">
3
+ <img alt="Spree Commerce x Stripe integration" src="https://vendo-production-res.cloudinary.com/image/upload/w_2000/q_auto/v1742930549/docs/github/Spree_Commerce_open-source_eCommerce_Stripe_payments_integration_-_Github_xlrcn8.jpg">
4
+ </a>
5
+
6
+ # Spree Stripe
7
+
8
+ This is the official Stripe payment gateway extension for [Spree Commerce](https://spreecommerce.org) [open-source eCommerce platform](https://spreecommerce.org/).
9
+
10
+ If you like what you see, consider giving this repo a GitHub star :star:
11
+
12
+ Thank you for supporting Spree open-source :heart:
13
+
14
+ > [!IMPORTANT]
15
+ > This Stripe integration for Spree is free to use for private projects but requires a [Commercial License](https://spreecommerce.org/why-consider-a-commercial-license-for-your-multi-tenant-or-saas-spree-based-project/) if you're planning to use it for your [SaaS](https://spreecommerce.org/multi-tenant-white-label-ecommerce/) or a [multi-tenant eCommerce](https://spreecommerce.org/multi-tenant-white-label-ecommerce/) website.
16
+ > Feel free to [reach out](https://spreecommerce.org/get-started/) to learn more.
17
+
18
+ > [!TIP]
19
+ > Looking for a [Stripe Connect integration](#looking-for-a-stripe-connect-integration-for-spree) for Spree? It's available with the [Enterprise Edition](https://spreecommerce.org/spree-commerce-version-comparison-community-edition-vs-enterprise-edition/).
20
+
21
+ ## Features
22
+
23
+ - Support for quick checkout using Apple Pay, Google Pay, Stripe Link
24
+ - Support for 3D Secure and other security standards
25
+ - Support for off-session payments
26
+ - Support for Storefront API integration (see the API docs [here](https://spreecommerce.org/docs/api-reference/storefront/stripe)).
27
+ - Accept payments in over 130 currencies
28
+ - Accept Credit Cards, Apple Pay, Google Pay, and more
29
+ - Accept SEPA Direct Debit payments
30
+ - Accept iDEAL payments
31
+ - Accept SOFORT payments
32
+ - Accept Bancontact payments
33
+ - Accept Alipay payments
34
+ - Accept WeChat Pay payments
35
+ - Accept Afterpay, Klarna, Affirm, and more
36
+
37
+ ## What's new?
38
+
39
+ ### Installment (BNPL) payments indicator on PDP (Product Detail Page)
40
+
41
+ ![Spree_x_Stripe_-_BNPL_Installment_payments_Product_Card_PDP_Product_Detail_Page](https://vendo-production-res.cloudinary.com/image/upload/w_2000/q_auto/v1742983146/docs/github/Spree_x_Stripe_-_BNPL_Installment_payments_Product_Card_PDP_Product_Detail_Page_amhfkw.jpg)
42
+
43
+ ### Quick payment options on the cart (Apple Pay, Google Pay, Link)
44
+
45
+ ![Apple_Pay_Google_Pay_Link_-_Quick_payment_options_on_the_cart](https://vendo-production-res.cloudinary.com/image/upload/w_2000/q_auto/v1742930027/docs/github/Spree_x_Stripe_-_Apple_Pay_Google_Pay_Link_-_Quick_payment_options_on_the_cart_aw45x9.jpg)
46
+
47
+ ### Quick payments bypassing checkout 1st step (Apple Pay, Google Pay, Link)
48
+
49
+ ![Apple_Pay_Google_Pay_Link_-_Quick_payments_bypassing_checkout](https://vendo-production-res.cloudinary.com/image/upload/w_2000/q_auto/v1742930027/docs/github/Spree_x_Stripe_-_Apple_Pay_Google_Pay_Link_-_Quick_payments_bypassing_checkout_on_Cart_n6gbh6.jpg)
50
+
51
+ ### Various payment options on the payment step (cards, BNPL, Apple Pay, Google Pay, Link)
52
+
53
+ ![Quick payments bypassing checkout 1st step (Apple Pay, Google_Pay, Link)](https://vendo-production-res.cloudinary.com/image/upload/w_2000/q_auto/v1742930027/docs/github/Spree_x_Stripe_-_Apple_Pay_Google_Pay_Link_-_Checkout_payment_step_rxxnr9.jpg)
54
+
55
+ ## Spree 5 Demo
56
+
57
+ Check out the [Spree Commerce demo](https://demo.spreecommerce.org/) for yourself, including this Stripe integration.
58
+
59
+ This demo runs on Spree 5 which is the biggest Spree release ever. Stay tuned for the official announcement on all the exciting features and integrations - coming up soon!
60
+
61
+ ![Spree Commerce 5 version](https://vendo-production-res.cloudinary.com/image/upload/w_2000/q_auto/v1742985405/docs/github/Spree_Commerce_open-source_eCommerce_myzurl.jpg)
62
+
63
+ ## Installation
64
+
65
+ 1. Add this extension to your Gemfile with this line:
66
+
67
+ ```ruby
68
+ bundle add spree_stripe --github=spree/spree_stripe
69
+ ```
70
+
71
+ 2. Run the install generator
72
+
73
+ ```ruby
74
+ bundle exec rails g spree_stripe:install
75
+ ```
76
+
77
+ 3. Restart your server
78
+
79
+ If your server was running, restart it so that it can find the assets properly.
80
+
81
+ ## Developing
82
+
83
+ 1. Create a dummy app
84
+
85
+ ```bash
86
+ bundle update
87
+ bundle exec rake test_app
88
+ ```
89
+
90
+ 2. Add your new code
91
+ 3. Run tests
92
+
93
+ ```bash
94
+ bundle exec rspec
95
+ ```
96
+
97
+ When testing your applications integration with this extension you may use it's factories.
98
+ Simply add this require statement to your spec_helper:
99
+
100
+ ```ruby
101
+ require 'spree_stripe/factories'
102
+ ```
103
+
104
+ ## Releasing a new version
105
+
106
+ ```shell
107
+ bundle exec gem bump -p -t
108
+ bundle exec gem release
109
+ ```
110
+
111
+ For more options please see [gem-release README](https://github.com/svenfuchs/gem-release)
112
+
113
+ ## Contributing
114
+
115
+ If you'd like to contribute, please take a look at the
116
+ [instructions](CONTRIBUTING.md) for installing dependencies and crafting a good
117
+ pull request.
118
+
119
+ Copyright (c) 2025 [Vendo Connect Inc.](https://getvendo.com), released under [AGPL 3.0 license](https://github.com/spree/spree_stripe/blob/main/LICENSE.md). Please refer to [this blog post](https://spreecommerce.org/why-spree-is-changing-its-open-source-license-to-agpl-3-0-and-introducing-a-commercial-license/) and [that blog post](https://spreecommerce.org/open-source-ecommerce-transparency/) to learn more about Spree licensing.
120
+
121
+ ## Looking for a Stripe Connect integration for Spree?
122
+
123
+ Spree Commerce [Enterprise Edition](https://spreecommerce.org/spree-commerce-version-comparison-community-edition-vs-enterprise-edition/) comes with a fully automated Stripe Connect integration for a [multi-vendor marketplace use case](https://spreecommerce.org/marketplace-ecommerce/):
124
+
125
+ - Automated split payments between marketplace and vendors
126
+ - Support for multiple payment methods including cards and digital wallets
127
+ - Configurable marketplace fees and commission structures
128
+ - Automated payouts to vendors
129
+ - Comprehensive transaction reporting
130
+ - Built-in fraud prevention tools
131
+
132
+ Feel free to [reach out](https://spreecommerce.org/get-started/) to learn more.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default do
10
+ if Dir['spec/dummy'].empty?
11
+ Rake::Task[:test_app].invoke
12
+ Dir.chdir('../../')
13
+ end
14
+ Rake::Task[:spec].invoke
15
+ end
16
+
17
+ desc 'Generates a dummy app for testing'
18
+ task :test_app do
19
+ ENV['LIB_NAME'] = 'spree_stripe'
20
+ Rake::Task['extension:test_app'].invoke
21
+ end
@@ -0,0 +1,3 @@
1
+ //= link spree_stripe/application.js
2
+ //= link_tree ../../javascript/spree_stripe/controllers .js
3
+ //= link_tree ../../../vendor/javascript .js
@@ -0,0 +1,21 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Storefront
5
+ module Stripe
6
+ class BaseController < ::Spree::Api::V2::BaseController
7
+ before_action :require_stripe_gateway
8
+
9
+ def require_stripe_gateway
10
+ render_error_payload('Stripe gateway is not present') unless stripe_gateway
11
+ end
12
+
13
+ def stripe_gateway
14
+ @stripe_gateway ||= current_store.stripe_gateway
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,61 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Storefront
5
+ module Stripe
6
+ class PaymentIntentsController < BaseController
7
+ include Spree::Api::V2::Storefront::OrderConcern
8
+ before_action :ensure_order
9
+
10
+ # POST /api/v2/storefront/stripe/payment_intents
11
+ def create
12
+ spree_authorize! :update, spree_current_order, order_token
13
+
14
+ stripe_payment_method_id = permitted_attributes[:stripe_payment_method_id].presence
15
+ stripe_payment_method_id ||= spree_current_order.valid_credit_cards.where(payment_method: stripe_gateway).first&.gateway_payment_profile_id
16
+
17
+ @payment_intent = SpreeStripe::CreatePaymentIntent.new.call(
18
+ spree_current_order,
19
+ stripe_gateway,
20
+ stripe_payment_method_id: stripe_payment_method_id,
21
+ off_session: permitted_attributes[:off_session] || false
22
+ )
23
+
24
+ render_serialized_payload { serialize_resource(@payment_intent) }
25
+ end
26
+
27
+ # GET /api/v2/storefront/stripe/payment_intents
28
+ def show
29
+ spree_authorize! :show, spree_current_order, order_token
30
+
31
+ @payment_intent = spree_current_order.payment_intents.find(params[:id])
32
+
33
+ render_serialized_payload { serialize_resource(@payment_intent) }
34
+ end
35
+
36
+ # PATCH /api/v2/storefront/stripe/payment_intents/:id
37
+ def update
38
+ spree_authorize! :update, spree_current_order, order_token
39
+
40
+ @payment_intent = spree_current_order.payment_intents.find(params[:id])
41
+ @payment_intent.attributes = permitted_attributes
42
+ @payment_intent.save!
43
+
44
+ render_serialized_payload { serialize_resource(@payment_intent) }
45
+ end
46
+
47
+ private
48
+
49
+ def permitted_attributes
50
+ params.require(:payment_intent).permit(:amount, :stripe_payment_method_id, :off_session)
51
+ end
52
+
53
+ def resource_serializer
54
+ Spree::V2::Storefront::PaymentIntentSerializer
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,19 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Storefront
5
+ module Stripe
6
+ class SetupIntentsController < BaseController
7
+ before_action :require_spree_current_user
8
+
9
+ def create
10
+ setup_intent = SpreeStripe::CreateSetupIntent.call(gateway: stripe_gateway, user: try_spree_current_user)
11
+
12
+ render_serialized_payload(200) { setup_intent.value }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ module SpreeStripe
2
+ class ApplePayDomainVerificationController < ::Spree::StoreController
3
+ def show
4
+ gateway = SpreeStripe::Gateway.last
5
+
6
+ raise ActiveRecord::RecordNotFound if gateway.nil? || !gateway.apple_domain_association_file_content
7
+
8
+ render plain: gateway.apple_domain_association_file_content
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,61 @@
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 < Spree::StoreController
5
+ include 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 @stripe_payment_intent.status == 'succeeded'
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?
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
@@ -0,0 +1,9 @@
1
+ module SpreeStripe
2
+ module StoreControllerDecorator
3
+ def self.prepended(base)
4
+ base.helper SpreeStripe::BaseHelper
5
+ end
6
+ end
7
+ end
8
+
9
+ Spree::StoreController.prepend(SpreeStripe::StoreControllerDecorator) if defined?(Spree::StoreController)
@@ -0,0 +1,17 @@
1
+ module StripeEvent
2
+ module WebhookControllerDecorator
3
+ def secrets(payload, signature)
4
+ all_signing_keys = SpreeStripe::WebhookKey.pluck(:signing_secret).uniq.compact
5
+ all_signing_keys << ENV['STRIPE_SIGNING_SECRET'] if ENV['STRIPE_SIGNING_SECRET'].present?
6
+
7
+ return all_signing_keys if all_signing_keys.any?
8
+
9
+ raise Stripe::SignatureVerificationError.new(
10
+ 'Cannot verify signature without a `StripeEvent.signing_secret`',
11
+ signature, http_body: payload
12
+ )
13
+ end
14
+ end
15
+
16
+ WebhookController.prepend(WebhookControllerDecorator)
17
+ end
@@ -0,0 +1,13 @@
1
+ module SpreeStripe
2
+ module BaseHelper
3
+ def current_stripe_gateway
4
+ @current_stripe_gateway ||= current_store.stripe_gateway
5
+ end
6
+
7
+ def current_stripe_payment_intent
8
+ return if current_stripe_gateway.nil?
9
+
10
+ @current_stripe_payment_intent ||= SpreeStripe::CreatePaymentIntent.new.call(@order, current_stripe_gateway)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ import '@hotwired/turbo-rails'
2
+ import { Application } from '@hotwired/stimulus'
3
+
4
+ let application
5
+
6
+ if (typeof window.Stimulus === "undefined") {
7
+ application = Application.start()
8
+ application.debug = false
9
+ window.Stimulus = application
10
+ } else {
11
+ application = window.Stimulus
12
+ }
13
+
14
+ import CheckoutStripeButtonController from 'spree_stripe/controllers/stripe_button_controller'
15
+ import CheckoutStripeController from 'spree_stripe/controllers/stripe_controller'
16
+
17
+ application.register('checkout-stripe-button', CheckoutStripeButtonController)
18
+ application.register('checkout-stripe', CheckoutStripeController)