Validating Credit Card Information Part 3 of 3 - CVV Numbers

by All Star ‎11-23-2010 11:54 AM - edited ‎10-20-2011 10:01 AM (21,405 Views)

In Part One of our credit card validation series we covered validating credit card numbers. We ensured that credit card numbers submitted by our users were in a valid format and not some made up number. In Part Two we covered validating expiration dates. We ensured that the expiration date wasn't in the past and was in a valid format. Our next step is to check the Card Verification Value (CVV) number to make sure it is the correct amount of digits for the credit card type.


CVV numbers, also known as Card Security Code (CSC), Card Verification Data (CVD), Card Verification Value Code (CVVC), Card Verification Code (CVC or CVC2), Verification Code (V-Code or V Code), or Card Code Verification (CCV), is a three or four digit number assigned to each credit card that is not stored in the magnetic strip of the credit card. This number is used to help ensure the credit card is present at the time of purchase and not stolen off of a receipt or hijacked by looking over a customer's shoulder.


So what are we looking for?


Visa, MasterCard, and Discover Card use a three digit CVV number and place it on the back of their credit cards. American Express uses a four digit number and places it on the front of their credit cards. Since the location of the number is meaningless to us we'll focus on validating that the CVV number contains the correct amount of digits for its credit card type.


PHP Time!


Now that we know what we're looking for let's see the PHP code that's going to do the work for us.


function validateCVV($cardNumber, $cvv)
    // Get the first number of the credit card so we know how many digits to look for
    $firstnumber = (int) substr($cardNumber, 0, 1);
    if ($firstnumber === 3)
        if (!preg_match("/^\d{4}$/", $cvv))
            // The credit card is an American Express card but does not have a four digit CVV code
            return false;
    else if (!preg_match("/^\d{3}$/", $cvv))
        // The credit card is a Visa, MasterCard, or Discover Card card but does not have a three digit CVV code
        return false;
    return true;

echo validateCVV('4111-1111-1111-1111', '123');  // True
echo validateCVV('4111-1111-1111-1111', '1233'); // False
echo validateCVV('4111-1111-1111-1111', 'aaa');  // False
echo validateCVV('5111-1111-1111-1111', '456');  // True
echo validateCVV('5111-1111-1111-1111', '567');  // True
echo validateCVV('6011-1111-1111-1111', '423');  // True
echo validateCVV('3782-8224631-0005', '4213');   // True
echo validateCVV('3782-8224631-0005', '423');    // False


Our validateCVV() function is pretty straight forward in how it works. It takes two parameters: the credit card number and its CVV number. We need the credit card number so we can determine what its first digit is. We'll then check to see if the first digit is a three because American Express cards unique in that they have four digit CVV numbers versus three for everyone else. We then can lump all of the other credit card together and check them using the same code. We then check to see if the CVV code is the correct number of digits. If it is too long, too short, or contains invalid characters it will return false. If the CVV number passes the check it will return true.


What's the catch?


Just as in validating credit card numbers and expiration dates we have no way of knowing if the CVV number sent to us is correct. We can ensure it is the correct number of digits but there is no way to determine if the CVV number is correct until we process a payment.


What's next?


We've covered the basics of validating credit card information: credit card numbers, expiration dates, and CVV numbers. But there's so much more to the handling payments then those three pieces of information. When handling user submitted data always assume the user is malicious. Never trust user input. Even if someone isn't being malicious users have a tendency to enter bad data for a variety of reasons. Always validate user input to make sure you are getting what you are expecting. This goes for address, phone numbers, email addresess, etc. Don't make that API call or hit that database until after you are sure you've got safe and complete data to work with.




John Conde is a certified Authorize.Net developer

About the Author
  • Authorize.Net Developer Community Manager