شبا والبطاقة المصرفية

تحقق من أرقام شبا (IBAN) بمعيار ISO 7064 mod-97-10 ومن أرقام البطاقات المصرفية بالمجموع الاختباري Luhn، وابحث عن المصرف المُصدِر مع تنبيهات صريحة حول البيانات.

في هذه الصفحة
  1. البدء السريع
  2. شبا (IBAN)
    1. الصيغة
    2. التطبيع
    3. ما الذي يُفحص
  3. رقم البطاقة المصرفية
    1. الصيغة والفحوص
  4. بيانات البحث عن المصرف
  5. ملاحظات عملية

البدء السريع#

<?php
require 'vendor/autoload.php';

use RtlyKit\Validation\BankCard;
use RtlyKit\Validation\Sheba;
use function RtlyKit\is_bank_card;
use function RtlyKit\is_sheba;

var_dump(Sheba::isValid('IR800170000000000000000123'));   // bool(true)
var_dump(is_sheba('800170000000000000000123'));           // bool(true)، تُضاف "IR" نيابةً عنك
var_dump(BankCard::isValid('6037-9912-3456-7893'));       // bool(true)
var_dump(is_bank_card('۶۰۳۷۹۹۱۲۳۴۵۶۷۸۹۳'));               // bool(true)، أرقام فارسية

echo Sheba::getBankName('IR800170000000000000000123'), "\n";   // بانک ملی ایران
echo BankCard::getBankName('6219861234567898'), "\n";          // بانک سامان

الأرقام في هذه الأمثلة مصطنعة: تجتاز المجموع الاختباري لكنها لا تخص حسابات حقيقية. وتطبّق الفئتان كلتاهما عقد Validator المشترك، ولا تُلقيان استثناءً بسبب مُدخَل سيّئ، ولهما أيضًا الدالتان المساعدتان validate_sheba() وvalidate_bank_card().

شبا (IBAN)#

الصيغة#

رقم شبا هو IBAN الإيراني: IR، ثم رقما تحقق، ثم BBAN من 22 رقماً، أي 26 نويسة في المجموع. وتحدد الأرقام الثلاثة الأولى من BBAN المصرف.

IR 80 017 0000000000000000123
│  │  │   └─ rest of the BBAN (19 digits)
│  │  └──── bank code (3 digits)
│  └─────── check digits
└────────── country code

التطبيع#

تحوّل Sheba::normalize() النص إلى أحرف كبيرة، وتحوّل الأرقام الفارسية والعربية، وتحذف المسافات والشرطات والمسافات الصفرية. أما النص المكوّن من 24 رقمًا بالضبط، وهي الصيغة الشائعة «بدون IR» التي تطبعها المصارف، فتُضاف إليه البادئة IR. وأي مُدخَل آخر يُترك كما كُتب ثم يفشل في فحص الصيغة:

echo Sheba::normalize('800170000000000000000123');        // IR800170000000000000000123
echo Sheba::normalize('ir80 0170 0000');                   // IR8001700000
echo json_encode(Sheba::validate('ir80-0170-0000-0000-0000-0001-23')->isValid());   // true

ما الذي يُفحص#

  1. النوع والحجم (invalid_type وinput_too_long).
  2. الصيغة: IR يليه 24 رقمًا بالضبط، وإلا invalid_format.
  3. المجموع الاختباري: ISO 7064 mod-97-10. تُنقل النويسات الأربع الأولى إلى النهاية، ويتحول I وR إلى 18 و27، ويجب أن يساوي العدد الناتج بالنسبة إلى 97 القيمة 1؛ وإلا invalid_checksum.

يجري البحث عن المصرف قبل المجموع الاختباري، فيكون رمز المصرف موجودًا في details() حتى مع رقم تحقق خاطئ:

$r = Sheba::validate('IR060170000000000000000123');
var_dump($r->isValid());       // bool(false)
print_r($r->errors());         // Array ( [0] => invalid_checksum )
echo $r->details()['bank_name']; // بانک ملی ایران

$ok = Sheba::validate('IR800170000000000000000123');
echo json_encode($ok->details(), JSON_UNESCAPED_UNICODE);
// {"normalized":"IR800170000000000000000123","bank_code":"017","bank_name":"بانک ملی ایران"}

$unknown = Sheba::validate('IR049990000000000000000123');
var_dump($unknown->isValid(), $unknown->details()['bank_name']);   // bool(true)  NULL

التفاصيل: normalized وbank_code (نص من ثلاثة أرقام، أو null عند فشل الصيغة) وbank_name (أو null حين لا يكون الرمز في الجدول). ورقم شبا صحيح المجموع الاختباري ورمز مصرفه غير معروف هو رقم صالح؛ والاسم وحده هو المفقود.

أسماء المصارف. الأسماء هي أسماء المصرف المُصدِر وقت التخصيص. وتحتفظ رموز المصارف التي اندمجت لاحقًا باسمها الأصلي.

رقم البطاقة المصرفية#

