
Card Testing Shield for WooCommerce — stop card testing on your checkout
A WooCommerce plugin that stops card testing on the checkout: it counts card payment attempts and gateway declines per IP address, browser session and e-mail, adds a growing pause after every decline and refuses the next attempt before it reaches the payment gateway. Classic and block checkout, "Pay for order", "Add payment method". The base version is free; Pro adds limits per card BIN and network, an automatic lockdown during a wave of declines, block lists, a 90-day log and CSV.
- Compatibility
- WooCommerce 8.0+ (tested on 11.2) · WordPress 6.2+ (tested on 7.1) · PHP 7.4+ (run on 8.3) · classic and block checkout · Stripe, WooPayments, Braintree, Square, Authorize.Net, NMI and other card gateways · counters in Redis, APCu or a database table
- Licence
- one site, annual
- Trial
- 7 days, no card, one per site
- Updated
- October 2026
What Free has,
and what Pro adds
The free version works with no time limit. Pro adds the rest of the features in the table.
What it looks like

The trial starts when you ask
A fresh install is the free version, nothing switches on by itself. The “Try Pro for 7 days” button → e-mail → the key right in the window and by e-mail.

One key — one site
Moving the store? Unbind the licence on the old domain and activate it on the new one yourself. For studios — keys for 5 or 25 sites, or unlimited.
Technical requirements
WooCommerce 8.0+ (tested on 11.2.1), classic and block checkout, “Pay for order”, “Add payment method”
WordPress 6.2+ (tested on 7.1) · PHP 7.4+ (full run on PHP 8.3, syntax check on 7.4)
Gateways: any card gateway through the standard WooCommerce hooks. WooCommerce Stripe Gateway (tested with 11.0.1, “Add payment method” AJAX from 9.7) and WooPayments (its AJAX card check, reviewed on 11.2) are wired in separately. Braintree, Square, Authorize.Net and NMI are wired in from their source code, with no live payments through them
BIN limit (Pro): only for gateways that send the card number or BIN to the site — Authorize.Net, NMI, the standard WooCommerce card form
Counters: Redis object cache (tested with Redis Object Cache), APCu or the plugin’s own database table — the shield picks the fastest one available
Proxies: Cloudflare (CF-Connecting-IP only from Cloudflare’s networks) or the header of your proxy or load balancer
Admin languages: English, Ukrainian, Russian
Version history
Attempt and decline limits per address, session and e-mail; a growing pause after declines; a limit on simultaneous payments; classic and block checkout, “Pay for order” and “Add payment…
Frequently bought with Card Testing Shield for WooCommerce
4 modules in one order — 40% cheaper than separately


Nova Poshta Premium — Nova Poshta for WooCommerce

Mono Acquiring — monobank card payments for WooCommerce

