measuredcode

Ukraine · Croatia

Stripe says paid, WooCommerce says cancelled: how to find and fix those orders

WooCommerce cancelled an order Stripe shows as paid? Why “Unpaid order cancelled – time limit reached” happens and how to find and fix every affected order.

5 min

reading time

WooCommerce Stripe Gateway

applies to

Scroll ↓

A customer paid, Stripe shows the payment as succeeded, and the WooCommerce order says: “Unpaid order cancelled – time limit reached.” The money is in your account, the order is cancelled, and the customer waits for something that will never ship.

This guide explains why it happens and what to do, in four steps: stop the cancellations, find the cause, find every affected order, and fix each one without charging anyone twice.

The short version

  • The cancel comes from WooCommerce: the order never learned about the payment.
  • Clear Hold stock (minutes) while you look for the cause.
  • Check every unpaid Stripe order against Stripe, then fix each one by hand.

Why it happens

The cancellation comes from WooCommerce, not from Stripe. When stock management is on, WooCommerce holds stock for each new checkout order for the time set in WooCommerce > Settings > Products > Inventory > Hold stock (minutes), 60 by default. When that time runs out, it cancels every checkout order that is still in Pending payment.

So the cancel is only the last step. The real problem is that the order never learned about the payment. The usual causes:

  • Stripe’s webhook never reached the store, or the store rejected it (wrong signing secret, firewall, security plugin, caching).
  • The customer closed the tab before the redirect back to your site, and no webhook covered for it.
  • The gateway received the event but could not match it to the order. This has happened with Adaptive Pricing and some express checkout flows in recent gateway versions.

Orders without stock management are not cancelled, but they get stuck in Pending payment or Failed for the same reasons. Everything below applies to them too.

Step 1: stop paid orders from being cancelled

While you look for the cause, clear the Hold stock (minutes) field and save. WooCommerce then stops cancelling unpaid orders, so a paid order stays in Pending payment where you can still find it, instead of moving to Cancelled and releasing its stock.

The trade-off: abandoned checkouts also stay in Pending payment. Clean them up by hand now and then, and put the field back once the cause is fixed.

Step 2: find out why the confirmation did not arrive

Take one affected order and follow its payment from Stripe to the store.

  1. Check the webhook in the gateway. In the WooCommerce Stripe Gateway settings, the webhook status for live and test mode should say it is configured. If it does not, reconfigure it there.
  2. Check the deliveries in Stripe. In the Stripe Dashboard, open your webhook endpoint and find the payment_intent.succeeded event (or checkout.session.completed for Stripe Checkout) around the order’s time:
    • no delivery attempt: the endpoint or the event subscription is missing.
    • an error response: something on your site blocks the request, often a firewall, security plugin or cache.
    • a success response, yet the order is still pending: the store accepted the event but did not apply it, so look at the gateway’s log.
  3. Read the gateway log. Turn on debug logging in the gateway settings, then look in WooCommerce > Status > Logs for entries about that order or its payment ID.
  4. Check for a known bug. Update the gateway and read its changelog and open GitHub issues. Several recent releases fixed orders not being confirmed in specific checkout flows.

Step 3: find every affected order

One order is rarely the only one. By hand, you filter WooCommerce orders by Pending payment, Failed, On hold and Cancelled, open each Stripe order, copy its payment ID and look it up in Stripe. That works for five orders, not for fifty.

We built a free plugin for this check: Paidcheck. It takes the unpaid Stripe orders from the last 1, 2 or 7 days, reads each payment from Stripe and lists the orders that Stripe shows as paid, with both amounts, both statuses and a link to the payment in your Stripe Dashboard. It only reads: it never changes an order or anything in Stripe, and it can use a restricted key with read access only.

Step 4: fix each paid order

For every order Stripe shows as paid:

  1. In Stripe, confirm the payment succeeded and the amount and currency match the order total.
  2. Look for a second payment from the same customer. People who saw an error often pay again. Refund the extra one in Stripe.
  3. In WooCommerce, change the order to Processing (or Completed if nothing ships) and add an order note with the Stripe payment ID, so the next person knows why.
  4. If the order had been cancelled, check stock: moving it to Processing reduces stock again, and the item may have sold out meanwhile.

Do not send the customer a new payment link for an order Stripe already shows as paid.

Catch it before the customer does

Most shops learn about these orders from an angry email. A check once a week, or after every gateway update, finds them first.

We’re working on Paidcheck Pro, which runs this check on a schedule and emails you when it finds a paid order that WooCommerce missed. If that would help your shop, join the waitlist.

WooCommerce plugin, free on wordpress.org

Paidcheck

Finds WooCommerce orders that Stripe has taken payment for but the store still shows as pending, failed or cancelled, after a missed webhook or a closed tab. It only reads: nothing in the store or in Stripe is changed.

Working on a store?

Tell us about it: a design, a problem or just an idea. We’ll talk it through.

Discuss a project