ورود

View Full Version : آموزش: تشخیص صحت شناسه ملی اشخاص حقوقي



saeedjaihoni
جمعه 27 اردیبهشت 1392, 17:09 عصر
مطلب زير رو از اين آدرس گرفتم و كد جاوا اسكريپتش هم بصورتي كه مي بينيد بود و من لازم ديدم كه اونو براي دوستاني كه به اين كد نياز دارن به كد دلفي تبديل كنم
لينك منبع : http://www.aliarash.com/article/shenasameli/shenasa_meli.htm

امروزه در اکثر نرم افزارهای تولیدی نیاز به استفاده از شناسه ملی اشخصاص حقوقی به عنوان یک مشخصه منحصر به فرد برای اطلاعات شخص حقوقي می باشد.
برای استعلام شناسه ملی می توانید به سایت http://www.ilenc.ir مراجعه نموده و با وارد کردن مشخصات شخص حقوقی مورد نظر اقدام به جستجوی شناسه ملی داده شده نمایید. نتیجه این جستجو محل ثبت ، نام شخص حقوقی، شماره ثبت ، شناسه ملی ، تاریخ ثبت و آدرس و کد پستی شخص حقوقی می باشد
هر چند روش بالا برای اطمینان از صحت و ارتباط شناسه داده شده با شخص مورد نظر روش خوبی است ولی همواره نیازمند داشتن یک اتصال اینترنتی بوده و به صورت موردی باید جستجو شود. (شبیه بررسی مدارک در مراحل اولیه کارها ) اما مهندسان نرم افزار و برنامه نویسان نیازمند يک الگوی کنترلی برای صحت کد می باشند تا بتوانند از ورود کد های نامعتبر جلوگیری کرده و یا کد های موجود در سیستم را وارسی نمایند.
متاسفانه در حال حاضر هیچ الگوریتمی برای تشخیص صحت کد ورودی در اختیار برنامه نویسان وجود ندارد.
اخیرا با توجه به نیاز خودم به کنترل صحت کد ورودی ،الگوریتم مربوط به کنترل صحت شناسه ملی را بدست آوردم و چون مطمئن هستم افراد زیادی هم همین نیاز را دارند روال انجام کار را در این جا توضیح می دهم
شناسه ملی شماره ای است 11 رقمی که از سمت چپ چهار رقم کد شهرستان محل ثبت ، شش رقم بعدی کد منحصر به فرد برای شخص حقوقی دارنده شناسه در شهرستان محل ثبت و رقم آخر آن هم یک رقم کنترل است که از روی 10 رقم سمت چپ بدست می آید. برای بررسی کنترل کد کافی است مجدد از روی 10 رقم سمت چپ رقم کنترل را محاسبه کنیم
ساختار شناسه ملی در زیر نشان داده شده است
ساختار شناسه ملی
ارقام کد رقم کنترل 10 رقم سمت چپ شناسه ملی
موقعیت
1
2 3 4 5 6 7 8 9 10

1- برای محاسبه رقم کنترل از روی سایر ارقام ، هر رقم را با رقم دهگان کد +2 کرده و سپس در ضریب آن ضرب می کنیم و حاصل را با هم جمع می کنیم.
2- مجموع بدست آمده از مرحله یک را بر 11 تقسیم می کنیم
3- اگر باقیمانده برابر 10 باشد ، باقیمانده را برابر 0 قرار می دهیم
4-اگر رقم کنترل برابر باقیمانده باشد شناسه ملی صحیح فرض می شود در غیر این صورت شناسه ملی مورد نظر صحیح نمی باشد

مثال : آیا کد 10380284790 یک شناسه ملی معتبر است؟ (نمایش اطلاعات مالک شناسه)
برای این منظور باید براساس جدول زیر عمل کنیم. دقت کنید که ضریب ارقام دهگان به بعد عبارتند از 17 ، 19 ، 23 ، 27، 29 و همین الگو مجددا تکرار شده است
ساختار شناسه ملی
ساختار کد رقم کنترل 10 رقم سمت چپ شناسه ملی
ارقام شناسه 0 9 7 4 8 2 0 8 3 0 1
رقم دهگان +2 11 11 11 11 11 11 11 11 11 11
ضريب ارقام 17 19 23 27 29 17 19 23 27 29
محاسبه حاصل ضرب 340 342 345 513 377 187 361 322 297 348