Telegram notifications and Viber/SMS for customers for WooCommerce
Full module description
Card Testing Shield for WooCommerce stops card testing on your checkout. Card testing looks like this: a script runs a list of stolen card numbers through your shop, one small payment after another, to find the cards that still work. The shop pays for it: hundreds of declined transactions, a gateway fee per attempt, chargebacks, and later a letter from Stripe or the acquiring bank about a frozen or closed account.
The shield counts what a card tester cannot hide: how many card payments come from one IP address, one browser session and one e-mail, and how many of them the gateway declined. Once a limit is used up, the next attempt is refused on your own server — it never reaches the payment gateway and costs no fee. A real buyer does not notice: they make one payment, rarely two.
For bots that crawl the catalogue and filters with GET requests we have a separate plugin — Crawler Shield for WooCommerce. Card Testing Shield guards something else: the POST requests of payments on the checkout, “Pay for order” and “Add payment method”. They do not get in each other’s way; on the test they ran together.
What the buyer sees
An ordinary buyer sees nothing new: the same form, the same gateway. One who has used up a limit gets a neutral message where checkout errors normally appear, without a hint about which limit it was: “We could not accept another card payment from you right now. Please try again later, choose another payment method or contact us.” During a short pause it adds how many seconds are left before the next try. The message text can be changed in the settings. Other payment methods — bank transfer, cash on delivery — stay open.
An attempt is counted only when WooCommerce has accepted the form and hands the order to the gateway. A buyer fixing a typo in the address or a missing field never spends one.
What the admin gets
- WooCommerce → Card Testing Shield with the Overview, Rules and Log tabs.
- Overview: card payment attempts, payments declined by the gateway and refused by the shield for 24 hours and 7 days; an hourly table with a “Would refuse” column for monitor mode.
- “A customer cannot pay?” — enter an IP address or an e-mail: you see what the shield counted, until when the refusal and the pause last, and the Release button drops it all at once.
- “How the shield sees this shop”: the watched payment methods, the address the shield sees for you (with a warning if it is the address of your server or proxy), where the counters live, and whether WooCommerce’s own “Rate limit Checkout” is on.
The Log records every declined payment and every refusal: the time, where (checkout, block checkout, “Pay for order”, “Add payment method”), the address, the e-mail, the payment method, the order and the reason — for example “pause after a decline” or “several payments at the same moment”. Filters: Refused, Would refuse, Declined, Lockdown. Repeated refusals of the same client during an attack are not written one by one, so the database does not swell. Free keeps the log for 7 days, Pro for up to 90 with CSV export.
How it works — step by step
- Which payment methods to watch. By default all card gateways: Stripe, WooPayments, Braintree, Square, Authorize.Net, NMI and others. Bank transfer, cheque and cash on delivery are not watched unless you tick them.
- Attempt. When WooCommerce has accepted the form and hands the order to the gateway, the shield adds an attempt to the counters of the IP address, the browser session (cart) and the billing e-mail. Defaults: 10 attempts per address and 6 per session or e-mail within 60 minutes.
- Decline. The gateway declined the payment — the shield counts a decline (limits of 5 per address and 3 per session or e-mail by default) and sets a pause: 10 seconds after the first decline, then 20, 40 and up to 5 minutes. A person typing the card a second time does not notice it; a script running a list slows to a crawl.
- Late declines. If the gateway reports a decline later — by webhook or after a failed 3-D Secure — the order turns Failed and the shield counts it once, even if the status is set twice. A successful 3-D Secure is not a decline.
- Simultaneous payments. A script can send 20 cards in parallel — then all 20 would reach the gateway before the first decline is counted. So the shield lets through at most 3 payments in 10 seconds from one address, browser or account; the counter is atomic (Redis, APCu or a single query to the table). The limit can be changed or switched off with the
catcode_cts_burstfilter. - Refusal. A client that hit a limit is refused for a set time (60 minutes by default) with a neutral message. Customers who have paid before, shop managers and administrators are never limited; nor are whitelisted addresses, networks, e-mails and domains.
- “Add payment method”. The favourite of testers who register thousands of free accounts. The shield limits it separately (5 cards and 3 declines per address or account by default) — in the WooCommerce form and in the AJAX card checks of Stripe and WooPayments.
- Monitor mode. Not sure the limits fit your shop? Switch on Monitor for a few days: the shield only logs whom it would refuse and refuses nobody.
Pro. Testers run generated numbers of one bank range through many addresses — Pro counts declines per card BIN (the first six digits) across all visitors. This works with gateways that send the card number or the BIN to the site: the Authorize.Net and NMI plugins and the standard WooCommerce card form. Stripe, Braintree and Square turn the card into a token in the browser and the number never reaches the site — there the other limits do the work. Pro also counts declines per /24 network (IPv4) or /48 (IPv6) for attacks from neighbouring addresses. During a wave of declines (20 declined card payments in 15 minutes across the shop by default) Pro starts a 60-minute lockdown: tighter limits for everyone except trusted customers, optionally no card payments for guests, and an e-mail to you. A lockdown can also be started and ended by hand. For “Add payment method” there is a minimum account age (24 hours by default) or an “only accounts with a paid order” rule. Block lists cover IP addresses and networks, e-mails and e-mail domains, and BINs.
Under the hood
- Check points:
woocommerce_checkout_processfor the classic checkout, a check of the Store API request before it runs for the block checkout (the answer is an ordinary payment error),woocommerce_before_pay_actionfor “Pay for order”,woocommerce_add_payment_method_form_is_validand the Stripe and WooPayments AJAX actions for “Add payment method”. - The payment outcome is read from the WooCommerce and gateway answer: success, decline, 3-D Secure. A late decline comes through the order turning Failed, once per order.
- Sliding window: a limit reads the current period plus the share of the previous one that still overlaps, so two quick bursts on both sides of a full hour do not double the limit.
- Atomic counters: INCR in Redis, apcu_inc or a single
INSERT … ON DUPLICATE KEY UPDATE— parallel requests do not read stale values. - Visitor address: CF-Connecting-IP is accepted only from Cloudflare’s official networks, so a script cannot pass someone else’s address in a header.
- Data: nothing leaves your server, the free version makes no external requests. The card number is stored nowhere.
- Deleting the plugin removes its tables, settings and cron jobs.
Installation
- Plugins → Add New → Upload Plugin: choose
catcode-card-testing-shield-for-woocommerce-free-1.0.0.zipand activate it (WooCommerce must be active). - Open WooCommerce → Card Testing Shield → Rules. The defaults suit most shops; if unsure, choose Monitor for a few days and look at the log.
- If the site is behind Cloudflare or another proxy, check “Your address as the shield sees it” on the Overview tab and set “Visitor address” in Rules → Server if needed.
- Whitelist the addresses of your office or call centre if you take payments by phone.
- For Pro: paste the licence key from the e-mail after purchase, or click “Try Pro for 7 days” at the bottom of the Rules tab.
Questions
about the module
Didn't find the answer? Message us on Telegram and we'll reply within a business day.
What is card testing and how does it hurt a shop?
A script runs stolen card numbers through your checkout as small payments to find the cards that still work. The shop pays for it: hundreds of declined transactions, gateway fees per attempt, chargebacks, and in the end a payment provider that freezes or closes the account.
Will real customers be blocked?
The defaults allow 6 attempts and 3 declines per browser session and e-mail, and 10 attempts and 5 declines per IP address, per hour — a real buyer rarely needs more than two or three. Customers who have paid before are never limited. If somebody does get refused, look them up on the Overview tab by IP or e-mail and release them.
Does it replace a CAPTCHA or my gateway's fraud tools?
No, it works alongside them. A CAPTCHA can be solved by a farm and does nothing for "Pay for order" or saved cards. Gateway fraud rules only see the attempts that already reached the gateway and cost you a fee. The shield stops repeat attempts on your own server.
What about WooCommerce's own "Rate limit Checkout"?
That feature (Settings → Advanced → Features) allows 3 block-checkout requests a minute per address or account, whatever their outcome. It does not cover the classic checkout, "Pay for order" or saved cards, and does not look at declines or e-mails. Both can be on at the same time.
My shop is behind Cloudflare — does the shield see the buyer's real address?
Yes: the address is taken from CF-Connecting-IP automatically, but only for requests that really come from Cloudflare's networks. Behind another proxy or load balancer, choose its header in Rules → Server. The Overview tab shows which address the shield sees for you.
Does the plugin store card data?
No. The log keeps the address, the e-mail, the payment method and the order — never a card number. For gateways that send the number to the site, Pro reads only the first six digits (the BIN) in memory and keeps only those. The free version makes no external requests.
No reviews yet. Be the first.
No questions yet. Ask one — we answer within 24 hours.
Not quite what you are looking for?
We build custom modules for WordPress, WooCommerce, OpenCart and Shopify. Tell us about the task and we'll prepare an estimate.
Order a custom module
Buying the module
—
