WooCommerce orders stuck in Pending Payment can look like a broken Stripe integration, especially when several appear close together. But the same status can represent very different situations: a customer who simply abandoned checkout, a customer who never reached Stripe, or a payment that genuinely succeeded in Stripe but failed to settle back into WooCommerce.
In one investigation, Freshy initially found evidence that suggested a pricing-state mismatch between WooCommerce, Stripe, and a wholesale-pricing plugin. That theory was never proven. When a similar set of Pending Payment orders appeared later, direct Stripe access provided the missing context: the customers had not completed payment, the orders cancelled automatically after the Stripe Checkout Sessions expired, and there was no checkout bug. The case became a useful lesson in how to distinguish normal abandonment from an actual Stripe settlement failure before changing plugins or checkout code.
Issue background
A WooCommerce store reported orders remaining in Pending Payment instead of moving into processing and fulfillment.
The initial concern was serious: the store believed some customers had paid in Stripe while WooCommerce had failed to record the completed payment. If true, that would mean money had been captured while the order remained outside the normal fulfillment workflow.
The affected order pattern prompted several possible explanations:
- Stripe webhooks were not reaching WooCommerce.
- WooCommerce Stripe was receiving the webhook but failing during settlement.
- Custom checkout hooks were interrupting the order lifecycle.
- Wholesale pricing changes were causing Stripe and WooCommerce totals to diverge.
- Customers were simply abandoning hosted Stripe Checkout Sessions before payment.
Those scenarios can produce similar-looking WooCommerce order lists, so the order status alone was not enough to identify the cause.
Diagnosis
The first investigation went deep into the WooCommerce and Stripe lifecycle.
Freshy confirmed that successful orders normally contained Stripe settlement metadata such as:
_stripe_intent_id
_stripe_source_id
_stripe_charge_captured
along with Stripe fee data and a WooCommerce transaction ID.
Some problematic orders contained only earlier checkout metadata such as:
_stripe_checkout_session_id
_stripe_upe_redirect_processed = 1
That showed the orders had entered the Stripe Checkout flow but had not reached the same final WooCommerce state as healthy paid orders.
The team also confirmed that Stripe webhooks were generally reaching the site and that there had been no matching Stripe configuration change, plugin activation, or WooCommerce setting change during the original failure window.
One order also showed a discrepancy between the WooCommerce total and the amount being reviewed in Stripe. Because the store used a wholesale-pricing plugin that modifies cart prices through hooks such as:
woocommerce_before_calculate_totals
woocommerce_after_calculate_totals
Freshy formed a working theory that Stripe and WooCommerce might occasionally be operating from different pricing states.
That was a hypothesis, not a confirmed root cause, and the investigation was paused when the reported problem stopped recurring.
A later group of Pending Payment orders supplied the missing lesson. Freshy initially treated the cluster as suspicious because several pending orders existed at once. After obtaining direct Stripe dashboard access, the evidence showed that the later orders were normal checkout abandonment.
One WooCommerce order explained the lifecycle explicitly:
The checkout session has expired. Order status changed from Pending payment to Cancelled.
The actual sequence was:
- The customer clicked Place Order.
- WooCommerce created an order in Pending Payment status.
- The customer was sent to the Stripe-hosted payment page.
- The customer did not finish paying.
- The order remained pending while the Stripe Checkout Session was valid.
- When that session expired, WooCommerce cancelled the order automatically.
Stripe showed that several customers had reached a checkout page but never completed payment. Another order had no Stripe record at all, meaning that customer abandoned before reaching Stripe.
No money had been taken in those cases.
Resolution steps
The investigation produced a practical workflow for diagnosing future Pending Payment orders:
- Do not treat Pending Payment as proof of a payment failure. It is a normal temporary WooCommerce status for an order whose payment has not finished.
- Inspect WooCommerce order notes. Look for payment-intent creation, successful payment events, status transitions, or a later note showing that the checkout session expired and the order was cancelled.
- Check the Stripe transaction directly. Search Stripe using the customer, email, timestamp, Checkout Session, or Payment Intent rather than relying only on WooCommerce metadata.
- Determine whether money actually moved. A Stripe customer or Checkout Session record does not mean payment was captured. Confirm whether a Payment Intent succeeded and whether a charge exists.
- Compare with a healthy WooCommerce order. Successful orders provide a useful baseline for expected Stripe metadata, transaction IDs, and order notes.
- Verify webhook health. If Stripe shows a successful payment but WooCommerce is still pending, confirm that the relevant webhook reached the site and was processed.
- Only then investigate plugin interactions. Pricing plugins, custom checkout hooks, and order-save callbacks are worth instrumenting when there is evidence that payment succeeded but WooCommerce failed afterward.
- Instrument the checkout lifecycle if necessary. Useful WooCommerce hooks can include:
woocommerce_before_calculate_totals
woocommerce_after_calculate_totals
woocommerce_checkout_create_order
woocommerce_checkout_order_processed
woocommerce_checkout_update_order_meta
- Compare totals at each stage. If WooCommerce and Stripe genuinely disagree on the amount after payment, log cart totals, order totals, and the Stripe session values to find where the pricing state changed.
- Let abandoned sessions cancel normally. If the customer simply did not finish paying, there is no payment to refund and no fulfillment action required.
The later investigation also exposed a useful analytical trap. Counting how many orders remain in Pending Payment when looking back at old months is misleading because pending orders automatically leave that state after their sessions expire. Historical months will therefore appear to have almost no pending orders even if many shoppers abandoned checkout at the time.
To measure abandonment trends, use order creation and cancellation history rather than a snapshot of how many old orders are still pending today.
Final outcome
The original Stripe investigation produced a wholesale-pricing theory but did not prove it before the issue went quiet. The task was later closed after a similar incident was investigated with direct Stripe access.
That later evidence confirmed that the comparable Pending Payment orders were normal abandoned checkouts. Customers had either left before reaching Stripe or opened a Stripe Checkout Session without completing payment. WooCommerce then cancelled those orders automatically when the sessions expired.
The result is an important troubleshooting distinction: Pending Payment is a state to investigate, not a diagnosis.
If Stripe shows a successful charge but WooCommerce never records settlement, that is a real integration problem and warrants webhook, metadata, pricing, and checkout-lifecycle analysis. If Stripe shows no successful payment and the order later cancels itself, the system is usually behaving as designed.
If your WooCommerce store has Pending Payment orders and you need help determining whether they represent normal abandonment or a real Stripe settlement problem, contact Freshy. Our WordPress team can trace the order through WooCommerce, Stripe Checkout, webhooks, and custom pricing logic before changes are made to a working payment flow.