Created
April 5, 2013 21:28
-
-
Save wesen/5322764 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function validateCreditCard($cardnumber, $cardname) { | |
| if ($cardname[0]) { | |
| // accept masked cc numbers | |
| return true; | |
| } | |
| $ccErrorNo = 0; | |
| $ccErrors = array (); | |
| $ccErrors[0] = "Unknown card type."; | |
| $ccErrors[1] = "No card number provided."; | |
| $ccErrors[2] = "Credit card number is in invalid format."; | |
| $ccErrors[3] = "Credit card number is invalid."; | |
| $ccErrors[4] = "Credit card number has an inappropriate number of digits."; | |
| // Array to hold the permitted card characteristics | |
| $cards = array(); | |
| // Define the cards we support. You may add addtional card types. | |
| // Name: As in the selection box of the form - must be same as user's | |
| // Length: List of possible valid lengths of the card number for the card | |
| // prefixes: List of possible prefixes for the card | |
| // checkdigit Boolean to say whether there is a check digit | |
| $cards[0] = array("name" => "Visa","length" => "13,16","prefixes" => "4","checkdigit" => true); | |
| $cards[1] = array("name" => "MasterCard","length" => "16","prefixes" => "51,52,53,54,55","checkdigit" => true); | |
| $cards[2] = array("name" => "DinersClub","length" => "14,16","prefixes" => "300,301,302,303,304,305,36,38,55","checkdigit" => true); | |
| $cards[3] = array("name" => "CarteBlanche","length" => "14","prefixes" => "300,301,302,303,304,305,36,38","checkdigit" => true); | |
| $cards[4] = array("name" => "AmEx","length" => "15","prefixes" => "34,37","checkdigit" => true); | |
| $cards[5] = array("name" => "Discover","length" => "16","prefixes" => "6011,650","checkdigit" => true); | |
| $cards[6] = array("name" => "JCB","length" => "15,16","prefixes" => "3,1800,2131","checkdigit" => true); | |
| $cards[7] = array("name" => "enRoute","length" => "15","prefixes" => "2014,2149","checkdigit" => true); | |
| $cards[8] = array("name" => "Solo","length" => "16,18,19","prefixes" => "6334, 6767","checkdigit" => true); | |
| $cards[9] = array("name" => "Switch","length" => "16,18,19","prefixes" => "4903,4905,4911,4936,564182,633110,6333,6759","checkdigit" => true); | |
| $cards[10] = array("name" => "Maestro", "length" => "16,18","prefixes" => "5020,6","checkdigit" => true); | |
| $cards[11] = array("name" => "VisaElectron","length" => "16","prefixes" => "417500,4917,4913","checkdigit" => true); | |
| // Establish card type | |
| $cardType = -1; | |
| for ($i=0; $i<count($cards); $i++) { | |
| // See if it is this card (ignoring the case of the string) | |
| if (strtolower($cardname.toLowerCase) == strtolower($cards[i]["name"])) { | |
| $cardType = $i; | |
| break; | |
| } | |
| } | |
| // If card type not found, report an error | |
| if ($cardType == -1) { | |
| $ccErrorNo = 0; | |
| return false; | |
| } | |
| // Ensure that the user has provided a credit card number | |
| if (strlen($cardnumber) == 0) { | |
| $ccErrorNo = 1; | |
| return false; | |
| } | |
| // Now remove any spaces from the credit card number | |
| $cardnumber = preg_replace("/\s/g", "",$cardnumber); | |
| // Check that the number is numeric | |
| $cardNo = $cardnumber; | |
| $cardexp = "/^[0-9]{13,19}$/"; | |
| if(!preg_match('/^[0-9]{13,19}$/', $cardNo)) { | |
| $ccErrorNo = 2; | |
| return false; | |
| } | |
| // Now check the modulus 10 check digit - if required | |
| if ($cards[$cardType]["checkdigit"]) { | |
| $checksum = 0; // running checksum total | |
| $mychar = ""; // next char to process | |
| $j = 1; // takes value of 1 or 2 | |
| // Process each digit one by one starting at the right | |
| $calc; | |
| for ($i = strlen($cardNo) - 1; $i >= 0; $i--) { | |
| // Extract the next digit and multiply by 1 or 2 on alternative digits. | |
| $calc = int(substr($cardNo,$i,1)) * j; | |
| // If the result is in two digits add 1 to the checksum total | |
| if ($calc > 9) { | |
| $checksum = $checksum + 1; | |
| $calc = $calc - 10; | |
| } | |
| // Add the units element to the checksum total | |
| $checksum = $checksum + $calc; | |
| // Switch the value of j | |
| if ($j==1) {$j = 2;} else {$j = 1;} | |
| } | |
| // All done - if checksum is divisible by 10, it is a valid modulus 10. | |
| // If not, report an error. | |
| if ($checksum % 10 != 0) { | |
| $ccErrorNo = 3; | |
| return false; | |
| } | |
| } | |
| // The following are the card-specific checks we undertake. | |
| $LengthValid = false; | |
| $PrefixValid = false; | |
| $undefined; | |
| // We use these for holding the valid lengths and prefixes of a card type | |
| $prefix = array (); | |
| $lengths = array (); | |
| // Load an array with the valid prefixes for this card | |
| $prefix = split(",",$cards[$cardType]["prefixes"]); | |
| // Now see if any of them match what we have in the card number | |
| for ($i=0; $i<count($prefix); $i++) { | |
| $exp = "/^".$prefix[$i]."/"; | |
| if (preg_match($exp,$cardNo)) $PrefixValid = true; | |
| } | |
| // If it isn't a valid prefix there's no point at looking at the length | |
| if (!$PrefixValid) { | |
| $ccErrorNo = 3; | |
| return false; | |
| } | |
| // See if the length is valid for this card | |
| $lengths = split(",",$cards[$cardType]["length"]); | |
| for ($j=0; j<count(lengths); $j++) { | |
| if (strlen($cardNo) == $lengths[$j]) $LengthValid = true; | |
| } | |
| // See if all is OK by seeing if the length was valid. We only check the | |
| // length if all else was hunky dory. | |
| if (!$LengthValid) { | |
| $ccErrorNo = 4; | |
| return false; | |
| }; | |
| // The credit card is in the required format. | |
| return true; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment