22 Kasım 2011 Salı

Vergi Kimlik No Doğrulama Algoritması

Portföylerinde bireysel müşteriler yanında kurumsal müşteriler de bulunan e-ticaret sitelerinin sipariş bilgileri yanında, fatura işlemleri için vergi kimlik numarası da istemeleri gerekiyor. Bu tarz projelerde vergi kimlik numarasını birebir örtüştüğünü kurumsal bilgilerle doğrulamak yerine aşağıdaki fonksiyonu kullanarak, vergi numarasının geçerliliğini denetleyebilirsiniz. 


Bir önceki yazımızda, TC Kimlik No doğrulama algoritması ile ilgili bir kod paylaşmıştık.  Portföylerinde bireysel müşteriler yanında kurumsal müşteriler de bulunan e-ticaret sitelerinin sipariş bilgileri yanında, fatura işlemleri için vergi kimlik numarası da istemeleri gerekiyor. Bu tarz projelerde vergi kimlik numarasını birebir örtüştüğünü kurumsal bilgilerle doğrulamak yerine aşağıdaki fonksiyonu kullanarak, vergi numarasının geçerliliğini denetleyebilirsiniz. Bu kod şu adreste T-SQL fonksiyonu olarak mevcuttu, Google aramaları sonucunda kaynağı bulup, Javascript ile tekrar yazarak kendim için işe yarar hale getirdim.



Buyrun, umarım işinize yarar:


