## Summary

A broken WooCommerce checkout loses money every hour it stays down. The symptoms customers report are almost always one of five: the **Place order** button spins forever, the page shows *"There was an error processing your order"*, a *"nonce verification failed"* or *"session has expired"* message, the payment is taken but the order stays **Pending payment**, or the checkout page simply reloads.

This guide gives you the fast isolation steps first. If you would rather hand it over, SazM fixes a broken checkout for a **fixed $99, delivered within 48 hours**, entirely in writing: no calls, no project manager, one senior developer.

## Where the Error Usually Lives

Open your logs before changing anything. WooCommerce writes its own logs separately from PHP:

```text
wp-content/uploads/wc-logs/fatal-errors-2026-11-05-<hash>.log
wp-content/uploads/wc-logs/<gateway>-2026-11-05-<hash>.log   # stripe, paypal, etc.
/var/log/nginx/error.log  or  /var/log/apache2/error.log
/var/log/php8.2-fpm.log
```

Typical lines and what they point to:

```text
PHP Fatal error:  Uncaught TypeError: ... in /wp-content/plugins/<plugin>/includes/class-checkout.php:212
  -> a plugin or theme hooked into checkout is incompatible with your PHP or WooCommerce version

SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON   (browser console)
  -> /?wc-ajax=checkout returned HTML (a PHP notice, a cache page or a security block) instead of JSON

cURL error 28: Operation timed out after 30001 milliseconds
  -> your server cannot reach the payment gateway API in time (firewall, DNS, IPv6 or host egress limits)

Webhook signature verification failed / No signatures found matching the expected signature
  -> the gateway webhook secret is wrong, so paid orders never move out of Pending payment
```

## Quick Fix Breakdown (DIY)

- **Read the AJAX response.** Open DevTools → Network, click *Place order*, select the `?wc-ajax=checkout` request. If the response is not JSON, the text before the JSON is your bug.
- **Exclude checkout from every cache.** Cart, checkout and my-account must never be page-cached. For nginx FastCGI cache:

```nginx
set $skip_cache 0;
if ($request_uri ~* "/(cart|checkout|my-account)/|wc-ajax=") { set $skip_cache 1; }
if ($http_cookie ~* "woocommerce_items_in_cart|wp_woocommerce_session_") { set $skip_cache 1; }
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
```

  A cached checkout serves an old nonce to every visitor, which is the most common cause of *"nonce verification failed"*.
- **Stop PHP notices from breaking JSON.** On a live store:

```php
// wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
@ini_set('display_errors', '0');
```

- **Isolate the conflict on staging, not live.**

```bash
wp plugin list --status=active
wp plugin deactivate --all --exclude=woocommerce,woocommerce-gateway-stripe
wp theme activate storefront
# test checkout, then re-enable plugins one at a time
wp plugin activate <slug>
```

- **Test the gateway connection from the server itself.**

```bash
curl -sS -o /dev/null -w "%{http_code} %{time_total}s\n" https://api.stripe.com/v1
curl -4 -sS -o /dev/null -w "%{http_code} %{time_total}s\n" https://api-m.paypal.com
```

  A timeout here is a hosting or firewall problem, not a WooCommerce problem.
- **Check the webhook.** In your gateway dashboard, look at recent webhook deliveries. Failures with 401, 403 or 500 mean paid orders will never be marked as paid. Re-copy the signing secret into the plugin settings.
- **Check sessions and cron.** Expired-session errors often come from a full `wp_woocommerce_sessions` table or a dead WP-Cron:

```bash
wp db query "SELECT COUNT(*) FROM wp_woocommerce_sessions;"
wp cron event list --fields=hook,next_run_relative | grep woocommerce
```

- **Look for a security block.** A WAF or security plugin (ModSecurity, Wordfence, Cloudflare rules) blocking `wc-ajax=checkout` returns a 403 page instead of JSON. Check the firewall log for that URL.

If none of these isolates it within an hour, stop. Each extra hour of guessing is lost orders.

## Hand It Over: $99 Fixed, Within 48 Hours

Most checkout failures are not hard to fix. They take a long time because the store owner, the host, the theme vendor and the gateway support each point at someone else. One developer who reads the logs, reproduces the failure on staging and fixes the root cause ends that.

What you get for **$99**:

- **A fixed price agreed before work starts.** One checkout issue, one flat fee, no hourly meter.
- **Delivery within 48 hours** of access, verified on staging before anything touches your live store.
- **Fully written, fully async.** You send the store URL, the error and when it started. You get questions, progress and proof in writing. There are no calls, meetings or project managers in between, so your time zone does not matter.
- **Written proof it works:** the root cause in plain language, what changed, a recording of a test order completing, and a rollback note.
- **Money-back guarantee** if the agreed root cause cannot be resolved.
- **Safe access only:** a separate admin account, staging first, test-mode gateway keys. Never send card data or passwords through the inquiry form.

Behind it: 20+ years in production (since Oct 2006) and 100+ projects in the portfolio. Agencies with several stores broken at once can queue them the same way, one ticket each.

**[Get your WooCommerce checkout fixed for $99 →](/woocommerce-checkout-fix)** · [Queue an urgent fix](/checkout/emergency) · [See past projects](/projects)

If the store is also slow at checkout (INP over 200 ms, slow LCP on mobile), the $199 [Core Web Vitals fix](/articles/core-web-vitals-inp-lcp-remediation) can be done in the same window.

## Frequently Asked Questions

### Why does my WooCommerce checkout keep spinning?
The checkout AJAX request (`?wc-ajax=checkout`) is returning something other than valid JSON, usually a PHP notice, a cached page or a firewall block. Open the browser Network tab, click Place order and read that request's response.

### How do I fix "nonce verification failed" on WooCommerce checkout?
Exclude cart, checkout and my-account pages and the `wc-ajax` endpoint from every page cache (plugin, server and CDN), then clear all caches. A cached checkout serves an expired nonce to every visitor.

### Why are paid orders stuck in Pending payment?
The payment gateway webhook is failing, so WooCommerce never learns the payment succeeded. Check webhook deliveries in your gateway dashboard and re-copy the signing secret into the plugin settings.

### How much does it cost to fix a broken WooCommerce checkout?
SazM fixes one checkout issue for a fixed $99, delivered within 48 hours, with a money-back guarantee if the agreed root cause cannot be resolved. Everything is handled in writing.

### Do I need a call to explain the checkout problem?
No. Send the store URL, the exact error and what changed recently. A written report with a screenshot or recording is more precise than a call and becomes the test that proves the fix works.
