在设计一个新平台时,我们试图整合IBAN号码。我们必须确保IBAN经过验证,并且存储到数据库的IBAN始终正确。那么,验证这个数字的正确方法是什么呢?
2nc8po8w1#
正如我在另一个问题中解释的逻辑,我自己创建了一个函数。根据维基百科文章中解释的逻辑,在下面找到一个合适的函数。国家特定验证。每个国家/地区的算法和字符长度见https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN。
function checkIBAN($iban) { if(strlen($iban) < 5) return false; $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(array_key_exists(substr($iban,0,2), $Countries) && 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])){ if(!isset($Chars[$MovedCharArray[$key]])) return false; $MovedCharArray[$key] = $Chars[$MovedCharArray[$key]]; } $NewString .= $MovedCharArray[$key]; } if(bcmod($NewString, '97') == 1) { return true; } } return false; }
8hhllhi22#
对@PeterFox答案进行了轻微修改,包括在bcmath不可用时支持bcmod(),
bcmath
bcmod()
<?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; }
k10s72fa3#
接受的答案不是首选的验证方式。specification表示以下内容:1.检查IBAN总长度是否正确(根据国家)。否则,IBAN无效1.将两个校验位替换为00(例如GB 00(英国)1.将四个初始字符移到字符串的末尾1.将字符串中的字母替换为数字,根据需要扩展字符串,例如A或a = 10,B或b = 11,Z或z = 35。因此,每个字母字符都被2个数字替换1.将字符串转换为整数(即忽略前导零)1.计算新数的mod-97,结果为余数1.从98中减去余数,并将结果用于两个校验位。如果结果是一个个位数,用前导0填充它,使其成为一个两位数我已经编写了一个类,它根据规范验证、格式化和解析字符串。希望这能帮助一些保存自己滚动所需的时间。代码可以在GitHub here上找到。
mxg2im7a4#
顶级功能不工作。只要尝试一个字符串与'%'在它...我用这个:
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; }
7ajki6be5#
我在cakephp 3.7 validation class中找到了这个解决方案。简单漂亮的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); }
5fjcxozz6#
此功能检查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; } } // prevent: "gmp_mod() $num1 is not an integer string" error $converted = ltrim($converted, '0'); return strlen($converted) && gmp_strval(gmp_mod($converted, '97')) == 1; }
好好享受吧!
8e2ybdfx7#
我建议对校验和计算进行一些优化
function calculateIBANChecksum($CIBAN){ $CX = str_split($CIBAN); $checksum = $CX[0]; array_shift($CX); foreach ($CX as $pos => $DIGIT) { $checksum *= 10; $checksum += $DIGIT * 1; $checksum %= 97; } return (98 - $checksum);
}
7条答案
按热度按时间2nc8po8w1#
正如我在另一个问题中解释的逻辑,我自己创建了一个函数。根据维基百科文章中解释的逻辑,在下面找到一个合适的函数。国家特定验证。
每个国家/地区的算法和字符长度见https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN。
8hhllhi22#
对@PeterFox答案进行了轻微修改,包括在
bcmath
不可用时支持bcmod()
,k10s72fa3#
接受的答案不是首选的验证方式。specification表示以下内容:
1.检查IBAN总长度是否正确(根据国家)。否则,IBAN无效
1.将两个校验位替换为00(例如GB 00(英国)
1.将四个初始字符移到字符串的末尾
1.将字符串中的字母替换为数字,根据需要扩展字符串,例如A或a = 10,B或b = 11,Z或z = 35。因此,每个字母字符都被2个数字替换
1.将字符串转换为整数(即忽略前导零)
1.计算新数的mod-97,结果为余数
1.从98中减去余数,并将结果用于两个校验位。如果结果是一个个位数,用前导0填充它,使其成为一个两位数
我已经编写了一个类,它根据规范验证、格式化和解析字符串。希望这能帮助一些保存自己滚动所需的时间。
代码可以在GitHub here上找到。
mxg2im7a4#
顶级功能不工作。
只要尝试一个字符串与'%'在它...
我用这个:
7ajki6be5#
我在cakephp 3.7 validation class中找到了这个解决方案。简单漂亮的php实现。
5fjcxozz6#
此功能检查IBAN,需要GMP激活http://php.net/manual/en/book.gmp.php。
好好享受吧!
8e2ybdfx7#
我建议对校验和计算进行一些优化
}