在 PHP 中验证信用卡的最佳方法是什么?

给定一个信用卡号并且没有其他信息,在PHP中确定它是否是有效数字的最佳方法是什么?

现在,我需要一些可以与美国运通,Discover,万事达卡和Visa配合使用的东西,但如果它也可以与其他类型的一起使用,可能会有所帮助。


答案 1

验证卡号有三个部分:

  1. 模式 - 它是否与发卡机构模式(例如VISA/万事达卡/等)相匹配
  2. CHECKSUM - 它实际上是校验和吗(例如,不仅仅是“34”后面的13个随机数,使其成为AMEX卡号)
  3. 确实存在 - 它是否真的有一个关联的帐户(如果没有商家帐户,您不太可能获得此帐户)

模式

  • 万事达卡前缀=51-55,长度=16(Mod10校验和)
  • VISA 前缀 = 4,长度 = 13 或 16 (Mod10)
  • AMEX 前缀 = 34 或 37,长度 = 15 (Mod10)
  • 大来俱乐部/Carte 前缀=300-305、36 或 38,长度=14 (Mod10)
  • 发现前缀 = 6011,622126-622925,644-649,65,长度 = 16, (Mod10)
  • 等(前缀的详细列表))

校验和

大多数卡使用 Luhn 算法进行校验和:

维基百科上描述的Luhn算法

维基百科链接上有许多实现的链接,包括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;

}
?>

答案 2

PHP中你不能没有的10个正则表达式中

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

推荐