PHP에서 신용 카드를 검증하는 가장 좋은 방법은 무엇입니까?
-
05-07-2019 - |
문제
신용 카드 번호와 추가 정보가 주어지면 PHP에서 유효한 번호 여부를 결정하는 가장 좋은 방법은 무엇입니까?
지금은 American Express, Discover, Mastercard 및 Visa와 함께 작동하는 것이 필요하지만 다른 유형과도 작동하는 경우 도움이 될 수 있습니다.
해결책
카드 번호의 검증에는 세 부분이 있습니다.
- 무늬 - 발행자 패턴과 일치합니까 (예 : 비자/마스터 카드 등).
- 체크섬 - 실제로 확인을합니까 (예 : Amex 카드 번호로 만들기 위해 "34"이후 13 개의 랜덤 숫자가 아니라)
- 정말 존재합니다 - 실제로 관련 계정이 있습니까 (상인 계정없이이를 얻지 못할 가능성이 높습니다).
무늬
- 마스터 카드 접두사 = 51-55, 길이 = 16 (mod10 checksummed)
- 비자 접두사 = 4, 길이 = 13 또는 16 (mod10)
- Amex 접두사 = 34 또는 37, 길이 = 15 (mod10)
- Diners Club/Carte Prefix = 300-305, 36 또는 38, 길이 = 14 (mod10)
- 접두사 발견 = 6011,62126-622925,644-649,65, 길이 = 16, (mod10)
- 등. (접두사의 자세한 목록)
체크섬
대부분의 카드는 Luhn 알고리즘을 사용하여 체크섬을 사용합니다.
PHP를 포함하여 Wikipedia 링크에는 많은 구현에 대한 링크가 있습니다.
<?
/* 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;
}
?>
다른 팁
에서 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
당신의 끝에 코드에서 검증하지 않는 것이 더 낫습니다. 카드 정보를 결제 게이트웨이로 바로 보내고 응답을 처리하십시오. Luhn이 먼저 확인하는 것과 같은 일을하지 않으면 사기를 감지하는 데 도움이됩니다. 실패한 시도를 볼 수 있습니다.
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 알고리즘 많은 신용 카드 형식의 형식을 검증하는 데 사용할 수있는 체크섬 (및 캐나다 사회 보험 번호도 ...)입니다.
Wikipedia 기사는 또한 많은 다른 구현과 연결됩니다. PHP는 다음과 같습니다.
http://planzero.org/code/bits/viewcode.php?src=luhn_check.phps
많은 재무 번호의 검증을 처리하는 배 패키지가 있으며 신용 카드 검증도 있습니다. http://pear.php.net/package/validate_finance_creditcard
그건 그렇고, 여기에 있습니다 신용 카드 계정 번호를 테스트하십시오 PayPal에 의해.
다른 사람들이 유용하다고 생각할 수있는 몇 가지 추가 코드 스 니펫을 던지면 (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)
이것은 일부 기본 정규 패턴을 사용하여 숫자가 유효하도록하기위한 것입니다.
이것은 누군가가 숫자를 사용하는지 확인하지 않습니다.
http://www.roscripts.com/how_to_validate_credit_card_numbers-106.html