spree_stripe 1.2.5 → 1.2.6

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: e37d17d73e754ef2f8526777041be558487592f42818dbe3a554dc663fb0eb97
4
- data.tar.gz: c139162cc9fece31518aad3c5ac849de9c392648ee005693f3aa131ea4a98963
3
+ metadata.gz: aba1375f50b74ab3e4fa3887f9b40c314f56f3e96898e21a02ab43efddc2dd07
4
+ data.tar.gz: a812910d9968f97b3f4ba54fa4026e5ca824e13b8ed4e86bc4a11377904e0285
5
5
  SHA512:
6
- metadata.gz: 857e2aecfe5e8860da213246d1098819eca5ab56060c4d91bebe1ac49af3b6207a279d1f86239f263488d8c878ef94a76dafa1a3b4cab0a8279e30b8bb2b49c8
7
- data.tar.gz: d2770b0f50b05d0e8f91b52fbc79c321108464c791ca356248d5361913f54c160fb6cf4ea08170c3055a56d2843c2abcabf3ddcac22916e5426a3b10761c5867
6
+ metadata.gz: 265ada6aa1bbbc80df01e8bdf347e1d9f24e6cec65e71c1480946dcfa0c9682df1d691c0fb80959807c5164027a0fec6e58dfa700d8dc5eeb5e1511327e67693
7
+ data.tar.gz: ef1a978a396ad0b67758811b48cd475c6ffbfdedb6b5292e138c89439711030c164dccd48f0c377094e5cac92c9376ee40888afc00932e74de4bf4b849cfe4b9
@@ -1,5 +1,9 @@
1
1
  module StripeEvent
2
2
  module WebhookControllerDecorator
3
+ def self.prepended(base)
4
+ base.include Spree::Core::ControllerHelpers::Store
5
+ end
6
+
3
7
  def secrets(payload, signature)
4
8
  all_signing_keys = SpreeStripe::WebhookKey.pluck(:signing_secret).uniq.compact
5
9
  all_signing_keys << ENV['STRIPE_SIGNING_SECRET'] if ENV['STRIPE_SIGNING_SECRET'].present?
@@ -222,6 +222,8 @@ export default class extends Controller {
222
222
  if (response.ok) {
223
223
  return responseJson.included.find(item => item.type === 'address').attributes;
224
224
  } else {
225
+ const errors = Array.isArray(responseJson.error) ? responseJson.error.join('. ') : responseJson.error || 'Billing address is invalid';
226
+ showFlashMessage(errors, 'error');
225
227
  this.submitTarget.disabled = false;
226
228
  return false;
227
229
  }
@@ -261,11 +263,6 @@ export default class extends Controller {
261
263
  const errors = Array.isArray(responseJson.error) ? responseJson.error.join('. ') : responseJson.error || 'Billing address is invalid';
262
264
  showFlashMessage(errors, 'error');
263
265
 
264
- const flashMessage = document.getElementsByClassName('flash-message')[0];
265
- if (flashMessage) {
266
- flashMessage.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'nearest' });
267
- }
268
-
269
266
  this.submitTarget.disabled = false;
270
267
  return false;
271
268
  }
@@ -0,0 +1,10 @@
1
+ module SpreeStripe
2
+ class UpdateCustomerJob < BaseJob
3
+ def perform(user_id)
4
+ return unless Spree.user_class.present?
5
+
6
+ user = Spree.user_class.find(user_id)
7
+ SpreeStripe::UpdateCustomer.new.call(user: user)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ module SpreeStripe
2
+ module AddressDecorator
3
+ def self.prepended(base)
4
+ base.after_update :update_stripe_customer, if: :should_update_stripe_customer?
5
+ end
6
+
7
+ delegate :update_stripe_customer, to: :user, allow_nil: true
8
+
9
+ private
10
+
11
+ def should_update_stripe_customer?
12
+ user_default_billing? && previous_changes.any?
13
+ end
14
+ end
15
+ end
16
+
17
+ if ActiveRecord::Base.connection.database_exists? && ActiveRecord::Base.connection.table_exists?('spree_addresses')
18
+ Spree::Address.prepend(SpreeStripe::AddressDecorator)
19
+ end
@@ -15,8 +15,8 @@ module SpreeStripe
15
15
 
16
16
  has_many :payment_intents, class_name: 'SpreeStripe::PaymentIntent', foreign_key: 'payment_method_id', dependent: :delete_all
17
17
 
18
- def self.webhook_url
19
- "https://#{Rails.application.routes.default_url_options[:host]}/stripe"
18
+ def webhook_url
19
+ StripeEvent::Engine.routes.url_helpers.root_url(host: stores.first.url, protocol: 'https')
20
20
  end
21
21
 
22
22
  def provider_class
@@ -128,18 +128,13 @@ module SpreeStripe
128
128
  gateway_customers.find_by(user: user) || create_customer(order: order, user: user)
129
129
  end
130
130
 
