spree_stripe 1.3.0 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f99142efe129494bc6d2bd1690e85dfae817eb652833217b24d14055811d778
4
- data.tar.gz: 9916be21b249554ec30e9b46e014634626a2763d1881d8808b14eb87079bc228
3
+ metadata.gz: ed3fcc600ad3010c438e0fd42e964612f151d1bfacf1fab96bc781ca2e5d2fe2
4
+ data.tar.gz: c57032392b824d12f83aa4b63bc452cfdd88d22da8a88452426d150cddb226a4
5
5
  SHA512:
6
- metadata.gz: 5791e797836bf0b150915a01b61649ca3da6e5b4f758ec446842d1503919c59f4aaabc09767651e50e5d7c4deaa9bdda3bdb491529bbed20226331cca7fb15bf
7
- data.tar.gz: 9ec61e460685afd67d0f19aaba2af8d5a33716397e9f56d9939b4b24020cd569a7d11322e7489345bd0be8b1250d777bc69bead40e944de120db58177ea6cec2
6
+ metadata.gz: f39b40bd6e0ceceb9f152fe4f2f7a2337368bd41bb823bbd1a403a2d126bc2b5c4446e82cd288758f93c422c8360cab41fb6f92bfeeb73ac5eb4ca0dc2ff4c5d
7
+ data.tar.gz: 8464c1cbbc5d25fb74390cd500f1ec8a7dddf2615d2281407ae8fe3ab361b5738e11aa1223d2c9c75a76a991122eba0f248f5152706b645aad44ee3acf985686
data/README.md CHANGED
@@ -140,7 +140,7 @@ We’re thrilled to unveil [Spree 5](https://spreecommerce.org/announcing-spree-
140
140
  - New integrations: a native [Stripe integration](https://github.com/spree/spree_stripe), and also Stripe Connect, Klaviyo integrations available with the Enterprise Edition
141
141
  - Enterprise Edition Admin Features: Audit Log, [Multi-Vendor Marketplace](https://spreecommerce.org/marketplace-ecommerce/), [Multi-tenant / White-label SaaS eCommerce](https://spreecommerce.org/multi-tenant-white-label-ecommerce/)
142
142
 
143
- Read the [full Spree 5 announcement here](https://spreecommerce.org/announcing-spree-5-the-biggest-open-source-release-ever/).
143
+ Read the [full Spree 5 announcement here](https://spreecommerce.org/announcing-spree-5-the-biggest-open-source-release-ever/) and the [changelog of Spree 5](https://github.com/spree/spree/releases) followup improvements.
144
144
 
145
145
  Check out the [Spree 5 demo](https://demo.spreecommerce.org/) for yourself, including this Stripe integration.
146
146
 
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
2
+ <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18.75a60.07 60.07 0 0 1 15.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 0 1 3 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 0 0-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 0 1-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 0 0 3 15h-.75M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm3 0h.008v.008H18V10.5Zm-12 0h.008v.008H6V10.5Z" />
3
+ </svg>
@@ -0,0 +1,22 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" id="katman_1" x="0px" y="0px" style="enable-background:new 0 0 1190.55 841.89;" xml:space="preserve" viewBox="238.65 160 712.7 521">
2
+ <style type="text/css">
3
+ .st0{fill:#26367D;}
4
+ .st1{clip-path:url(#SVGID_00000165933728503162618370000013584018841918814628_);}
5
+ .st2{fill:#FFFFFF;}
6
+ .st3{fill:#FBBA2C;}
7
+ </style>
8
+ <path class="st0" d="M302,160h586c34.99,0,63.35,28.36,63.35,63.35v394.3c0,34.99-28.36,63.35-63.35,63.35H302 c-34.99,0-63.35-28.36-63.35-63.35v-394.3C238.65,188.36,267.01,160,302,160z"/>
9
+ <g>
10
+ <defs>
11
+ <rect id="SVGID_1_" x="341.04" y="162.96" width="507.9" height="506.81"/>
12
+ </defs>
13
+ <clipPath id="SVGID_00000137126528663880082090000017192719521453020821_">
14
+ <use xlink:href="#SVGID_1_" style="overflow:visible;"/>
15
+ </clipPath>
16
+ <g style="clip-path:url(#SVGID_00000137126528663880082090000017192719521453020821_);">
17
+ <path class="st0" d="M367.09,226.31h455.81c14.38,0,26.04,13.62,26.04,30.41v319.29c0,16.79-11.66,30.41-26.04,30.41H367.09 c-14.38,0-26.05-13.62-26.05-30.41V256.72C341.04,239.93,352.71,226.31,367.09,226.31z"/>
18
+ <path class="st2" d="M404.53,381.92c0,3.22,0,5.34,1.06,8.55c0,1.09,1.05,2.12,1.05,3.22c2.06,13.91,8.3,20.27,21.76,21.38 c9.3,1.08,19.64,2.12,29,3.22c5.18,0,8.3,3.22,8.3,9.58c0,6.38-2.06,10.69-8.3,10.69h-18.64c-6.24,0-8.3-3.22-9.3-12.81h-24.82 v9.66c0,1.08,1.06,3.22,1.06,4.24c1.05,9.6,7.24,16.03,16.58,18.15c6.22,1.09,12.4,1.09,18.64,2.12h18.64 c6.24-1.09,11.4-2.12,17.58-4.24c7.24-2.12,12.42-7.48,13.46-16.03c1.06-7.48,1.06-16.03,1.06-23.5 c-1.05-8.55-5.16-14.94-13.46-17.1l-18.64-3.23c-6.22-1.09-12.42-1.09-18.64-1.09c-7.24,0-9.3-3.22-9.3-9.58 c0-7.48,3.12-9.6,9.3-10.69h10.34c9.3,0,11.4,1.11,12.42,10.69v1.09h24.82v-6.43c0-13.91-6.22-22.47-20.7-24.6 c-14.46-2.12-28.98-2.12-43.46,1.09c-11.4,2.12-16.58,7.48-18.64,20.27C405.55,378.69,404.53,379.8,404.53,381.92z M631.19,458.83 v-27.8h35.18c13.46,0,22.76-8.55,24.82-21.38c1.06-8.55,2.06-17.1,1.06-25.61c-1.06-19.24-10.34-28.82-28.98-29.93 c-17.58-1.09-35.18-1.09-52.82-1.09c-4.12,0-5.18,1.11-5.18,5.35v101.5C613.61,459.92,622.91,459.92,631.19,458.83z M631.19,407.53V377.6c0,0,2.06-2.12,3.12-2.12h18.64c7.24,1.11,10.36,4.32,10.36,11.78v10.69c0,6.43-2.06,9.58-8.3,9.58H631.19z M708.83,459.92c1.06-5.34,2.06-11.77,4.18-17.1c0-1.11,2.06-2.14,3.12-2.14h33.1c1.06,0,2.06,2.12,3.12,3.22 c2.06,5.35,3.12,10.69,5.18,16.03h27.94c-1.06-2.12-2.06-5.34-3.12-7.46l-27.94-96.23c0-1.09-2.06-3.22-3.12-3.22h-39.34 c-4.18,12.88-7.24,25.67-11.4,38.49c-6.24,22.41-13.46,45.9-19.64,68.37C680.9,459.87,708.83,459.92,708.83,459.92z M747.12,421.43h-26.94c4.12-15,8.3-31.01,12.42-45.96h1.05c4.18,15,9.34,29.93,13.46,45.96H747.12z"/>
19
+ <path class="st3" d="M575.35,441.71c-16.6,0-29-7.46-34.18-19.24h37.28l4.12-11.77h-45.58v-8.55l46.59,2.12l5.16-13.86h-49.68 c5.16-14.94,18.64-22.46,36.22-22.46c7.44-0.05,14.81,1.44,21.76,4.26l4.12-14.94c-4.12-2.14-13.46-4.26-26.92-4.26 c-27.95,0-49.71,13.91-56.94,38.49h-12.35l-5.18,11.78h15.52v9.53h-9.3l-6.22,11.78h17.58c6.24,21.37,25.88,34.18,53.82,34.18 c13.46,0,23.82-2.12,27.94-4.26l-3.12-14.94C591.93,440.69,583.63,441.71,575.35,441.71z"/>
20
+ </g>
21
+ </g>
22
+ </svg>
@@ -56,7 +56,7 @@ module Spree
56
56
  render_error_payload(Spree.t('order_already_completed'))
57
57
  elsif order != spree_current_order
58
58
  raise ActiveRecord::RecordNotFound
59
- elsif stripe_payment_intent.status == 'succeeded'
59
+ elsif @payment_intent.accepted?
60
60
  spree_authorize! :update, spree_current_order, order_token
61
61
 
62
62
  SpreeStripe::CompleteOrder.new(payment_intent: @payment_intent).call
@@ -26,7 +26,7 @@ module SpreeStripe
26
26
  elsif @order.completed?
27
27
  redirect_to spree.checkout_complete_path(@order.token), status: :see_other
28
28
  # if the payment intent is successful, we need to process the payment and complete the order
29
- elsif @stripe_payment_intent.status == 'succeeded'
29
+ elsif @payment_intent_record.accepted?
30
30
  @order = SpreeStripe::CompleteOrder.new(payment_intent: @payment_intent_record).call
31
31
 
32
32
  # set the session flag to indicate that the order was placed now
@@ -2,6 +2,9 @@ module SpreeStripe
2
2
  class Gateway < ::Spree::Gateway
3
3
  include SpreeStripe::Gateway::Tax if defined?(SpreeStripe::Gateway::Tax)
4
4
 
5
+ DELAYED_NOTIFICATION_PAYMENT_METHOD_TYPES = %w[sepa_debit us_bank_account].freeze
6
+ BANK_PAYMENT_METHOD_TYPES = %w[customer_balance us_bank_account].freeze
7
+
5
8
  preference :publishable_key, :password
6
9
  preference :secret_key, :password
7
10
 
@@ -23,6 +26,28 @@ module SpreeStripe
23
26
  self.class
24
27
  end
25
28
 
29
+ def payment_intent_accepted?(payment_intent)
30
+ payment_intent.status.in?(payment_intent_accepted_statuses(payment_intent))
31
+ end
32
+
33
+ def payment_intent_delayed_notification?(payment_intent)
34
+ payment_method = payment_intent.payment_method
35
+ return false unless payment_method.respond_to?(:type)
36
+
37
+ payment_intent.payment_method.type.in?(DELAYED_NOTIFICATION_PAYMENT_METHOD_TYPES)
38
+ end
39
+
40
+ def payment_intent_charge_not_required?(payment_intent)
41
+ payment_intent_bank_payment_method?(payment_intent)
42
+ end
43
+
44
+ def payment_intent_bank_payment_method?(payment_intent)
45
+ payment_method = payment_intent.payment_method
46
+ return false unless payment_method.respond_to?(:type)
47
+
48
+ payment_intent.payment_method.type.in?(BANK_PAYMENT_METHOD_TYPES)
49
+ end
50
+
26
51
  # @param amount_in_cents [Integer] the amount in cents to capture
27
52
  # @param payment_source [Spree::CreditCard | Spree::PaymentSource]
28
53
  # @param gateway_options [Hash] this is an instance of Spree::Payment::GatewayOptions.to_hash
@@ -52,7 +77,7 @@ module SpreeStripe
52
77
  payment = ensure_payment_intent_exists_for_payment(payment, amount_in_cents, payment_source)
53
78
  stripe_payment_intent = retrieve_payment_intent(payment.response_code)
54
79
 
55
- response = if stripe_payment_intent.status == 'succeeded'
80
+ response = if payment_intent_accepted?(stripe_payment_intent)
56
81
  # payment intent is already confirmed via Stripe JS SDK
57
82
  stripe_payment_intent
58
83
  else
@@ -92,8 +117,13 @@ module SpreeStripe
92
117
  end
93
118
  end
94
119
 
95
- def void(response_code, source, gateway_options)
96
- raise NotImplementedError
120
+ def void(response_code, _source, _gateway_options)
121
+ return failure('Response code is blank') if response_code.blank?
122
+
123
+ protect_from_error do
124
+ response = cancel_payment_intent(response_code)
125
+ success(response.id, response)
126
+ end
97
127
  end
98
128
 
99
129
  def cancel(payment_intent_id, payment = nil)
@@ -205,7 +235,7 @@ module SpreeStripe
205
235
  end
206
236
 
207
237
  def retrieve_payment_intent(payment_intent_id)
208
- send_request { Stripe::PaymentIntent.retrieve(payment_intent_id) }
238
+ send_request { Stripe::PaymentIntent.retrieve({ id: payment_intent_id, expand: ['payment_method'] }) }
209
239
  end
210
240
 
211
241
  def confirm_payment_intent(payment_intent_id)
@@ -419,5 +449,12 @@ module SpreeStripe
419
449
 
420
450
  SpreeStripe::CustomerPresenter.new(name: name, email: email, address: address).call
421
451
  end
452
+
453
+ def payment_intent_accepted_statuses(payment_intent)
454
+ statuses = %w[succeeded]
455
+ statuses << 'processing' if payment_intent_delayed_notification?(payment_intent)
456
+ statuses << 'requires_action' if payment_intent_charge_not_required?(payment_intent)
457
+ statuses
458
+ end
422
459
  end
423
460
  end
@@ -14,13 +14,13 @@ module SpreeStripe
14
14
  'pass' => 'P',
15
15
  'unchecked' => 'I'
16
16
  }
17
- }.freeze
17
+ }.freeze unless defined?(AVS_CODES)
18
18
 
19
19
  CVV_CODES = {
20
20
  'pass' => 'M',
21
21
  'fail' => 'N',
22
22
  'unchecked' => 'P'
23
- }.freeze
23
+ }.freeze unless defined?(CVV_CODES)
24
24
 
25
25
  def self.prepended(base)
26
26
  base.store_accessor :private_metadata, :stripe_charge_id
@@ -26,12 +26,27 @@ module SpreeStripe
26
26
  delegate :api_options, to: :payment_method
27
27
  delegate :store, :currency, to: :order
28
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
+
29
41
  def stripe_payment_intent
30
42
  @stripe_payment_intent ||= payment_method.retrieve_payment_intent(stripe_id)
31
43
  end
32
44
 
33
45
  def stripe_charge
34
- @stripe_charge ||= payment_method.retrieve_charge(stripe_payment_intent.latest_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
35
50
  end
36
51
 
37
52
  # here we create a payment if it doesn't exist
@@ -1,6 +1,6 @@
1
1
  module SpreeStripe
2
2
  module PaymentMethodDecorator
3
- STRIPE_TYPE = 'SpreeStripe::Gateway'.freeze
3
+ STRIPE_TYPE = 'SpreeStripe::Gateway'.freeze unless defined?(STRIPE_TYPE)
4
4
 
5
5
  def self.prepended(base)
6
6
  base.has_many :payment_methods_webhook_keys, class_name: 'SpreeStripe::PaymentMethodsWebhookKey'
@@ -0,0 +1,17 @@
1
+ module SpreeStripe
2
+ module PaymentSources
3
+ class BankTransfer < ::Spree::PaymentSource
4
+ def actions
5
+ %w[credit]
6
+ end
7
+
8
+ def self.display_name
9
+ Spree.t(:bank_transfer)
10
+ end
11
+
12
+ def name
13
+ Spree.t(:bank_transfer)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -8,6 +8,10 @@ module SpreeStripe
8
8
  def self.display_name
9
9
  'SEPA Debit'
10
10
  end
11
+
12
+ def name
13
+ 'SEPA Debit'
14
+ end
11
15
  end
12
16
  end
13
17
  end
@@ -76,6 +76,9 @@ module SpreeStripe
76
76
  payment_method_options: {
77
77
  card: {
78
78
  setup_future_usage: SETUP_FUTURE_USAGE
79
+ },
80
+ sepa_debit: {
81
+ setup_future_usage: SETUP_FUTURE_USAGE
79
82
  }
80
83
  }
81
84
  }
@@ -9,7 +9,7 @@ module SpreeStripe
9
9
  def call
10
10
  order = payment_intent.order
11
11
 
12
- return order if order.completed? || order.canceled?
12
+ return order if (order.completed? && order.paid?) || order.canceled?
13
13
 
14
14
  charge = payment_intent.stripe_charge
15
15
 
@@ -21,10 +21,14 @@ module SpreeStripe
21
21
  payment = payment_intent.find_or_create_payment!
22
22
 
23
23
  # process the payment
24
- payment.process!
24
+ if payment_intent.successful?
25
+ payment.process!
26
+ else
27
+ payment.authorize!
28
+ end
25
29
 
26
30
  # complete the order
27
- Spree::Dependencies.checkout_complete_service.constantize.call(order: order)
31
+ Spree::Dependencies.checkout_complete_service.constantize.call(order: order) unless order.completed?
28
32
  end
29
33
 
30
34
  order.reload
@@ -34,6 +38,8 @@ module SpreeStripe
34
38
 
35
39
  # we need to perform this for quick checkout orders which do not have these fields filled
36
40
  def add_customer_information(order, charge)
41
+ return order if charge.blank?
42
+
37
43
  billing_details = charge.billing_details
38
44
  address = billing_details.address
39
45
 
@@ -19,6 +19,15 @@ module SpreeStripe
19
19
  stripe_billing_details: stripe_charge.billing_details,
20
20
  gateway: gateway
21
21
  ).call
22
+ elsif payment_intent.charge_not_required?
23
+ stripe_payment_intent = payment_intent.stripe_payment_intent
24
+ source = SpreeStripe::CreateSource.new(
25
+ order: order,
26
+ stripe_payment_method_details: stripe_payment_intent.payment_method,
27
+ stripe_payment_method_id: stripe_payment_intent.payment_method.id,
28
+ stripe_billing_details: nil,
29
+ gateway: gateway
30
+ ).call
22
31
  end
23
32
 
24
33
  # sometimes a job is re-tried and creates a double payment record so we need to avoid it!
@@ -34,6 +34,8 @@ module SpreeStripe
34
34
  SpreeStripe::PaymentSources::Link.create!(source_params)
35
35
  when 'affirm'
36
36
  SpreeStripe::PaymentSources::Affirm.create!(source_params)
37
+ when 'customer_balance', 'us_bank_account'
38
+ SpreeStripe::PaymentSources::BankTransfer.create!(source_params)
37
39
  else
38
40
  raise "[STRIPE] Unknown payment method #{stripe_payment_method_details.type}"
39
41
  end
@@ -2,16 +2,13 @@ module SpreeStripe
2
2
  module WebhookHandlers
3
3
  class PaymentIntentPaymentFailed
4
4
  def call(event)
5
- return unless ['affirm', 'afterpay_clearpay'].include?(event.data.object&.last_payment_error&.payment_method&.type)
6
-
7
5
  payment_intent = SpreeStripe::PaymentIntent.find_by(stripe_id: event.data.object.id)
8
6
  return if payment_intent.nil?
9
7
 
10
8
  order = payment_intent.order
11
-
12
9
  return if order.canceled?
13
10
 
14
- order.cancel!
11
+ order.cancel! if order.can_cancel?
15
12
  end
16
13
  end
17
14
  end
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  en:
3
3
  spree:
4
+ bank_transfer: Bank Transfer
4
5
  stripe:
5
6
  payment_intent_errors:
6
7
  canceled: Payment intent canceled
@@ -1,5 +1,5 @@
1
1
  module SpreeStripe
2
- VERSION = '1.3.0'.freeze
2
+ VERSION = '1.4.0'.freeze
3
3
 
4
4
  def gem_version
5
5
  Gem::Version.new(VERSION)
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_stripe
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vendo Connect Inc.
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-11-06 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: spree
@@ -178,7 +177,6 @@ dependencies:
178
177
  - - ">="
179
178
  - !ruby/object:Gem::Version
180
179
  version: '0'
181
- description:
182
180
  email: hello@spreecommerce.org
183
181
  executables: []
184
182
  extensions: []
@@ -188,7 +186,9 @@ files:
188
186
  - README.md
189
187
  - Rakefile
190
188
  - app/assets/config/spree_stripe_manifest.js
189
+ - app/assets/images/payment_icons/banktransfer.svg
191
190
  - app/assets/images/payment_icons/link.svg
191
+ - app/assets/images/payment_icons/sepadebit.svg
192
192
  - app/controllers/spree/api/v2/storefront/stripe/base_controller.rb
193
193
  - app/controllers/spree/api/v2/storefront/stripe/payment_intents_controller.rb
194
194
  - app/controllers/spree/api/v2/storefront/stripe/setup_intents_controller.rb
@@ -222,6 +222,7 @@ files:
222
222
  - app/models/spree_stripe/payment_sources/affirm.rb
223
223
  - app/models/spree_stripe/payment_sources/after_pay.rb
224
224
  - app/models/spree_stripe/payment_sources/alipay.rb
225
+ - app/models/spree_stripe/payment_sources/bank_transfer.rb
225
226
  - app/models/spree_stripe/payment_sources/ideal.rb
226
227
  - app/models/spree_stripe/payment_sources/klarna.rb
227
228
  - app/models/spree_stripe/payment_sources/link.rb
@@ -298,7 +299,6 @@ homepage: https://github.com/spree/spree_stripe
298
299
  licenses:
299
300
  - AGPL-3.0-or-later
300
301
  metadata: {}
301
- post_install_message:
302
302
  rdoc_options: []
303
303
  require_paths:
304
304
  - lib
@@ -314,8 +314,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
314
314
  version: '0'
315
315
  requirements:
316
316
  - none
317
- rubygems_version: 3.5.3
318
- signing_key:
317
+ rubygems_version: 4.0.2
319
318
  specification_version: 4
320
319
  summary: Official Spree Commerce Stripe payment gateway extension
321
320
  test_files: []