در سناریوهای IVR و تماسهای خودکار، گاهی از تماسگیرنده «کد ملی» دریافت میکنیم. قبل از هر استعلام بیرونی، بهتر است صحت فرمت و رقم کنترلی (Checksum) کد ملی بررسی شود تا از درخواستهای اشتباه و هزینههای بیهوده جلوگیری شود.
منطق اعتبارسنجی کد ملی (۱۰ رقم)
-
دقیقاً ۱۰ رقم (با صفرهای ابتدای عدد).
-
همهٔ ارقام یکسان نباشند (مثل ۱۱۱۱۱۱۱۱۱۱ نامعتبر است).
-
رقم کنترلی:
-
مجموع ∑i=08di×(۱۰−i)\sum_{i=0}^{8} d_i \times (10-i) را حساب کنید.
-
باقیماندهٔ تقسیم بر ۱۱ را بگیرید: r=summod 11r = sum \mod 11.
-
اگر r<2r < 2 → رقم دهم باید برابر rr باشد.
-
اگر r≥2r \ge 2 → رقم دهم باید برابر ۱۱−r11 – r باشد.
-
فایل PHP (چکسام)
نام فایل: national_id_check.php
<?php
/**
* national_id_check.php
* Simple Iranian National ID validator (format + checksum).
* Usage (CLI): php national_id_check.php 0012345679
* Usage (Web): national_id_check.php?code=0012345679 -> JSON output
*/
function isValidIranianNationalId(string $code): bool
{
// Normalize: keep digits only
$code = preg_replace('/\D+/', '', $code ?? '');
// Must be exactly 10 digits
if (strlen($code) !== 10) {
return false;
}
// Reject all-same digits (e.g., 0000000000, 1111111111, ...)
if (preg_match('/^(\d)\1{9}$/', $code)) {
return false;
}
// Checksum
$check = intval($code[9]);
$sum = 0;
for ($i = 0; $i < 9; $i++) {
$sum += intval($code[$i]) * (10 - $i);
}
$r = $sum % 11;
if ($r < 2) {
return $check === $r;
}
return $check === (11 - $r);
}
// ---- Entry point: CLI or Web ----
$input = null;
// CLI
if (php_sapi_name() === 'cli') {
$input = $argv[1] ?? null;
if ($input === null) {
fwrite(STDERR, "Usage: php national_id_check.php <NATIONAL_ID>\n");
exit(2);
}
$valid = isValidIranianNationalId($input);
echo $valid ? "VALID\n" : "INVALID\n";
exit($valid ? 0 : 1);
}
// Web
$input = $_GET['code'] ?? $_POST['code'] ?? '';
$valid = isValidIranianNationalId($input);
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'code' => $input,
'valid' => $valid,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
تست سریع
خط فرمان:
php national_id_check.php 0012345679
خروجی: VALID یا INVALID و کد خروج ۰/۱.
وب/لوکال:
http://localhost/national_id_check.php?code=0012345679
خروجی JSON:
استفاده در استریسک بهصورت AGI
اگر بخواهی سریع در Dialplan استفادهاش کنی، میتوانی همین منطق را داخل اسکریپت AGI بگذاری و نتیجه را در یک متغیر برگردانی. نمونهٔ دیالپلن:
exten => 123,1,NoOp(Validate Melli Code)
same => n,Read(MCODE,beep,10) ; دریافت ۱۰ رقم
same => n,System(/usr/bin/php /var/lib/asterisk/agi-bin/national_id_check.php ${MCODE} >/tmp/mcode.out 2>&1)
same => n,Set(VALID_RESULT=${SHELL(cat /tmp/mcode.out | tail -1)})
same => n,GotoIf($["${VALID_RESULT}"="VALID"]?ok:bad)
same => n(ok),NoOp(Code is valid)
same => n,Playback/ok
same => n,Hangup()
same => n(bad),NoOp(Code is invalid)
same => n,Playback/invalid
same => n,Hangup()
برای خروجی مستقیم به متغیر، میتوانی نسخهٔ AGI بنویسی که SET VARIABLE چاپ کند، ولی چون خواستی «فقط یک فایل سادهٔ PHP که فرمت را چک کند»، همین روال System/سHELL هم کافی و تمیز است.
پرسشهای پرتکرار (خیلی کوتاه)
-
چرا همهٔ ارقام یکسان رد میشود؟ چون طبق قواعد رسمی، اینها کد ملی معتبر نیستند.
-
کد با صفر ابتدای عدد معتبر است؟ بله؛ حتماً باید طول ۱۰ رقم حفظ شود.
-
این اسکریپت استعلام هویتی انجام میدهد؟ خیر؛ فقط اعتبارسنجی محلی (لوکال) فرمت/چکسام.