Skip to content

Instantly share code, notes, and snippets.

@Sroose
Created November 24, 2019 14:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Sroose/47f8ce5cf5fe36f52eba01dabc474d8c to your computer and use it in GitHub Desktop.
Save Sroose/47f8ce5cf5fe36f52eba01dabc474d8c to your computer and use it in GitHub Desktop.
IBAN validation in PHP - example use for new Respect rule
<?php
/**
* Based on https://stackoverflow.com/a/20983340 and improved
*/
namespace OpenAPIServer\ValidationRules;
use Respect\Validation\Rules\AbstractRule;
/**
* This custom rule will check valid IBAN (coutnry code, length and checksum). Expects trimmed input!
*/
class Iban extends AbstractRule
{
public function validate($input)
{
$iban = strtolower($input);
// The official min length is 5. Also prevents substringing too short input.
if(strlen($iban) < 5) return false;
// lengths of iban per country
$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
);
// subsitution scheme for letters
$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
);
// Check input country code is known
if (!isset($Countries[ substr($iban,0,2) ])) return false;
// Check total length for given country code
if (strlen($iban) != $Countries[ substr($iban,0,2) ]) { return false; }
// Move first 4 chars to end
$MovedChar = substr($iban, 4) . substr($iban,0,4);
// Replace letters by their numeric variant
$MovedCharArray = str_split($MovedChar);
$NewString = "";
foreach ($MovedCharArray as $k => $v) {
if ( !is_numeric($MovedCharArray[$k]) ) {
// if any other cahracter then the known letters, its bogus
if(!isset($Chars[$MovedCharArray[$k]])) return false;
$MovedCharArray[$k] = $Chars[$MovedCharArray[$k]];
}
$NewString .= $MovedCharArray[$k];
}
// Now we just need to validate the checksum
// Use bcmod if available
if (function_exists("bcmod")) { return bcmod($NewString, '97') == 1; }
// Else use this workaround
// 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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment