Skip to content

Add plugin purchase refund system - #342

Merged
simonhamp merged 5 commits into
mainfrom
refund-plugin-purchases
Sep 30, 2026
Merged

simonhamp merged 5 commits into
mainfrom
refund-plugin-purchases

Conversation

@simonhamp

@simonhamp simonhamp commented Apr 9, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Adds a complete refund flow for plugin purchases from the Filament admin panel
  • Issues a full Stripe refund, revokes the license, and cancels/reverses the developer payout — all from a single button
  • Enforces a 14-day refund window; blocks refunds on comped, zero-price, or already-refunded licenses
  • Bundle purchases are refunded all-or-nothing (all sibling licenses sharing the same payment intent)
  • Refunded licenses are excluded from isActive(), the active() scope, and the sales_view

Changes

  • PayoutStatus enum: Added Cancelled case
  • PluginPayout model: Added markAsCancelled(), isCancelled(), cancelled() scope
  • PluginLicense model: Added isRefunded(), isRefundable(), refundedBy() relationship; updated isActive() and active() scope
  • StripeConnectService: Added refundPaymentIntent() and reverseTransfer() methods
  • RefundPluginPurchase action: Orchestrates Stripe refund → DB transaction (license revocation + payout cancellation/reversal)
  • Filament relation managers: Added "Refund" button (danger, with confirmation modal) and "Refunded" column to both Plugin and User license tables
  • Migration: Adds refunded_at, stripe_refund_id, refunded_by to plugin_licenses; updates sales_view to exclude refunded rows
  • Factories: New PluginPayoutFactory with transferred()/cancelled() states; added refunded() state to PluginLicenseFactory

Test plan

  • 11 feature tests covering all paths (tests/Feature/PluginPurchaseRefundTest.php)
  • Manual: Navigate to Plugin → Licenses tab, verify Refund button appears for eligible licenses
  • Manual: Navigate to User → Plugins tab, verify Refund button appears and is hidden for ineligible licenses
  • Manual: Confirm refund modal shows correct amount, user email, and bundle warning when applicable
  • Run full test suite to verify no regressions

🤖 Generated with Claude Code

simonhamp and others added 5 commits April 10, 2026 00:26
Adds ability for admins to refund plugin purchases from Filament,
including Stripe refund, license revocation, and payout cancellation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolves conflicts in PluginPayoutFactory (kept main's states and
added cancelled) and package-lock.json (took main's).

Main added a Held payout status that gets promoted to Pending, and a
manual retry for Failed payouts. The refund only cancelled Pending
payouts, so a refunded purchase could still pay out later. It now
cancels any payout that isn't already cancelled, and still reverses
ones that were transferred.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Admin license tables, Third-Party Sales and Payouts now show who
refunded a sale, when, and the Stripe refund ID. Third-Party Sales
gets the Refund button and a Refunded filter too. The refund action
is now one shared Filament action.

Buyers no longer see refunded plugins under Purchased Plugins; they
show as refunded in Purchase History instead. Both pages fit on
mobile without scrolling sideways.

On the developer dashboard, refunded payouts show as Refunded instead
of Failed, refunds don't count as sales, pending payouts say when
they should reach the seller's Stripe account, and the plugin and
payout lists use the same table style as the rest of the dashboard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The lockfile got regenerated with a local npm while resolving merge
conflicts, which dropped @docsearch/css. CI installs from the lockfile,
so the asset build failed before any tests ran. This branch doesn't
touch JS dependencies, so it now uses main's lockfile as-is.

Also adds a test that a refunded buyer loses access and gets it back
by buying the plugin again through the normal checkout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@simonhamp
simonhamp marked this pull request as ready for review September 30, 2026 18:51
@simonhamp
simonhamp merged commit a54e056 into main Sep 30, 2026
3 checks passed
@simonhamp
simonhamp deleted the refund-plugin-purchases branch September 30, 2026 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant