alihoushy/iranian-sheba

Validate and normalize Iranian SHEBA / IBAN numbers with mod-97 and detect the owning bank.

Maintainers

Package info

github.com/alihoushy/iranian-sheba

pkg:composer/alihoushy/iranian-sheba

Transparency log

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-07-29 06:50 UTC

This package is auto-updated.

Last update: 2026-07-29 06:53:50 UTC


README

شماره شبا

نسخه در Packagist تست‌ها کیفیت کد تعداد نصب مجوز

اعتبارسنجی و نرمال‌سازی شماره شبا (IBAN ایران) با الگوریتم استاندارد mod-97 و تشخیص بانک از روی کد آن.

این پکیج PHP خالص است؛ به هیچ فریمورکی وابسته نیست و در Laravel، Symfony، Slim یا پروژه‌های بدون فریمورک به یک شکل کار می‌کند.

چرا این پکیج؟

  • بدون وابستگی: هیچ پکیج دیگری نصب نمی‌کند و از bcmath یا gmp هم استفاده نمی‌کند؛ باقی‌مانده رقم‌به‌رقم محاسبه می‌شود.
  • ورودی واقعی را می‌پذیرد: ارقام فارسی و عربی-هندی، حروف کوچک، فاصله، خط تیره و حتی شبای بدون پیشوند IR.
  • استاندارد را کامل رعایت می‌کند: ارقام کنترل رزروشده ۰۰، ۰۱ و ۹۹ رد می‌شوند؛ این‌ها از نظر mod-97 درست‌اند و پیاده‌سازی‌های ساده‌انگارانه می‌پذیرندشان.
  • تغییرناپذیر: هر نمونه Sheba تضمین‌شده معتبر است؛ اعتبارسنجی فقط یک‌بار در لحظه ساخت انجام می‌شود.

نیازمندی‌ها

  • PHP نسخه ۸.۱ یا بالاتر
  • اکستنشن mbstring

نصب

composer require alihoushy/iranian-sheba

شروع سریع

<?php

use AliHoushy\IranianSheba\Sheba;

Sheba::isValid('IR820540102680020817909002');   // true
Sheba::isValid('IR820540102680020817909003');   // false — یک رقم دستکاری شده

$sheba = Sheba::from('IR82 0540 1026 8002 0817 9090 02');

$sheba->value();               // 'IR820540102680020817909002'
$sheba->format();              // 'IR82 0540 1026 8002 0817 9090 02'
$sheba->checkDigits();         // '82'
$sheba->bankCode();            // '054'
$sheba->accountIdentifier();   // '0102680020817909002'

$bank = $sheba->bank();
$bank->name;                   // 'بانک پارسیان'
$bank->englishName;            // 'Parsian Bank'
$bank->slug;                   // 'parsian'
(string) $bank;                // 'بانک پارسیان'

ساختار شبا

طبق استاندارد ISO 13616، شبای ایران ۲۶ نویسه دارد:

بخش طول نمونه متد
کد کشور ۲ IR Sheba::COUNTRY_CODE
ارقام کنترل ۲ 82 checkDigits()
کد بانک ۳ 054 bankCode()
شناسه حساب ۱۹ 0102680020817909002 accountIdentifier()

[!NOTE] accountIdentifier() لزوماً همان «شماره حساب» شما در بانک نیست. هر بانک قاعده متفاوتی برای نگاشت شماره حساب داخلی خود به این ۱۹ رقم دارد و این پکیج آن نگاشت را انجام نمی‌دهد.

نرمال‌سازی ورودی

ورودی‌های زیر همگی به شبای یکسان IR820540102680020817909002 تبدیل می‌شوند:

Sheba::from('IR820540102680020817909002');        // استاندارد
Sheba::from('ir820540102680020817909002');        // حروف کوچک
Sheba::from('IR82 0540 1026 8002 0817 9090 02');  // گروه‌بندی چهارتایی
Sheba::from('IR82-0540-1026-8002-0817-9090-02');  // با خط تیره
Sheba::from('IR۸۲۰۵۴۰۱۰۲۶۸۰۰۲۰۸۱۷۹۰۹۰۰۲');        // ارقام فارسی
Sheba::from('820540102680020817909002');          // بدون پیشوند IR

