验证 IBAN PHP
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20983339/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Validate IBAN PHP
提问by Peter Fox
As designing a new platform we tried to integrate the IBAN numbers. We have to make sure that the IBAN is validated and the IBAN stored to the database is always correct. So what would be a proper way to validate the number?
在设计新平台时,我们尝试整合 IBAN 号码。我们必须确保 IBAN 得到验证并且存储到数据库中的 IBAN 始终正确。那么验证数字的正确方法是什么?
回答by Peter Fox
As the logic was explained in my other question I've tried to create a function myself. Based on the logic explained in the wikipedia article find a proper function below. Country specific validation.
由于在我的另一个问题中解释了逻辑,我尝试自己创建一个函数。根据维基百科文章中解释的逻辑,在下面找到一个合适的函数。特定国家/地区的验证。
Will it fit the
是否适合
http://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
http://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
function checkIBAN($iban)
{
$iban = strtolower(str_replace(' ','',$iban));
$Countries = array('al'=>28,'ad'=>24,'at'=>20,'az'=>28,'bh'=>22,'be'=>16,'ba'=>20,'br'=>29,'bg'=>22,'cr'=>21,'hr'=>21,'cy'=>28,'cz'=>24,'dk'=>18,'do'=>28,'ee'=>20,'fo'=>18,'fi'=>18,'fr'=>27,'ge'=>22,'de'=>22,'gi'=>23,'gr'=>27,'gl'=>18,'gt'=>28,'hu'=>28,'is'=>26,'ie'=>22,'il'=>23,'it'=>27,'jo'=>30,'kz'=>20,'kw'=>30,'lv'=>21,'lb'=>28,'li'=>21,'lt'=>20,'lu'=>20,'mk'=>19,'mt'=>31,'mr'=>27,'mu'=>30,'mc'=>27,'md'=>24,'me'=>22,'nl'=>18,'no'=>15,'pk'=>24,'ps'=>29,'pl'=>28,'pt'=>25,'qa'=>29,'ro'=>24,'sm'=>27,'sa'=>24,'rs'=>22,'sk'=>24,'si'=>19,'es'=>24,'se'=>24,'ch'=>21,'tn'=>24,'tr'=>26,'ae'=>23,'gb'=>22,'vg'=>24);
$Chars = array('a'=>10,'b'=>11,'c'=>12,'d'=>13,'e'=>14,'f'=>15,'g'=>16,'h'=>17,'i'=>18,'j'=>19,'k'=>20,'l'=>21,'m'=>22,'n'=>23,'o'=>24,'p'=>25,'q'=>26,'r'=>27,'s'=>28,'t'=>29,'u'=>30,'v'=>31,'w'=>32,'x'=>33,'y'=>34,'z'=>35);
if(strlen($iban) == $Countries[substr($iban,0,2)]){
$MovedChar = substr($iban, 4).substr($iban,0,4);
$MovedCharArray = str_split($MovedChar);
$NewString = "";
foreach($MovedCharArray AS $key => $value){
if(!is_numeric($MovedCharArray[$key])){
$MovedCharArray[$key] = $Chars[$MovedCharArray[$key]];
}
$NewString .= $MovedCharArray[$key];
}
if(bcmod($NewString, '97') == 1)
{
return true;
}
}
return false;
}
回答by Сухой27
Slight modification of @PeterFox answer including support for bcmod()when bcmathis not available,
对@PeterFox 答案的轻微修改,包括对bcmod()何时bcmath不可用的支持,
<?php
function isValidIBAN ($iban) {
$iban = strtolower($iban);
$Countries = array(
'al'=>28,'ad'=>24,'at'=>20,'az'=>28,'bh'=>22,'be'=>16,'ba'=>20,'br'=>29,'bg'=>22,'cr'=>21,'hr'=>21,'cy'=>28,'cz'=>24,
'dk'=>18,'do'=>28,'ee'=>20,'fo'=>18,'fi'=>18,'fr'=>27,'ge'=>22,'de'=>22,'gi'=>23,'gr'=>27,'gl'=>18,'gt'=>28,'hu'=>28,
'is'=>26,'ie'=>22,'il'=>23,'it'=>27,'jo'=>30,'kz'=>20,'kw'=>30,'lv'=>21,'lb'=>28,'li'=>21,'lt'=>20,'lu'=>20,'mk'=>19,
'mt'=>31,'mr'=>27,'mu'=>30,'mc'=>27,'md'=>24,'me'=>22,'nl'=>18,'no'=>15,'pk'=>24,'ps'=>29,'pl'=>28,'pt'=>25,'qa'=>29,
'ro'=>24,'sm'=>27,'sa'=>24,'rs'=>22,'sk'=>24,'si'=>19,'es'=>24,'se'=>24,'ch'=>21,'tn'=>24,'tr'=>26,'ae'=>23,'gb'=>22,'vg'=>24
);
$Chars = array(
'a'=>10,'b'=>11,'c'=>12,'d'=>13,'e'=>14,'f'=>15,'g'=>16,'h'=>17,'i'=>18,'j'=>19,'k'=>20,'l'=>21,'m'=>22,
'n'=>23,'o'=>24,'p'=>25,'q'=>26,'r'=>27,'s'=>28,'t'=>29,'u'=>30,'v'=>31,'w'=>32,'x'=>33,'y'=>34,'z'=>35
);
if (strlen($iban) != $Countries[ substr($iban,0,2) ]) { return false; }
$MovedChar = substr($iban, 4) . substr($iban,0,4);
$MovedCharArray = str_split($MovedChar);
$NewString = "";
foreach ($MovedCharArray as $k => $v) {
if ( !is_numeric($MovedCharArray[$k]) ) {
$MovedCharArray[$k] = $Chars[$MovedCharArray[$k]];
}
$NewString .= $MovedCharArray[$k];
}
if (function_exists("bcmod")) { return bcmod($NewString, '97') == 1; }
// http://au2.php.net/manual/en/function.bcmod.php#38474
$x = $NewString; $y = "97";
$take = 5; $mod = "";
do {
$a = (int)$mod . substr($x, 0, $take);
$x = substr($x, $take);
$mod = $a % $y;
}
while (strlen($x));
return (int)$mod == 1;
}
回答by esserj
The accepted answer is not the preferred way of validation, the specificationdictates the following:
接受的答案不是首选的验证方式,规范规定了以下内容:
1. Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid
2. Replace the two check digits by 00 (e.g. GB00 for the UK)
3. Move the four initial characters to the end of the string
4. Replace the letters in the string with digits, expanding the string as necessary, such that A or a = 10,
B or b = 11, and Z or z = 35. Each alphabetic character is therefore replaced by 2 digits
5. Convert the string to an integer (i.e. ignore leading zeroes)
6. Calculate mod-97 of the new number, which results in the remainder
7. Subtract the remainder from 98, and use the result for the two check digits. If the result is a single digit
number, pad it with a leading 0 to make a two-digit number
I've written a class that validates, formats and parses strings according to the spec, hope this helps save some the time to roll their own. Code found here:
我编写了一个根据规范验证、格式化和解析字符串的类,希望这有助于节省一些时间来推出自己的。代码在这里找到:
回答by SVetter
Sorry, I can not yet comment due to low Rep, so the new link to user3733632s answer:
抱歉,由于 Rep 低,我还不能发表评论,所以新的 user3733632s 链接回答:
https://github.com/globalcitizen/php-iban
https://github.com/globalcitizen/php-iban
(the project is no longer hosted at google code as of March 2015, and the project will get a new version after some cleanup.)
(截至 2015 年 3 月,该项目不再托管在 google code,该项目将在一些清理后获得新版本。)
回答by jhabai
top rated function does NOT work.
最受好评的功能不起作用。
Just try a string with '%' in it...
只需尝试一个带有 '%' 的字符串...
I'm using this one :
我正在使用这个:
function checkIBAN($iban) {
// Normalize input (remove spaces and make upcase)
$iban = strtoupper(str_replace(' ', '', $iban));
if (preg_match('/^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$/', $iban)) {
$country = substr($iban, 0, 2);
$check = intval(substr($iban, 2, 2));
$account = substr($iban, 4);
// To numeric representation
$search = range('A','Z');
foreach (range(10,35) as $tmp)
$replace[]=strval($tmp);
$numstr=str_replace($search, $replace, $account.$country.'00');
// Calculate checksum
$checksum = intval(substr($numstr, 0, 1));
for ($pos = 1; $pos < strlen($numstr); $pos++) {
$checksum *= 10;
$checksum += intval(substr($numstr, $pos,1));
$checksum %= 97;
}
return ((98-$checksum) == $check);
} else
return false;
}
回答by user3733632
Google Code hosts a project of an open source php-iban validator: https://code.google.com/p/php-iban/
Google Code 托管了一个开源 php-iban 验证器项目:https: //code.google.com/p/php-iban/
回答by Fabrice G
This function check the IBAN and need GMP activate http://php.net/manual/en/book.gmp.php.
此功能检查 IBAN 并需要 GMP 激活http://php.net/manual/en/book.gmp.php。
function checkIban($string){
$to_check = substr($string, 4).substr($string, 0,4);
$converted = '';
for ($i = 0; $i < strlen($to_check); $i++){
$char = strtoupper($to_check[$i]);
if(preg_match('/[0-9A-Z]/',$char)){
if(!preg_match('/\d/',$char)){
$char = ord($char)-55;
}
$converted .= $char;
}
}
return (strlen($converted) > 0 && gmp_strval(gmp_mod($converted, "97")) == 1);
}
enjoy !
请享用 !
回答by Aivaras Godliauskas
I found this solution in cakephp 3.7 validation class. Plain beautiful php realization.
我在cakephp 3.7 验证类中找到了这个解决方案。简单漂亮的 php 实现。
/**
* Check that the input value has a valid International Bank Account Number IBAN syntax
* Requirements are uppercase, no whitespaces, max length 34, country code and checksum exist at right spots,
* body matches against checksum via Mod97-10 algorithm
*
* @param string $check The value to check
*
* @return bool Success
*/
public static function iban($check)
{
if (!preg_match('/^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$/', $check)) {
return false;
}
$country = substr($check, 0, 2);
$checkInt = intval(substr($check, 2, 2));
$account = substr($check, 4);
$search = range('A', 'Z');
$replace = [];
foreach (range(10, 35) as $tmp) {
$replace[] = strval($tmp);
}
$numStr = str_replace($search, $replace, $account . $country . '00');
$checksum = intval(substr($numStr, 0, 1));
$numStrLength = strlen($numStr);
for ($pos = 1; $pos < $numStrLength; $pos++) {
$checksum *= 10;
$checksum += intval(substr($numStr, $pos, 1));
$checksum %= 97;
}
return ((98 - $checksum) === $checkInt);
}
回答by Andrei Ivanouski
Latest countires list (2020-04-07):
最新国家名单(2020-04-07):
$countries = [
'ad' => 24,
'ae' => 23,
'al' => 28,
'at' => 20,
'az' => 28,
'ba' => 20,
'be' => 16,
'bg' => 22,
'bh' => 22,
'br' => 29,
'by' => 28,
'ch' => 21,
'cr' => 21,
'cy' => 28,
'cz' => 24,
'de' => 22,
'dk' => 18,
'do' => 28,
'ee' => 20,
'es' => 24,
'fi' => 18,
'fo' => 18,
'fr' => 27,
'gb' => 22,
'ge' => 22,
'gi' => 23,
'gl' => 18,
'gr' => 27,
'gt' => 28,
'hr' => 21,
'hu' => 28,
'ie' => 22,
'il' => 23,
'is' => 26,
'it' => 27,
'jo' => 30,
'kw' => 30,
'kz' => 20,
'lb' => 28,
'li' => 21,
'lt' => 20,
'lu' => 20,
'lv' => 21,
'mc' => 27,
'md' => 24,
'me' => 22,
'mk' => 19,
'mr' => 27,
'mt' => 31,
'mu' => 30,
'nl' => 18,
'no' => 15,
'pk' => 24,
'pl' => 28,
'ps' => 29,
'pt' => 25,
'qa' => 29,
'ro' => 24,
'rs' => 22,
'sa' => 24,
'se' => 24,
'si' => 19,
'sk' => 24,
'sm' => 27,
'tl' => 23,
'tn' => 24,
'tr' => 26,
'ua' => 29,
'vg' => 24,
'xk' => 20,
];

