web-dev-qa-db-ja.com

IBANを検証するPHP

新しいプラットフォームを設計するときに、IBAN番号を統合しようとしました。 IBANが検証され、データベースに保存されているIBANが常に正しいことを確認する必要があります。では、数を検証する適切な方法は何でしょうか?

14
Peter Fox

他の質問でロジックが説明されたので、自分で関数を作成しようとしました。ウィキペディアの記事で説明されているロジックに基づいて、以下の適切な関数を見つけてください。国固有の検証。

それは合いますか

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;
}
41
Peter Fox

bcmathが使用できない場合のbcmod()のサポートを含む@PeterFox回答のわずかな変更

<?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;
}
6
Сухой27

受け入れられた回答は、検証の推奨される方法ではありません。 指定 は、次のことを指示します。

 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

5
esserj

申し訳ありませんが、担当者が少ないため、まだコメントできません。そのため、user3733632sへの新しいリンクで回答します。

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

(プロジェクトは2015年3月の時点でGoogleコードでホストされておらず、プロジェクトはいくつかのクリーンアップ後に新しいバージョンを取得します。)

4
SVetter

この関数は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);
}

楽しい !

0
Fabrice G

最新の国リスト(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,
];

https://ru.wikipedia.org/wiki/IBAN

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

Google Codeは、オープンソースのphp-ibanバリデーターのプロジェクトをホストしています: https://code.google.com/p/php-iban/

0
user3733632

トップ定格の機能が動作しません。

'%'を含む文字列を試してください...

私はこれを使っています:

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;
}
0
jhabai