Как лучше всего проверить кредитную карту в PHP?

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
69
0
72 980
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Это нужно только для того, чтобы убедиться, что числа действительны, с использованием некоторых базовых шаблонов 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");

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

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

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

Этот алгоритм может идентифицировать эмитента карты, грубо говоря, он не проверяет, имеет ли число смысл ... например, он не проверяет контрольную сумму с помощью алгоритма Луна!

Ray Hayes 06.10.2008 19:32
Ответ принят как подходящий

Проверка номера карты состоит из трех частей:

  1. ШАБЛОН - соответствует ли он шаблону эмитента (например, VISA / Mastercard и т. д.)
  2. КОНТРОЛЬНАЯ СУММА - действительно ли это контрольная сумма (например, не просто 13 случайных чисел после «34», чтобы сделать его номером карты AMEX)
  3. ДЕЙСТВИТЕЛЬНО СУЩЕСТВУЕТ - действительно ли у него есть связанный аккаунт (без мерчанта вы вряд ли получите его)

Шаблон

  • Префикс MASTERCARD = 51-55, длина = 16 (контрольная сумма Mod10)
  • Префикс VISA = 4, длина = 13 или 16 (Mod10)
  • Префикс AMEX = 34 или 37, длина = 15 (Mod10)
  • Префикс Diners Club / Carte = 300-305, 36 или 38, длина = 14 (Mod10)
  • Префикс обнаружения = 6011,622126-622925,644-649,65, длина = 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;

}
?>

Под шаблоном вы можете добавить «Discover», prefix = «6» (возможно, «60»), Length = 16.

James Curran 06.10.2008 19:48

MasterCard имеет префикс 51-55, а не 51 или 55 в соответствии с beachnet.com/~hstiles/cardtype.html

Ben 24.09.2010 01:22

Эта функция удаляет все нецифровые символы из строки, поэтому номер карты «FRED» является действительным. Перед вызовом этой функции убедитесь, что вы проверили, что номер карты состоит только из цифр!

Matt Connolly 08.02.2012 07:53

Хороший звонок Мэтт Коннолли. Вы можете просто проверить, подходит ли $number_length (или > 0, если на то пошло), внутри функции.

ayman 23.02.2012 12:04

Ваш префикс MasterCard не включает 3 действительных префикса. 52, 53 и 54.

David Barnes 13.03.2013 02:04

Номер кредитной карты, состоящий только из нулей, также считается действительным.

Gazillion 15.11.2013 00:59

Большое спасибо, дружище, эта функция все еще работает! Я попробовал один из ELO, но он не проверял карты Amex, а вот этот!

William 12.11.2016 13:52

Как проверить часть - 3? ДЕЙСТВИТЕЛЬНО СУЩЕСТВУЕТ

Biju P Dais 31.01.2018 16:40

@BijuPDais, как указано в тексте - чтобы проверить, существует ли он на самом деле, вам, вероятно, нужно быть продавцом и фактически попытаться выставить счет на карту. Многие действия (например, отели) сначала взимают плату, а затем возвращают небольшую сумму на кредитную карту. Из всех методов проверки - это единственный ИСТИННЫЙ тест на действительность карты!

Ray Hayes 03.02.2018 16:52

@Ray Hayes, спасибо за отзыв. Вот что я сделал. Я выполнил транзакцию в «тестовом режиме». Если номер карты неверный, я получу сообщение об ошибке. Единственная проблема заключается в том, что я не могу проверить, верны ли введенные CVV и даты истечения срока действия. То есть я могу только проверить действительность номера карты.

Biju P Dais 06.02.2018 11:19

алгоритм Луна - это контрольная сумма, которая может использоваться для проверки формата множества форматов кредитных карт (а также номеров канадского социального страхования ...)

Статья в Википедии также содержит ссылки на множество различных реализаций; вот 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?

joseantgv 05.09.2017 17:16

Этот ответ не будет выполнен для новой идентификации mastercard 2-й серии mastercard.us/content/mccom/en-us/issuers/get-support/…

Samy Massoud 04.12.2017 08:58

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

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

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

Единственная проблема в том, что за каждую транзакцию взимается плата. Он может быть небольшим, но он складывается, и если кто-то использует большое количество мошеннических номеров карт через вашу систему, сборы могут стать непомерными.

John Conde 15.12.2011 00:02

Просто добавьте некоторые дополнительные фрагменты кода, которые другие могут найти полезными (не 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)

Другие вопросы по теме