131
+ # Creates a Stripe customer based on the order or user
132
+ #
133
+ # @param order [Spree::Order] the order to use for creating the Stripe customer
134
+ # @param user [Spree::User] the user to use for creating the Stripe customer
135
+ # @return [Stripe::Customer] the created Stripe customer
131
136
  def create_customer(order: nil, user: nil)
132
- user ||= order&.user
133
- address = order&.bill_address || user&.bill_address
134
- name = order&.name || user&.name
135
- email = order&.email || user&.email
136
-
137
- payload = SpreeStripe::CustomerPresenter.new(
138
- name: name,
139
- email: email,
140
- address: address
141
- ).call
142
-
137
+ payload = build_customer_payload(order: order, user: user)
143
138
  response = send_request { Stripe::Customer.create(payload) }
144
139
 
145
140
  customer = gateway_customers.build(user: user, profile_id: response.id)
@@ -147,6 +142,22 @@ module SpreeStripe
147
142
  customer
148
143
  end
149
144
 
145
+ # Updates a Stripe customer based on the order or user
146
+ #
147
+ # @param order [Spree::Order] the order to use for updating the Stripe customer
148
+ # @param user [Spree::User] the user to use for updating the Stripe customer
149
+ # @return [Stripe::Customer] the updated Stripe customer
150
+ def update_customer(order: nil, user: nil)
151
+ user ||= order&.user
152
+ return if user.blank?
153
+
154
+ customer = gateway_customers.find_by(user: user)
155
+ return if customer.blank?
156
+
157
+ payload = build_customer_payload(order: order, user: user)
158
+ send_request { Stripe::Customer.update(customer.profile_id, payload) }
159
+ end
160
+
150
161
  # Creates a Stripe payment intent for the order
151
162
  #
152
163
  # @param amount_in_cents [Integer] the amount in cents
@@ -362,5 +373,14 @@ module SpreeStripe
362
373
  end
363
374
  end
364
375
  end
376
+
377
+ def build_customer_payload(order: nil, user: nil)
378
+ user ||= order&.user
379
+ address = order&.bill_address || user&.bill_address
380
+ name = order&.name || user&.name
381
+ email = order&.email || user&.email
382
+
383
+ SpreeStripe::CustomerPresenter.new(name: name, email: email, address: address).call
384
+ end
365
385
  end
366
386
  end
@@ -0,0 +1,9 @@
1
+ module SpreeStripe
2
+ module GatewayCustomerDecorator
3
+ def self.prepended(base)
4
+ base.scope :stripe, -> { joins(:payment_method).where("#{Spree::PaymentMethod.table_name}.type" => SpreeStripe::Gateway.to_s) }
5
+ end
6
+ end
7
+ end
8
+
9
+ Spree::GatewayCustomer.prepend(SpreeStripe::GatewayCustomerDecorator)
@@ -12,6 +12,17 @@ module SpreeStripe
12
12
  payment_intent.update!(amount: total_minus_store_credits)
13
13
  end
14
14
  end
15
+
16
+ def associate_user!(user, override_email = true)
17
+ super(user, override_email)
18
+
19
+ return if payment_intents.empty?
20
+
21
+ responses = payment_intents.map { |payment_intent| payment_intent.update_stripe_payment_intent }
22
+ customer_id = responses.find { |response| response.params['customer'].present? }&.params['customer']
23
+
24
+ payment_intents.update_all(customer_id: customer_id) if customer_id.present?
25
+ end
15
26
  end
16
27
  end
17
28
 
@@ -0,0 +1,21 @@
1
+ module SpreeStripe
2
+ module UserDecorator
3
+ def self.prepended(base)
4
+ base.after_update :update_stripe_customer, if: :should_update_stripe_customer?
5
+ end
6
+
7
+ def update_stripe_customer
8
+ SpreeStripe::UpdateCustomerJob.perform_later(id)
9
+ end
10
+
11
+ private
12
+
13
+ def should_update_stripe_customer?
14
+ ship_address_previously_changed? || bill_address_previously_changed? ||
15
+ first_name_previously_changed? || last_name_previously_changed? ||
16
+ email_previously_changed?
17
+ end
18
+ end
19
+ end
20
+
21
+ Spree.user_class.prepend(SpreeStripe::UserDecorator) if Spree.user_class.present?
@@ -28,7 +28,7 @@ module SpreeStripe
28
28
  line2: address.address2,
29
29
  postal_code: address.zipcode,
30
30
  country: address.country_name,
31
- state: address.state_name
31
+ state: address.state_name_text
32
32
  }
33
33
  end
34
34
  end
@@ -2,15 +2,15 @@ module SpreeStripe
2
2
  class CreateGatewayWebhooks
3
3
  def call(payment_method:, events: SpreeStripe::Config[:supported_webhook_events], connect: false)
4
4
  webhook_list = Stripe::WebhookEndpoint.list({}, { api_key: payment_method.preferred_secret_key })
5
- webhook = find_webhook(webhook_list[:data], events)
5
+ webhook = find_webhook(payment_method, webhook_list[:data], events)
6
6
 
