2014-01-07 50 views
6

當設計一個新平臺時,我們試圖整合IBAN號碼。我們必須確保IBAN得到驗證,並且IBAN存儲到數據庫始終是正確的。那麼驗證號碼的正確方法是什麼?驗證IBAN PHP

+0

大部分沒有國家特定的檢查,建議。 –

+1

有趣的是:如果你點擊@MarcinOrlowski lmfgtfy鏈接,這個問題會彈出作爲第一個搜索結果;) –

+0

@FrederikKammer也許是因爲這個鏈接,所以在某種程度上是無限循環: ) –

回答

25

由於邏輯在我的另一個問題中已經解釋過,我試圖自己創建一個函數。根據維基百科文章中解釋的邏輯,在下面找到一個合適的功能。國家特定的驗證。

將它符合

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; 
     } 
     else{ 
      return FALSE; 
     } 
    } 
    else{ 
     return FALSE; 
    } 
} 
+0

不錯!唯一錯過它的是將$ NewString變量初始化爲一個空字符串,如果沒有,它會拋出一個錯誤。 – sucotronic

+0

@sucotronic剛剛更新了答案。 –

+0

@PeterFox你從哪裏得到國家及其IBAN長度的列表,列表中是否包含每個國家? – BadHorsie

3

@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; 
} 
4

對不起,我還不能由於低衆議員發表評論,所以新的鏈接user3733632s答案:

https://github.com/globalcitizen/php-iban

(該項目不再在谷歌代碼託管截至2015年3月,該項目將在一些清理後得到一個新版本。)

+1

這個庫看起來不太好。它的架構很差 - 有一個類,但它沒有命名空間,所以它不能自動加載。所有方法都委託給程序功能。最重要的是,沒有任何測試,這對於與金融交易相關的任何事情都是絕對必要的。 – pfrenssen

0

最高評價功能不起作用。

剛剛嘗試一個字符串「%」在它...

我用這一個:

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; 
} 
3

接受的答案是沒有驗證的首選方式,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 

我已經寫了驗證,格式和解析字符串根據規範中的一個類,希望這有助於節省一些時間推出自己的。代碼在這裏找到:

https://gist.github.com/esserj/a54ffd11182417cf920d

+0

這根本不是真的。你在做什麼是計算檢查數字,這是完全好的,但沒有必要如果你只是想驗證IBAN。如果您沒有將支票數字重置爲零,並且最終不從98減去,那麼如果IBAN有效,您將得到1。如果您只想驗證就足夠了。 – inta

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

享受!