Projects Stopping card-testing fraud at a WooCommerce checkout
Stopping card-testing fraud at a WooCommerce checkout
Built for a WooCommerce store losing money to automated card-testing fraud, anonymised here

- How long
- 2025
- My role
- Software ArchitectureDevelopment, API Design, Security
- Kind of project
- Store extensionMedium project
The problem, in the owner’s words.
Card testing is when someone runs a batch of stolen card numbers through a store in small, cheap orders to find out which ones still work, then sells the ones that do. It costs a store gateway fees, chargebacks and, eventually, their payment provider’s trust. This client had no defence against it at all.
What I did.
I built a checkout roadblock for the client: before payment, the shopper has to verify a six-digit code sent to their email. It only challenges orders under a configurable value, since that is where card testing concentrates, so genuine higher-value customers are not slowed down. The check is a thin WordPress plugin that talks to a central API I run, signed with HMAC so requests can’t be forged, with tenant IDs so the same API can serve more than one store safely if it’s ever extended. If the API is ever unreachable, the plugin can fail open (never blocking a real sale) or fall back to generating and checking the code locally, whichever the store owner prefers.
What they got.
A checkout-level fraud control that costs nothing to run per transaction, doesn’t touch the payment gateway itself, and never has to become the reason a real customer can’t check out.
For your technical person
Two parts. A central Next.js API (deployed serverless, using Vercel KV in production and Redis locally) issues and verifies one-time codes over HMAC-SHA256-signed requests, keyed by tenant_id so multiple WooCommerce stores can share one API safely. The WooCommerce side is a standalone plugin (readme.txt shows stable tag 0.2.0, tested to WooCommerce 6.6, PHP 8.0+) with an admin settings page for the API base URL, tenant ID, shared secret and behaviour toggles: minimum order value to trigger a challenge, fail-open on API downtime, and an optional local fallback that can generate and check codes without the central API. Local dev stack: Docker Compose running WordPress, WooCommerce, MySQL, MailHog to capture the OTP emails, and Redis with a Redis Commander UI for inspecting stored codes.
Related work.
Running into the same problem? Tell me about yours.
+27 87 150 9305Monday to Friday, 09:00 to 20:00 SAST. Or email info@antondevilliers.com.