If the gateway returned money but WooCommerce shows no refund, financial records, customer email, tax reporting and stock decisions can disagree. Creating another refund in WooCommerce through the normal gateway button may send the money twice.
Verify the provider transaction first and separate financial refund from inventory restock.
Confirm the provider refund
Record original transaction ID, refund ID, amount, currency, status and creation time. Distinguish pending from completed refunds and check whether it was full or partial.
Match it to the WooCommerce order and original capture. Do not rely on customer screenshots alone, and never request card details.
Add a private order note with the verified provider reference before making local corrections.
Determine how the refund was initiated
A refund started inside WooCommerce should normally create a local refund record and call the provider. A refund made directly in the gateway dashboard may require a webhook or manual WooCommerce record.
Identify:
initiating system/user
gateway refund reference
local refund record, if any
webhook event and delivery result
stock/restock decision
This prevents the same money movement being mistaken for two separate refunds.
Inspect WooCommerce and PHP logs
Match the refund time with gateway logs, PHP errors and private order notes. A provider API call may succeed before a PHP fatal or database failure prevents WooCommerce from saving the local refund.
A browser timeout is an unknown result. Search the gateway by the original transaction and idempotency reference before retrying.
Keep secrets and full payloads out of diagnostic logs.
Check refund webhook delivery
If the provider sends refund events, inspect delivery attempts and HTTP status. A domain migration, expired SSL certificate, firewall or wrong signing secret can block the update.
Replaying an event may be safe only if the handler recognises the provider refund ID. Confirm idempotency and current local state first.
Do not disable site-wide security controls to allow one webhook path.
Create the local financial record safely
After proving the external refund, use WooCommerce’s documented manual-refund workflow or supported APIs to record it without calling the gateway again. The interface often distinguishes “Refund manually” from “Refund via gateway.”
Select the exact line quantities, tax and shipping amounts supported by the original calculation. Do not invent a refund total simply to make the order balance reach zero.
Link the external refund ID in a private note and preserve an audit trail.
Decide stock separately
Money returned does not prove goods returned. Restock only items physically returned or never shipped according to business policy.
For partial refunds, choose quantities deliberately. Check variation IDs and warehouse integrations. A gateway refund made outside WooCommerce cannot know whether an item is saleable.
Avoid changing order status merely to trigger automatic restock.
Check bundled products carefully: the financial line refunded and the physical components returned to inventory may not have identical quantities.
Reconcile downstream systems
Confirm accounting, tax documents, customer email, ERP and analytics represent the refund once. Some systems listen to a WooCommerce refund-created hook; a manual local record may appropriately trigger them.
Check that it does not resend the financial refund. Test external integration behaviour in staging or with vendor documentation before recording a large batch.
Verify future refund flow
Use gateway sandbox or a controlled small transaction. Initiate a partial refund through the intended workflow and confirm one provider refund, one WooCommerce record, correct totals and chosen stock effect.
Recurring care should compare gateway refunds with WooCommerce refund records and alert on unmatched IDs. Refund reconciliation protects cash, inventory and customer trust simultaneously.