هریک از ارقام سمت چپ شناسه ملی (10 رقم سمت چپ شناسه ملی) را با رقم دهگان شناسه ملی +2 جمع می کنیم و حاصل را در را ضریب آن رقم ضرب کرده و نتیجه ها را با هم جمع می کنیم .
دقت کنید در اینجا رقم دهگان 9 و رقم دهگان +2 برابر با 11 می باشد. بنابراین همه ارقام کد با 11 جمع شده و سپس در ضریب مربوط به خودش ضرب شده است.
(1+11)*29+(0+11)*27+(3+11)*23+(8+11)*19+(0+11)*17+ (2+11)*29+(8+11)*27+(4+11)*23+(7+11)*19+(9+11)*17= 3432
3432÷11=312 و R=0
چون باقیمانده برابر صفر است پس باید رقم کنترل این شناسه برابر صفر باشد.
با دقت در شناسه ملی مورد نظر متوجه می شویم که رقم کنترل ورودی برابر صفر است پس شناسه ملی مورد نظر به عنوان یک شناسه ملی معتبر قابل قبول است.


كد جاوا اسكريپت :
function checkCodeMeli(code)
{

var L=code.length;

if(L<11 || parseInt(code,10)==0) return false;

if(parseInt(code.substr(3,6),10)==0) return false;
var c=parseInt(code.substr(10,1),10);
var d=parseInt(code.substr(9,1),10)+2;
var z=new Array(29,27,23,19,17);
var s=0;
for(var i=0;i<10;i++)
s+=(d+parseInt(code.substr(i,1),10))*z[i%5];
s=s%11;if(s==10) s=0;
return (c==s);

}


كد دلفي :
function TForm1.ShMeli(Code : String):Boolean;
var L,C,D,S,I : Integer;
flag : Boolean;
begin

flag := (Code = '00000000000') or (code = '11111111111') or (code = '22222222222') or (code = '33333333333');
flag := (Code = '44444444444') or (code = '55555555555') or (code = '66666666666') or (code = '77777777777') or flag;
flag := (Code = '88888888888') or (code = '99999999999') or flag;
if not flag then
begin
if Code = '' then
ShMeli:= False
else
if Length(Code) < 11 then
ShMeli := False
else
begin
C:= StrToInt(Code[11]); // شناسايي رقم كنترل
L:=Length(Code); // محاسبه طول كد
D:= StrToInt(Code[10])+2; /// محاسبه دهگان +2

S := 0; //1- براي محاسبه رقم کنترل از روي ساير ارقام ، هر رقم را با رقم
// دهگان کد +2 کرده و سپس در ضريب آن ضرب مي کنيم و حاصل را با هم جمع مي کنيم.
S := s + ((d+StrToInt(Code[1]))*29);
S := s + ((d+StrToInt(Code[2]))*27);
S := s + ((d+StrToInt(Code[3]))*23);
S := s + ((d+StrToInt(Code[4]))*19);
S := s + ((d+StrToInt(Code[5]))*17);
S := s + ((d+StrToInt(Code[6]))*29);
S := s + ((d+StrToInt(Code[7]))*27);
S := s + ((d+StrToInt(Code[8]))*23);
S := s + ((d+StrToInt(Code[9]))*19);
S := s + ((d+StrToInt(Code[10]))*17);
S := s mod 11; //2- مجموع بدست آمده از مرحله يک را بر 11 تقسيم مي کنيم
if s = 10 then //3- اگر باقيمانده برابر 10 باشد ، باقيمانده را برابر 0 قرار مي دهيم
s := 0
else
if s = c then //4-اگر رقم کنترل برابر باقيمانده باشد شناسه ملي صحيح فرض مي شود
ShMeli := True;
end;
end
else ShMeli := False; //در غير اين صورت شناسه ملي مورد نظر صحيح نمي باشد
end;

مثال :
procedure TForm1.Button1Click(Sender: TObject);
begin

if CodeMeli(Edit1.Text)=true then
ShowMessage('.كد صحيح است')
else
ShowMessage('.كد معتبر نيست');


end;

developing
شنبه 28 اردیبهشت 1392, 09:25 صبح
با سلام

دوستان من این کد رو امتحان کردم درست نبود.

