Ver Mensaje Individual
  #25 (permalink)  
Antiguo 03/08/2006, 12:34
hyadus
 
Fecha de Ingreso: agosto-2006
Mensajes: 1
Antigüedad: 18 años, 3 meses
Puntos: 0
Me tomé la libertad de "convertir" el código para calcular el RFC a C#, espero que alguien le sea útil. Saludos.

------------------------------------------------------------

Código:
/// <summary>
/// Contiene Funciones para el calculo de RFC y CURP
/// </summary>
public class CURPRFC
{
	/// <summary>
	/// Calcula el RFC de una persona física su homoclave incluida.
	/// </summary>
	/// <param name="nombre">Nombre(s) de la persona</param>
	/// <param name="apellidoPaterno">Apellido paterno de la persona</param>
	/// <param name="apellidoMaterno">Apellido materno de la persona</param>
	/// <param name="fecha">Fecha en formato dd/MM/yy (12/10/68)</param>
	/// <returns>Regresa el RFC como cadena de caracteres</returns>
	static public string CalcularRFC(string nombre, string apellidoPaterno, string apellidoMaterno, string fecha)
	{
		//Cambiamos todo a mayúsculas
		nombre = nombre.ToUpper();
		apellidoPaterno = apellidoPaterno.ToUpper();
		apellidoMaterno = apellidoMaterno.ToUpper();

		//RFC que se regresará
		string rfc = String.Empty;

		//Quitamos los espacios al principio y final del nombre y apellidos
		nombre.Trim();
		apellidoPaterno = apellidoPaterno.Trim();
		apellidoMaterno = apellidoMaterno.Trim();
	
		//Quitamos los artículos de los apellidos
		apellidoPaterno = QuitarArticulos(apellidoPaterno);
		apellidoMaterno = QuitarArticulos(apellidoMaterno);

		//Agregamos el primer caracter del apellido paterno
		rfc = apellidoPaterno.Substring(0, 1);

		//Buscamos y agregamos al rfc la primera vocal del primer apellido
		foreach (char c in apellidoPaterno)
		{
			if (EsVocal(c))
			{
				rfc += c;
				break;
			}
		}

		//Agregamos el primer caracter del apellido materno
		rfc += apellidoMaterno.Substring(0, 1);

		//Agregamos el primer caracter del primer nombre
		rfc += nombre.Substring(0, 1);

		//agregamos la fecha yymmdd (por ejemplo: 680825, 25 de agosto de 1968 )
		rfc += fecha.Substring(6, 2) +
			fecha.Substring(3, 2) +
			fecha.Substring(0, 2);

		//Le agregamos la homoclave al rfc 
		CalcularHomoclave(apellidoPaterno + " " + apellidoMaterno + " " + nombre, fecha, ref rfc);

		return rfc;
	}

