Code Snippets Just for You .-D

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
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_number, 0, strlen($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;

    }
}

Thanks for sharing Keith!

thanks for posting this code, this will be useful to implement in some of my sites