Intereting Posts
Meta Refresh с целевой рамой Как работать с $ _SERVER У Firefox есть проблемы при загрузке с пространством в имени файла Можете ли вы определить или изменить константу в PHP? Имитировать конструкцию языка php-массива или проанализировать с помощью регулярного выражения? Получение последнего вложенного идентификатора из MySQL в Yii Проверьте язык строки на основе глифов в PHP Тестирование производительности на стороне сервера веб-приложения php Laravel: Запуск очереди: постоянное прослушивание в Windows Azure Web App не удалось отправить почту в php, используя класс почтовой программы Почему в ячейке используется левая и верхняя набивка с использованием TCPDF в php? php echo результат при повторении через цикл API-интерфейс Google API с использованием метода CURL post как передать переменные с php-страницы на javascript и отобразить данные Вызов функции из строки в C #

Каков наилучший способ проверки кредитной карты на PHP?

Учитывая номер кредитной карты и никакой дополнительной информации, как лучше всего в PHP определить, действительно ли он действительный номер?

Сейчас мне нужно что-то, что будет работать с American Express, Discover, MasterCard и Visa, но может быть полезно, если оно будет работать и с другими типами.

Solutions Collecting From Web of "Каков наилучший способ проверки кредитной карты на PHP?"

Для подтверждения номера карты есть три части:

  1. PATTERN – соответствует ли шаблон эмитентов (например, VISA / Mastercard / etc.)
  2. CHECKSUM – действительно ли это контрольная сумма (например, не только 13 случайных чисел после «34», чтобы сделать их номером карты AMEX)
  3. ДЕЙСТВИТЕЛЬНО СУЩЕСТВУЕТ – у него фактически есть связанная учетная запись (вы вряд ли получите это без учетной записи продавца)

Шаблон

  • Префикс MASTERCARD = 51-55, длина = 16 (контрольная сумма Mod10)
  • Префикс VISA = 4, Длина = 13 или 16 (Mod10)
  • Префикс AMEX = 34 или 37, длина = 15 (Mod10)
  • Diners Club / Carte Prefix = 300-305, 36 или 38, Length = 14 (Mod10)
  • Discover Prefix = 6011,622126-622925,644-649,65, Length = 16, (Mod10)
  • и т. д. ( подробный список префиксов )

Контрольная сумма

Большинство карт используют алгоритм Луна для контрольных сумм:

Алгоритм Луна описан в Википедии

Есть ссылки на многие реализации в ссылке Википедии, включая 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; } ?> 

Из 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

Вероятно, лучше не проверять код в конце. Отправьте информацию о карте прямо на ваш платежный шлюз, а затем обработайте их ответ. Это помогает им обнаруживать мошенничество, если вы не делаете ничего подобного, как сначала проверяете Луна, – пусть они видят неудачные попытки.

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"); 

Более теоретическую информацию можно найти здесь:

Проверка кредитной карты – контрольные цифры

Контрольная сумма

Для подтверждения кредитной карты мы можем использовать следующее. Он отлично работает для меня.

 protected function luhn($number) { // Force the value to be a string as this method uses string functions. // Converting to an integer may pass PHP_INT_MAX and result in an error! $number = (string)$number; if (!ctype_digit($number)) { // Luhn can only be used on numbers! return FALSE; } // Check number length $length = strlen($number); // Checksum of the card number $checksum = 0; for ($i = $length - 1; $i >= 0; $i -= 2) { // Add up every 2nd digit, starting from the right $checksum += substr($number, $i, 1); } for ($i = $length - 2; $i >= 0; $i -= 2) { // Add up every 2nd digit doubled, starting from the right $double = substr($number, $i, 1) * 2; // Subtract 9 from the double where value is greater than 10 $checksum += ($double >= 10) ? ($double - 9) : $double; } // If the checksum is a multiple of 10, the number is valid return ($checksum % 10 === 0); } protected function ValidCreditcard($number) { $card_array = array( 'default' => array( 'length' => '13,14,15,16,17,18,19', 'prefix' => '', 'luhn' => TRUE, ), 'american express' => array( 'length' => '15', 'prefix' => '3[47]', 'luhn' => TRUE, ), 'diners club' => array( 'length' => '14,16', 'prefix' => '36|55|30[0-5]', 'luhn' => TRUE, ), 'discover' => array( 'length' => '16', 'prefix' => '6(?:5|011)', 'luhn' => TRUE, ), 'jcb' => array( 'length' => '15,16', 'prefix' => '3|1800|2131', 'luhn' => TRUE, ), 'maestro' => array( 'length' => '16,18', 'prefix' => '50(?:20|38)|6(?:304|759)', 'luhn' => TRUE, ), 'mastercard' => array( 'length' => '16', 'prefix' => '5[1-5]', 'luhn' => TRUE, ), 'visa' => array( 'length' => '13,16', 'prefix' => '4', 'luhn' => TRUE, ), ); // Remove all non-digit characters from the number if (($number = preg_replace('/\D+/', '', $number)) === '') return FALSE; // Use the default type $type = 'default'; $cards = $card_array; // Check card type $type = strtolower($type); if (!isset($cards[$type])) return FALSE; // Check card number length $length = strlen($number); // Validate the card length by the card type if (!in_array($length, preg_split('/\D+/', $cards[$type]['length']))) return FALSE; // Check card number prefix if (!preg_match('/^' . $cards[$type]['prefix'] . '/', $number)) return FALSE; // No Luhn check required if ($cards[$type]['luhn'] == FALSE) return TRUE; return $this->luhn($number); } 

Алгоритм luhn – это контрольная сумма, которая может использоваться для проверки формата большого количества форматов кредитных карт (а также номеров канадского социального страхования …)

Статья в Википедии также ссылается на множество различных реализаций; вот PHP:

http://planzero.org/code/bits/viewcode.php?src=luhn_check.phps

Существует пакет PEAR, который обрабатывает проверку многих финансовых номеров, а также подтверждение кредитной карты: http://pear.php.net/package/Validate_Finance_CreditCard

Кстати, вот несколько тестовых номеров кредитных карт по PayPal.

Просто добавьте некоторые дополнительные фрагменты кода, которые другие могут найти полезными (а не PHP-код).

PYTHON (однострочный код, возможно, не такой эффективный)

Чтобы проверить:

 >>> 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, возвращаемый результат всегда будет FALSE, поэтому все нулевые номера 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 (li) 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 (li) 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) 

Это только для того, чтобы убедиться, что числа действительны, используя некоторые базовые шаблоны RegEX.

Обратите внимание, что это не проверяет, используются ли какие-либо данные кем-либо.

http://www.roscripts.com/How_to_validate_credit_card_numbers-106.html