	/// <summary>
	/// Calcula la homoclave
	/// </summary>
	/// <param name="nombreCompleto">El nombre completo de la persona en el formato "ApellidoPaterno ApellidoMaterno Nombre(s)"</param>
	/// <param name="fecha">fecha en el formato "dd/MM/yy"</param>
	/// <param name="rfc">rfc sin homoclave, esta se pasa con ref y después de la función tendrá la homoclave</param>
	static private void CalcularHomoclave(string nombreCompleto, string fecha, ref string rfc)
	{
		//Guardara el nombre en su correspondiente numérico
		StringBuilder nombreEnNumero = new StringBuilder(); ;
		//La suma de la secuencia de números de nombreEnNumero
		long valorSuma = 0;

		#region Tablas para calcular la homoclave
		//Estas tablas realmente no se porque son como son
		//solo las copie de lo que encontré en internet

		#region TablaRFC 1
		Hashtable tablaRFC1 = new Hashtable();
		tablaRFC1.Add("&", 10);
		tablaRFC1.Add("Ñ", 10);
		tablaRFC1.Add("A", 11);
		tablaRFC1.Add("B", 12);
		tablaRFC1.Add("C", 13);
		tablaRFC1.Add("D", 14);
		tablaRFC1.Add("E", 15);
		tablaRFC1.Add("F", 16);
		tablaRFC1.Add("G", 17);
		tablaRFC1.Add("H", 18);
		tablaRFC1.Add("I", 19);
		tablaRFC1.Add("J", 21);
		tablaRFC1.Add("K", 22);
		tablaRFC1.Add("L", 23);
		tablaRFC1.Add("M", 24);
		tablaRFC1.Add("N", 25);
		tablaRFC1.Add("O", 26);
		tablaRFC1.Add("P", 27);
		tablaRFC1.Add("Q", 28);
		tablaRFC1.Add("R", 29);
		tablaRFC1.Add("S", 32);
		tablaRFC1.Add("T", 33);
		tablaRFC1.Add("U", 34);
		tablaRFC1.Add("V", 35);
		tablaRFC1.Add("W", 36);
		tablaRFC1.Add("X", 37);
		tablaRFC1.Add("Y", 38);
		tablaRFC1.Add("Z", 39);
		tablaRFC1.Add("0", 0);
		tablaRFC1.Add("1", 1);
		tablaRFC1.Add("2", 2);
		tablaRFC1.Add("3", 3);
		tablaRFC1.Add("4", 4);
		tablaRFC1.Add("5", 5);
		tablaRFC1.Add("6", 6);
		tablaRFC1.Add("7", 7);
		tablaRFC1.Add("8", 8);
		tablaRFC1.Add("9", 9);
		#endregion

		#region TablaRFC 2
		Hashtable tablaRFC2 = new Hashtable();
		tablaRFC2.Add(0, "1");
		tablaRFC2.Add(1, "2");
		tablaRFC2.Add(2, "3");
		tablaRFC2.Add(3, "4");
		tablaRFC2.Add(4, "5");
		tablaRFC2.Add(5, "6");
		tablaRFC2.Add(6, "7");
		tablaRFC2.Add(7, "8");
		tablaRFC2.Add(8, "9");
		tablaRFC2.Add(9, "A");
		tablaRFC2.Add(10, "B");
		tablaRFC2.Add(11, "C");
		tablaRFC2.Add(12, "D");
		tablaRFC2.Add(13, "E");
		tablaRFC2.Add(14, "F");
		tablaRFC2.Add(15, "G");
		tablaRFC2.Add(16, "H");
		tablaRFC2.Add(17, "I");
		tablaRFC2.Add(18, "J");
		tablaRFC2.Add(19, "K");
		tablaRFC2.Add(20, "L");
		tablaRFC2.Add(21, "M");
		tablaRFC2.Add(22, "N");
		tablaRFC2.Add(23, "P");
		tablaRFC2.Add(24, "Q");
		tablaRFC2.Add(25, "R");
		tablaRFC2.Add(26, "S");
		tablaRFC2.Add(27, "T");
		tablaRFC2.Add(28, "U");
		tablaRFC2.Add(29, "V");
		tablaRFC2.Add(30, "W");
		tablaRFC2.Add(31, "X");
		tablaRFC2.Add(32, "Y");
		#endregion

		#region TablaRFC 3
		Hashtable tablaRFC3 = new Hashtable();
		tablaRFC3.Add("A", 10);
		tablaRFC3.Add("B", 11);
		tablaRFC3.Add("C", 12);
		tablaRFC3.Add("D", 13);
		tablaRFC3.Add("E", 14);
		tablaRFC3.Add("F", 15);
		tablaRFC3.Add("G", 16);
		tablaRFC3.Add("H", 17);
		tablaRFC3.Add("I", 18);
		tablaRFC3.Add("J", 19);
		tablaRFC3.Add("K", 20);
		tablaRFC3.Add("L", 21);
		tablaRFC3.Add("M", 22);
		tablaRFC3.Add("N", 23);
		tablaRFC3.Add("O", 25);
		tablaRFC3.Add("P", 26);
		tablaRFC3.Add("Q", 27);
		tablaRFC3.Add("R", 28);
		tablaRFC3.Add("S", 29);
		tablaRFC3.Add("T", 30);
		tablaRFC3.Add("U", 31);
		tablaRFC3.Add("V", 32);
		tablaRFC3.Add("W", 33);
		tablaRFC3.Add("X", 34);
		tablaRFC3.Add("Y", 35);
		tablaRFC3.Add("Z", 36);
		tablaRFC3.Add("0", 0);
		tablaRFC3.Add("1", 1);
		tablaRFC3.Add("2", 2);
		tablaRFC3.Add("3", 3);
		tablaRFC3.Add("4", 4);
		tablaRFC3.Add("5", 5);
		tablaRFC3.Add("6", 6);
		tablaRFC3.Add("7", 7);
		tablaRFC3.Add("8", 8);
		tablaRFC3.Add("9", 9);
		tablaRFC3.Add("", 24);
		tablaRFC3.Add(" ", 37);
		#endregion

		#endregion

		//agregamos un cero al inicio de la representación númerica del nombre
		nombreEnNumero.Append("0"); 

		//Recorremos el nombre y vamos convirtiendo las letras en 
		//su valor numérico
		foreach (char c in nombreCompleto)
		{
			if (tablaRFC1.ContainsKey(c.ToString()))
				nombreEnNumero.Append(tablaRFC1[c.ToString()].ToString());
			else
				nombreEnNumero.Append("00");
		}

		//Calculamos la suma de la secuencia de números 
		//calculados anteriormente
		//la formula es:
		//( (el caracter actual multiplicado por diez)
		//mas el valor del caracter siguiente )
		//(y lo anterior multiplicado por el valor del caracter siguiente)
		for (int i = 0; i < nombreEnNumero.Length - 1; i++)
		{
			valorSuma += ((Convert.ToInt32(nombreEnNumero[i].ToString()) * 10) + Convert.ToInt32(nombreEnNumero[i + 1].ToString())) * Convert.ToInt32(nombreEnNumero[i + 1].ToString());
		}

		//Lo siguiente no se porque se calcula así, es parte del algoritmo.
		//Los magic numbers que aparecen por ahí deben tener algún origen matemático
		//relacionado con el algoritmo al igual que el proceso mismo de calcular el 
		//digito verificador.
		//Por esto no puedo añadir comentarios a lo que sigue, lo hice por acto de fe.

		int div = 0, mod = 0;
		div = Convert.ToInt32(valorSuma) % 1000;
		mod = div % 34;
		div = (div - mod) / 34;

		int indice = 0;
		string hc = String.Empty;  //los dos primeros caracteres de la homoclave
		while (indice <= 1)
		{
			if (tablaRFC2.ContainsKey((indice == 0) ? div : mod))
				hc += tablaRFC2[(indice == 0) ? div : mod];
			else
				hc += "Z";
			indice++;
		}

		//Agregamos al RFC los dos primeros caracteres de la homoclave
		rfc += hc;

		//Aqui empieza el calculo del digito verificador basado en lo que tenemos del RFC
		//En esta parte tampoco conozco el origen matemático del algoritmo como para dar 
		//una explicación del proceso, así que ¡tengamos fe hermanos!.
		int rfcAnumeroSuma = 0, sumaParcial = 0;
		for (int i = 0; i < rfc.Length; i++)
		{
			if (tablaRFC3.ContainsKey(rfc[i].ToString()))
			{
				rfcAnumeroSuma = Convert.ToInt32(tablaRFC3[rfc[i].ToString()]);
				sumaParcial += (rfcAnumeroSuma * (14 - (i + 1)));
			}
		}

		int moduloVerificador = sumaParcial % 11;
		if (moduloVerificador == 0)
			rfc += "0";
		else
		{
			sumaParcial = 11 - moduloVerificador;
			if (sumaParcial == 10)
				rfc += "A";
			else
				rfc += sumaParcial.ToString();
		}

		//en este punto la variable rfc pasada ya debe tener la homoclave
		//recuerda que la variable rfc se paso como "ref string" lo cual
		//hace que se modifique la original.
	}

	/// <summary>
	/// Verifica si el caracter pasado es una vocal
	/// </summary>
	/// <param name="letra">Caracter a comprobar</param>
	/// <returns>Regresa true si es vocal, de lo contrario false</returns>
	static private bool EsVocal(char letra)
	{
		//Aunque para el caso del RFC cambié todas las letras a mayúsculas
		//igual agregé las minúsculas.
		if (letra == 'A' || letra == 'E' || letra == 'I' || letra == 'O' || letra == 'U' ||
			letra == 'a' || letra == 'e' || letra == 'i' || letra == 'o' || letra == 'u')
			return true;
		else
			return false;
	}

	/// <summary>
	/// Remplaza los artículos comúnes en los apellidos en México con caracter vacío (String.Empty).
	/// </summary>
	/// <param name="palabra">Palabra que se le quitaran los artículos</param>
	/// <returns>Regresa la palabra sin los artículos</returns>
	static private string QuitarArticulos(string palabra)
	{
		return palabra.Replace("DEL ", String.Empty).Replace("LAS ", String.Empty).Replace("DE ", String.Empty).Replace("LA ", String.Empty).Replace("Y ", String.Empty).Replace("A ", String.Empty);
	}
}