اگر ورودی دقیقاً ۲۴ رقم و بدون پیشوند باشد، IR خودکار به آن افزوده می‌شود — چون بسیاری از سامانه‌ها شبا را بدون پیشوند نمایش می‌دهند.

برای نرمال‌سازی بدون سنجش ارقام کنترل:

Sheba::normalize('ir82 0540 1026 8002 0817 9090 02');  // 'IR820540102680020817909002'
Sheba::normalize('سلام');                               // null

مدیریت خطا

use AliHoushy\IranianSheba\Exception\InvalidShebaException;

// ۱) بولین ساده
if (! Sheba::isValid($input)) { /* ... */ }

// ۲) خروجی nullable
$sheba = Sheba::tryFrom($input);
if ($sheba === null) { /* ... */ }

// ۳) استثنا با پیام فارسی و دسترسی به ورودی خام
try {
    $sheba = Sheba::from($input);
} catch (InvalidShebaException $e) {
    $e->getMessage();  // 'ارقام کنترل شبا با الگوریتم استاندارد mod-97 هم‌خوانی ندارد.'
    $e->input();       // ورودی خام کاربر، پیش از نرمال‌سازی
}

پیام خطا سه حالت را از هم جدا می‌کند: شکل نادرست، ارقام کنترل رزروشده، و ناهم‌خوانی mod-97. همه استثناها رابط AliHoushy\IranianSheba\Exception\ShebaException را پیاده‌سازی می‌کنند.

کار با بانک‌ها

use AliHoushy\IranianSheba\Banks;

Banks::forCode('012');          // Bank: بانک ملت
Banks::forCode('۱۲');           // همان — ارقام فارسی و پر شدن با صفر
Banks::forSlug('mellat');       // جست‌وجو با شناسه لاتین
Banks::search('پارسیان');       // جست‌وجوی جزئی در نام فارسی و انگلیسی
Banks::search('parsian');       // همان نتیجه
Banks::all();                   // هر ۳۸ بانک
Banks::codes();                 // فهرست کدها
Banks::has('099');              // false

اگر کد بانک ناشناخته باشد، bank() مقدار null برمی‌گرداند. توجه کنید که این با نامعتبر بودن شبا فرق دارد: یک شبا می‌تواند از نظر ارقام کنترل کاملاً درست باشد ولی کد بانکش در دیتاست نباشد.

$sheba = Sheba::from('IR740990000000000000000001');

Sheba::isValid((string) $sheba);   // true  — شبا درست است
$sheba->hasKnownBank();            // false — ولی کد ۰۹۹ بانک شناخته‌شده‌ای نیست
$sheba->bank();                    // null

[!NOTE] «بانک مهر ایران» در منبع داده دو کد دارد: 060 و 090. برای همین Banks::forSlug('mehr-iran') همیشه کد کوچک‌تر یعنی 060 را برمی‌گرداند و Banks::codesForSlug('mehr-iran') هر دو را می‌دهد.

مرجع API

Sheba

متد خروجی توضیح
Sheba::from(string) self ساخت نمونه؛ برای ورودی نامعتبر استثنا پرتاب می‌کند
Sheba::tryFrom(string) ?self مانند بالا، اما null برمی‌گرداند
Sheba::isValid(string) bool فقط اعتبارسنجی
Sheba::normalize(string) ?string نرمال‌سازی بدون سنجش ارقام کنترل
value() string شبای نرمال‌شده
format(string $separator = ' ') string گروه‌بندی چهارتایی استاندارد IBAN
checkDigits() string دو رقم کنترل
bankCode() string کد سه‌رقمی بانک
accountIdentifier() string شناسه ۱۹ رقمی حساب
bank() ?Bank بانک صادرکننده؛ برای کد ناشناخته null
hasKnownBank() bool آیا کد بانک در دیتاست هست؟
equals(self) bool مقایسه بر پایه مقدار
__toString() string معادل value()

