A CVV verification test confirms that your payment integration checks the card security code during authorization and then discards it. The test passes when a correct code gets approved, a wrong code gets declined with the right reason code, and nothing about the code shows up in your logs, database, or error messages.
CVV Verification Check Guide: How to Sell CVV Online Safely
I treat it as two separate problems. First, does the gateway validate the code at all? Second, does your own code keep it somewhere it should not? Most failed tests I see are the second one.
What the test actually checks
The CVV, CVV2, CVC2, or CID is a short numeric code printed on the card. The length depends on the network:
- Visa, Mastercard, Discover: three digits on the back, near the signature panel.
- American Express: four digits on the front, above the card number.
It is not the same thing as a PIN. It never appears in the magnetic stripe data or the chip, so only keyed transactions carry it. That matters for testing because card-present flows will not send a CVV at all.
Ultimate Guide to CVV Verification Tools: Buy CVV Online Safely
How to run a proper sandbox test
Every major gateway ships test card numbers with fixed CVV behavior. Stripe, Adyen, Braintree, and Authorize.net each publish a set. Pick one card per scenario instead of reusing a single number.
- Correct card number with correct CVV: expect approval.
- Correct card number with wrong CVV: expect a CVV mismatch decline, distinct from insufficient funds or expired card.
- Missing CVV field: expect a decline or a "CVV not provided" response, depending on gateway settings.
- Four-digit Amex code in a three-digit field: expect validation to fail before the request leaves your server.
- Retry after a mismatch: confirm the second attempt is a new authorization, not a cached result.
Run each case twice, once through your checkout UI and once through a direct API call. The two paths often validate differently, especially when a client-side form does its own length check.
What to check after the test
Response handling is where most integrations break. A CVV mismatch should map to a specific decline reason, not a generic "payment failed." Your support team needs the difference, and so does the customer.
- Confirm the decline code is logged. The code, not the digits entered.
- Confirm the CVV is absent from request logs, APM traces, and queue payloads.
- Confirm the value is never written to your order table, even briefly.
- Confirm your error message does not echo the submitted digits.
The rules you cannot test around
PCI DSS requirement 3.2 says the card verification code must not be stored after authorization in any form. That includes hashed and encrypted forms, which surprises people. If your test environment captures a real card's CVV for debugging, you have a compliance problem, not a test.
Use sandbox card numbers only. Never run a verification test with a live card number you do not own, and never use a live merchant account to check whether validation works. Test credentials exist for that purpose.
One more habit worth building: rerun the CVV test after every gateway SDK upgrade and after any change to your checkout form. Validation rules shift between versions, and a suite that covers four decline paths catches the change in minutes.