Validar NIF, CIF, NIE según ley vigente

Función en javascript que nos permite validar los NIF, CIF y NIE españoles según las leyes vigentes teniendo en cuenta todas las combinaciones incluidas las nuevas variantes de NIE con ‘T’, ‘Y’ y ‘Z’ así como todas las variantes de CIF para empresas, entidades, asociaciones, etc.

La función retorna los siguientes valores:

  • 1 > NIF correcto / -1 > NIF incorrecto
  • 2 > CIF correcto / -2 > CIF incorrecto
  • 3 > NIE correcto / -3 > NIE incorrecto
  • 0 > Valor desconocido (campo vacio, formato incorrecto, etc)

ACTUALIZACIÓN: Versión corregida con los comentarios de los usuarios!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//Retorna: 1 = NIF ok, 2 = CIF ok, 3 = NIE ok, -1 = NIF error, -2 = CIF error, -3 = NIE error, 0 = ??? error
function valida_nif_cif_nie( a )
{
	var temp = a.toUpperCase();
	var cadenadni = "TRWAGMYFPDXBNJZSQVHLCKE";
 
	if( temp!= '' )
	{
		//si no tiene un formato valido devuelve error
		if( ( !/^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$/.test( temp ) && !/^[T]{1}[A-Z0-9]{8}$/.test( temp ) ) && !/^[0-9]{8}[A-Z]{1}$/.test( temp ) )
		{
			return 0;
		}
 
		//comprobacion de NIFs estandar
		if( /^[0-9]{8}[A-Z]{1}$/.test( temp ) )
		{
			posicion = a.substring( 8,0 ) % 23;
			letra = cadenadni.charAt( posicion );
			var letradni = temp.charAt( 8 );
			if( letra == letradni )
			{
				return 1;
			}
			else
			{
				return -1;
			}
		}
 
 
		//algoritmo para comprobacion de codigos tipo CIF
		suma = parseInt(a.charAt(2))+parseInt(a.charAt(4))+parseInt(a.charAt(6));
 
		for( i = 1; i < 8; i += 2 )
		{
			temp1 = 2 * parseInt( a.charAt( i ) );
			temp1 += '';
			temp1 = temp1.substring(0,1);
			temp2 = 2 * parseInt( a.charAt( i ) );
			temp2 += '';
			temp2 = temp2.substring( 1,2 );
			if( temp2 == '' )
			{
				temp2 = '0';
			}
 
			suma += ( parseInt( temp1 ) + parseInt( temp2 ) );
		}
		suma += '';
		n = 10 – parseInt( suma.substring( suma.length-1, suma.length ) );
 
		//comprobacion de NIFs especiales (se calculan como CIFs)
		if( /^[KLM]{1}/.test( temp ) )
		{
			if( a.charAt( 8 ) == String.fromCharCode( 64 + n ) )
			{
				return 1;
			}
			else
			{
				return -1;
			}
		}
 
		//comprobacion de CIFs
		if( /^[ABCDEFGHJNPQRSUVW]{1}/.test( temp ) )
		{
			temp = n + '';
			if( a.charAt( 8 ) == String.fromCharCode( 64 + n ) || a.charAt( 8 ) == parseInt( temp.substring( temp.length-1, temp.length ) ) )
			{
				return 2;
			}
			else
			{
				return -2;
			}
		}
 
		//comprobacion de NIEs
		//T
		if( /^[T]{1}[A-Z0-9]{8}$/.test( temp ) )
		{
			if( a.charAt( 8 ) == /^[T]{1}[A-Z0-9]{8}$/.test( temp ) )
			{
				return 3;
			}
			else
			{
				return -3;
			}
		}
		//XYZ
		if( /^[XYZ]{1}/.test( temp ) )
		{
			temp = temp.replace( 'X','0' )
			temp = temp.replace( 'Y','1' )
			temp = temp.replace( 'Z','2' )
			pos = temp.substring(0, 8) % 23;
 
			if( a.toUpperCase().charAt( 8 ) == cadenadni.substring( pos, pos + 1 ) )
			{
				return 3;
			}
			else
			{
				return -3;
			}
		}
	}
 
	return 0;
}

Para los cálculos se usa esta función auxiliar que emula el str_replace de PHP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function str_replace( search, position, replace, subject )
{
	var f = search, r = replace, s = subject, p = position;
	var ra = r instanceof Array, sa = s instanceof Array, f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;
 
	while( j = 0, i-- )
	{
		if( s[i] )
		{
			while( s[p] = s[p].split( f[j] ).join( ra ? r[j] || "" : r[0] ), ++j in f){};
		}
	};
 
	return sa ? s : s[0];
}
Esta entrada fue publicada en JavaScript y etiquetada con , , , , . Guarda el enlace permanente.

