-
-
Save afgomez/5691823 to your computer and use it in GitHub Desktop.
/** | |
* ValidateSpanishID. Returns the type of document and checks its validity. | |
* | |
* Usage: | |
* ValidateSpanishID( str ); | |
* | |
* > ValidateSpanishID( '12345678Z' ); | |
* // { type: 'dni', valid: true } | |
* | |
* > ValidateSpanishID( 'B83375575' ); | |
* // { type: 'cif', valid: false } | |
* | |
* The algorithm is adapted from other solutions found at: | |
* - http://www.compartecodigo.com/javascript/validar-nif-cif-nie-segun-ley-vigente-31.html | |
* - http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal | |
*/ | |
ValidateSpanishID = (function() { | |
'use strict'; | |
var DNI_REGEX = /^(\d{8})([A-Z])$/; | |
var CIF_REGEX = /^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/; | |
var NIE_REGEX = /^[XYZ]\d{7,8}[A-Z]$/; | |
var ValidateSpanishID = function( str ) { | |
// Ensure upcase and remove whitespace | |
str = str.toUpperCase().replace(/\s/, ''); | |
var valid = false; | |
var type = spainIdType( str ); | |
switch (type) { | |
case 'dni': | |
valid = validDNI( str ); | |
break; | |
case 'nie': | |
valid = validNIE( str ); | |
break; | |
case 'cif': | |
valid = validCIF( str ); | |
break; | |
} | |
return { | |
type: type, | |
valid: valid | |
}; | |
}; | |
var spainIdType = function( str ) { | |
if ( str.match( DNI_REGEX ) ) { | |
return 'dni'; | |
} | |
if ( str.match( CIF_REGEX ) ) { | |
return 'cif'; | |
} | |
if ( str.match( NIE_REGEX ) ) { | |
return 'nie'; | |
} | |
}; | |
var validDNI = function( dni ) { | |
var dni_letters = "TRWAGMYFPDXBNJZSQVHLCKE"; | |
var letter = dni_letters.charAt( parseInt( dni, 10 ) % 23 ); | |
return letter == dni.charAt(8); | |
}; | |
var validNIE = function( nie ) { | |
// Change the initial letter for the corresponding number and validate as DNI | |
var nie_prefix = nie.charAt( 0 ); | |
switch (nie_prefix) { | |
case 'X': nie_prefix = 0; break; | |
case 'Y': nie_prefix = 1; break; | |
case 'Z': nie_prefix = 2; break; | |
} | |
return validDNI( nie_prefix + nie.substr(1) ); | |
}; | |
var validCIF = function( cif ) { | |
var match = cif.match( CIF_REGEX ); | |
var letter = match[1], | |
number = match[2], | |
control = match[3]; | |
var even_sum = 0; | |
var odd_sum = 0; | |
var n; | |
for ( var i = 0; i < number.length; i++) { | |
n = parseInt( number[i], 10 ); | |
// Odd positions (Even index equals to odd position. i=0 equals first position) | |
if ( i % 2 === 0 ) { | |
// Odd positions are multiplied first. | |
n *= 2; | |
// If the multiplication is bigger than 10 we need to adjust | |
odd_sum += n < 10 ? n : n - 9; | |
// Even positions | |
// Just sum them | |
} else { | |
even_sum += n; | |
} | |
} | |
var control_digit = (10 - (even_sum + odd_sum).toString().substr(-1) ); | |
var control_letter = 'JABCDEFGHI'.substr( control_digit, 1 ); | |
// Control must be a digit | |
if ( letter.match( /[ABEH]/ ) ) { | |
return control == control_digit; | |
// Control must be a letter | |
} else if ( letter.match( /[KPQS]/ ) ) { | |
return control == control_letter; | |
// Can be either | |
} else { | |
return control == control_digit || control == control_letter; | |
} | |
}; | |
return ValidateSpanishID; | |
})(); |
Los NIF terminados en 0 siempre dan error, como @uiktiomasfeliz y @gtamborero indican. Eso es porque hay un error con la comprobación de éste. El enlace de wikipedia ( código de identificación fical ) dice que el código de verificación debe ser 10 - el último dígito de C, pero si C termina en 0, éste debe ser 0.
He modificado el código para sacar el control digit. Quedaría así:
var control_digit = (10 - (even_sum + odd_sum).toString().substr(-1)).toString().substr(-1) ;
De este modo lo que hago es obtener el último dígito de dicha resta, por lo que si hacemos 10-0, el resultado del código sería 0.
No valida bien NIF del tipo K
K0867756N
Aquí lo valida bien:
https://comunidadhorizontal.com/utiles/validar-cif-nif-nie/
He mirado el código y no lo reconoce de ninguno de los 3 type (DNI, CIF, NIE), pues la expresión regular de CIF no lo contempla:
([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])
Veo que sólo permite letra final hasta J y en mi ejemplo tengo una N y es un NIF válido...
@afgomez Gracias por crear este gist. Lo he adaptado, he corregido la validación del CIF y lo he empaquetado como una pequeña librería en npm:
https://github.com/jvmonjo/spain-id
La corrección de @tompare está bien. Lo puedo confirmar al menos con un CIF de una SL (empiezan por B).
Aquí publico el gist con la corrección del dígito de control de @tompare:
https://gist.github.com/carlos-mg89/4aaafa310c9e4b91f5fb890540f38cae
He probado con el NIF K0867756N despues de aplicar la corrección y sigue sin funcionar.
Parece que no identifica los DNI "Españoles residentes menores 14 años sin DNI (NIF K)"
Adjunto enlace de la Agencia Tributaria:
https://www.agenciatributaria.es/AEAT.internet/Inicio/La_Agencia_Tributaria/Campanas/_Campanas_/Fiscalidad_de_no_residentes/_Identificacion_/Preguntas_frecuentes_sobre_obtencion_de_NIF_de_no_Residentes/_Que_tipos_de_NIF_de_personas_fisicas_utiliza_la_normativa_tributaria_espanola_.shtml
He probado actualmente con 4 CIF existentes y no me valida ninguno como true
Los problemas con CIFs que no validan (ejemplo "B72327000") se solucionan haciendo el módulo 10 para calcular el dígito de control.
Es decir, cambiar:
var control_digit = (10 - (even_sum + odd_sum).toString().substr(-1) );
Por:
var control_digit = (10 - (even_sum + odd_sum).toString().substr(-1) ) % 10;
En el replace faltaría añadir /g para que cambie todas ocurrecias:
str.toUpperCase().replace(/\s, '').replace('-', '');
str.toUpperCase().replace(/\s/g, '').replace('-', '');
Hola trabajo con Angular, me gustaría saber si tenéis algún validator form con este método. Gracias de antemano.
Buenas. Los CIF de organizaciones públicas que acaban en letra L no pasan por esta validación ¿no?
Este control es correcto según la definición de wikipedia https://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal donde indica que los CIFs que empiezan por A|B|E|H el digito de control debe ser un número.
Recientemente pero me han passado CIFs validos que empezando por E y por A tienen letra de control... y son validos, p.e E9729353D. Alguien sabe donde encontrar la especificación oficial sobre el calculo del digito/letra de control?