Refund handling
Issue a refund through WooCommerce or FluentCart and Split Pay reverses the connected-account transfers that belong to that refund.
Automatic refund handling#
Transfers are reversed automatically. WooCommerce uses line-item and shipping details where the transfer record identifies that component. Amount-only refunds, FluentCart refunds, and WooCommerce global rows without a line association use the individual refund amount as a share of the order total.
Issue the refund from the same store platform that created the order:
- WooCommerce: create the refund on the WooCommerce order. Split Pay reads the refund’s line items, tax, shipping, and total.
- FluentCart: use FluentCart’s refund screen for the normal store-record workflow. Split Pay also listens to FluentCart’s Stripe refund webhook, so a refund created in Stripe can trigger the same reversal when FluentCart receives the event and maps it to the order. See FluentCart refund handling.
Before refunding an older order, keep it in the original charge’s Test/Live mode and platform account. Named gateway adapters read their current mode for the reversal; an unmatched universal adapter can use the only available platform key, whose prefix determines effective mode. Split Pay stops if it cannot verify the original transfer in the selected account.
You issue a refund — Navigate to the order in your store admin (WooCommerce → Orders or the FluentCart → Orders screen), open the order, click Refund, enter the amount, and confirm.
Split Pay builds the exact reversal plan — WooCommerce line-item refunds are matched to affected product-level legs, and refunded shipping is matched to shipping legs. Sequential global rows use their saved line contributions. Global or legacy rows without a line association use the refund-to-order ratio.
Split Pay uses the amount actually sent — Fee allocation, debt recovery, or a transfer ceiling can reduce a vendor’s payout. Refunds use the net amount recorded as sent, never the larger planned amount.
Each result is recorded — The order notes and durable reversal record show which transfer was reversed, recorded as debt, or left incomplete for recovery.
Full refund example#
A $150 order with two transfers:
| Transfer | Original Amount | Reversal Amount |
|---|---|---|
| Vendor A (acct_xxx) | $45.00 | $45.00 (100%) |
| Vendor B (acct_yyy) | $30.00 | $30.00 (100%) |
WooCommerce partial refund examples#
For a line-item refund, product-level transfer legs follow the refunded item. If Vendor A’s $90 item produced a $45 product-level transfer and Vendor B’s $60 item produced a $30 product-level transfer, refunding only Vendor A’s item reverses $45 from Vendor A and $0 from Vendor B. Shipping transfers are unchanged unless the refund includes shipping. A non-sequential global row without an item association uses the overall refund ratio instead.
For an amount-only refund with no item or shipping breakdown, Split Pay falls back to the refund-to-order ratio. A $37.50 refund on the same $150 order is 25%:
| Transfer | Original Amount | Reversal Amount |
|---|---|---|
| Vendor A (acct_xxx) | $45.00 | $11.25 (25%) |
| Vendor B (acct_yyy) | $30.00 | $7.50 (25%) |
Settlement currency and rounding#
Split Pay records what Stripe actually transferred in Stripe’s settlement currency. Reversals use that same currency and its minor units. This keeps cross-currency orders and zero-decimal currencies tied to the original transfer instead of converting the refund again.
Handling failed reversals#
A reversal can fail when the connected account lacks enough available balance or Split Pay cannot verify the exact transfer state:
- Each transfer leg has its own durable reversal record and order note.
- Other prepared legs continue processing; a proven successful reversal is not repeated.
- An unresolved leg remains incomplete and retryable through Split Pay’s automatic recovery path. Review the order notes before taking manual action.
If a vendor’s Stripe balance is insufficient and refund reclaim is off, let Split Pay’s automatic refund recovery finish and follow the order notes. Use a manual Stripe reversal only after an order note says manual review is required, or after you have reconciled and stopped any queued recovery for that reversal. Retry Split Pay Transfers retries failed payouts; it is not a manual refund-reversal control.
To recover future shortfalls automatically, turn on Reclaim shortfalls from future transfers.
Reclaim shortfalls from future transfers#
By default, a reversal rejected because the vendor’s balance is too low remains a failed reversal for you to resolve. With Reclaim refund shortfalls from a vendor’s future transfers enabled, Split Pay records the full unreversed amount as outstanding debt and deducts it from that vendor’s future transfers until the balance reaches zero.
This optional feature is off by default, and PRO is required to enable or change it. Once enabled, the saved ledger remains active if the PRO license later lapses so an existing recovery balance does not silently stop; renew PRO before changing the setting. Split Pay does not guess how much of a failed reversal might have been available or send a second partial reversal after Stripe rejects the full request.
Example
A vendor was paid $100. The customer is refunded in full, but Stripe rejects the $100 transfer reversal because the vendor’s available balance is too low.
| Step | What Split Pay does |
|---|---|
| Refund issued | Split Pay requests the full $100 reversal. |
| Stripe rejects it | No partial reversal is guessed or sent. |
| Debt recorded | Split Pay records $100 as outstanding debt for that vendor. |
| Vendor’s next transfer ($80 due) | Split Pay withholds $80; $20 remains outstanding. |
| Following transfer ($50 due) | Split Pay withholds $20, sends $30, and clears the debt. |
With the default 100% per-transfer recovery limit, a future transfer smaller than the outstanding debt is fully withheld and the remaining balance carries over. Developers can lower that limit with the spp_debt_recovery_max_fraction filter. Each deduction is recorded as an order note.
Enabling it
Go to Split Pay → Global Transfer Settings and enable Reclaim refund shortfalls from a vendor’s future transfers.
Seeing what each vendor owes
Outstanding balances appear on the Split Pay → Platform Status tab, broken down per connected account, Stripe mode, and currency, along with how much has been recovered so far. If a vendor has left your store and will never receive another transfer, use Mark cleared to write the balance off — this only updates the ledger, it never moves money.
How it stays safe
- Per currency and per Stripe mode — a USD debt is only ever recovered from USD transfers, and a test-mode debt never affects live payouts (and vice-versa).
- Never over-charges a vendor — debt is reserved atomically before each transfer, so two orders processed at the same time can't both claw back the same balance.
- Idempotent — a refund that fires twice (for example a manual refund plus a webhook) records the shortfall only once, and a transfer that's retried never double-deducts.
- Accurate refunds afterwards — the transfer log stores the net amount the vendor actually received, so refunding a debt-reduced order reverses exactly what was paid out, never more.
- Forward-only — turning the feature on doesn't retroactively create debt for refunds that already failed; it applies from the moment it's enabled. Turning it back off pauses recovery and leaves existing balances visible on the Platform Status tab.
Requirements for automatic reversals#
- Transfer log entries — The plugin reverses transfers recorded in its transfer log. Orders placed before installation won't have log entries and must be reversed manually.
- Original settlement currency — Split Pay reverses the transfer in the currency and minor units recorded for the original Stripe settlement. See Stripe’s Transfer Reversals API reference.
- Connected account balance — The connected account needs enough available Stripe balance unless optional refund reclaim records the rejected amount as debt.
- Refund trigger — For WooCommerce, create the refund on the WooCommerce order; a Stripe-only refund does not fire WooCommerce’s order-refunded hook. FluentCart can also reach Split Pay from its Stripe refund webhook when FluentCart receives and maps the event to the order. See the FluentCart refund-handling note.
Manual reversals in Stripe#
Use a manual Stripe reversal only for an order Split Pay cannot reverse automatically. Match the exact tr_... transfer, mode, currency, and proven full or partial amount before acting; Stripe can reject a reversal when the connected account lacks enough available balance. Follow Stripe’s current Transfer Reversals reference for the Dashboard or API procedure.
A Dashboard or API reversal happens outside Split Pay and does not update the plugin’s saved reversal record. Do not combine it with an automatic Split Pay reversal for the same amount without reconciling both records first.
Retrying failed transfers#
If transfers fail during initial processing (e.g., network issues or temporary Stripe errors), you can retry them directly from the order page. See Retry Failed Transfers for details.
How Split Pay chooses each reversal amount#
- Full refund: reverse the remaining amount recorded for every completed transfer on the order.
- WooCommerce product refund: use the refunded fraction of the matching ordered item for product-level legs.
- WooCommerce shipping refund: use the refunded fraction of the order’s shipping for shipping legs.
- Sequential global split: use the signed principal and tax contributions saved for each ordered line.
- Amount-only, FluentCart, non-sequential global, or legacy fallback: multiply the amount actually transferred by
refund amount / order total. - Safety limit: never request more than Stripe reports as remaining reversible on the original transfer.