من کوچیک تر از اون هستم که ...
اما از اساتیدی مثل آقا شاهین و داش یوسف انتظار داشتیم قبل از اینکه تشکر کنند (که برای خیلی ها در این تالار به عنوان تایید یک پست به کار می ره) بیشتر دقت کنند.

من کد زیر رو به عنوان تایید کدملی استفاده می کنم که به ازای هر کاری که می خوام نتیجه ی خوبی می ده مثلا اگه تعداد اعداد 10 تا نباشه یا اینکه مشابه باشه تابع مقادیر خاص خودش رو بر می گردونه.

البته نظرات شما راهنمای کار ما خواهد بود.

function ValidateNationalCode(NationalCode: string): Byte;
const
Valid = 1;
NumberNotEqual10 = 2;
SameNumber = 4;
var
I, Sum, a, c: Integer;
First5, Last5, First2, First34: string;
begin
Result := 0;
if Length(NationalCode) <> 10 then
Exit(NumberNotEqual10);
Last5 := RightStr(NationalCode, 5);
First5 := LeftStr(NationalCode, 5);
First2 := LeftStr(First5, 2);
First34:= RightStr(First5, 2);
if (First5 = Last5)and(First2 = First34)and(First2[1] = First2[2])
and(First2[1]= First5[3])then
Exit(SameNumber);
Sum := 0;
for I := 1 to Length(NationalCode) - 1 do
Sum := Sum + (11 - i) * StrToInt(NationalCode[i]);
a := StrToInt(NationalCode[10]);
c := sum mod 11;
if ((c < 2) and (c = a))or
((c >= 2) and (a = 11 - c))then
Result := Valid;
end;

Mask
شنبه 28 اردیبهشت 1392, 10:04 صبح
بیش از چندین پست در همین سایت در این مورد وجود داره. لطفا قبلا از ایجاد پست جستجو کنید. و چرخ رو دوباره اختراع نکنید.

hossein_h62
شنبه 28 اردیبهشت 1392, 13:35 عصر
با سلام

دوستان من این کد رو امتحان کردم درست نبود.

من کوچیک تر از اون هستم که ...
اما از اساتیدی مثل آقا شاهین و داش یوسف انتظار داشتیم قبل از اینکه تشکر کنند (که برای خیلی ها در این تالار به عنوان تایید یک پست به کار می ره) بیشتر دقت کنند.

من کد زیر رو به عنوان تایید کدملی استفاده می کنم که به ازای هر کاری که می خوام نتیجه ی خوبی می ده مثلا اگه تعداد اعداد 10 تا نباشه یا اینکه مشابه باشه تابع مقادیر خاص خودش رو بر می گردونه.

البته نظرات شما راهنمای کار ما خواهد بود.

function ValidateNationalCode(NationalCode: string): Byte;
const
Valid = 1;
NumberNotEqual10 = 2;
SameNumber = 4;
var
I, Sum, a, c: Integer;
First5, Last5, First2, First34: string;
begin
Result := 0;
if Length(NationalCode) <> 10 then
Exit(NumberNotEqual10);
Last5 := RightStr(NationalCode, 5);
First5 := LeftStr(NationalCode, 5);
First2 := LeftStr(First5, 2);
First34:= RightStr(First5, 2);
if (First5 = Last5)and(First2 = First34)and(First2[1] = First2[2])
and(First2[1]= First5[3])then
Exit(SameNumber);
Sum := 0;
for I := 1 to Length(NationalCode) - 1 do
Sum := Sum + (11 - i) * StrToInt(NationalCode[i]);
a := StrToInt(NationalCode[10]);
c := sum mod 11;
if ((c < 2) and (c = a))or
((c >= 2) and (a = 11 - c))then
Result := Valid;
end;

