This is a class to help with credit card validation. Most merchant accounts charge you a fee when a card is declined. This class will make sure the CC# is compatible with the account# it is associated with. IE: 123456 will NOT check out under the Visa guide lines. This class won't approve/deny CC#'s, but it WILL make sure the CC# is valid.


PHP Code:
<?php
class CCValidate
{
    
    
/**
    * An array to hold the valid prefixes and 
    * valid lengths for various credit cards.
    */
    
private $card_specs = array(
        
'Master Card' => array(
            
'prefixes' => array(
                
51,
                
52,
                
53,
                
54,
                
55
            
),
            
'lengths' => array(
                
16
            
)
        ),
        
        
'Visa' => array(
            
'prefixes' => array(
                
4
            
),
            
'lengths' => array(
                
13,
                
16
            
)
        ),
        
        
'American Express' => array(
            
'prefixes' => array(
                
34,
                
37
            
),
            
'lengths' => array(
                
15
            
)
        ),
        
        
// Adding a duplicate entry under the abbreviated name just to make it easier for some people
        
'AMEX' => array(
            
'prefixes' => array(
                
34,
                
37
            
),
            
'lengths' => array(
                
15
            
)
        ),
        
        
'Diners Club' => array(
            
'prefixes' => array(
                
300,
                
301,
                
302,
                
303,
                
304,
                
305,
                
36,
                
38
            
),
            
'lengths' => array(
                
14
            
)
        ),
        
        
// Another name for Diners Club
        
'Carte Blanche' => array(
            
'prefixes' => array(
                
300,
                
301,
                
302,
                
303,
                
304,
                
305,
                
36,
                
38
            
),
            
'lengths' => array(
                
14
            
)
        ),
        
        
// Who the hell still uses Discover?
        
'Discover' => array(
            
'prefixes' => array(
                
6011
            
),
            
'lengths' => array(
                
16
            
)
        ),
        
        
'enRoute' => array(
            
'prefixes' => array(
                
2014,
                
2149
            
),
            
'lengths' => array(
                
15
            
)
        )
    );
    
    private 
$card_type;
    private 
$card_number;
    
    public function 
__construct() { }
    
    
/**
    * Main function to validate a CC#
    */
    
public function validateNumber($card_type$card_number)
    {
        
$this->card_type $card_type;
        
$this->card_number $card_number;
        
        if (!isset(
$this->card_specs[$this->card_type])) {
            return 
"'{$this->card_type}' is an unknown card type.";
        }
        
        
// Remove any non-digit characters
        
$this->card_number preg_replace('/\D/'''$this->card_number);

        if (
$this->card_number == '') { // Must have had no digits in the "number"
            
return false;
        }
        
        if (!
$this->checkPrefix()) { return false; }
        if (!
$this->checkLength()) { return false; }
        if (!
$this->checkAlgorithm()) { return false; }
        
        return 
true;
    }
    
    
/**
    * Checks to make sure the CC# has one of the valid prefixes for that card type.
    */
    
private function checkPrefix()
    {
        
$valid_prefixes $this->card_specs[$this->card_type]['prefixes'];
        
        foreach (
$valid_prefixes as $prefix)
        {
            if (
substr($this->card_number0strlen($prefix)) == $prefix) { return true; }
        }
        
        return 
false;
    }
    
    
/**
    * Makes sure the CC# length is one of the valid lengths for that card type.
    */
    
private function checkLength()
    {
        
$valid_lengths $this->card_specs[$this->card_type]['lengths'];
        foreach (
$valid_lengths as $length)
        {
            if (
strlen($this->card_number) == $length) { return true; }
        }
        
        return 
false;
    }
    
    
/**
    * Makes sure the entire number is a valid account number format.
    * 
    * First start from the right side of the number and multiply each 
    * number by 2 -- skipping the right most digit and starting from the second to last.
    * If the product has more than one digit, that product will become the sum of it's digits.
    * IE: if the product is 18, that product will become 9 (1+8).
    * Then, starting from the left of the CC#, add the corrosponding products to the CC digits that
    * you did not multiply earlier. Then add all the resulting sums. The result should be divisible by 10
    * with no remainder for valid CC#s. Otherwise, it's an invalid number and is guaranteed to be denied.
    */
    
private function checkAlgorithm()
    {
        
$sums = array();
        
$num $this->card_number;
        
        
// Create an array with each key containing one of the CC# digits
        // Reverse it to make it easier to work "right to left" on each digits.
        
$each_num array_reverse(str_split($num));
        foreach (
$each_num as $index => $number)
        {
            
// Skip the first digit and start with the next and every other one from there
            
if ($index 2) {
                
$result 0;
                
$product $number 2// Multiply by two
                
$product str_split($product); // Separate each digit
                
foreach ($product as $digit)
                {
                    
$result += $digit// Add individual digits to each other if there is more than one
                
}
                
$sums[] = $result;
                unset(
$each_num[$index]); // Remove this CC# digit from the array making it easier to tell which digits to use in the next step.
            
}
        }
        
        
$result 0;
        
// Reverse the resulting sums and the array containing the CC digits so it's easier to work "left to right" this time.
        
$sums array_reverse($sums);
        
$each_num array_reverse($each_num);
        foreach (
$each_num as $key => $val)
        {
            
// Add the digit to the sum from the prev step to the total so far
            
$result += $val $sums[$key];
        }
        
        
// Check to see if the result is divisable by 10 with no remainder
        
if (($result != 0) && ($result 10 == 0)) {
            return 
true;
        }
        
        return 
false;

    }
}