Cálculo del dígito verificador utilizando la función Módulo11
El código de control es un mecanismo de detección de errores utilizado para verificar la corrección de un dato, generalmente en soporte informático. Los dígitos de control o dígitos verificadores se usan principalmente para detectar errores en el tecleo o transmisión de los datos. Generalmente consisten en uno o más caracteres numéricos o alfabéticos añadidos al dato original y calculados a partir de éste mediante un determinado algoritmo. Algunos de los ejemplos de uso frecuentes son los números de identificación personal, códigos de barras, tarjetas de crédito y códigos bancarios, como es el caso del Sistema de Rentas Internas (SRI) del Ecuador que utiliza el dígito de verificación como parte de su clave de acceso dentro del proceso de solicitud de números de autorización utilizando el mecanismo del Módulo 11.
Módulo 11
En el caso del SRI el dígito verificador será aplicado sobre toda la clave de acceso (48 dígitos) y deberá ser incorporado por el contribuyente a través del método denominado Módulo 11, con un factor de chequeo ponderado (2), este mecanismo de detección de errores, será verificado al momento de la recepción del comprobante. Cuando el resultado del dígito verificador obtenido sea igual a once (11), el digito verificador será el cero (0) y cuando el resultado del dígito verificador obtenido sea igual a diez 10, el digito verificador será el uno (1).
Como podemos ver en la figura siguiente, el dígito verificador forma parte de la estructura que debemos enviarle al WS del SRI. Para este ejemplo les mostraré una manera de implementar dicha función a través de un método en Java.
El algoritmo deberá realizar el siguiente procedimiento:
Como podemos ver en la figura siguiente, el dígito verificador forma parte de la estructura que debemos enviarle al WS del SRI. Para este ejemplo les mostraré una manera de implementar dicha función a través de un método en Java.
El algoritmo deberá realizar el siguiente procedimiento:
public class Modulo11 { public String invertirCadena(String cadena) { String cadenaInvertida = ""; for (int x = cadena.length() - 1; x >= 0; x--) { cadenaInvertida = cadenaInvertida + cadena.charAt(x); } return cadenaInvertida; } public int obtenerSumaPorDigitos(String cadena) { int pivote = 2; int longitudCadena = cadena.length(); int cantidadTotal = 0; int b = 1; for (int i = 0; i < longitudCadena; i++) { if (pivote == 8) { pivote = 2; } int temporal = Integer.parseInt("" + cadena.substring(i, b)); b++; temporal *= pivote; pivote++; cantidadTotal += temporal; } cantidadTotal = 11 - cantidadTotal % 11; return cantidadTotal; } public static void main(String args[]) throws Exception { Modulo11 a = new Modulo11(); System.out.println(a.obtenerSumaPorDigitos(a.invertirCadena("41261533"))); } }
Espero que esta explicación les sea de utilidad y cualquier consulta no duden en comentarla. Saludos.
Y para los interesados, brindamos asesoría en el tema de facturación electrónica. El temario del taller lo pueden descargar aquí: Temario del Taller.
Gracias me sirve pero pana, una pregunta que no entiendo todavia de donde sale la cadena de verificacion.,41261533 ?
ResponderBorrarCreo que falta incluir algo como esto en el método obtenerSumaPorDigitos, antes del return cantidadTotal
ResponderBorrarswitch (cantidadTotal) {
case 10:
cantidadTotal = 1;
break;
case 11:
cantidadTotal = 0;
break;
}
Saludos, esa cadena es uno de los tantos numeros, llamados claves que pueden ser para pruebas o para producción,que el SRI entrega al contribuyente
ResponderBorrarHola Rolando:
ResponderBorrarGrcias por la información, sin embargo me surge la siguiente duda los números base, se multiplican iniciando con 2,3,4, hasta 7, e inicia nuevamente la cadena al llegar a 7, me surgen las siguientes interrogantes:
¿Porque después de 7 no se continua con 8,y 9?
¿Existe una regla universal para el uso del Modulo 11?
¿Utilizando está formula en varios números, solamente valido 3 números de 6)
¿Pero si utilizo el número 8 después del 7 valida todos los números, 6 en total?
¿Es esto correcto?
Agradeciendo de antemano las respuestas a las interrogantes planteadas, gracias anticipadas.
Hugo R.González B.
La cadena a validar son los 49 dígitos del contenido del campo ClaveAcceso específicamente los 48 primeros (que constituiría el dato de entrada para los métodos expuestos), el ultimo es el verificador..
ResponderBorrarComo puedo obtener el mismo resultado pero con un código diferente?
ResponderBorrarEn Ruby podría ser algo así:
ResponderBorrardef mod11(s)
c = 1
sum = s.reverse.chars.map{ |v| c = (c < 7)? c+=1 : 2; c * v.to_i }.sum
11 - (sum % 11)
end
mod11 '41261533'
=> 6
Aunque podría mejorar :)
Si la cadena a validar son los 48 primeros digitos del campo claveAcceso, ¿por que en el ejemplo usan la cadena de verificacion 41261533 de apenas 8 digitos.? Podrían poner un ejemplo real por favor, con el ruc, la composición de los 48 digitos y luego el dígito verificador.
ResponderBorrarEl algoritmo da un ejemplo de una cadena pequeña la cual el SRI la pone como lo explica aquí http://es.wikipedia.org/wiki/C%C3%B3digo_de_control
ResponderBorrarDebes de coger los 48 dígitos en invertirlos para la secuencia de calculo que empieza con 2 y termina en 7, después sumas todo y ejecutas la función mod(resulado_de_suma, 11) , restas 11 menos el resultado del mod() .Cuando el resultado del dígito verificador obtenido sea igual a once (11), el digito verificador será el cero (0) y cuando el resultado del dígito verificador obtenido sea igual a diez 10, el digito verificador será el uno (1).
Suerte.
Buenas noches una ayuda, el codigo numerico que es parte de acceso de donde lo saco. Como la genero??.Gracias por su ayuda
ResponderBorrarNormalmente en este campo colocamos el secuencial que manejamos a nivel de nuestra aplicación (completando a 8 ceros por la izquierda, si es necesario).
ResponderBorrarSaludos.
Saludos, Tengo esta cadena 060820140109928098410011001001000101253002199121, haciendo el algoritmo que me indican me sale como resultado como dígito verificador de (10) esto se debe que la suma de los 48 dígitos multiplicados por los valores que van del (2) al (7) me da como resultado 518 y si a eso hago la operación de [11 - (518 mod 11)] y este resultado da 1, entonces 11 - 1 = 10.... Que esta mal....
ResponderBorrarEs porque al algoritmo le falta la ultima validacion que es la siguiente "Si el resultado es 11 el dígito de control es 0 y si el resultado es 10 el dígito de control resultante es 1."
Borrarentonces antes del return faltaria estas dos lineas
if (cantidadTotal==11)cantidadTotal=0;
if (cantidadTotal==10)cantidadTotal=1;
return cantidadTotal;
me podrian ayudar con la programacion en c# ... gracias
ResponderBorrarBuenos Dias me Podrian ayudar con este codigo en lenguaje c#.. gracias
ResponderBorrarTengo el codigo en VB.net
ResponderBorrarMe podian ayudar con el codigo en NSIS.
ResponderBorrarPlease--!.
El Código en VFP
ResponderBorrarFUNCTION MODULO11
PARAMETER AIL
* *
* --------------------------------------------------------------------------------------------- *
* ESTE PROGRAMA SE ENCARGA DE RECIBIR UNA CADENA DE 48 DIGITOS Y DEVOLVER EL DIGITO VERIFICADOR *
* CON EL MODULO 11 CON UN CHEQUE PONDERADO DE 2 *
* SE UTILIZA PARA LA FACTUACION ELECTRONICA *
* --------------------------------------------------------------------------------------------- *
* *
LOCAL FEA01,FEA02,FEA03,FEA04,I,PIVOTE,CANTIDADTOTAL,CADENAINVERTIDA
*
FEA01=ALLTRIM(AIL)
FEA02=LEN(FEA01)
*
CADENAINVERTIDA=''
FOR I=FEA02 TO 1 STEP -1
CADENAINVERTIDA=CADENAINVERTIDA+SUBSTR(FEA01,I,1)
ENDFOR
*
*
PIVOTE=2
CANTIDADTOTAL=0
FOR I=1 TO FEA02
IF PIVOTE=8
PIVOTE=2
ENDIF
FEA03=INT(VAL(SUBSTR(CADENAINVERTIDA,I,1)))*PIVOTE
CANTIDADTOTAL=CANTIDADTOTAL+FEA03
PIVOTE=PIVOTE+1
ENDFOR
CANTIDADTOTAL=11-MOD(CANTIDADTOTAL,11)
IF CANTIDADTOTAL=11
CANTIDADTOTAL=0
ELSE
IF CANTIDADTOTAL=10
CANTIDADTOTAL=1
ENDIF
ENDIF
RETURN(CANTIDADTOTAL)
private String invertirCadena(String cadena) {
ResponderBorrarString cadenaInvertida = "";
for (int x = cadena.length() - 1; x >= 0; x--) {
cadenaInvertida = cadenaInvertida + cadena.charAt(x);
}
return cadenaInvertida;
}
private int obtenerSumaPorDigitos(String cadena) {
cadena = this.invertirCadena(cadena);
int pares = 0;
int impares = 0;
int cantidadTotal = 0;
int b = 1;
int longitudCadena = cadena.length();
for(int i = 0;i < longitudCadena;i++){
if(b%2 == 0){
pares = pares+Integer.parseInt(Character.toString(cadena.charAt(i)));
}
else{
impares = impares+Integer.parseInt(Character.toString(cadena.charAt(i)));
}
b++;
}
impares = impares*3;
int sumaTotal = pares+impares;
int decena = 100;
while(sumaTotal > decena){
decena = decena+10;
}
cantidadTotal = decena-sumaTotal;
switch (cantidadTotal) {
case 10:
cantidadTotal = 0;
break;
case 11:
cantidadTotal = 1;
break;
}
return cantidadTotal;
}
Mejoré un poco el código siguiendo el algoritmo para codigos de barras E.A.N,
Salud. --anondeco!
Gracias Ivan Lopez, de pronto tienes el codigo para firnar el archivo XML con la firma electronica en formato P12 desde vfp gracias mil
ResponderBorrarEn PHP:
ResponderBorrarfunction invertirCadena($cadena)
{
$cadenaInvertida = "";
for ($x = strlen($cadena) - 1; $x >= 0; $x--)
{
$cadenaInvertida = $cadenaInvertida.substr($cadena, $x,1);
}
return $cadenaInvertida;
}
function obtenerSumaPorDigitos($cadena)
{
$pivote = 2;
$longitudCadena = strlen($cadena);
$cantidadTotal = 0;
$b = 1;
for ($i = 0; $i < $longitudCadena; $i++)
{
if ($pivote == 8)
{
$pivote = 2;
}
//$temporal = intval(substr($cadena,$i, $b));
$temporal = intval(substr($cadena,$i, 1));
$b++;
$temporal = $temporal * $pivote;
$pivote++;
$cantidadTotal = $cantidadTotal + $temporal;
}
$cantidadTotal = 11 - $cantidadTotal % 11;
return $cantidadTotal;
}
En el codigo php hay un pequeño problema, en la linea:
ResponderBorrar$temporal = intval(substr($cadena,$i, 1));
en lugar de 1, es la variable $b
.. Gracias por el aporte
No me funciono el codigo en php, pero si me funciono el siguiente:
ResponderBorrarfunction obtenerSumaPorDigitos($_rol) {
/* Bonus: remuevo los ceros del comienzo. */
while($_rol[0] == "0") {
$_rol = substr($_rol, 1);
}
$factor = 2;
$suma = 0;
for($i = strlen($_rol) - 1; $i >= 0; $i--) {
$suma += $factor * $_rol[$i];
$factor = $factor % 7 == 0 ? 2 : $factor + 1;
}
$dv = 11 - $suma % 11;
/* Por alguna razón me daba que 11 % 11 = 11. Esto lo resuelve. */
$dv = $dv == 11 ? 0 : ($dv == 10 ? "K" : $dv);
echo '
El digito verificador es: '.$dv.'
';
return $dv;
}
Hola el algoritmo en java está muy bien pero falta considerar 2 casos al final que es cuando el digito verificado es 10 u 11, es lo siguiente "Si el resultado es 11 el dígito de control es 0 y si el resultado es 10 el dígito de control resultante es 1."
ResponderBorrarentonces antes del return faltaria estas dos lineas
if (cantidadTotal==11)cantidadTotal=0;
if (cantidadTotal==10)cantidadTotal=1;