سلام
مطلبی که دوستمون در پست1 گذاشتند همونطور که از عنوان تاپیک مشخص هست مربوطه به شناسه ملی اشخاص حقوقی هست، نه کد ملی اشخاص حقیقی؛ این دو هم ساختار متفاوتی دارن و هم الگوریتم کنترلی متفاوت. کدی که شما (developing (http://barnamenevis.org/member.php?116920-developing)) گذاشتید مربوط به کد ملی اشخاص حقیقی هست.
در ضمن کد پست 1 رو کنترل کردم فقط یه اصلاح کوچیک میخواد که باید در Line 37 کلمه ELSE به end تغییر پیدا کنه. با یه سری شناسه ملی هم کنترلش کردم مشکل دیگه ای نداشت.
کد نهایی اینجوری میشه :
function TForm1.ShMeli(Code : String):Boolean;
var L,C,D,S,I : Integer;
flag : Boolean;
begin

flag := (Code = '00000000000') or (code = '11111111111') or (code = '22222222222') or (code = '33333333333');
flag := (Code = '44444444444') or (code = '55555555555') or (code = '66666666666') or (code = '77777777777') or flag;
flag := (Code = '88888888888') or (code = '99999999999') or flag;
if not flag then
begin
if Code = '' then
ShMeli:= False
else
if Length(Code) < 11 then
ShMeli := False
else
begin
C:= StrToInt(Code[11]); // شناسايي رقم كنترل
L:=Length(Code); // محاسبه طول كد
D:= StrToInt(Code[10])+2; /// محاسبه دهگان +2

S := 0; //1- براي محاسبه رقم کنترل از روي ساير ارقام ، هر رقم را با رقم
// دهگان کد +2 کرده و سپس در ضريب آن ضرب مي کنيم و حاصل را با هم جمع مي کنيم.
S := s + ((d+StrToInt(Code[1]))*29);
S := s + ((d+StrToInt(Code[2]))*27);
S := s + ((d+StrToInt(Code[3]))*23);
S := s + ((d+StrToInt(Code[4]))*19);
S := s + ((d+StrToInt(Code[5]))*17);
S := s + ((d+StrToInt(Code[6]))*29);
S := s + ((d+StrToInt(Code[7]))*27);
S := s + ((d+StrToInt(Code[8]))*23);
S := s + ((d+StrToInt(Code[9]))*19);
S := s + ((d+StrToInt(Code[10]))*17);
S := s mod 11; //2- مجموع بدست آمده از مرحله يک را بر 11 تقسيم مي کنيم
if s = 10 then //3- اگر باقيمانده برابر 10 باشد ، باقيمانده را برابر 0 قرار مي دهيم
s := 0
end;
if s = c then //4-اگر رقم کنترل برابر باقيمانده باشد شناسه ملي صحيح فرض مي شود
ShMeli := True;
end
else ShMeli := False; //در غير اين صورت شناسه ملي مورد نظر صحيح نمي باشد
end;

f.beigirad
یک شنبه 17 شهریور 1392, 12:52 عصر
کسی میدونه کد شناسایی اتباع رو چجوری اعتبار سنجی کنیم؟

lightblue
یک شنبه 21 مهر 1392, 10:02 صبح
سلام

ضمن تشکر فراوان از saeedjaihoni (http://barnamenevis.org/member.php?43743-saeedjaihoni) من دیدم زحمت کشیدن برای جاوا اسکریپت و دلفی کد نوشتن من هم برای جاوا کد تشخیص صحت شناسه ملی اشخاص حقوقی و کد ملی اشخاص حقیقی رو باز نویسی کردم:


public static boolean checkLegalNationalCode(String nationalCode) {

if (nationalCode.length() < 11 || Integer.parseInt(nationalCode) == 0)
return false;

if (Integer.parseInt(nationalCode.substring(3, 9)) == 0)
return false;

int c = Integer.parseInt(nationalCode.substring(10, 11));
int d = Integer.parseInt(nationalCode.substring(9, 10)) + 2;
int[] z = new int[] { 29, 27, 23, 19, 17 };
int s = 0;

for (byte i = 0; i < 10; i++)
s += (d + Integer.parseInt(nationalCode.substring(i, i + 1))) * z[i % 5];

s = s % 11;

if (s == 10)
s = 0;

return (c == s);
}

public static boolean checkPersonalNationalCode(String nationalCode) {
boolean retVal = false;
float c, n, r;

if (!(nationalCode.length() < 10 ||
nationalCode == "0000000000" ||
nationalCode == "1111111111" ||
nationalCode == "2222222222" ||
nationalCode == "3333333333" ||
nationalCode == "4444444444" ||
nationalCode == "5555555555" ||
nationalCode == "6666666666" ||
nationalCode == "7777777777" ||
nationalCode == "8888888888" ||
nationalCode == "9999999999"))
{
c = Float.valueOf(nationalCode.substring(9, 10));

n = Integer.valueOf(nationalCode.substring(0, 1)) * 10 +
Integer.valueOf(nationalCode.substring(1, 2)) * 9 +
Integer.valueOf(nationalCode.substring(2, 3)) * 8 +
Integer.valueOf(nationalCode.substring(3, 4)) * 7 +
Integer.valueOf(nationalCode.substring(4, 5)) * 6 +
Integer.valueOf(nationalCode.substring(5, 6)) * 5 +
Integer.valueOf(nationalCode.substring(6, 7)) * 4 +
Integer.valueOf(nationalCode.substring(7, 8)) * 3 +
Integer.valueOf(nationalCode.substring(8, 9)) * 2;

r = (n - ((int)(n / 11) * 11));

if ((r == 0 && r == c) || (r == 1 && c == 1) || (r > 1 && c == (11 - r)))
retVal = true;
}
return retVal;
}

tazarvmmr
یک شنبه 16 شهریور 1393, 16:05 عصر
امروز دنبال الگوریتم تشخیص شناسه ملی اشخاص حقوقی بودم که بعد از یکی دو جا که اشتباه گفته بودن درستشو اینجا پیدا کردم و خوشبختانه کد دلفی هم دوستان گذاشته بودن، با اجازتون کد رو برداشتم و استفاده کردم ولی از اونجاییکه قطعا کد برای توضیح نوشته شده صرفا، در نامگذاری ها و طریقه نوشتن خیلی حوصله به خرج داده نشده، من بااجازتون یک مقداری به لحاظ نحوه نوشتن تغییرش دادم و فکر میکنم شاید اینجا قرارش بدم بد نباشه، شاید کسی به دردش خورد :)


function IsThisNICCorrect(NIC: string): boolean;
var
Len,
ControlCode,
Factor,
Sum,
Remaining : Integer;
Flag : Boolean;
begin
Result := false;
Len := Length(NIC);
Flag := (NIC = '00000000000') or (NIC = '11111111111') or (NIC = '22222222222') or (NIC = '33333333333');
Flag := (NIC = '44444444444') or (NIC = '55555555555') or (NIC = '66666666666') or (NIC = '77777777777') or Flag;
Flag := (NIC = '88888888888') or (NIC = '99999999999') or Flag;
if (Flag = true) or (Len < 11) then
Exit;
ControlCode := StrToInt(NIC[11]);
Factor := StrToInt(NIC[10]) + 2;
Sum := 0;
Sum := Sum + ((Factor + StrToInt(NIC[1])) * 29);
Sum := Sum + ((Factor + StrToInt(NIC[2])) * 27);
Sum := Sum + ((Factor + StrToInt(NIC[3])) * 23);
Sum := Sum + ((Factor + StrToInt(NIC[4])) * 19);
Sum := Sum + ((Factor + StrToInt(NIC[5])) * 17);
Sum := Sum + ((Factor + StrToInt(NIC[6])) * 29);
Sum := Sum + ((Factor + StrToInt(NIC[7])) * 27);
Sum := Sum + ((Factor + StrToInt(NIC[8])) * 23);
Sum := Sum + ((Factor + StrToInt(NIC[9])) * 19);
Sum := Sum + ((Factor + StrToInt(NIC[10])) * 17);
Remaining := Sum mod 11;
if Remaining = 10 then
Remaining := 0;
Result := (Remaining = ControlCode);
end;

shahab_8121
یک شنبه 26 مهر 1394, 00:54 صبح
با سلام خدمت تمام اساتید گرامی
ببخشید ک بعد مدتها دوباره این تاپیک رو دوباره فعال کردم . خطایی تو این روشی ک دوستان ارائه کردن واضح ک یه مثال نقضش این کد نمونه است 12345678910 که تو این الگوریتم به عنوان درست حساب می کنه اما در واقع یک کد غیر معتبر می باشد.
از نظر الگوریتمی صحیح می باشد اما هنوز به عنوان شرکت ثبت نشده است :)

یوسف زالی
یک شنبه 26 مهر 1394, 09:51 صبح
این الگوریتم که به جایی وصل نیست که بیاد ببینه کی چه شرکتی ثبت کرده.منظورتون رو نمی فهمم.