Customers reported they couldn’t place orders – clicking “Place Order” reloaded the page and the cart was empty. Orders were not reaching the system. The problem only affected card payments, bank transfer worked. Resolution time: 4 hours.
Symptoms
- Clicking “Place Order” refreshes the page without confirmation
- Cart is empty after attempting to place an order
- In browser DevTools Network: POST request to
/rest/V1/carts/mine/payment-informationreturns 400 or 500 - Problem only with card payment method
- In
var/log/exception.log: CSRF validation error or payment gateway error
Diagnosis
# Open DevTools > Network > XHR
# Place order and watch requests
# Find failed request to /rest/V1/carts/
# Check response - 400 error:
# {"message": "Payment method is not available"}
# or 422 error:
# {"message": "Unable to authorize the payment"}
# Check payment gateway logs
tail -f var/log/payment_vendor.log
Cause
The SSL certificate had expired on the staging environment, preventing the payment gateway webhook from connecting back. On production an additional issue: a module was caching the payment token which expired after 15 minutes – customers with slow connections were getting expired tokens.
Solution
<?php
// Cache token with TTL matching gateway token TTL (15 min)
$token = $this->cache->get('payment_token');
if (!$token || $this->isTokenExpiringSoon($token)) {
$token = $this->gatewayClient->generateToken();
$this->cache->set('payment_token', $token, ttl: 600); // 10 minutes
}
private function isTokenExpiringSoon(string $token): bool
{
$payload = json_decode(base64_decode(explode('.', $token)[1]), true);
return ($payload['exp'] - time()) < 120; // less than 2 minutes to expiry
}
Takeaways
Checkout is the most critical path in a shop. Monitoring payment gateway API errors and alerts on 4xx/5xx responses should be standard. SSL certificates require automatic renewal (Let's Encrypt + certbot).
