ginei11 / lectorCedulas

Modulo para la lectura de cédulas de formato PDF417
20 stars 6 forks source link

Documentacion cédula colombiana #2

Open mdemaredeb opened 4 years ago

mdemaredeb commented 4 years ago

Buenas! Quería saber si usaste alguna documentación sobre el código de barras de la cédula. Estoy intentando escribir programa que funcione con un lector HID, por lo que necesito saber "parsear" lo que lee el lector (ya que lee un string gigante con caracteres especiales y un monton de cosas) Desde ya, gracias!

csantosr commented 4 years ago

Hola! Quería saber si encontraste algún documento sobre esto ya que estamos en una situación parecida. Te lo agradezco :)

mdemaredeb commented 4 years ago

Hola! Literalmente la semana pasada conseguí por fin hablar con alguien de Colombia, y me comentó como lo hacían ellos. Te dejo el código que escribí (javascript) y te lo explico brevemente:

var idAndName;
input.split(/[\x00-\x20]+/g).some(function (el) {
    if (/[0-9]{10,}[A-Z]+$/.test(el)) {
        idAndName = el;
        return true;
    }
});
if(idAndName)
    var output = parseInt(idAndName.match(/[0-9]{10}(?=[A-Z])/)[0]).toString();

La variable input empieza inicializada con el valor de la lectura. Contiene sectores divididos con ciertos caracteres específicos. Según me dijo, pueden ser espacios, 'tabs', NULL u otros. En las cédulas que tenía para probar, en una estaba dividida por NULLs (\x00) y en la otra por \x12, por eso lo primero que hago es un input.split(/[\x00-\x20]+/g), e itero sobre cada división Después, busco la primera división que contenga /[0-9]{10,}[A-Z]+$/, o sea, al menos 10 números seguidos por letras. Esta división es la que contiene la cédula de identidad concatenada con el nombre. Esta división también puede contener otros números al principio que no están relacionados con la cédula, no se bien qué son, pero los saco en el paso siguiente Según me dijeron, sus cédulas tienen como máximo 10 dígitos, y si tienen menos, rellenan los primeros n con ceros. Por lo tanto, con idAndName.match(/[0-9]{10}(?=[A-Z])/)[0] me quedo con los últimos 10 dígitos antes de que empiecen las letras, eliminando esos números que no estaban relacionados con la cédula Por último, hacer parseInt(...).toString() de eso le elimina los ceros al principio y me queda la cédula en output Espero que te sirva!

csantosr commented 4 years ago

Hola! Agradezco mucho tu respuesta. Por si te interesa, ayer estuve investigando sobre la reglamentación de este código de barras y al parecer está protegido por derechos de autor, lo que me hace pensar que solo nos quedan estos espacios para poder construir conocimiento y código al respecto, Tengo entendido que estos espacios no alfanuméricos contienen información biométrica y de seguridad. Así que tal vez te sea más seguro extraer caracteres alfanuméricos en vez de hacer un split. Por si te interesa, he estado trabajando en un código con javascript para extraer esta información, no solo la cédula sino toda la información que podemos rescatar. Me basé en la manera como lo hacen en este repo pero hice algunos cambios como lo son las personas con un solo nombre o un solo apellido.

