Notes
The pay-for-order page is a checkout too
Bots test cards on the WooCommerce pay-for-order page by retrying a failed order. Here is how it works and how to protect or close it.
4 min read
You protected the checkout, the attack slowed, and then the gateway showed a fresh run of declines. The order list did not grow this time. The same few failed orders just kept collecting new payment attempts. The bot found the pay-for-order page.
What the pay-for-order page is
WooCommerce lets a customer pay for an order that already exists. You see this when you create an order in the admin and send the customer a payment link, or when a payment fails and the customer tries again.
The link points to the order-pay endpoint under your checkout page, with the order ID and the order key in the URL. It looks something like this:
https://example.com/checkout/order-pay/1234/?pay_for_order=true&key=wc_order_AbC123xYz
The page shows the order summary and the payment methods. When the customer submits it, WooCommerce runs the gateway for that order. That is a full card charge, on a page most checkout protections do not cover.
Why bots like it
From an attacker's point of view, the pay-for-order page has two useful traits.
First, it skips the cart and most of the checkout. There is no product to add, no shipping to pick, and no billing form to fill in. The script submits a card for an order and reads the result.
Second, one order can take many attempts. By default WooCommerce allows payment on orders in the pending and failed statuses. A failed order stays payable, so a script that gets one order key can try card after card against it.
How a bot gets an order key
The order key is a random string, so a bot cannot guess it. It usually gets one in a simple way: it places an order through the normal checkout with a bad card. The payment fails, the order stays in failed or pending, and the redirect or the order received page gives the bot the key.
This is why the pattern often starts on the checkout and moves here. The first order costs the bot one request through your protected checkout. Every attempt after that goes through the pay page.
WooCommerce has added extra checks for guests who open order links from a new session, such as asking for the billing email. That helps against strangers, but the bot that placed the order already knows the email it used.
How to spot it
The signs are different from a checkout attack:
- A small number of failed orders, each with many failed payment notes from the gateway.
- Gateway dashboard attempts that do not line up one to one with new orders.
- Access log requests to paths containing
/order-pay/withpay_for_order=true, often from the same few IP addresses.
Open one of the failed orders and read the order notes. If you see a long list of declines on the same order, with different card brands or last four digits, the pay page is being used to test cards.
What protects it
Treat the pay-for-order page as a checkout, because it is one. Any check you run on the checkout should run here too, on the server, before the gateway is called.
- Put the same bot check on the pay form that you use on checkout, and refuse the payment on the server if the token is missing or bad.
- Limit how many payment attempts one order can take in a short window.
- Cancel failed guest orders after a set time, so they stop being payable. Pending orders already have a hold stock setting that cancels unpaid orders, but failed orders need their own rule.
- Use your gateway's fraud rules, which see every attempt regardless of the page.
Many stores never use the pay-for-order page at all. If you never send payment links and you do not want customers to retry from a failed order, blocking the page is a fair choice. Check first that your gateway does not rely on it for its own retry flow.
Do not forget it in testing
When you test your checkout protection, test this page too. Place an order with a test card that declines, copy the pay link from the order screen in the admin, open it in a private window, and try to pay. If the payment goes to the gateway without your bot check running, the route is open.
Where Checkout Bouncer fits
Checkout Bouncer covers pay-for-order as its own route. Its Checkout Scanner lists the route, and you can set it to Protect, which adds the reCAPTCHA v3 check to the pay form, or Block, which returns an error page for stores that never use payment links.