What is the best way to validate a credit card in PHP?

Given a credit card number and no additional information, what is the best way in PHP to determine whether or not it is a valid number?

Right now I need something that will work with American Express, Discover, MasterCard, and Visa, but it might be helpful if it will also work with other types.


There are three parts to the validation of the card number:

  • PATTERN - does it match an issuers pattern (eg VISA/Mastercard/etc.)
  • CHECKSUM - does it actually check-sum (eg not just 13 random numbers after "34" to make it an AMEX card number)
  • REALLY EXISTS - does it actually have an associated account (you are unlikely to get this without a merchant account)
  • Pattern

  • MASTERCARD Prefix=51-55, Length=16 (Mod10 checksummed)
  • VISA Prefix=4, Length=13 or 16 (Mod10)
  • AMEX Prefix=34 or 37, Length=15 (Mod10)
  • Diners Club/Carte Prefix=300-305, 36 or 38, Length=14 (Mod10)
  • Discover Prefix=6011,622126-622925,644-649,65, Length=16, (Mod10)
  • etc. (detailed list of prefixes)
  • Checksum

    Most cards use the Luhn algorithm for checksums:

    Luhn Algorithm described on Wikipedia

    There are links to many implementations on the Wikipedia link, including 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;
    
    }
    ?>
    

    From 10 regular expressions you can't live without in PHP:

    function check_cc($cc, $extra_check = false){
        $cards = array(
            "visa" => "(4d{12}(?:d{3})?)",
            "amex" => "(3[47]d{13})",
            "jcb" => "(35[2-8][89]ddd{10})",
            "maestro" => "((?:5020|5038|6304|6579|6761)d{12}(?:dd)?)",
            "solo" => "((?:6334|6767)d{12}(?:dd)?d?)",
            "mastercard" => "(5[1-5]d{14})",
            "switch" => "(?:(?:(?:4903|4905|4911|4936|6333|6759)d{12})|(?:(?:564182|633110)d{10})(dd)?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;
    }
    

    Sample input:

    $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/>";
    }
    

    This gives us

    4111 1111 1111 1111 - Visa
    

    It's probably better NOT to validate in code at your end. Send the card info right over to your payment gateway and then deal with their response. It helps them detect fraud if you don't do anything like Luhn checking first -- let them see the failed attempts.

    链接地址: http://www.djcxy.com/p/12206.html

    上一篇: 通过号码确定信用卡类型?

    下一篇: 在PHP中验证信用卡的最佳方式是什么?