const contentSplited = data.match(/[A-Za-z0-9+_]+/gi);
let gap,
    capitalIndex,
    documentNumber,
    firstSurname,
    secondSurname,
    firstName,
    secondName,
    gender,
    bloodType,
    birthday;

  if (data.includes("PubDSK")) {
    gap = 0;
    if (contentSplited[2 + gap].length > 7) {
      gap--;
    }
    capitalIndex = contentSplited[3 + gap].match(/[A-Z]/).index;
    documentNumber = parseInt(contentSplited[3 + gap].substring(
      capitalIndex - 10,
      capitalIndex
    )).toString();
    firstSurname = contentSplited[3 + gap].substring(capitalIndex);
    secondSurname = contentSplited[4 + gap];
    firstName = contentSplited[5 + gap];
    secondName = contentSplited[6 + gap];
    gender = contentSplited[7 + gap].includes("M") ? "Male" : "Female";
    bloodType = contentSplited[7 + gap].substring(
      contentSplited[7 + gap].length - 2     
    );    
    birthday = contentSplited[7 + gap].substring(2, 10);    
  } else {
    gap = 0;  
    capitalIndex = contentSplited[2 + gap].match(/[A-Z]/).index;
    documentNumber = parseInt(contentSplited[2 + gap].substring(    
      capitalIndex - 10,                                            
      capitalIndex          
    )).toString();    
    firstSurname = contentSplited[2 + gap].substring(capitalIndex);
    secondSurname = "";                                                
    firstName = "";        
    secondName = "";   
    if (!isNaN(contentSplited[4 + gap][0])) { // Se revisa si tiene solo dos campos de nombre, esto quiere decir que tiene un apellido y un nombre
      firstName = contentSplited[3 + gap];
      gap -= 2;
    } else if (!isNaN(contentSplited[5 + gap][0])) { // En el caso de que tenga tres campos de nombre se interpretará como que solo tiene un nombre y dos apellidos
      secondSurname = contentSplited[3 + gap];
      firstName = contentSplited[4 + gap];
      gap--;
    }
    gender = contentSplited[6 + gap].includes("M") ? "Male" : "Female";
    bloodType = "";
    if (contentSplited[6 + gap][contentSplited[6 + gap].length - 1] == "2")
      bloodType = contentSplited[6 + gap].substring(
        contentSplited[6 + gap].length - 4,
        contentSplited[6 + gap].length - 1
      );
    else
      bloodType = contentSplited[6 + gap].substring(
        contentSplited[6 + gap].length - 2
      );

    birthday = contentSplited[6 + gap].substring(2, 10);
  }

Pronto haré un PR con estos cambios pero como podrás ver, tendré que traducirlo a java. Espero te sirva! Happy coding!

mdemaredeb commented 4 years ago

Buenísimo! Gracias por la información!

jhohann commented 4 years ago

Buenas tardes, he tratado de hacer funcionar el código y no me ha sido posible, si me pueden dar una mano con algo de información adicional se los agradecería.

csantosr commented 4 years ago

Hola! ¿Podrías dar más información acerca del problema?

jhohann commented 4 years ago

Hola Cristian, te agradezco por responder, soy nuevo en android, desplegue todo el codigo que aparece en el repositorio y me aparece un error en el mainXml, te agradezco de antemano tu ayuda.

Si no es mucho abuso y tu tienes el código funcional y me lo pudieras compartir me sería de gran ayuda.

El jue., 27 ago. 2020, 6:12 p. m., Cristian Fernando Santos Ribero < notifications@github.com> escribió:

Hola! ¿Podrías dar más información acerca del problema?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/ginei11/lectorCedulas/issues/2#issuecomment-682236972, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALYWQ75EILCZMFCGTXDYLMLSC3R7FANCNFSM4KPF3IWQ .

StriderCortes commented 2 years ago

Hola buenos días, estoy realizando la misma comprobacion de Cedulas en mi proyecto, pero con una cedula con solo un apellido o un solo nombre falla el codigo, use el codigo que desarrollo @csantosr, pero falla igualmente, me podiran ayudar?

StriderCortes commented 2 years ago

pude solucionarlo pero las cédulas mas recientes manejar un formato de datos ligeramente diferente.

csantosr commented 2 years ago

hola, cómo lo lograste? cuál fue el problema? Me encantaría saber

StriderCortes commented 2 years ago

Existen variables en la data que envían las Cédulas las mas recientes y las mas antiguas que no poseen PubDSK y empese a filtrar los campos usando este codigo:

if(Codigo.length >= 6) { Espacio= 0; } else if (Codigo.length >= 7) { Espacio--; } else{ Espacio - 2; }