在设计新平台时,我们尝试整合IBAN号码。我们必须确保IBAN已经过验证,并且存储到数据库的IBAN始终是正确的。那么验证数字的正确方法是什么?
答案 0 :(得分:34)
正如我在其他问题中解释的那样,我试图自己创建一个函数。基于维基百科文章中解释的逻辑,在下面找到适当的功能。国家特定验证。
它是否适合
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;
}
答案 1 :(得分:5)
@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;
}
答案 2 :(得分:4)
很抱歉,由于Rep很低,我还无法发表评论,所以对用户3733632s的新链接回答:
https://github.com/globalcitizen/php-iban
(截至2015年3月,该项目已不再托管在谷歌代码中,该项目将在清理完成后获得新版本。)
答案 3 :(得分:4)
接受的答案不是首选的验证方式,specification规定了以下内容:
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
我已经编写了一个根据规范验证,格式化和解析字符串的类,希望这有助于节省一些时间来推销自己的字符串。代码在这里找到:
答案 4 :(得分:1)
最新国家列表(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,
];
答案 5 :(得分:0)
Google Code主持一个开源php-iban验证器的项目:https://code.google.com/p/php-iban/
答案 6 :(得分:0)
评分最高的功能不起作用。
只需尝试使用&#39;%&#39;在它...
我正在使用这个:
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;
}
答案 7 :(得分:0)
此功能检查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);
}
享受!
答案 8 :(得分:0)
我在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);
}