528 lines
14 KiB
PHP
528 lines
14 KiB
PHP
|
<?php
|
|||
|
|
|||
|
namespace Modules\Banche;
|
|||
|
|
|||
|
use UnexpectedValueException;
|
|||
|
|
|||
|
/**
|
|||
|
* Format:
|
|||
|
* b = National bank code (Codice ABI)
|
|||
|
* s = Bank/branch code (sort code, or CAB – Codice d'Avviamento Bancario)
|
|||
|
* c = Account number
|
|||
|
* d = Account type
|
|||
|
* i = National identification number
|
|||
|
* k = IBAN check digits
|
|||
|
* x = National check digits (CIN).
|
|||
|
*/
|
|||
|
class IBAN
|
|||
|
{
|
|||
|
public static $countries = [
|
|||
|
'AL' => [
|
|||
|
'length' => 28,
|
|||
|
'pattern' => '8n 16c',
|
|||
|
'structure' => 'ALkk bbbs sssx cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'AD' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '8n 12c',
|
|||
|
'structure' => 'ADkk bbbb ssss cccc cccc cccc',
|
|||
|
],
|
|||
|
'AT' => [
|
|||
|
'length' => 20,
|
|||
|
'pattern' => '16n',
|
|||
|
'structure' => 'ATkk bbbb bccc cccc cccc',
|
|||
|
],
|
|||
|
'AZ' => [
|
|||
|
'length' => 28,
|
|||
|
'pattern' => '4c 20n',
|
|||
|
'structure' => 'AZkk bbbb cccc cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'BH' => [
|
|||
|
'length' => 22,
|
|||
|
'pattern' => '4a 14c',
|
|||
|
'structure' => 'BHkk bbbb cccc cccc cccc cc',
|
|||
|
],
|
|||
|
'BE' => [
|
|||
|
'length' => 16,
|
|||
|
'pattern' => '12n',
|
|||
|
'structure' => 'BEkk bbbc cccc ccxx',
|
|||
|
],
|
|||
|
'BA' => [
|
|||
|
'length' => 20,
|
|||
|
'pattern' => '16n',
|
|||
|
'structure' => 'BA39 bbbs sscc cccc ccxx',
|
|||
|
],
|
|||
|
'BR' => [
|
|||
|
'length' => 29,
|
|||
|
'pattern' => '23n 1a 1c',
|
|||
|
'structure' => 'BR39 bbbb bbbb ssss sccc cccc cccc c',
|
|||
|
],
|
|||
|
'BG' => [
|
|||
|
'length' => 22,
|
|||
|
'pattern' => '4a 6n 8c',
|
|||
|
'structure' => 'BGkk bbbb ssss ddcc cccc cc',
|
|||
|
],
|
|||
|
'CR' => [
|
|||
|
'length' => 21,
|
|||
|
'pattern' => '17n',
|
|||
|
'structure' => 'CRkk bbbc cccc cccc cccc c',
|
|||
|
],
|
|||
|
'HR' => [
|
|||
|
'length' => 21,
|
|||
|
'pattern' => '17n',
|
|||
|
'structure' => 'HRkk bbbb bbbc cccc cccc c',
|
|||
|
],
|
|||
|
'CY' => [
|
|||
|
'length' => 28,
|
|||
|
'pattern' => '8n 16c',
|
|||
|
'structure' => 'CYkk bbbs ssss cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'CZ' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '20n',
|
|||
|
'structure' => 'CZkk bbbb ssss sscc cccc cccc',
|
|||
|
],
|
|||
|
'DK' => [
|
|||
|
'length' => 18,
|
|||
|
'pattern' => '14n',
|
|||
|
'structure' => 'DKkk bbbb cccc cccc cc',
|
|||
|
],
|
|||
|
'DO' => [
|
|||
|
'length' => 28,
|
|||
|
'pattern' => '4a 20n',
|
|||
|
'structure' => 'DOkk bbbb cccc cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'EE' => [
|
|||
|
'length' => 20,
|
|||
|
'pattern' => '16n',
|
|||
|
'structure' => 'EEkk bbss cccc cccc cccx',
|
|||
|
],
|
|||
|
'FO' => [
|
|||
|
'length' => 18,
|
|||
|
'pattern' => '14n',
|
|||
|
'structure' => 'FOkk bbbb cccc cccc cx',
|
|||
|
],
|
|||
|
'FI' => [
|
|||
|
'length' => 18,
|
|||
|
'pattern' => '14n',
|
|||
|
'structure' => 'FIkk bbbb bbcc cccc cx',
|
|||
|
],
|
|||
|
'FR' => [
|
|||
|
'length' => 27,
|
|||
|
'pattern' => '10n 11c 2n',
|
|||
|
'structure' => 'FRkk bbbb bggg ggcc cccc cccc cxx',
|
|||
|
],
|
|||
|
'GE' => [
|
|||
|
'length' => 22,
|
|||
|
'pattern' => '2c 16n',
|
|||
|
'structure' => 'GEkk bbcc cccc cccc cccc cc',
|
|||
|
],
|
|||
|
'DE' => [
|
|||
|
'length' => 22,
|
|||
|
'pattern' => '18n',
|
|||
|
'structure' => 'DEkk bbbb bbbb cccc cccc cc',
|
|||
|
],
|
|||
|
'GI' => [
|
|||
|
'length' => 23,
|
|||
|
'pattern' => '4a 15c',
|
|||
|
'structure' => 'GIkk bbbb cccc cccc cccc ccc',
|
|||
|
],
|
|||
|
'GR' => [
|
|||
|
'length' => 27,
|
|||
|
'pattern' => '7n 16c',
|
|||
|
'structure' => 'GRkk bbbs sssc cccc cccc cccc ccc',
|
|||
|
],
|
|||
|
'GL' => [
|
|||
|
'length' => 18,
|
|||
|
'pattern' => '14n',
|
|||
|
'structure' => 'GLkk bbbb cccc cccc cc',
|
|||
|
],
|
|||
|
'GT' => [
|
|||
|
'length' => 28,
|
|||
|
'pattern' => '4c 20c',
|
|||
|
'structure' => 'GTkk bbbb cccc cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'HU' => [
|
|||
|
'length' => 28,
|
|||
|
'pattern' => '24n',
|
|||
|
'structure' => 'HUkk bbbs sssk cccc cccc cccc cccx',
|
|||
|
],
|
|||
|
'IS' => [
|
|||
|
'length' => 26,
|
|||
|
'pattern' => '22n',
|
|||
|
'structure' => 'ISkk bbbb sscc cccc iiii iiii ii',
|
|||
|
],
|
|||
|
'IE' => [
|
|||
|
'length' => 22,
|
|||
|
'pattern' => '4c 14n',
|
|||
|
'structure' => 'IEkk aaaa bbbb bbcc cccc cc',
|
|||
|
],
|
|||
|
'IL' => [
|
|||
|
'length' => 23,
|
|||
|
'pattern' => '19n',
|
|||
|
'structure' => 'ILkk bbbn nncc cccc cccc ccc',
|
|||
|
],
|
|||
|
'IT' => [
|
|||
|
'length' => 27,
|
|||
|
'pattern' => '1a 10n 12c',
|
|||
|
'structure' => 'ITkk xbbb bbss sssc cccc cccc ccc',
|
|||
|
],
|
|||
|
'KZ' => [
|
|||
|
'length' => 20,
|
|||
|
'pattern' => '3n 13c',
|
|||
|
'structure' => 'KZkk bbbc cccc cccc cccc',
|
|||
|
],
|
|||
|
'KW' => [
|
|||
|
'length' => 30,
|
|||
|
'pattern' => '4a 22c',
|
|||
|
'structure' => 'KWkk bbbb cccc cccc cccc cccc cccc cc',
|
|||
|
],
|
|||
|
'LV' => [
|
|||
|
'length' => 21,
|
|||
|
'pattern' => '4a 13c',
|
|||
|
'structure' => 'LVkk bbbb cccc cccc cccc c',
|
|||
|
],
|
|||
|
'LB' => [
|
|||
|
'length' => 28,
|
|||
|
'pattern' => '4n 20c',
|
|||
|
'structure' => 'LBkk bbbb cccc cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'LI' => [
|
|||
|
'length' => 21,
|
|||
|
'pattern' => '5n 12c',
|
|||
|
'structure' => 'LIkk bbbb bccc cccc cccc c',
|
|||
|
],
|
|||
|
'LT' => [
|
|||
|
'length' => 20,
|
|||
|
'pattern' => '16n',
|
|||
|
'structure' => 'LTkk bbbb bccc cccc cccc',
|
|||
|
],
|
|||
|
'LU' => [
|
|||
|
'length' => 20,
|
|||
|
'pattern' => '3n 13c',
|
|||
|
'structure' => 'LUkk bbbc cccc cccc cccc',
|
|||
|
],
|
|||
|
'MK' => [
|
|||
|
'length' => 19,
|
|||
|
'pattern' => '3n 10c 2n',
|
|||
|
'structure' => 'MK07 bbbc cccc cccc cxx',
|
|||
|
],
|
|||
|
'MT' => [
|
|||
|
'length' => 31,
|
|||
|
'pattern' => '4a 5n 18c',
|
|||
|
'structure' => 'MTkk bbbb ssss sccc cccc cccc cccc ccc',
|
|||
|
],
|
|||
|
'MR' => [
|
|||
|
'length' => 27,
|
|||
|
'pattern' => '23n',
|
|||
|
'structure' => 'MRkk bbbb bsss sscc cccc cccc cxx',
|
|||
|
],
|
|||
|
'MU' => [
|
|||
|
'length' => 30,
|
|||
|
'pattern' => '4a 19n 3a',
|
|||
|
'structure' => 'MUkk bbbb bbss cccc cccc cccc cccc cc',
|
|||
|
],
|
|||
|
'MC' => [
|
|||
|
'length' => 27,
|
|||
|
'pattern' => '10n 11c 2n',
|
|||
|
'structure' => 'MCkk bbbb bsss sscc cccc cccc cxx',
|
|||
|
],
|
|||
|
'MD' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '2c 18n',
|
|||
|
'structure' => 'MDkk bbcc cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'ME' => [
|
|||
|
'length' => 22,
|
|||
|
'pattern' => '18n',
|
|||
|
'structure' => 'ME25 bbbc cccc cccc cccc xx',
|
|||
|
],
|
|||
|
'NL' => [
|
|||
|
'length' => 18,
|
|||
|
'pattern' => '4a 10n',
|
|||
|
'structure' => 'NLkk bbbb cccc cccc cc',
|
|||
|
],
|
|||
|
'NO' => [
|
|||
|
'length' => 15,
|
|||
|
'pattern' => '11n',
|
|||
|
'structure' => 'NOkk bbbb cccc ccx',
|
|||
|
],
|
|||
|
'PK' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '4c 16n',
|
|||
|
'structure' => 'PKkk bbbb cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'PS' => [
|
|||
|
'length' => 29,
|
|||
|
'pattern' => '4c 21n',
|
|||
|
'structure' => 'PSkk bbbb zzzz zzzz zccc cccc cccc c',
|
|||
|
],
|
|||
|
'PL' => [
|
|||
|
'length' => 28,
|
|||
|
'pattern' => '24n',
|
|||
|
'structure' => 'PLkk bbbs sssx cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'PT' => [
|
|||
|
'length' => 25,
|
|||
|
'pattern' => '21n',
|
|||
|
'structure' => 'PT50 bbbb ssss cccc cccc cccx x',
|
|||
|
],
|
|||
|
'RO' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '4a 16c',
|
|||
|
'structure' => 'ROkk bbbb cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'SM' => [
|
|||
|
'length' => 27,
|
|||
|
'pattern' => '1a 10n 12c',
|
|||
|
'structure' => 'SMkk xbbb bbss sssc cccc cccc ccc',
|
|||
|
],
|
|||
|
'SA' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '2n 18c',
|
|||
|
'structure' => 'SAkk bbcc cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'RS' => [
|
|||
|
'length' => 22,
|
|||
|
'pattern' => '18n',
|
|||
|
'structure' => 'RSkk bbbc cccc cccc cccc aa',
|
|||
|
],
|
|||
|
'SK' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '20n',
|
|||
|
'structure' => 'SKkk bbbb ssss sscc cccc cccc',
|
|||
|
],
|
|||
|
'SI' => [
|
|||
|
'length' => 19,
|
|||
|
'pattern' => '15n',
|
|||
|
'structure' => 'SI56 bbss sccc cccc cxx',
|
|||
|
],
|
|||
|
'ES' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '20n',
|
|||
|
'structure' => 'ESkk bbbb ssss xxcc cccc cccc',
|
|||
|
],
|
|||
|
'SE' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '20n',
|
|||
|
'structure' => 'SEkk bbbc cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'CH' => [
|
|||
|
'length' => 21,
|
|||
|
'pattern' => '5n 12c',
|
|||
|
'structure' => 'CHkk bbbb bccc cccc cccc c',
|
|||
|
],
|
|||
|
'TN' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '20n',
|
|||
|
'structure' => 'TNkk bbss sccc cccc cccc cccc',
|
|||
|
],
|
|||
|
'TR' => [
|
|||
|
'length' => 26,
|
|||
|
'pattern' => '5n 17c',
|
|||
|
'structure' => 'TRkk bbbb b0cc cccc cccc cccc cc',
|
|||
|
],
|
|||
|
'AE' => [
|
|||
|
'length' => 23,
|
|||
|
'pattern' => '3n 16n',
|
|||
|
'structure' => 'AEkk bbbc cccc cccc cccc ccc',
|
|||
|
],
|
|||
|
'GB' => [
|
|||
|
'length' => 22,
|
|||
|
'pattern' => '4a 14n',
|
|||
|
'structure' => 'GBkk bbbb ssss sscc cccc cc',
|
|||
|
],
|
|||
|
'VG' => [
|
|||
|
'length' => 24,
|
|||
|
'pattern' => '4c 16n',
|
|||
|
'structure' => 'VGkk bbbb cccc cccc cccc cccc',
|
|||
|
],
|
|||
|
];
|
|||
|
|
|||
|
protected static $parsers = [
|
|||
|
'b' => 'bank_code',
|
|||
|
's' => 'branch_code',
|
|||
|
'c' => 'account_number',
|
|||
|
'd' => 'account_type',
|
|||
|
'i' => 'id',
|
|||
|
'k' => 'check_digits',
|
|||
|
'x' => 'national_check_digits',
|
|||
|
];
|
|||
|
|
|||
|
/**
|
|||
|
* @var string
|
|||
|
*/
|
|||
|
protected $iban;
|
|||
|
/**
|
|||
|
* @var string
|
|||
|
*/
|
|||
|
protected $nation;
|
|||
|
/**
|
|||
|
* @var string
|
|||
|
*/
|
|||
|
protected $bank_code;
|
|||
|
/**
|
|||
|
* @var string
|
|||
|
*/
|
|||
|
protected $branch_code;
|
|||
|
/**
|
|||
|
* @var string
|
|||
|
*/
|
|||
|
protected $account_number;
|
|||
|
/**
|
|||
|
* @var string
|
|||
|
*/
|
|||
|
protected $account_type;
|
|||
|
/**
|
|||
|
* @var string
|
|||
|
*/
|
|||
|
protected $id;
|
|||
|
/**
|
|||
|
* @var string
|
|||
|
*/
|
|||
|
protected $check_digits;
|
|||
|
/**
|
|||
|
* @var string
|
|||
|
*/
|
|||
|
protected $national_check_digits;
|
|||
|
|
|||
|
public function __construct($iban)
|
|||
|
{
|
|||
|
$iban = str_replace(' ', '', $iban);
|
|||
|
$this->iban = $iban;
|
|||
|
|
|||
|
$this->nation = $nation = substr($iban, 0, 2);
|
|||
|
$info = self::$countries[$nation];
|
|||
|
|
|||
|
$structure = $info['structure'];
|
|||
|
$structure = str_replace(' ', '', $structure);
|
|||
|
|
|||
|
$regex = $nation;
|
|||
|
$keys = array_keys(self::$parsers);
|
|||
|
|
|||
|
$length = strlen($this->iban);
|
|||
|
$current = strlen($nation);
|
|||
|
while ($current <= $length) {
|
|||
|
$char = $structure[$current];
|
|||
|
if (in_array($char, $keys)) {
|
|||
|
$count = substr_count($structure, $char);
|
|||
|
$regex .= '(?<'.self::$parsers[$char].'>[A-Z0-9]{'.$count.'})';
|
|||
|
$current += $count;
|
|||
|
} else {
|
|||
|
$regex .= $char;
|
|||
|
++$current;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
preg_match_all('/^'.$regex.'/', $iban, $matches);
|
|||
|
$matches = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
|
|||
|
foreach ($matches as $key => $value) {
|
|||
|
if (empty($value[0])) {
|
|||
|
throw new UnexpectedValueException('Invalid '.$key.' for format '.$regex);
|
|||
|
}
|
|||
|
|
|||
|
$this->{$key} = $value[0];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static function generate($contents = [])
|
|||
|
{
|
|||
|
$nation = $contents['nation'];
|
|||
|
$info = self::$countries[$nation];
|
|||
|
|
|||
|
$structure = $info['structure'];
|
|||
|
$structure = str_replace(' ', '', $structure);
|
|||
|
|
|||
|
$keys = array_keys(self::$parsers);
|
|||
|
|
|||
|
$length = strlen($structure);
|
|||
|
$current = strlen($nation);
|
|||
|
$result = $nation;
|
|||
|
while ($current <= $length) {
|
|||
|
$char = $structure[$current];
|
|||
|
if (in_array($char, $keys)) {
|
|||
|
$count = substr_count($structure, $char);
|
|||
|
$result .= str_pad($contents[self::$parsers[$char]], $count, STR_PAD_LEFT);
|
|||
|
$current += $count;
|
|||
|
} else {
|
|||
|
$result .= $char;
|
|||
|
++$current;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return new self($result);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
public function getIban()
|
|||
|
{
|
|||
|
return $this->iban;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
public function getNation()
|
|||
|
{
|
|||
|
return $this->nation;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
public function getBankCode()
|
|||
|
{
|
|||
|
return $this->bank_code;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
public function getBranchCode()
|
|||
|
{
|
|||
|
return $this->branch_code;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
public function getAccountNumber()
|
|||
|
{
|
|||
|
return $this->account_number;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
public function getAccountType()
|
|||
|
{
|
|||
|
return $this->account_type;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
public function getId()
|
|||
|
{
|
|||
|
return $this->id;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
public function getCheckDigits()
|
|||
|
{
|
|||
|
return $this->check_digits;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
public function getNationalCheckDigits()
|
|||
|
{
|
|||
|
return $this->national_check_digits;
|
|||
|
}
|
|||
|
}
|