function vergikimlik(kno) {
    var v1 = 0;
    var v2 = 0;
    var v3 = 0;
    var v4 = 0;
    var v5 = 0;
    var v6 = 0;
    var v7 = 0;
    var v8 = 0;
    var v9 = 0;
    var v11 = 0;
    var v22 = 0;
    var v33 = 0;
    var v44 = 0;
    var v55 = 0;
    var v66 = 0;
    var v77 = 0;
    var v88 = 0;
    var v99 = 0;
    var v_last_digit = 0;
    var toplam = 0;

/* desen isimli düzenli ifade cümleciği kodun bu versiyonunda, ileriki satırlarda kullanılmamaktadır. Ancak; kullanıcı tarafından sisteme belirtilen değerin, sayısal bir değer olup olmadığını kontrol etmek için, basamak işlemlerinden hemen önce desen.test(kno.charAt(basamaksayisi)) şeklinde kullanabilirsiniz. Uyarı için desenz 'e teşekkürler. */ 

9 yorum:

oz dedi ki...

Selamlar,

Çok güzel, elinize sağlık. İnternette bu konuyla ilgili tek kaynak nerdeyse.

Bir sorum olacak yalnız, VKN 10 haneden az olabiliyor muydu? Oluyorsa bu durumda sağa yanaşık olarak mı bu algoritmaya sokulması gerekir, yoksa sola yanaşık mı?

teşekkürler

zyhn dedi ki...

Sayın Öz;
Bildiğim kadarıyla vergi kimlik numaraları 10 haneden müteşekkildir. Müsait bir zamanda ilgili kanun maddeleri ve tebliğleri de inceleyerek bir blog yazısı kaleme alacağım.

İlginiz için sonsuz teşekkürler.

Adsız dedi ki...

C# da yazılmış biraz daha temiz Şekli.

public static Boolean FirmaVergiKontrol(string kno)
{

if (kno.ToSt().Length != 10) return false;
if (!kno.ToArray().All(n => char.IsNumber(n))) return false;


var v_last_digit = kno[9].ToInt();
int Toplam = 0;
for (int i = 9; i >= 1; i--)
{
int dig = kno[9 - i].ToInt(-111);
if (dig < 0) return false;
var v1 = ((dig + i) % 10);
int v11 = (int)(v1 * Math.Pow(2, i)) % 9;
if (v1 != 0 && v11 == 0) v11 = 9;
Toplam += v11;
// v11 = (v1 * 512) % 9;
}

if (Toplam % 10 == 0) Toplam = 0; else Toplam = (10 - (Toplam % 10));

if (Toplam == v_last_digit) return true;


return false;

}

Adsız dedi ki...

kodlarda

var desen = /[0-9]{10}/;

şu şekilde bir regex ifadesi var ama sanki kullanılmıyor hiç bir yerde.
Sanırım gereksiz o satır.

zyhn dedi ki...

Merhaba;
Öncelikle ilginiz için teşekkür ederim.

desen isimli düzenli ifade cümleciğini kodun ilk versionlarında kullanmış idik. Siz de her bir basamağı, desen.test(basamak) şeklinde parametre olarak vererek, sayısal bir değer olup olmadığını sınayabilirsiniz. Number(deger) fonksiyonları ile numerik bir değere çevrilme işleminden önce bunu kullanabilirsiniz. Aksi takdirde, Number isimli fonksiyona verdiğiniz değer, numerik bir değer değilse, NaN sonucu dönecektir. Tekrar teşekkür ederim. Selamlar.

kRm dedi ki...

Daha kısa ve öz, yine javascript versiyonu:

window.vergikimlik = function(kno) {
var a1 = [];
var a2 = [];
var toplam = 0;

if (kno.length == 10) {
for (i=0; i<9; i++) {
a1[i] = (Number(kno.charAt(i)) + 9-i) % 10;
a2[i] = ( a1[i] * Math.pow(2, 9-i) ) % 9;
if(a1[i] != 0 && a2[i] == 0) a2[i] = 9;
toplam += a2[i];
}

if (toplam % 10 == 0) toplam = 0;
else toplam = (10 - (toplam % 10));

return (toplam == Number(kno.charAt(9)));
} else return false;
}

Adsız dedi ki...

Merhaba yabancı uyruklu kişilere verilen vergi kimlik numaralarının, kurumlara verilen numaralara göre ayırdedici bir özelliği var mıdır?
teşekkür ederim
Ömer

glorifier dedi ki...

C#'da hem vergi numarası için hem de TC Kimlik Numarası kontrolü için aşağıdaki kodu kullanabilirsiniz:

public static bool ValidateVknTckn(string kno)
{
if (!kno.All(char.IsDigit))
return false;

if (kno.Length == 10)
{

var v1 = (Convert.ToInt32(kno[0].ToString()) + 9) % 10;
var v2 = (Convert.ToInt32(kno[1].ToString()) + 8) % 10;
var v3 = (Convert.ToInt32(kno[2].ToString()) + 7) % 10;
var v4 = (Convert.ToInt32(kno[3].ToString()) + 6) % 10;
var v5 = (Convert.ToInt32(kno[4].ToString()) + 5) % 10;
var v6 = (Convert.ToInt32(kno[5].ToString()) + 4) % 10;
var v7 = (Convert.ToInt32(kno[6].ToString()) + 3) % 10;
var v8 = (Convert.ToInt32(kno[7].ToString()) + 2) % 10;
var v9 = (Convert.ToInt32(kno[8].ToString()) + 1) % 10;
var v_last_digit = Convert.ToInt32(kno[9].ToString());

var v11 = (v1 * 512) % 9;
var v22 = (v2 * 256) % 9;
var v33 = (v3 * 128) % 9;
var v44 = (v4 * 64) % 9;
var v55 = (v5 * 32) % 9;
var v66 = (v6 * 16) % 9;
var v77 = (v7 * 8) % 9;
var v88 = (v8 * 4) % 9;
var v99 = (v9 * 2) % 9;

if (v1 != 0 && v11 == 0) v11 = 9;
if (v2 != 0 && v22 == 0) v22 = 9;
if (v3 != 0 && v33 == 0) v33 = 9;
if (v4 != 0 && v44 == 0) v44 = 9;
if (v5 != 0 && v55 == 0) v55 = 9;
if (v6 != 0 && v66 == 0) v66 = 9;
if (v7 != 0 && v77 == 0) v77 = 9;
if (v8 != 0 && v88 == 0) v88 = 9;
if (v9 != 0 && v99 == 0) v99 = 9;
var toplam = v11 + v22 + v33 + v44 + v55 + v66 + v77 + v88 + v99;

if (toplam % 10 == 0) toplam = 0;
else toplam = (10 - (toplam % 10));

if (toplam == v_last_digit)
return true;

return false;
}
else if (kno.Length == 11)
{
if (kno.StartsWith("0"))
return false;

var tekler = Convert.ToInt32(kno[0].ToString()) + Convert.ToInt32(kno[2].ToString()) + Convert.ToInt32(kno[4].ToString()) + Convert.ToInt32(kno[6].ToString()) + Convert.ToInt32(kno[8].ToString());
var ciftler = Convert.ToInt32(kno[1].ToString()) + Convert.ToInt32(kno[3].ToString()) + Convert.ToInt32(kno[5].ToString()) + Convert.ToInt32(kno[7].ToString());
var basamak10 = (tekler * 7 - ciftler) % 10;
var toplam = (tekler + ciftler + Convert.ToInt32(kno[9].ToString())) % 10;

if (basamak10 != Convert.ToInt32(kno[9].ToString()))
return false;

if (toplam != Convert.ToInt32(kno[10].ToString()))
return false;

else return true;
}
else return false;

}

salih dedi ki...

Oracle PL/SQL Kodu Aşağıda :


CREATE OR REPLACE FUNCTION VERGI_NO_KONTROL(vergino VARCHAR2) RETURN INTEGER IS
v1 NUMBER;
v2 NUMBER;
v3 NUMBER;
v4 NUMBER;
v5 NUMBER;
v6 NUMBER;
v7 NUMBER;
v8 NUMBER;
v9 NUMBER;
v11 NUMBER;
v22 NUMBER;
v33 NUMBER;
v44 NUMBER;
v55 NUMBER;
v66 NUMBER;
v77 NUMBER;
v88 NUMBER;
v99 NUMBER;
v_last_digit NUMBER;
toplam NUMBER;
BEGIN


if (LENGTH(vergino) = 10) THEN

v1 := MOD(TO_NUMBER(SUBSTR(vergino,1,1)) + 9,10);

v2 := MOD(TO_NUMBER(SUBSTR(vergino,2,1)) + 8,10) ;

v3 := MOD(TO_NUMBER(SUBSTR(vergino,3,1)) + 7,10) ;

v4 := MOD(TO_NUMBER(SUBSTR(vergino,4,1)) + 6,10) ;

v5 := MOD(TO_NUMBER(SUBSTR(vergino,5,1)) + 5,10) ;

v6 := MOD(TO_NUMBER(SUBSTR(vergino,6,1)) + 4,10) ;

v7 := MOD(TO_NUMBER(SUBSTR(vergino,7,1)) + 3,10) ;

v8 := MOD(TO_NUMBER(SUBSTR(vergino,8,1)) + 2,10) ;

v9 := MOD(TO_NUMBER(SUBSTR(vergino,9,1)) + 1,10) ;

v_last_digit := TO_NUMBER(SUBSTR(vergino,10,1));

v11 := MOD(v1 * 512,9);
v22 := MOD(v2 * 256 ,9);
v33 := MOD(v3 * 128,9);
v44 := MOD(v4 * 64,9);
v55 := MOD(v5 * 32,9);
v66 := MOD(v6 * 16,9);
v77 := MOD(v7 * 8,9);
v88 := MOD(v8 * 4,9);
v99 := MOD(v9 * 2,9);

if (v1 <> 0 and v11 = 0) then v11 := 9 ; END IF;
if (v2 <> 0 and v22 = 0) then v22 := 9 ; END IF;
if (v3 <> 0 and v33 = 0) then v33 := 9 ; END IF;
if (v4 <> 0 and v44 = 0) then v44 := 9 ; END IF;
if (v5 <> 0 and v55 = 0) then v55 := 9 ; END IF;
if (v6 <> 0 and v66 = 0) then v66 := 9 ; END IF;
if (v7 <> 0 and v77 = 0) then v77 := 9 ; END IF;
if (v8 <> 0 and v88 = 0) then v88 := 9 ; END IF;
if (v9 <> 0 and v99 = 0) then v99 := 9 ; END IF;

toplam := v11 + v22 + v33 + v44 + v55 + v66 + v77 + v88 + v99;


if (MOD(toplam,10) = 0) then toplam := 0;
else toplam := (10 - MOD(toplam,10));
end if;

if (toplam = v_last_digit) then
return 1;
else return 0;
end if;

ELSE RETURN 0;
END IF;

EXCEPTION
WHEN OTHERS THEN
RETURN 0;
END VERGI_NO_KONTROL;