73

クレジットカード番号があり、追加情報がない場合、それが有効な番号であるかどうかを判断するためのPHPの最良の方法は何ですか?

今のところ、American Express、Discover、MasterCard、Visaで動作するものが必要ですが、他のタイプでも動作する場合は役立つかもしれません。

4

8 に答える 8

154

カード番号の検証には、次の3つの部分があります。

  1. パターン-発行者のパターンと一致しますか(VISA / Mastercardなど)
  2. チェックサム-実際にチェックサムを実行しますか(たとえば、「34」の後の13個の乱数だけでなくAMEXカード番号にします)
  3. 本当に存在します-実際に関連付けられたアカウントがありますか(マーチャントアカウントなしでこれを取得する可能性は低いです)

パターン

  • MASTERCARDプレフィックス=51-55、長さ= 16(Mod10チェックサム)
  • VISAプレフィックス=4、長さ= 13または16(Mod10)
  • AMEXプレフィックス=34または37、長さ= 15(Mod10)
  • ダイナースクラブ/カルテプレフィックス=300-305、36または38、長さ= 14(Mod10)
  • Discover Prefix = 6011,622126-622925,644-649,65、Length = 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;

}
?>
于 2008-10-06T15:25:26.507 に答える
30

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 111111111111-ビザ
于 2008-10-06T15:31:43.530 に答える
13

最後にコードで検証しない方がよいでしょう。カード情報を支払いゲートウェイに直接送信し、その応答に対処します。最初に Luhn チェックのようなことをしないと、詐欺を検出するのに役立ちます。失敗した試みを彼らに見せてください。

于 2009-03-02T18:06:03.780 に答える
6

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

より多くの理論的情報はここで見つけることができます:

クレジットカードの検証-チェックディジット

チェックサム

于 2008-10-06T15:25:10.220 に答える
3

luhnアルゴリズムは、多くのクレジットカード形式の形式(およびカナダの社会保険番号...)を検証するために使用できるチェックサムです。

ウィキペディアの記事は、さまざまな実装にもリンクしています。これがPHPのものです:

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

于 2008-10-06T15:27:50.230 に答える
2

多くの財務番号の検証とクレジットカードの検証を処理するPEARパッケージがあります:http://pear.php.net/package/Validate_Finance_CreditCard

ちなみに、PayPalによるテストクレジットカードのアカウント番号は次のとおりです。

于 2008-10-07T11:56:40.360 に答える
0

他の人が役立つと思われるコードスニペットを追加するだけです (PHP コードではありません)。

PYTHON (1 行のコード。おそらくそれほど効率的ではありません)

検証します:

>>> 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" (credit-card-check および credit-card-digit)

「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 (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)
于 2014-12-12T14:28:09.397 に答える
-1

これは、いくつかの基本的な正規表現パターンを使用して番号が有効であることを確認するためだけのものです。

これは、番号が誰かによって使用されているかどうかを確認するものではないことに注意してください。

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

于 2008-10-06T15:23:31.783 に答える