PHPackages                             daycry/iban - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. daycry/iban

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

daycry/iban
===========

IBAN library for CodeIgniter 4 (validation, parsing, formatting and entity resolution), usable standalone too.

2.2.0(1mo ago)027↓75%MITPHPPHP ^8.3CI passing

Since Jul 10Pushed 1mo agoCompare

[ Source](https://github.com/daycry/iban-calculator)[ Packagist](https://packagist.org/packages/daycry/iban)[ RSS](/packages/daycry-iban/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (10)Dependencies (5)Versions (21)Used By (0)

[![Tests](https://github.com/daycry/iban-calculator/actions/workflows/phpunit.yml/badge.svg)](https://github.com/daycry/iban-calculator/actions/workflows/phpunit.yml)[![Coverage Status](https://camo.githubusercontent.com/4769475e7ec8beb8015f00c0da05cf3bfb113a6d84cabf47365079107b7b36f0/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6461796372792f6962616e2d63616c63756c61746f722f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/daycry/iban-calculator?branch=master)

[![PHPStan](https://github.com/daycry/iban-calculator/actions/workflows/phpstan.yml/badge.svg)](https://github.com/daycry/iban-calculator/actions/workflows/phpstan.yml)[![Code Style](https://github.com/daycry/iban-calculator/actions/workflows/code-style.yml/badge.svg)](https://github.com/daycry/iban-calculator/actions/workflows/code-style.yml)[![CodeQL](https://github.com/daycry/iban-calculator/actions/workflows/codeql.yml/badge.svg)](https://github.com/daycry/iban-calculator/actions/workflows/codeql.yml)

[![Latest Stable Version](https://camo.githubusercontent.com/fa19c833edd730498eb1f270b1b8a18675ddf8d14772518b7856c2b5875d35ca/68747470733a2f2f706f7365722e707567782e6f72672f6461796372792f6962616e2f762f737461626c65)](https://packagist.org/packages/daycry/iban)[![Total Downloads](https://camo.githubusercontent.com/8baf9f1eb96d642d53e58070cb94b231486751bc56e3e8f84a37fbcdd55761df/68747470733a2f2f706f7365722e707567782e6f72672f6461796372792f6962616e2f646f776e6c6f616473)](https://packagist.org/packages/daycry/iban)[![License](https://camo.githubusercontent.com/4ca92d63efb89bffca9a0751b2dbd86f1e07bf11df05139a8ddffd2adc0ecab1/68747470733a2f2f706f7365722e707567782e6f72672f6461796372792f6962616e2f6c6963656e7365)](https://packagist.org/packages/daycry/iban)[![PHP Version Require](https://camo.githubusercontent.com/5f6d2e2003bf437d2feffa84ad09eb2e609484209cffffff6dc962bae8624020/68747470733a2f2f706f7365722e707567782e6f72672f6461796372792f6962616e2f726571756972652f706870)](https://packagist.org/packages/daycry/iban)

[![PHPStan Level](https://camo.githubusercontent.com/d117944b58da8146f96b4ef7403807610a20eeb3fbcaaaf95157bbcdad1686eb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230382d627269676874677265656e2e737667)](phpstan.neon)[![Code Style](https://camo.githubusercontent.com/9a55c17459c810407cac6350c94a2c6f9545d3c249439e19a763f6856392bb39/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307374796c652d5053522d2d31322d626c75652e737667)](.php-cs-fixer.dist.php)

[![Stars](https://camo.githubusercontent.com/f8ff86d761a4700fa799a6d4624a1160ec451634b23d37453535f910b78a45a7/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f6461796372792f6962616e2d63616c63756c61746f722e737667)](https://github.com/daycry/iban-calculator/stargazers)[![Forks](https://camo.githubusercontent.com/7da416a0b2688085c8e4edce580193d29240edd9eeaa37ba80f004bbfcba075e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f6461796372792f6962616e2d63616c63756c61746f722e737667)](https://github.com/daycry/iban-calculator/network)[![Issues](https://camo.githubusercontent.com/c72f31b1cc9bd0f1e11c6d4df742c86f8000337cee2e0475639d06898812c5fc/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f6461796372792f6962616e2d63616c63756c61746f722e737667)](https://github.com/daycry/iban-calculator/issues)

Daycry Iban
===========

[](#daycry-iban)

IBAN validation, parsing, formatting and bank-entity resolution for CodeIgniter 4 — usable standalone, with a zero-dependency core.

```
composer require daycry/iban
```

Quickstart
----------

[](#quickstart)

### Facade (framework-free, works standalone)

[](#facade-framework-free-works-standalone)

```
use Daycry\Iban\Iban;
use Daycry\Iban\Enums\IbanFormat;

$iban = new Iban(); // zero-config: Registry() + NullProvider() by default

$iban->isValid('ES91 2100 0418 4502 0005 1332');           // true

$result = $iban->validate('ES9121000418450200051332', checkNational: true);
$result->isValid();                                          // bool
$result->firstViolation();                                   // ?Violation

$parsed = $iban->parse('ES9121000418450200051332');          // throws InvalidIbanException if invalid
$parsed = $iban->tryParse('not an iban');                    // null instead of throwing
$parsed->countryCode;                                         // 'ES'
$parsed->bankIdentifier;                                      // '2100'

$iban->format($parsed, IbanFormat::Print);                    // 'ES91 2100 0418 4502 0005 1332'
$iban->format($parsed, IbanFormat::Anonymized);                // 'ES******************1332'

$bank = $iban->resolve($parsed);
$bank->isResolved();                                           // false — NullProvider never resolves

// BIC / SWIFT (ISO 9362) — no checksum, so "valid" = well-formed + recognised country
$iban->isValidBic('CAIXESBBXXX');                              // true
$iban->parseBic('NWBKGB2L')->institutionCode;                  // 'NWBK'
$iban->validateIbanAndBic('GB29NWBK60161331926819', 'NWBKGB2L')->isValid(); // true (country + bank coherent)
```

### CI4 service

[](#ci4-service)

```
$svc = service('iban'); // Daycry\Iban\Iban, wired per Config\Iban

$svc->isValid('ES9121000418450200051332'); // true
```

### CI4 helper

[](#ci4-helper)

```
helper('iban');

iban_is_valid('ES9121000418450200051332');              // true
iban_valid('ES9121000418450200051332');                  // alias of iban_is_valid()
iban_country('ES9121000418450200051332');                // 'ES'
iban_format('ES9121000418450200051332', 'anonymized');   // 'ES******************1332'
bank_name('ES9121000418450200051332');                    // null with the default NullProvider / empty banks table
bank_bic('ES9121000418450200051332');                      // null, same reason
```

### spark commands

[](#spark-commands)

```
php spark iban:validate "ES91 2100 0418 4502 0005 1332" --national
php spark iban:validate GB29NWBK60161331926819 --bic=NWBKGB2L   # combined IBAN + BIC cross-check
php spark iban:bic NWBKGB2L                     # validate/parse a BIC on its own
php spark iban:parse ES9121000418450200051332 --json
php spark iban:resolve ES9121000418450200051332
php spark iban:update                          # lists the 30 bundled importers
php spark iban:update --source=oenb --dry-run   # preview an import, write nothing
```

Complete per-symbol API reference: [`docs/api-reference.md`](docs/api-reference.md). Task-oriented guide — the 16 `ViolationCode` cases, the national validators, caching, and the `Config\Iban` options: see [`docs/usage.md`](docs/usage.md). Importer/`iban:update` reference: see [`docs/importers.md`](docs/importers.md).

API overview
------------

[](#api-overview)

The public surface is the facade `Daycry\Iban\Iban` (also what `service('iban')` returns). Every method accepts a raw string; the ones that already have a parsed value object accept that too.

### IBAN

[](#iban)

MethodWhat it does`normalize(string $iban): string`Uppercases and strips spaces/separators to the canonical electronic form. Pure string operation — no validation.`validate(string|ParsedIban $iban, bool $checkNational = false): ValidationResult`Full validation: country is in the registry, correct length, BBAN token grammar, and MOD-97 check digits — plus, with `checkNational: true`, the country's national check digit (ES/BE/PT/SI/FI/FR/IT…). **Never throws**; returns a `ValidationResult` exposing `isValid()` and the list of `Violation`s.`isValid(string|ParsedIban $iban): bool`Boolean shortcut over `validate()`.`parse(string $iban): ParsedIban`Validates, then decomposes into a `ParsedIban` (country code, check digits, BBAN, bank identifier, branch identifier, account number, national check digit). **Throws `InvalidIbanException`** (which carries the failing `ValidationResult`) when the IBAN is invalid.`tryParse(string $iban): ?ParsedIban`Same as `parse()` but returns `null` instead of throwing.`format(string|ParsedIban $iban, IbanFormat $f = IbanFormat::Print): string`Renders `Electronic` (no spaces), `Print` (groups of 4), or `Anonymized` (country code + last 4 digits, the rest masked).`resolve(string|ParsedIban $iban): BankResult`Looks up the owning bank through the configured provider. **Always returns a `BankResult`** (the `ParsedIban` plus nullable bank fields); `isResolved()` is `false` with the default `NullProvider`, or filled in by `DatabaseProvider` / the iban.com fallback. `resolvedBy` tells you which provider answered.### BIC / SWIFT

[](#bic--swift)

MethodWhat it does`normalizeBic(string $bic): string`Uppercases and strips whitespace.`validateBic(string|ParsedBic $bic): ValidationResult`Structural ISO 9362 validation: length 8 or 11, character classes per position, and country code (positions 5-6) present in the bundled ISO 3166-1 registry. **Never throws.** A BIC has no checksum, so "valid" means *well-formed with a recognised country*, never "this BIC exists".`isValidBic(string|ParsedBic $bic): bool`Boolean shortcut over `validateBic()`.`parseBic(string $bic): ParsedBic`Validates, then slices into a `ParsedBic` (institution, country, location, optional branch code). **Throws `InvalidBicException`** when invalid.`tryParseBic(string $bic): ?ParsedBic`Same as `parseBic()` but returns `null`.`validateIbanAndBic(?string $iban, ?string $bic): ValidationResult`The "one, the other, or both" entry point: validates whichever value is provided, and when both are valid also cross-checks them — country always, and bank for the 19 countries whose IBAN bank code is the BIC's 4-letter prefix.`resolveBic(string|ParsedBic $bic): ?BankInfo`Resolves a bank straight from a BIC (BIC8 match against the provider's `banks` data). Returns `null` (never throws) on a malformed BIC or an unresolved lookup.### Sub-service accessors

[](#sub-service-accessors)

`validator()`, `parser()`, `resolver()`, `bicValidator()` and `bicParser()` return the underlying components, for when you want to reuse a single instance or call them directly.

The helper (`helper('iban')`) mirrors these as plain functions (`iban_validate()`, `iban_parse()`, `iban_resolve()`, `bic_is_valid()`, `iban_bic_validate()`, …) and every helper is degradation-safe — none throw. See [`docs/api-reference.md`](docs/api-reference.md) for the exhaustive per-symbol reference.

Database setup (optional)
-------------------------

[](#database-setup-optional)

Validation, parsing, formatting and BIC checks need **no database** — the core ships a compiled registry and works out of the box. The database is only for **bank-entity resolution** (`resolve()` / `resolveBic()`returning real bank names and BICs) and, optionally, for serving the ISO 3166-1 country list from a table instead of the bundled compiled list. These steps only apply under CodeIgniter 4.

### 1. Run the migrations

[](#1-run-the-migrations)

Both tables (`banks` and `iso_countries`) live in the package's module namespace, so migrate it:

```
php spark migrate -n "Daycry\Iban"    # creates the `banks` and `iso_countries` tables
# …or run every namespace's migrations together with your app's own:
php spark migrate --all
```

### 2. Enable the database provider

[](#2-enable-the-database-provider)

Publish the config (`php spark iban:publish`) and, in `app/Config/Iban.php`, switch the provider:

```
public string $provider = 'database';   // resolve() now reads the `banks` table
```

### 3. Populate the `banks` table

[](#3-populate-the-banks-table)

**No bank data ships with the package** (by licensing design — see [`docs/licensing.md`](docs/licensing.md)). You fill the table yourself from official sources with the bundled importers:

```
php spark iban:update                        # list the 30 bundled importers and their sources
php spark iban:update --source=bundesbank     # import one source (Germany)
php spark iban:update --source=epc            # EPC SEPA Register → GB, GI, IE, LV, RO (+ SEPA flags)
php spark iban:update --all                   # run every importer
php spark iban:update --source=oenb --dry-run  # preview an import, write nothing
```

The `BanksSeeder` is intentionally empty — it exists only as a seed hook; the importers are the real data path. See [`docs/importers.md`](docs/importers.md) for the full source list and coverage matrix.

### 4. (Optional) Serve ISO 3166-1 from the database

[](#4-optional-serve-iso-3166-1-from-the-database)

BIC validation uses the bundled compiled ISO 3166-1 list by default (`$isoCountrySource = 'php'` — nothing to install). To serve it from the `iso_countries` table instead (so you can edit it in the DB), set `$isoCountrySource = 'database'` in `app/Config/Iban.php` and seed the table from the compiled list:

```
php spark db:seed "Daycry\Iban\Database\Seeds\IsoCountriesSeeder"   # idempotent — upserts by alpha-2
```

Features
--------

[](#features)

- **ISO 13616 + MOD-97 validation** over a structural registry covering 78 countries — length, BBAN token grammar, and field offsets, all compiled into PHP (no runtime data files, no network).
- **Structural parsing**: country code, IBAN check digits, BBAN, bank identifier, branch identifier (where applicable), account number, and national check digit — all as a `ParsedIban` value object.
- **Three output formats**: `Electronic` (canonical, no spaces), `Print` (space-grouped every 4 chars), `Anonymized` (country code + last 4 digits visible, rest masked). See [`docs/formatting.md`](docs/formatting.md).
- **Pluggable bank-entity resolver**: `resolve()` always returns a `BankResult`; bank fields stay `null` with the default `NullProvider`, or get filled in by the optional `DatabaseProvider` once you seed the `banks` table — optionally cached via `Providers\CachedProvider` (`Config\Iban::$cacheTtl`). A bank-level fallback (`findByBankCode($cc, $bank, null)`) resolves branch-carrying IBANs even when only a bank-level row was imported.
- **National check-digit validation for 9 countries** (`checkNational: true`): ES, BE, PT, SI, FI, FR (+MC), IT (+SM) — see [`docs/usage.md`](docs/usage.md#national-check-digit-validators) for the algorithm per country (Estonia is deliberately not covered — its real algorithm needs bank-specific data the IBAN doesn't carry).
- **BIC / SWIFT validation (ISO 9362)**: validate, parse (`ParsedBic`), and — given both an IBAN and a BIC — cross-check them for country and (where structurally possible) bank coherence, plus optional BIC-first bank resolution (`resolveBic()`). Country codes are checked against a bundled 249-code ISO 3166-1 registry, so BICs from non-IBAN countries (US, JP, …) validate too. A BIC has no checksum, so "valid" means *well-formed + recognised country*, never "this BIC exists". Works standalone, no database. See [`docs/usage.md`](docs/usage.md#validating-a-bicswift).
- **30 bundled bank-data importers**, none of them bundling any actual data: `iban:update` lists/runs official-source importers for 25 countries (AT, DE, CH, NL, ES, CZ, GR, SI, SK, BG, MD, PL, AZ, BE, HR, LU, MT, HU, NO, GE, IL, UA, KZ, LI, BR) plus the EPC SEPA Register, which covers GB, GI, IE, LV and RO and also reports SEPA reachability (SCT/SCT Inst/SDD Core/SDD B2B) — live or from a local `--file`. 24 of 42 SEPA countries now resolve. See [`docs/importers.md`](docs/importers.md) for the full list and coverage matrix.
- **Zero-dependency core**: `Daycry\Iban\Iban` and everything under `Core/`, `Contracts/`, `DTO/`, `Enums/`, `Exceptions/`, `Registry/`, `National/`, `Resolver/` never import CodeIgniter — usable in a plain `php -r` script, a CLI tool, or any other framework. (The package as a whole additionally requires `ext-mbstring`, `ext-iconv` and `ext-zip`, used by the bundled importers to normalize source encodings and read `.xlsx` sources.)
- **First-class CI4 integration**: `service('iban')`, `helper('iban')`, `Config\Iban`, and 6 spark commands (`iban:validate`, `iban:parse`, `iban:resolve`, `iban:update`, `iban:publish`, `iban:bic`) — auto-discovered, no manual wiring required.

Standalone usage (outside CodeIgniter 4)
----------------------------------------

[](#standalone-usage-outside-codeigniter-4)

The core has zero framework dependencies (PHP `^8.3` + `ext-mbstring` + `ext-iconv` + `ext-zip` only), so you can use it without CI4 installed at all:

```
