spree_stripe 6.0.0.rc7 → 6.0.1

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: c0279ebe2cc2465e37abc70e3cab226d335c5394ab5808a1631c65e00959701d
4
- data.tar.gz: d71a287ac7a341db12b081b8512423545596655902bc7b4d6c4453dee59a5118
3
+ metadata.gz: 2e4ab3057fd40a41a397c25f79a996f56f09e2bc3c365f697b9b978ee55360b0
4
+ data.tar.gz: 3d6a18103e35891b4fd9bb7df0e2ad464483423c8ee03cbf45cc3d852d7fdfb4
5
5
  SHA512:
6
- metadata.gz: cd526139a29420c0992cc50163dc88dd85a2d20580f3f556afba79c5e2c9d064ed99c90ff8be2146aa03f430276a0ebe789114f196e25a8d9993fb25b8820e7a
7
- data.tar.gz: b37586cb450149226ea9cc413a14b19415b59e3b3616810e830815c8e28c32f7f240219e8b274ac046b19c5e8ca5e5deb6163b3814ebbfe55895c3f041999c8d
6
+ metadata.gz: 754a65d474d2840b3dc2e13e7ebccfdeb7ba62ae06e0c1ff7e62fb51eeb636201e83bfa073ce3b081c414d1916d257b5bd80d74a462338d11438b86fe9443b2f
7
+ data.tar.gz: a537698ea61e260e217f7d6b891a6d96132964d776bb558c9f2bf294d85027c41f41e7113558dd19a39edf486e3cc0a802970048d6b8745e74f7220a59e5771f
@@ -0,0 +1,13 @@
1
+ module SpreeStripe
2
+ module MaintenanceTasks
3
+ # Moves Stripe webhook signing secrets onto the gateway that uses them.
4
+ #
5
+ # Ships with this gem rather than core, which is what makes the manifest
6
+ # step optional: an installation without spree_stripe has neither the rake
7
+ # task nor this class, and the upgrade walk skips the step rather than
8
+ # failing on it.
9
+ class MigrateWebhookKeys < Spree::MaintenanceTasks::Upgrade::RakeStep
10
+ runs_rake_task 'spree:upgrade:migrate_stripe_webhook_keys'
11
+ end
12
+ end
13
+ end
@@ -266,15 +266,58 @@ module SpreeStripe
266
266
  raise Spree::Core::AmbiguousGatewayError, e.message
267
267
  end
268
268
 
269
- # Pulls a seller's money back after a refund.
269
+ # Pulls a seller's share of a refund back from their connected account.
270
270
  #
271
- # Ledger-only in open source: the row is written either way, so the books
272
- # stay correct, but reversing the Stripe transfer — and netting a negative
273
- # balance against future earnings — is where a marketplace needs the money
274
- # operations that Enterprise provides.
271
+ # Reverses the transfer that paid the earning, by the reversal's amount,
272
+ # so the money returns to the platform that refunded the customer. A
273
+ # seller who has already been paid out is left with a negative Stripe
274
+ # balance, which their next earnings make up before anything more is paid
275
+ # out to them.
276
+ #
277
+ # The reversal waits until its earning has reached Stripe: until then
278
+ # there is no transfer to take from. It is left pending, and the
279
+ # pending-transfers job asks again once the earning is sent.
280
+ #
281
+ # A retry first looks for a reversal an earlier attempt already made, so
282
+ # the seller is never charged twice for one refund.
275
283
  def reverse!(seller_transfer)