26 comentarios a Validar NIF, CIF, NIE según ley vigente

  1. Juanma dice:

    Hola,

    Muy buena función, sin embargo solo me funcionaba en FF y no en IE. El motivo era la utilización de “a[2]“, que al tratarse de cadenas no me lo pillaba bien. Lo cambié por a.charAt(), como también se usa en la función (pero en la sección de NIFs) et voila!

    Saludos

  2. amcmdw dice:

    La función falla en la validación de los NIES. La correcta arreglada es la siguiente:

    //Retorna: 1 = NIF ok, 2 = CIF ok, 3 = NIE ok, -1 = NIF error, -2 = CIF error, -3 = NIE error, 0 = ??? error
    function valida_nif_cif_nie(a)
    {

    var temp=a.toUpperCase();
    var cadenadni=”TRWAGMYFPDXBNJZSQVHLCKE”;
    if (temp!==”){

    //si no tiene un formato valido devuelve error
    if ((!/^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$/.test(temp) && !/^[T]{1}[A-Z0-9]{8}$/.test(temp)) && !/^[0-9]{8}[A-Z]{1}$/.test(temp))
    {
    return 0;
    }

    //comprobacion de NIFs estandar
    if (/^[0-9]{8}[A-Z]{1}$/.test(temp))
    {
    posicion = a.substring(8,0) % 23;
    letra = cadenadni.charAt(posicion);
    var letradni=temp.charAt(8);
    if (letra == letradni)
    {
    return 1;
    }
    else
    {
    return -1;
    }
    }

    //algoritmo para comprobacion de codigos tipo CIF
    suma = parseInt(a.charAt(2))+parseInt(a.charAt(4))+parseInt(a.charAt(6));

    for (i = 1; i < 8; i += 2)
    {
    temp1 = 2 * parseInt(a.charAt(i));
    temp1 += ”;
    temp1 = temp1.substring(0,1);
    temp2 = 2 * parseInt(a.charAt(i));
    temp2 += ”;
    temp2 = temp2.substring(1,2);
    if (temp2 == ”)
    {
    temp2 = ’0′;
    }

    suma += (parseInt(temp1) + parseInt(temp2));
    }
    suma += ”;
    n = 10 – parseInt(suma.substring(suma.length-1, suma.length));

    //comprobacion de NIFs especiales (se calculan como CIFs)
    if (/^[KLM]{1}/.test(temp))
    {
    if (a.charAt(8) == String.fromCharCode(64 + n))
    {
    return 1;
    }
    else
    {
    return -1;
    }
    }
    //comprobacion de CIFs
    if (/^[ABCDEFGHJNPQRSUVW]{1}/.test(temp))
    {
    temp = n + ”;
    if (a.charAt(8) == String.fromCharCode(64 + n) || a.charAt(8) == parseInt(temp.substring(temp.length-1, temp.length)))
    {
    return 2;
    }
    else
    {
    return -2;
    }
    }

    //comprobacion de NIEs
    //T
    if (/^[T]{1}/.test(temp))
    {
    if (a.charAt(8) == /^[T]{1}[A-Z0-9]{8}$/.test(temp))
    {
    return 3;
    }
    else
    {
    return -3;
    }
    }

    //XYZ
    if (/^[XYZ]{1}/.test(temp))
    {

    temp = temp.replace(‘X’,’0′)
    temp = temp.replace(‘Y’,’1′)
    temp = temp.replace(‘Z’,’2′)
    pos = temp.substring(0, 8) % 23;

    if (a.charAt(8) == cadenadni.substring(pos, pos + 1))
    {
    return 3;
    }
    else
    {
    return -3;
    }
    }
    }
    return 0;
    }

  3. fcka dice:

    ¿Esto va a funcionar bien en la validacion de los NIE’s?


    temp = temp.replace(’X’,’0′)
    temp = temp.replace(’Y’,’1′)
    temp = temp.replace(’Z’,’2′)

    Los digo porque asi puede que la ultima letra del NIE coincida con alguna de estas tres y se reemplace de manera incorrecta por un numero.

  4. fcka dice:

    Buenas he estado probando la funcion y la nueva version que creo que sería mas correcta es la siguiente, ya que he modificado la funcion str_replace y solo modifica el primer digito.

  5. fcka dice:

    function str_replace(search, position, replace, subject) {

    var f = search, r = replace, s = subject, p = position;
    var ra = r instanceof Array, sa = s instanceof Array, f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;

    while (j = 0, i–) {
    if (s[i]) {
    while (s[p] = s[p].split(f[j]).join(ra ? r[j] || “” : r[0]), ++j in f){};
    }
    };

    return sa ? s : s[0];

    }

  6. fcka dice:

    y el la zona de validacion de NIE cambiar a esta linea

    pos = str_replace(['X', 'Y', 'Z'], 0, ['0','1','2'], temp).substring(0, 8) % 23;

    Tambien en la validacion de los NIE’s que comienzan con T el if correcto seria


    if (/^[T]{1}[A-Z0-9]{8}$/.test(temp))
    ..

    Espero que os ayude un saludo

  7. Glifaus dice:

    Gracias todos, tanto a josep rosell por el código original como a los demás que habeis ayudado a pulirlo, me habeis sacado de un apuro. Gracias!

  8. Valen dice:

    Moltes gràcies, muchas gracias!!!

    Me he encontrado con problemas, que debido a mi bajo nivel de conocimiento de javascript he tenido que ir depurando. Básicamente, he tenido que substituir todas las referencias a los carácteres de strings (referenciados en formato array como a[8]) por una característica que ya se utilizaba en la parte de validación de NIF, .charAt(8) ).

    Una vez aplicado, ya he podido validar los CIF’s introducidos por pantalla.

  9. juan dice:

    pero ¿la version original se ha modificado para cumplir los errores comentados?

    gracias

  10. stankovic dice:

    Gracias por todo, a mi me ha sido util tb

  11. Elena dice:

    Duda muy tonta. Como recoger lo que devuelve la funcion

  12. Eleno dice:

    Elena, realmente pregunta muy tonta, tontísima diria yo. Cuanto intrusismo en esta profesió, que asco ….

  13. Rafa Garcia dice:

    Eleno, hay una posibilidad de que Elena esté empezando a estudiar javascript y programación. Tu naciste enseñado, por lo que vemos.

    Gracias por el aporte

  14. Eleno-no dice:

    Eleno, gente como tu hace que me sienta orgulloso de ser lo que tu calificas un “intruso”… aunque probablemente me haya echando mas años y horas de estudio que tu…

  15. Sergio dice:

    DEspués de tanto cambio podrían publicar la definitiva por favor?

  16. elsocorrista dice:

    :) genial!! lo que no me funciona es la validacion NIES
    pero el resto genial

  17. Diego dice:

    Muchas gracias.
    Va perfecto con la corrección que hizo amcmdw

  18. ibman dice:

    Pues a mi no me funciona con los NIE con la corrección de amcmdw

  19. XemaX dice:

    Muy útil este script.
    Detecte un pequeño error con los NIE correctos y en minúscula los consideraba erroneos (-3). Lo solucione cambiando la parte de //XYZ a:
    //XYZ
    if (/^[XYZ]{1}/.test(temp))
    {

    temp = temp.replace(‘X’,’0′)
    temp = temp.replace(‘Y’,’1′)
    temp = temp.replace(‘Z’,’2′)
    pos = temp.substring(0, 8) % 23;

    if (a.toUpperCase().charAt(8) == cadenadni.substring(pos, pos + 1))
    {
    return 3;
    }
    else
    {
    return -3;
    }
    }

    Sólo cambie a.charAt(8) del condicional por a.toUpperCase().charAt(8)

    Y todo como la seda.
    Las otras comprobaciones NIF y CIF correctas.

    Gracias por compartir vuestro tiempo y esfuerzo.
    Kisses

  20. Retroenlace: Validación de NIFs, NIEs, DNIs y CIFs en PHP | Viricmind Labs

  21. Javi dice:

    Tengo la función trabajando en producción sin problemas aparentes, he incluido las correcciones y aportaciones de estos comentarios (muchas gracias a todos) y he dejado la función str_replace como variable local de la propia función, aparte de eso solo he cambiado las posiciones de llaves y demás formatos… soy un poco maniatico.
    Espero que os ayude y que se vea bien el código en el post.
    //Retorna: 1 = NIF ok, 2 = CIF ok, 3 = NIE ok, -1 = NIF error, -2 = CIF error, -3 = NIE error, 0 = ??? error
    function validarDocumento(a) {
    var str_replace = function(search, position, replace, subject) {
    var f = search, r = replace, s = subject, p = position;
    var ra = r instanceof Array, sa = s instanceof Array, f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;
    while (j = 0, i–) {
    if (s[i]) {
    while (s[p] = s[p].split(f[j]).join(ra ? r[j] || “” : r[0]), ++j in f){};
    }
    };
    return sa ? s : s[0];
    }

    var temp=a.toUpperCase();
    var cadenadni=”TRWAGMYFPDXBNJZSQVHLCKE”;

    if (temp!==”){
    //si no tiene un formato valido devuelve error
    if ((!/^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$/.test(temp) && !/^[T]{1}[A-Z0-9]{8}$/.test(temp)) && !/^[0-9]{8}[A-Z]{1}$/.test(temp)) {
    return 0;
    }

    //comprobacion de NIFs estandar
    if (/^[0-9]{8}[A-Z]{1}$/.test(temp)) {
    posicion = a.substring(8,0) % 23;
    letra = cadenadni.charAt(posicion);
    var letradni=temp.charAt(8);
    if (letra == letradni) {
    return 1;
    } else {
    return -1;
    }
    }

    //algoritmo para comprobacion de codigos tipo CIF
    suma = parseInt(a.charAt(2))+parseInt(a.charAt(4))+parseInt(a.charAt(6));
    for (i = 1; i < 8; i += 2) {
    temp1 = 2 * parseInt(a.charAt(i));
    temp1 += ”;
    temp1 = temp1.substring(0,1);
    temp2 = 2 * parseInt(a.charAt(i));
    temp2 += ”;
    temp2 = temp2.substring(1,2);
    if (temp2 == ”) {
    temp2 = ’0′;
    }
    suma += (parseInt(temp1) + parseInt(temp2));
    }
    suma += ”;
    n = 10 – parseInt(suma.substring(suma.length-1, suma.length));

    //comprobacion de NIFs especiales (se calculan como CIFs)
    if (/^[KLM]{1}/.test(temp)) {
    if (a.charAt(8) == String.fromCharCode(64 + n)) {
    return 1;
    } else {
    return -1;
    }
    }

    //comprobacion de CIFs
    if (/^[ABCDEFGHJNPQRSUVW]{1}/.test(temp)) {
    temp = n + ”;
    if (a.charAt(8) == String.fromCharCode(64 + n) || a.charAt(8) == parseInt(temp.substring(temp.length-1, temp.length))) {
    return 2;
    } else {
    return -2;
    }
    }

    //comprobacion de NIEs
    //T
    if (/^[T]{1}[A-Z0-9]{8}$/.test(temp)) {
    if (a.charAt(8) == /^[T]{1}[A-Z0-9]{8}$/.test(temp)) {
    return 3;
    } else {
    return -3;
    }
    }

    //XYZ
    if (/^[XYZ]{1}/.test(temp)) {
    pos = str_replace(['X', 'Y', 'Z'], 0, ['0','1','2'], temp).substring(0, 8) % 23;
    if (a.charAt(8) == cadenadni.substring(pos, pos + 1)) {
    return 3;
    } else {
    return -3;
    }
    }
    }
    return 0;
    }

  22. Victor dice:

    Funciona. Muchas gracias

  23. Mik dice:

    Pues yo no se de donde ha salido el código de la función str_replace() pero a mi me da errores de sintaxis

    while (j = 0, i–) ??? Nunca había visto esta manera de definir un while. No se en qué navegador lo estais ejecutando pero a mi me da error en FF.

    En cualquier caso, buscando por el autor original encuentro otra versión de la misma función que sí que me funciona:
    http://phpjs.org/functions/str_replace:527

    Aunque la llamada debe hacerse como propone amcmdw, es decir, en cuatro instrucciones distintas.

    temp = temp.replace(‘X’,’0′);
    temp = temp.replace(‘Y’,’1′);
    temp = temp.replace(‘Z’,’2′);
    pos = temp.substring(0, 8) % 23;

    Espero que os sirva! Saludos!
    Mik.

  24. Dani dice:

    Hola, he ampliado las propiedades de la librería de validación de formularios vanadium.js (http://vanadiumjs.com/) añadiendo las funciones de este artículo, escritas por josep.rosell.

    La librería ampliada permite la validación de NIF/NIE/CIF sobre cualquier campo de formulario simplemente marcándolo con class=”:nif” (similar a cualquier otra validación de vanadium.js).

    Por si alguien le interesa, aquí os dejo el enlace a la libería:
    http://www.danimagan.com/vanadium/vanadium_nif_cif_nie_extended.rar

  25. Capo dice:

    Acabo de publicar una traducción -con pequeñas modificaciones- a MySQL. Si a alguien le interesa, los scripts están en: https://github.com/elcapo/mysql-validdoc-es.

    Gracias a Josep Rosell por compartir su código.

  26. Martin dice:

    Mik, la funcion que puso Javi esta correcta. Solo que tienes que controlar bien que las comillas y algunos carecteres como en while (j = 0, i–)

    Donde son signos menos seguidos — como si fuera ++

    Una vez corregidos los carecteres malos funciona de 10!

    Gracias Javi. Y por cierto Dani tu libreria contiene la version orginal de este post (que no funciona).

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>