Bank

چهار پراپرتی خواندنی code، slug، name و englishName به‌همراه equals()، toArray() و __toString().

Banks

متدهای ایستا: forCode()، has()، forSlug()، codesForSlug()، search()، all() و codes().

الگوریتم اعتبارسنجی

۱. ورودی نرمال می‌شود: ارقام غیرلاتین تبدیل، جداکننده‌ها حذف و حروف بزرگ می‌شوند. ۲. شکل نهایی باید IR به‌علاوه ۲۴ رقم باشد. ۳. ارقام کنترل ۰۰، ۰۱ و ۹۹ رد می‌شوند؛ ISO 13616 این مقادیر را رزرو کرده است. ۴. چهار نویسه نخست به انتهای رشته منتقل می‌شوند. ۵. حروف به عدد تبدیل می‌شوند (A=10 تا Z=35، پس IR می‌شود 1827). ۶. باقی‌مانده بر ۹۷ باید دقیقاً برابر ۱ باشد.

باقی‌مانده رقم‌به‌رقم محاسبه می‌شود، پس نه سرریز عدد صحیح رخ می‌دهد و نه به bcmath یا gmp نیاز است.

اطمینان از درستی

علاوه بر تست‌های نمونه‌محور، یک تست ویژگی‌محور برای هر ۳۸ بانک شبای معتبر تولید می‌کند و می‌سنجد که:

  • همه شباهای تولیدشده پذیرفته شوند و بانکشان درست تشخیص داده شود.
  • تغییر هر تک رقم در هر موقعیتی شبا را نامعتبر کند.
  • جابه‌جایی هر دو رقم مجاور شناسایی شود.

منبع داده

دیتاست بانک‌ها از پروژه persian-tools/persian-tools (مجوز MIT) برداشت شده و با دیتاست مستقل dart-persian-tools مقایسه شده است؛ هر دو روی هر ۳۸ کد هم‌نظرند. سپاس از نگهدارندگان آن پروژه‌ها.

اگر خطایی در نام یا کد بانکی دیدید، لطفاً Issue باز کنید.

تست

composer test      # اجرای تست‌ها
composer lint      # بررسی سبک کد (PSR-12 با Pint)
composer analyse   # آنالیز ایستا با PHPStan سطح ۹
composer check     # هر سه مورد بالا

مشارکت

از مشارکت شما استقبال می‌کنیم. لطفاً پیش از ارسال Pull Request فایل CONTRIBUTING.md را بخوانید.

امنیت

اگر آسیب‌پذیری امنیتی پیدا کردید، لطفاً به‌جای ثبت Issue عمومی، طبق راهنمای SECURITY.md گزارش دهید.

تغییرات

فهرست تغییرات هر نسخه در CHANGELOG.md نگهداری می‌شود.

مجوز

این پروژه تحت مجوز MIT منتشر شده است.

English

Validate and normalize Iranian SHEBA / IBAN numbers with mod-97 and detect the owning bank.

A framework-agnostic, pure-PHP package with zero runtime dependencies — no bcmath, no gmp.

composer require alihoushy/iranian-sheba
use AliHoushy\IranianSheba\Sheba;

Sheba::isValid('IR820540102680020817909002');       // true

$sheba = Sheba::from('IR82 0540 1026 8002 0817 9090 02');
$sheba->bankCode();        // '054'
$sheba->bank()?->name;     // 'بانک پارسیان'
$sheba->format();          // 'IR82 0540 1026 8002 0817 9090 02'

Unlike naive implementations, this package also rejects the check digits 00, 01 and 99, which satisfy the mod-97 test but are reserved by ISO 13616. A validity-correct IBAN with an unrecognised bank code is still accepted — use hasKnownBank() to tell the two situations apart.

The bank dataset comes from persian-tools/persian-tools (MIT), cross-checked against an independent dataset; both agree on all 38 codes.

Requires PHP 8.1+ and ext-mbstring. Released under the MIT license. The full documentation above is written in Persian, the primary language of this package's community.