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.
- checksums.yaml +7 -0
- data/LICENSE.md +14 -0
- data/README.md +132 -0
- data/Rakefile +21 -0
- data/app/assets/config/spree_stripe_manifest.js +3 -0
- data/app/controllers/spree/api/v2/storefront/stripe/base_controller.rb +21 -0
- data/app/controllers/spree/api/v2/storefront/stripe/payment_intents_controller.rb +61 -0
- data/app/controllers/spree/api/v2/storefront/stripe/setup_intents_controller.rb +19 -0
- data/app/controllers/spree_stripe/apple_pay_domain_verification_controller.rb +11 -0
- data/app/controllers/spree_stripe/payment_intents_controller.rb +61 -0
- data/app/controllers/spree_stripe/store_controller_decorator.rb +9 -0
- data/app/controllers/stripe_event/webhook_controller_decorator.rb +17 -0
- data/app/helpers/spree_stripe/base_helper.rb +13 -0
- data/app/javascript/spree_stripe/application.js +18 -0
- data/app/javascript/spree_stripe/controllers/stripe_button_controller.js +452 -0
- data/app/javascript/spree_stripe/controllers/stripe_controller.js +311 -0
- data/app/jobs/spree_stripe/base_job.rb +5 -0
- data/app/jobs/spree_stripe/complete_order_job.rb +8 -0
- data/app/jobs/spree_stripe/create_webhook_endpoint_job.rb +7 -0
- data/app/jobs/spree_stripe/register_domain_job.rb +20 -0
- data/app/models/spree_stripe/base.rb +6 -0
- data/app/models/spree_stripe/credit_card_decorator.rb +13 -0
- data/app/models/spree_stripe/custom_domain_decorator.rb +18 -0
- data/app/models/spree_stripe/gateway.rb +366 -0
- data/app/models/spree_stripe/order_decorator.rb +19 -0
- data/app/models/spree_stripe/payment_decorator.rb +46 -0
- data/app/models/spree_stripe/payment_intent.rb +66 -0
- data/app/models/spree_stripe/payment_method_decorator.rb +18 -0
- data/app/models/spree_stripe/payment_methods_webhook_key.rb +8 -0
- data/app/models/spree_stripe/payment_source_decorator.rb +9 -0
- data/app/models/spree_stripe/payment_sources/affirm.rb +9 -0
- data/app/models/spree_stripe/payment_sources/after_pay.rb +13 -0
- data/app/models/spree_stripe/payment_sources/alipay.rb +9 -0
- data/app/models/spree_stripe/payment_sources/ideal.rb +15 -0
- data/app/models/spree_stripe/payment_sources/klarna.rb +9 -0
- data/app/models/spree_stripe/payment_sources/link.rb +13 -0
- data/app/models/spree_stripe/payment_sources/przelewy24.rb +11 -0
- data/app/models/spree_stripe/payment_sources/sepa_debit.rb +13 -0
- data/app/models/spree_stripe/store_decorator.rb +24 -0
- data/app/models/spree_stripe/webhook_key.rb +14 -0
- data/app/presenters/spree_stripe/customer_presenter.rb +35 -0
- data/app/presenters/spree_stripe/payment_intent_presenter.rb +103 -0
- data/app/serializers/spree/api/v2/platform/affirm_serializer.rb +9 -0
- data/app/serializers/spree/api/v2/platform/after_pay_serializer.rb +9 -0
- data/app/serializers/spree/api/v2/platform/alipay_serializer.rb +9 -0
- data/app/serializers/spree/api/v2/platform/ideal_serializer.rb +9 -0
- data/app/serializers/spree/api/v2/platform/klarna_serializer.rb +9 -0
- data/app/serializers/spree/api/v2/platform/link_serializer.rb +9 -0
- data/app/serializers/spree/api/v2/platform/przelewy24_serializer.rb +9 -0
- data/app/serializers/spree/api/v2/platform/sepa_debit_serializer.rb +9 -0
- data/app/serializers/spree/v2/storefront/affirm_serializer.rb +7 -0
- data/app/serializers/spree/v2/storefront/after_pay_serializer.rb +7 -0
- data/app/serializers/spree/v2/storefront/alipay_serializer.rb +7 -0
- data/app/serializers/spree/v2/storefront/ideal_serializer.rb +7 -0
- data/app/serializers/spree/v2/storefront/klarna_serializer.rb +7 -0
- data/app/serializers/spree/v2/storefront/link_serializer.rb +7 -0
- data/app/serializers/spree/v2/storefront/payment_intent_serializer.rb +11 -0
- data/app/serializers/spree/v2/storefront/przelewy24_serializer.rb +7 -0
- data/app/serializers/spree/v2/storefront/sepa_debit_serializer.rb +7 -0
- data/app/services/spree_stripe/complete_order.rb +99 -0
- data/app/services/spree_stripe/create_gateway_webhooks.rb +55 -0
- data/app/services/spree_stripe/create_payment.rb +43 -0
- data/app/services/spree_stripe/create_payment_intent.rb +40 -0
- data/app/services/spree_stripe/create_setup_intent.rb +20 -0
- data/app/services/spree_stripe/create_source.rb +87 -0
- data/app/services/spree_stripe/register_domain.rb +22 -0
- data/app/services/spree_stripe/webhook_handlers/payment_intent_payment_failed.rb +18 -0
- data/app/services/spree_stripe/webhook_handlers/payment_intent_succeeded.rb +13 -0
- data/app/services/spree_stripe/webhook_handlers/setup_intent_succeeded.rb +34 -0
- data/app/views/spree/admin/payment_methods/configuration_guides/_spree_stripe.html.erb +0 -0
- data/app/views/spree/admin/payment_methods/custom_form_fields/_spree_stripe.html.erb +47 -0
- data/app/views/spree/admin/payment_methods/descriptions/_spree_stripe.html.erb +15 -0
- data/app/views/spree/checkout/payment/_spree_stripe.html.erb +63 -0
- data/app/views/spree_stripe/_head.html.erb +2 -0
- data/app/views/spree_stripe/_quick_checkout.html.erb +34 -0
- data/config/importmap.rb +8 -0
- data/config/initializers/spree.rb +8 -0
- data/config/initializers/stripe.rb +14 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +24 -0
- data/db/migrate/20250310152812_setup_spree_stripe_models.rb +41 -0
- data/lib/generators/spree_stripe/install/install_generator.rb +20 -0
- data/lib/spree_stripe/configuration.rb +5 -0
- data/lib/spree_stripe/engine.rb +36 -0
- data/lib/spree_stripe/factories.rb +3 -0
- data/lib/spree_stripe/testing_support/factories/after_pay_payment_source_factory.rb +6 -0
- data/lib/spree_stripe/testing_support/factories/alipay_payment_source_factory.rb +6 -0
- data/lib/spree_stripe/testing_support/factories/gateway_factory.rb +23 -0
- data/lib/spree_stripe/testing_support/factories/ideal_payment_source_factory.rb +6 -0
- data/lib/spree_stripe/testing_support/factories/klarna_payment_source_factory.rb +6 -0
- data/lib/spree_stripe/testing_support/factories/link_payment_source_factory.rb +6 -0
- data/lib/spree_stripe/testing_support/factories/payment_intent_factory.rb +24 -0
- data/lib/spree_stripe/testing_support/factories/payment_source_factory.rb +8 -0
- data/lib/spree_stripe/testing_support/factories/przelewy24_payment_source_factory.rb +6 -0
- data/lib/spree_stripe/testing_support/factories/sepa_debit_payment_source_factory.rb +6 -0
- data/lib/spree_stripe/testing_support/factories/webhook_key_factory.rb +23 -0
- data/lib/spree_stripe/version.rb +7 -0
- data/lib/spree_stripe.rb +14 -0
- data/vendor/javascript/@stripe--stripe-js--dist--pure.esm.js.js +4 -0
- 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
|
+

|
42
|
+
|
43
|
+
### Quick payment options on the cart (Apple Pay, Google Pay, Link)
|
44
|
+
|
45
|
+

|
46
|
+
|
47
|
+
### Quick payments bypassing checkout 1st step (Apple Pay, Google Pay, Link)
|
48
|
+
|
49
|
+

|
50
|
+
|
51
|
+
### Various payment options on the payment step (cards, BNPL, Apple Pay, Google Pay, Link)
|
52
|
+
|
53
|
+

|
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
|
+

|
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,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,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)
|