7
7
  ensure_webhook(payment_method, webhook, connect, events)
8
8
  end
9
9
 
10
10
  private
11
11
 
12
- def find_webhook(webhooks_data, enabled_events)
13
- webhook_url = SpreeStripe::Gateway.webhook_url
12
+ def find_webhook(payment_method, webhooks_data, enabled_events)
13
+ webhook_url = payment_method.webhook_url
14
14
 
15
15
  webhooks_data.find do |webhook|
16
16
  webhook[:url] == webhook_url && webhook[:enabled_events].sort == enabled_events.sort
@@ -32,7 +32,7 @@ module SpreeStripe
32
32
  end
33
33
 
34
34
  def create_webhook_endpoint(payment_method, connect, events)
35
- params = build_webhook_params(connect, events)
35
+ params = build_webhook_params(payment_method, connect, events)
36
36
  stripe_webhook = Stripe::WebhookEndpoint.create(params, { api_key: payment_method.preferred_secret_key })
37
37
 
38
38
  SpreeStripe::WebhookKey.create!(
@@ -44,9 +44,9 @@ module SpreeStripe
44
44
  Rails.cache.delete('stripe_webhook_signing_keys')
45
45
  end
46
46
 
47
- def build_webhook_params(connect, events)
47
+ def build_webhook_params(payment_method, connect, events)
48
48
  {
49
- url: SpreeStripe::Gateway.webhook_url,
49
+ url: payment_method.webhook_url,
50
50
  enabled_events: events,
51
51
  connect: connect
52
52
  }
@@ -0,0 +1,13 @@
1
+ module SpreeStripe
2
+ class UpdateCustomer
3
+ def call(user:)
4
+ gateway_customers = user.gateway_customers.stripe
5
+ return if gateway_customers.empty?
6
+
7
+ gateway_customers.each do |gateway_customer|
8
+ stripe_gateway = gateway_customer.payment_method
9
+ stripe_gateway.update_customer(user: user)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -27,7 +27,7 @@
27
27
  } do %>
28
28
  <div id="payment-request-button"></div>
29
29
 
30
- <div class="relative group-[.no-separator]:hidden flex py-5 items-center ">
30
+ <div class="relative group-[.no-separator]:hidden flex pt-5 items-center ">
31
31
  <div class="flex-grow border-t border-default"></div>
32
32
  <span class="flex-shrink mx-4 text-gray-500 text-sm">
33
33
  <%= Spree.t('storefront.checkout.or_continue_below') %>
@@ -1,5 +1,5 @@
1
1
  module SpreeStripe
2
- VERSION = '1.2.5'.freeze
2
+ VERSION = '1.2.6'.freeze
3
3
 
4
4
  def gem_version
5
5
  Gem::Version.new(VERSION)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_stripe
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vendo Connect Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-07-07 00:00:00.000000000 Z
11
+ date: 2025-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree
@@ -204,10 +204,13 @@ files:
204
204
  - app/jobs/spree_stripe/complete_order_job.rb
205
205
  - app/jobs/spree_stripe/create_webhook_endpoint_job.rb
206
206
  - app/jobs/spree_stripe/register_domain_job.rb
207
+ - app/jobs/spree_stripe/update_customer_job.rb
208
+ - app/models/spree_stripe/address_decorator.rb
207
209
  - app/models/spree_stripe/base.rb
208
210
  - app/models/spree_stripe/credit_card_decorator.rb
209
211
  - app/models/spree_stripe/custom_domain_decorator.rb
210
212
  - app/models/spree_stripe/gateway.rb
213
+ - app/models/spree_stripe/gateway_customer_decorator.rb
211
214
  - app/models/spree_stripe/order_decorator.rb
212
215
  - app/models/spree_stripe/payment_decorator.rb
213
216
  - app/models/spree_stripe/payment_intent.rb
@@ -223,6 +226,7 @@ files:
223
226
  - app/models/spree_stripe/payment_sources/przelewy24.rb
224
227
  - app/models/spree_stripe/payment_sources/sepa_debit.rb
225
228
  - app/models/spree_stripe/store_decorator.rb
229
+ - app/models/spree_stripe/user_decorator.rb
226
230
  - app/models/spree_stripe/webhook_key.rb
227
231
  - app/presenters/spree_stripe/customer_presenter.rb
228
232
  - app/presenters/spree_stripe/payment_intent_presenter.rb
@@ -251,6 +255,7 @@ files:
251
255
  - app/services/spree_stripe/create_setup_intent.rb
252
256
  - app/services/spree_stripe/create_source.rb
253
257
  - app/services/spree_stripe/register_domain.rb
258
+ - app/services/spree_stripe/update_customer.rb
254
259
  - app/services/spree_stripe/webhook_handlers/payment_intent_payment_failed.rb
255
260
  - app/services/spree_stripe/webhook_handlers/payment_intent_succeeded.rb
256
261
  - app/services/spree_stripe/webhook_handlers/setup_intent_succeeded.rb