alihoushy / iranian-sheba
Validate and normalize Iranian SHEBA / IBAN numbers with mod-97 and detect the owning bank.
Requires
- php: ^8.1
- ext-mbstring: *
Requires (Dev)
- laravel/pint: ^1.18
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^10.5 || ^11.0
README
شماره شبا
اعتبارسنجی و نرمالسازی شماره شبا (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.