Created
August 29, 2014 05:46
-
-
Save ivansky/468df87fe57cd1c90bd5 to your computer and use it in GitHub Desktop.
Check credit card type
This file contains 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
<?php | |
/** | |
* Validates a credit card number using an array of approved card types. | |
* | |
* @param $number | |
* The credit card number to validate. | |
* @param $card_types | |
* An array of credit card types containing any of the keys from the array | |
* returned by commerce_payment_credit_card_types(). Only numbers determined | |
* to be of the types specified will pass validation. This determination is | |
* based on the length of the number and the valid number ranges for the | |
* various types of known credit card types. | |
* | |
* @return | |
* FALSE if a number is not valid based on approved credit card types or the | |
* credit card type if it is valid and coud be determined. | |
* | |
* @see http://en.wikipedia.org/wiki/Bank_card_number#Issuer_Identification_Number_.28IIN.29 | |
* @see commerce_payment_credit_card_types() | |
*/ | |
function commerce_payment_validate_credit_card_type($number, $card_types) { | |
$strlen = strlen($number); | |
// Provide a check on the first digit (and card length if applicable). | |
switch (substr($number, 0, 1)) { | |
case '3': | |
// American Express begins with 3 and is 15 numbers. | |
if ($strlen == 15 && in_array('amex', $card_types)) { | |
return 'amex'; | |
} | |
// JCB begins with 3528-3589 and is 16 numbers. | |
if ($strlen == 16 && in_array('jcb', $card_types)) { | |
return 'jcb'; | |
} | |
// Carte Blanche begins with 300-305 and is 14 numbers. | |
// Diners Club International begins 36 and is 14 numbers. | |
if ($strlen == 14) { | |
$initial = (int) substr($number, 0, 3); | |
if ($initial >= 300 && $initial <= 305 && in_array('cb', $card_types)) { | |
return 'cb'; | |
} | |
if (substr($number, 0, 2) == '36' && in_array('dci', $card_types)) { | |
return 'dci'; | |
} | |
} | |
return FALSE; | |
case '4': | |
$initial = (int) substr($number, 0, 4); | |
$return = FALSE; | |
if ($strlen == 16) { | |
// Visa begins with 4 and is 16 numbers. | |
if (in_array('visa', $card_types)) { | |
$return = 'visa'; | |
} | |
// Visa Electron begins with 4026, 417500, 4256, 4508, 4844, 4913, or | |
// 4917 and is 16 numbers. | |
if (in_array($initial, array(4026, 4256, 4508, 4844, 4913, 4917)) || substr($number, 0, 6) == '417500') { | |
$return = in_array('visaelectron', $card_types) ? 'visaelectron' : FALSE; | |
} | |
} | |
// Switch begins with 4903, 4905, 4911, or 4936 and is 16, 18, or 19 | |
// numbers. | |
if (in_array($strlen, array(16, 18, 19)) && | |
in_array($initial, array(4903, 4905, 4911, 4936))) { | |
$return = in_array('switch', $card_types) ? 'switch' : FALSE; | |
} | |
return $return; | |
case '5': | |
// MasterCard begins with 51-55 and is 16 numbers. | |
// Diners Club begins with 54 or 55 and is 16 numbers. | |
if ($strlen == 16) { | |
$initial = (int) substr($number, 0, 2); | |
if ($initial >= 51 && $initial <= 55 && in_array('mastercard', $card_types)) { | |
return 'mastercard'; | |
} | |
if ($initial >= 54 && $initial <= 55 && in_array('dc', $card_types)) { | |
return 'dc'; | |
} | |
} | |
// Switch begins with 564182 and is 16, 18, or 19 numbers. | |
if (in_array('switch', $card_types) && substr($number, 0, 6) == '564182' && | |
in_array($strlen, array(16, 18, 19))) { | |
return 'switch'; | |
} | |
// Maestro begins with 5018, 5020, or 5038 and is 12-19 numbers. | |
if (in_array('maestro', $card_types) && $strlen >= 12 && $strlen <= 19 && | |
in_array(substr($number, 0, 4), array(5018, 5020, 5038))) { | |
return 'maestro'; | |
} | |
return FALSE; | |
case '6': | |
// Discover begins with 6011, 622126-622925, 644-649, or 65 and is 16 | |
// numbers. | |
if ($strlen == 16 && in_array('discover', $card_types)) { | |
if (substr($number, 0, 4) == '6011' || substr($number, 0, 2) == '65') { | |
return 'discover'; | |
} | |
$initial = (int) substr($number, 0, 6); | |
if ($initial >= 622126 && $initial <= 622925) { | |
return 'discover'; | |
} | |
$initial = (int) substr($number, 0, 3); | |
if ($initial >= 644 && $initial <= 649) { | |
return 'discover'; | |
} | |
} | |
// Laser begins with 6304, 6706, 6771, or 6709 and is 16-19 numbers. | |
$initial = (int) substr($number, 0, 4); | |
if (in_array('laser', $card_types) && $strlen >= 16 && $strlen <= 19 && | |
in_array($initial, array(6304, 6706, 6771, 6709))) { | |
return 'laser'; | |
} | |
// Maestro begins with 6304, 6759, 6761, or 6763 and is 12-19 numbers. | |
if (in_array('maestro', $card_types) && $strlen >= 12 && $strlen <= 19 && | |
in_array($initial, array(6304, 6759, 6761, 6763))) { | |
return 'maestro'; | |
} | |
// Solo begins with 6334 or 6767 and is 16, 18, or 19 numbers. | |
if (in_array('solo', $card_types) && in_array($strlen, array(16, 18, 19)) && | |
in_array($initial, array(6334, 6767))) { | |
return 'solo'; | |
} | |
// Switch begins with 633110, 6333, or 6759 and is 16, 18, or 19 numbers. | |
if (in_array('switch', $card_types) && in_array($strlen, array(16, 18, 19)) && | |
(in_array($initial, array(6333, 6759)) || substr($number, 0, 6) == 633110)) { | |
return 'switch'; | |
} | |
return FALSE; | |
} | |
return FALSE; | |
} | |
/** | |
* Validates a credit card number using the Luhn algorithm. | |
* | |
* @param $number | |
* The credit card number to validate. | |
* | |
* @return | |
* TRUE or FALSE indicating the number's validity. | |
* | |
* @see http://www.merriampark.com/anatomycc.htm | |
*/ | |
function commerce_payment_validate_credit_card_number($number) { | |
// Ensure every character in the number is numeric. | |
if (!ctype_digit($number)) { | |
return FALSE; | |
} | |
// Validate the number using the Luhn algorithm. | |
$total = 0; | |
for ($i = 0; $i < strlen($number); $i++) { | |
$digit = substr($number, $i, 1); | |
if ((strlen($number) - $i - 1) % 2) { | |
$digit *= 2; | |
if ($digit > 9) { | |
$digit -= 9; | |
} | |
} | |
$total += $digit; | |
} | |
if ($total % 10 != 0) { | |
return FALSE; | |
} | |
return TRUE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment