Учитывая номер кредитной карты и отсутствие дополнительной информации, как лучше всего в PHP определить, является ли это действительным номером?
Прямо сейчас мне нужно что-то, что будет работать с American Express, Discover, MasterCard и Visa, но может быть полезно, если оно будет работать и с другими типами.






Это нужно только для того, чтобы убедиться, что числа действительны, с использованием некоторых базовых шаблонов RegEX.
Обратите внимание: это не проверяет, используются ли номера кем-то.
http://www.roscripts.com/How_to_validate_credit_card_numbers-106.html
Код PHP
function validateCC($cc_num, $type) {
if ($type == "American") {
$denum = "American Express";
} elseif ($type == "Dinners") {
$denum = "Diner's Club";
} elseif ($type == "Discover") {
$denum = "Discover";
} elseif ($type == "Master") {
$denum = "Master Card";
} elseif ($type == "Visa") {
$denum = "Visa";
}
if ($type == "American") {
$pattern = "/^([34|37]{2})([0-9]{13})$/";//American Express
if (preg_match($pattern,$cc_num)) {
$verified = true;
} else {
$verified = false;
}
} elseif ($type == "Dinners") {
$pattern = "/^([30|36|38]{2})([0-9]{12})$/";//Diner's Club
if (preg_match($pattern,$cc_num)) {
$verified = true;
} else {
$verified = false;
}
} elseif ($type == "Discover") {
$pattern = "/^([6011]{4})([0-9]{12})$/";//Discover Card
if (preg_match($pattern,$cc_num)) {
$verified = true;
} else {
$verified = false;
}
} elseif ($type == "Master") {
$pattern = "/^([51|52|53|54|55]{2})([0-9]{14})$/";//Mastercard
if (preg_match($pattern,$cc_num)) {
$verified = true;
} else {
$verified = false;
}
} elseif ($type == "Visa") {
$pattern = "/^([4]{1})([0-9]{12,15})$/";//Visa
if (preg_match($pattern,$cc_num)) {
$verified = true;
} else {
$verified = false;
}
}
if ($verified == false) {
//Do something here in case the validation fails
echo "Credit card invalid. Please make sure that you entered a valid <em>" . $denum . "</em> credit card ";
} else { //if it will pass...do something
echo "Your <em>" . $denum . "</em> credit card is valid";
}
}
использование
echo validateCC("1738292928284637", "Dinners");
Более подробную теоретическую информацию можно найти здесь:
Проверка кредитной карты - контрольные цифры
Проверка номера карты состоит из трех частей:
Большинство карт используют алгоритм Луна для вычисления контрольных сумм:
Алгоритм Луна описан в Википедии
В ссылке Википедии есть ссылки на многие реализации, включая PHP:
<?
/* Luhn algorithm number checker - (c) 2005-2008 shaman - www.planzero.org *
* This code has been released into the public domain, however please *
* give credit to the original author where possible. */
function luhn_check($number) {
// Strip any non-digits (useful for credit card numbers with spaces and hyphens)
$number=preg_replace('/\D/', '', $number);
// Set the string length and parity
$number_length=strlen($number);
$parity=$number_length % 2;
// Loop through each digit and do the maths
$total=0;
for ($i=0; $i<$number_length; $i++) {
$digit=$number[$i];
// Multiply alternate digits by two
if ($i % 2 == $parity) {
$digit*=2;
// If the sum is two digits, add them together (in effect)
if ($digit > 9) {
$digit-=9;
}
}
// Total up the digits
$total+=$digit;
}
// If the total mod 10 equals 0, the number is valid
return ($total % 10 == 0) ? TRUE : FALSE;
}
?>
Под шаблоном вы можете добавить «Discover», prefix = «6» (возможно, «60»), Length = 16.
MasterCard имеет префикс 51-55, а не 51 или 55 в соответствии с beachnet.com/~hstiles/cardtype.html
Эта функция удаляет все нецифровые символы из строки, поэтому номер карты «FRED» является действительным. Перед вызовом этой функции убедитесь, что вы проверили, что номер карты состоит только из цифр!
Хороший звонок Мэтт Коннолли. Вы можете просто проверить, подходит ли $number_length (или > 0, если на то пошло), внутри функции.
Ваш префикс MasterCard не включает 3 действительных префикса. 52, 53 и 54.
Номер кредитной карты, состоящий только из нулей, также считается действительным.
Большое спасибо, дружище, эта функция все еще работает! Я попробовал один из ELO, но он не проверял карты Amex, а вот этот!
Как проверить часть - 3? ДЕЙСТВИТЕЛЬНО СУЩЕСТВУЕТ
@BijuPDais, как указано в тексте - чтобы проверить, существует ли он на самом деле, вам, вероятно, нужно быть продавцом и фактически попытаться выставить счет на карту. Многие действия (например, отели) сначала взимают плату, а затем возвращают небольшую сумму на кредитную карту. Из всех методов проверки - это единственный ИСТИННЫЙ тест на действительность карты!
@Ray Hayes, спасибо за отзыв. Вот что я сделал. Я выполнил транзакцию в «тестовом режиме». Если номер карты неверный, я получу сообщение об ошибке. Единственная проблема заключается в том, что я не могу проверить, верны ли введенные CVV и даты истечения срока действия. То есть я могу только проверить действительность номера карты.
алгоритм Луна - это контрольная сумма, которая может использоваться для проверки формата множества форматов кредитных карт (а также номеров канадского социального страхования ...)
Статья в Википедии также содержит ссылки на множество различных реализаций; вот PHP:
http://planzero.org/code/bits/viewcode.php?src=luhn_check.phps
От 10 регулярных выражений, без которых невозможно жить в PHP:
function check_cc($cc, $extra_check = false){
$cards = array(
"visa" => "(4\d{12}(?:\d{3})?)",
"amex" => "(3[47]\d{13})",
"jcb" => "(35[2-8][89]\d\d\d{10})",
"maestro" => "((?:5020|5038|6304|6579|6761)\d{12}(?:\d\d)?)",
"solo" => "((?:6334|6767)\d{12}(?:\d\d)?\d?)",
"mastercard" => "(5[1-5]\d{14})",
"switch" => "(?:(?:(?:4903|4905|4911|4936|6333|6759)\d{12})|(?:(?:564182|633110)\d{10})(\d\d)?\d?)",
);
$names = array("Visa", "American Express", "JCB", "Maestro", "Solo", "Mastercard", "Switch");
$matches = array();
$pattern = "#^(?:".implode("|", $cards).")$#";
$result = preg_match($pattern, str_replace(" ", "", $cc), $matches);
if ($extra_check && $result > 0){
$result = (validatecard($cc))?1:0;
}
return ($result>0)?$names[sizeof($matches)-2]:false;
}
Пример ввода:
$cards = array(
"4111 1111 1111 1111",
);
foreach($cards as $c){
$check = check_cc($c, true);
if ($check!==false)
echo $c." - ".$check;
else
echo "$c - Not a match";
echo "<br/>";
}
Это дает нам
4111 1111 1111 1111 - Visa
Где функция validatecard?
Этот ответ не будет выполнен для новой идентификации mastercard 2-й серии mastercard.us/content/mccom/en-us/issuers/get-support/…
Существует пакет PEAR, который обрабатывает проверку многих финансовых номеров, а также проверку кредитных карт: http://pear.php.net/package/Validate_Finance_CreditCard
Кстати, вот несколько Номера счетов тестовых кредитных карт от PayPal.
Вероятно, лучше НЕ проверять код на вашей стороне. Отправьте информацию о карте прямо на ваш платежный шлюз, а затем обработайте их ответ. Это помогает им обнаруживать мошенничество, если вы сначала не выполняете ничего похожего на проверку Луна - пусть они увидят неудачные попытки.
Единственная проблема в том, что за каждую транзакцию взимается плата. Он может быть небольшим, но он складывается, и если кто-то использует большое количество мошеннических номеров карт через вашу систему, сборы могут стать непомерными.
Просто добавьте некоторые дополнительные фрагменты кода, которые другие могут найти полезными (не PHP-код).
ПИТОН (однострочный код; вероятно, не так эффективно)
Для проверки:
>>> not(sum(map(int, ''.join(str(n*(i%2+1)) for i, n in enumerate(map(int, reversed('1234567890123452'))))))%10)
True
>>> not(sum(map(int, ''.join(str(n*(i%2+1)) for i, n in enumerate(map(int, reversed('1234567890123451'))))))%10)
False
Чтобы вернуть требуемую контрольную цифру:
>>> (10-sum(map(int, ''.join(str(n*(i%2+1)) for i, n in enumerate(map(int, reversed('123456789012345')), start=1)))))%10
2
>>> (10-sum(map(int, ''.join(str(n*(i%2+1)) for i, n in enumerate(map(int, reversed('234567890123451')), start=1)))))%10
1
Функции MySQL
Функции "ccc" и "ccd" (проверка кредитной карты и цифра кредитной карты)
Обратите внимание, что функция «ccc» имеет дополнительную проверку, при которой, если вычисленная сумма равна 0, возвращаемый результат всегда будет ЛОЖЬ, поэтому полностью нулевое число CC никогда не будет подтверждено как правильное (при нормальном поведении оно будет проверяться правильно). Эта функция может быть добавлена / удалена по мере необходимости; может быть полезно, в зависимости от конкретных требований.
DROP FUNCTION IF EXISTS ccc;
DROP FUNCTION IF EXISTS ccd;
DELIMITER //
CREATE FUNCTION ccc (n TINYTEXT) RETURNS BOOL
BEGIN
DECLARE x TINYINT UNSIGNED;
DECLARE l TINYINT UNSIGNED DEFAULT length(n);
DECLARE i TINYINT UNSIGNED DEFAULT l;
DECLARE s SMALLINT UNSIGNED DEFAULT 0;
WHILE i > 0 DO
SET x = mid(n,i,1);
IF (l-i) mod 2 = 1 THEN
SET x = x * 2;
END IF;
SET s = s + x div 10 + x mod 10;
SET i = i - 1;
END WHILE;
RETURN s != 0 && s mod 10 = 0;
END;
CREATE FUNCTION ccd (n TINYTEXT) RETURNS TINYINT
BEGIN
DECLARE x TINYINT UNSIGNED;
DECLARE l TINYINT UNSIGNED DEFAULT length(n);
DECLARE i TINYINT UNSIGNED DEFAULT l;
DECLARE s SMALLINT UNSIGNED DEFAULT 0;
WHILE i > 0 DO
SET x = mid(n,i,1);
IF (l-i) mod 2 = 0 THEN
SET x = x * 2;
END IF;
SET s = s + x div 10 + x mod 10;
SET i = i - 1;
END WHILE;
RETURN ceil(s/10)*10-s;
END;
Затем функции можно использовать непосредственно в SQL-запросах:
mysql> SELECT ccc(1234567890123452);
+-----------------------+
| ccc(1234567890123452) |
+-----------------------+
| 1 |
+-----------------------+
1 row in set (0.00 sec)
mysql> SELECT ccc(1234567890123451);
+-----------------------+
| ccc(1234567890123451) |
+-----------------------+
| 0 |
+-----------------------+
1 row in set (0.00 sec)
mysql> SELECT ccd(123456789012345);
+----------------------+
| ccd(123456789012345) |
+----------------------+
| 2 |
+----------------------+
1 row in set (0.00 sec)
mysql> SELECT ccd(234567890123451);
+----------------------+
| ccd(234567890123451) |
+----------------------+
| 1 |
+----------------------+
1 row in set (0.00 sec)
Этот алгоритм может идентифицировать эмитента карты, грубо говоря, он не проверяет, имеет ли число смысл ... например, он не проверяет контрольную сумму с помощью алгоритма Луна!