الصيغة والفحوص#

تتكون البطاقة المصرفية الإيرانية من 16 رقمًا. وتُبقي BankCard::normalize() على الأرقام فقط بعد تحويل الفارسية والعربية منها، فالمسافات والشرطات وسائر الفواصل مسموح بها. والفحوص بالترتيب:

  1. النوع والحجم.
  2. 16 رقمًا بالضبط، وإلا invalid_format.
  3. تطابق الأرقام الستة عشر جميعها (مثل 0000000000000000) يعطي repeated_digits.
  4. المجموع الاختباري Luhn، وإلا invalid_checksum. بدءًا من اليمين يُضاعَف كل رقم ثانٍ (مع طرح 9 حين تتجاوز النتيجة 9)، ويجب أن يقبل مجموع الأرقام القسمة على 10.
$ok = BankCard::validate('6037-9912 3456 7893');
echo json_encode($ok->details(), JSON_UNESCAPED_UNICODE);
// {"normalized":"6037991234567893","bin":"603799","bank_name":"بانک ملی ایران"}

print_r(BankCard::validate('6037991234567890')->errors());   // [invalid_checksum]
print_r(BankCard::validate('0000000000000000')->errors());   // [repeated_digits]
print_r(BankCard::validate('1234')->errors());               // [invalid_format]

$x = BankCard::validate('9999991234567893');   // المجموع الاختباري سليم، لكن BIN غير موجود في الجدول
var_dump($x->isValid(), $x->details()['bank_name']);   // bool(true)  NULL

التفاصيل: normalized وbin (أول ستة أرقام، أو null إذا فشلت الصيغة) وbank_name. وكما في شبا، يجري البحث عن BIN قبل فحصي تكرار الأرقام والمجموع الاختباري.

الدالتان BankCard::getBankName() وSheba::getBankName() اختصاران يُرجعان الاسم لرقم صالح فقط، وnull فيما عدا ذلك:

var_dump(BankCard::getBankName('6037991234567890'));   // NULL، لأن المجموع الاختباري يفشل
var_dump(BankCard::getBankName('6037991234567893'));   // string(26) "بانک ملی ایران"

بيانات البحث عن المصرف#

الجدولالمفتاحعدد البنود
رموز BIN للبطاقاتأول 6 أرقام من البطاقة39
رموز المصارف في شبا3 أرقام بعد IRkk38

لا يُدرَج البند إلا إذا اتفق مصدران مستقلان على الأقل على المطابقة (جداول بادئات المصارف العامة ومجموعات البيانات المجتمعية). أما البنود ذات المصدر الواحد أو المتعارضة فتُترك عن قصد.

ما فحصناه في 2026-10-08:

  • تذكر مواصفة IBAN الوطنية المنشورة لدى البنك المركزي الإيراني 19 رمزًا للمصارف، وهي كلها تطابق جدولنا. وتحسم القائمة أيضًا أمر الرمز 051: فهو يخص مؤسسة «توسعه» الائتمانية.
  • رموز BIN للبطاقات وبقية رموز شبا تتفق مع عدة صفحات عامة. وبالنسبة إلى BIN 585983 (تجارت) لدينا أيضًا إعلان المصرف نفسه كما نقلته وكالتا أنباء.
من المفيد أن تعرف. الجداول صغيرة، فكثير من البطاقات الصالحة صادر عن مصرف غير مدرج، ويكون bank_name عندئذ null. ولم نصل إلى سجل رسمي لرموز BIN، وقائمة البنك المركزي مؤرخة بسنة 2017، لذلك تعتمد الرموز الأحدث على صفحات عامة. المصارف تندمج وتغيّر أسماءها وتعيد تخصيص النطاقات، فاعرض الاسم على أنه تلميح، ولا تستخدمه في قرار قانوني أو مالي. التفاصيل في الدقة والبيانات.

لا تعتمد الصلاحية على هذه الجداول أبدًا. فالرقم صحيح المجموع الاختباري صالح سواء عُرف مصرفه أم لم يُعرف.

ملاحظات عملية#

  • يكشف المجموع الاختباري الأخطاء المطبعية لا الأرقام المزيفة. ولا يستطيع أن يخبرك بأن بطاقة موجودة أو بأن حسابًا يخص شخصًا ما.
  • تحقق من رقم البطاقة للشكل فقط. ولا تسجّل أرقام البطاقات كاملة في السجلات أبداً، ولا تخزّن CVV2 ولا كلمة السر الثانية.
  • خزّن القيمة المطبَّعة، لتكون 6037-9912-3456-7893 و6037991234567893 السجل نفسه.
  • يجب أن تبقى أرقام البطاقات وأرقام شبا نصوصًا. فالعدد المكوّن من 16 رقمًا قد يتجاوز ما يستطيع رقم JSON أو عدد عشري تمثيله بدقة.

سقف الحجم وقواعد النوع هي نفسها لكل أداة تحقق؛ انظر معالجة المُدخَلات.