276
- seller_transfer.update!(status: 'completed')
284
+ return complete_without_sending(seller_transfer) if minor_units(seller_transfer).zero?
285
+
286
+ earning = seller_transfer.reversed_from
287
+ raise Spree::Core::GatewayError, 'Reversal has no earning to take back from' if earning.nil?
288
+ # Never sent, so nothing reached the seller's account.
289
+ return complete_without_sending(seller_transfer) if earning.failed?
290
+ return seller_transfer unless earning.completed?
291
+
292
+ # Confirmed without a transfer to point at — settled by hand, say. Only
293
+ # a person can say where that money is.
294
+ if earning.reference.blank?
295
+ raise Spree::Core::AmbiguousGatewayError, 'The earning has no Stripe transfer to reverse'
296
+ end
297
+
298
+ api_options = gateway_for(seller_transfer.seller.store).api_options
299
+ reversal = made_reversal(earning, seller_transfer, api_options) || Stripe::Transfer.create_reversal(
300
+ earning.reference,
301
+ {
302
+ amount: minor_units(seller_transfer),
303
+ metadata: {
304
+ spree_seller_transfer_id: seller_transfer.id,
305
+ spree_order_number: seller_transfer.order.number
306
+ }
307
+ },
308
+ api_options.merge(idempotency_key: idempotency_key(seller_transfer))
309
+ )
310
+
311
+ # The earning may have been sent after this row was written, and only
312
+ # then learned the currency it settled in.
313
+ seller_transfer.update!(
314
+ { status: 'completed', reference: reversal.id }.merge(earning.reversal_settlement(seller_transfer.amount.abs))
315
+ )
277
316
  seller_transfer
317
+ rescue *AMBIGUOUS_ERRORS => e
318
+ # The reversal may have been made before the answer was lost, so core
319
+ # parks it rather than taking the money back twice.
320
+ raise Spree::Core::AmbiguousGatewayError, e.message
278
321
  end
279
322
 
280
323
  private
@@ -300,6 +343,21 @@ module SpreeStripe
300
343
  seller_transfer
301
344
  end
302
345
 
346
+ # The reversal an earlier attempt made but never recorded — the row failed
347
+ # to save, or the process stopped first. Found by the row it names, since
348
+ # the idempotency key that would also stop a second one lasts only a day.
349
+ #
350
+ # A failed lookup moved no money, so it is a refusal the retry job can
351
+ # repeat rather than an outcome nobody knows.
352
+ def made_reversal(earning, seller_transfer, api_options)
353
+ reversals = Stripe::Transfer.list_reversals(earning.reference, { limit: 100 }, api_options)
354
+ reversals.auto_paging_each.find do |reversal|
355
+ reversal.metadata['spree_seller_transfer_id'] == seller_transfer.id.to_s
356
+ end
357
+ rescue Stripe::StripeError => e
358
+ raise Spree::Core::GatewayError, e.message
359
+ end
360
+
303
361
  # Nil rather than raising: a checklist row asking why it is incomplete
304
362
  # must not take the page down because Stripe is unreachable.
305
363
  def retrieve_account(seller)
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: 6.0.0.rc7
4
+ version: 6.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vendo Connect Inc.
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2026-10-26 00:00:00.000000000 Z
12
+ date: 2026-10-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: spree_core
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - '='
19
19
  - !ruby/object:Gem::Version
20
- version: 6.0.0.rc7
20
+ version: 6.0.1
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - '='
26
26
  - !ruby/object:Gem::Version
27
- version: 6.0.0.rc7
27
+ version: 6.0.1
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: stripe
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -72,6 +72,7 @@ files:
72
72
  - Rakefile
73
73
  - app/jobs/spree_stripe/base_job.rb
74
74
  - app/jobs/spree_stripe/create_webhook_endpoint_job.rb
75
+ - app/maintenance_tasks/spree_stripe/maintenance_tasks/migrate_webhook_keys.rb
75
76
  - app/models/spree/payment_sessions/stripe.rb
76
77
  - app/models/spree/payment_setup_sessions/stripe.rb
77
78
  - app/models/spree_stripe/gateway.rb
@@ -111,9 +112,9 @@ licenses:
111
112
  - MIT
112
113
  metadata:
113
114
  bug_tracker_uri: https://github.com/spree/spree/issues
114
- changelog_uri: https://github.com/spree/spree/releases/tag/v6.0.0.rc7
115
+ changelog_uri: https://github.com/spree/spree/releases/tag/v6.0.1
115
116
  documentation_uri: https://docs.spreecommerce.org/
116
- source_code_uri: https://github.com/spree/spree/tree/v6.0.0.rc7
117
+ source_code_uri: https://github.com/spree/spree/tree/v6.0.1
117
118
  post_install_message:
118
119
  rdoc_options: []
119
120
  require_paths: