Encontre el codigo que lo obtiene con la homoclave.
la idea es implementarlo en delphi, no se como pasarlo aqui les muestro un link donde se encuentra (pero esta en C# y Visual Fox PRO), la idea (y creo que de muchos) es tenerlo en delphi....
http://www.forosdelweb.com/showthread.php?t=317714
por si no lo pueden abrir a qui les pongo el codigo:
Cita:
CODIGO DESARROLLADO EN VISUAL FOX PRO PARA GENERAR RFC CON HOMOCLAVE Y DIGITO VERIFICADOR SEGUN HACIENDA EN MEXICO
FUNCTION GENERA_RFC(CL_PAT,CL_MAT,CL_NOM,DL_FECNAC)
DIMENSION arre8(10),arre6(4),arre2(10),arre9(1),anex11(1),anex12(1),anex31(1),anex32(1)
arre8[1]="DE "
arre8[2]="DEL "
arre8[3]="LA "
arre8[4]="LOS "
arre8[5]="LAS "
arre8[6]="Y "
arre8[7]="MC "
arre8[8]="MAC "
arre8[9]="VON "
arre8[10]="VAN "
arre6[1]="JOSE "
arre6[2]="MARIA "
arre6[3]="J "
arre6[4]="MA "
arre2[1]="A"
arre2[2]="E"
arre2[3]="I"
arre2[4]="O"
arre2[5]="U"
arre2[6]="a"
arre2[7]="e"
arre2[8]="i"
arre2[9]="o"
arre2[10]="u"
arre9[1]=""
sino = "S"
malas ="BUEIBUEYCACACACOCAGACAGOCAKACAKOCOGECOJAKOGEKOJOKAKAKULOMAMEMAMO"
malas = malas +"MEARMEASMEONMIONCOJECOJICOJOCULOFETOGUEYJOTOKACAKACOKAGA"
malas = malas + "KAGOMOCOMULAPEDAPEDOPENEPUTAPUTOQULORATARUIN"
for x = 1 to Len(malas) step 4
DIMENSION arre9(X)
arre9(X)=SubStr(malas, x, 4)
next
anex11[1] = ''
anex12[1] = ''
taba11 = "*0123456789&\ABCDEFGHIJKLMNOPQRSTUVWXYZ"
taba12 = "000001020304050607080910101112131415161718192122232425262728293233343536373839"
for x = 1 to Len(taba11)
DIMENSION anex11(x),anex12(x)
anex11(x)=SubStr(taba11, x, 1)
two = x * 2 - 1
anex12(x)=SubStr(taba12, two, 2)
next
malas = ""
taba11 = ""
taba12 = ""
taba21 = "00010203040506070809101112131415161718192021222324252627282930313233"
taba22 = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ"
for x = 1 to Len(taba21) step 2
DIMENSION anex21(x),anex22(x)
anex21(x)=SubStr(taba21, x, 2)
two = ( x + 1 ) / 2
anex22(x)=SubStr(taba22, two, 1)
next
taba21 = ""
taba22 = ""
taba11 = "0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ*"
taba12 = "0001020304050607080910111213141516171819202122232425262728293031323334353637"
anex31(1) = ''
anex32(1) = ''
FOR x = 1 to Len(taba11)
DIMENSION anex31(x),anex32(x)
anex31(x)=SubStr(taba11, x, 1)
two = (x * 2) - 1
anex32(x)=SubStr(taba12, two, 2)
NEXT
STORE SPACE(0) TO taba11,taba12,wrfc,wnumer6,wlos3
STORE Space(30) TO wpaterno,wmaterno,wnombre,paterno,materno,nombre
mask = Replicate("!", 30)
wanual = VAL(STR(YEAR(dl_fecnac),4)+PADL(ALLTRIM(STR(MONTH(dl_Fecnac),2)),2,'0')+PADL(ALLTRIM(STR(DAY(dl_fecn ac),2)),2,'0'))
wpaterno = CL_PAT
wmaterno = CL_MAT
wnombre = CL_NOM
IF nacio(wanual) = .F.
=MESSAGEBOX('La Fecha de Nacimiento es Incorrecta',16+0,'Error')
RETURN SPACE(0)
ENDIF
IF los3(wpaterno, wmaterno, wnombre) = .F.
=MESSAGEBOX('El Nombre del Empleado es Incorrecto',16+0,'Error')
RETURN SPACE(0)
ENDIF
finice = .F.
octava()
sexta()
tercera()
wbase = alltrim(alltrim(paterno) + " " + alltrim(materno) +" " + alltrim(nombre))
IF ( Len(paterno) = 0 .OR. Len(materno) = 0 )
septima()
finice = .T.
ENDIF
IF ( !finice )
IF ( Len(paterno) < 3 )
cuarta()
finice = .T.
ENDIF
ENDIF
IF ( !finice )
prime_segu()
ENDIF
RETURN wrfc
ENDFUNC
PROCEDURE SHOW_IT( Arg1 )
cuatro = SubStr(Arg1, 1, 4)
van = ascan(arre9, cuatro)
if ( van > 0 )
wrfc = stuff(wrfc, 4, 1, "X")
endif
homoni()
digito()
RETURN
ENDPROC
PROCEDURE PRIME_SEGU()
letra = SubStr(paterno, 2, 1)
for x = 2 to Len(paterno)
van = ascan(arre2, SubStr(paterno, x, 1))
if ( van > 0 )
letra = arre2[ van ]
x = Len(paterno) + 8
endif
next
wrfc = SubStr(paterno, 1, 1) + letra + SubStr(materno, 1, 1) + SubStr(nombre, 1, 1)
wrfc = wrfc + wnumer6 + "000"
show_it(wrfc)
RETURN
ENDPROC
PROCEDURE TERCERA()
IF ( SubStr(nombre, 1, 2) = "CH" )
nombre = stuff(nombre, 1, 2, "C")
ELSE
IF ( SubStr(nombre, 1, 2) = "LL" )
nombre = stuff(nombre, 1, 2, "L")
ENDIF
ENDIF
IF ( SubStr(paterno, 1, 2) = "CH" )
paterno = stuff(paterno, 1, 2, "C")
ELSE
IF ( SubStr(paterno, 1, 2) = "LL" )
paterno = stuff(paterno, 1, 2, "L")
ENDIF
ENDIF
IF ( SubStr(materno, 1, 2) = "CH" )
materno = stuff(materno, 1, 2, "C")
ELSE
IF ( SubStr(materno, 1, 2) = "LL" )
materno = stuff(materno, 1, 2, "L")
ENDIF
ENDIF
RETURN
ENDPROC
********************************
PROCEDURE CUARTA()
wrfc = SubStr(paterno, 1, 1) + SubStr(materno, 1, 1) +SubStr(nombre, 1, 2) + wnumer6 + "000"
show_it(wrfc)
RETURN
ENDPROC
********************************
PROCEDURE SEXTA()
posi = At(" ", nombre)
IF ( posi > 0 )
FOR xx = 1 to ALen(arre6,1)
nombre = strtran(nombre, arre6[xx])
NEXT
ENDIF
RETURN
ENDPROC
********************************
PROCEDURE SEPTIMA()
IF ( Len(paterno) = 0 .AND. Len(materno) > 0 )
unosolo = materno
ELSE
IF ( Len(paterno) > 0 .AND. Len(materno) = 0 )
unosolo = paterno
ENDIF
ELSE
unosolo = nombre
endif
wrfc = SubStr(unosolo, 1, 2) + SubStr(nombre, 1, 2) + wnumer6 + "000"
show_it(wrfc)
RETURN
ENDPROC
********************************
PROCEDURE OCTAVA()
FOR xx = 1 to aLen(arre8,1)
paterno = strtran(paterno, arre8[ xx ])
materno = strtran(materno, arre8[ xx ])
nombre = strtran(nombre, arre8[ xx ])
NEXT
RETURN
ENDPROC
Function NACIO( Arg1 )
LOCAL ll_error
DIMENSION Local1(12)
Local1(1)=31
Local1(2)=28
Local1(3)=31
Local1(4)=30
Local1(5)=31
Local1(6)=30
Local1(7)=31
Local1(8)=31
Local1(9)=30
Local1(10)=31
Local1(11)=30
Local1(12)=31
if ( Arg1 = 0 )
bb = .F.
else
todo = Str(Arg1, 8)
bb = .T.
uno = Val(SubStr(todo, 7, 2))
dos = Val(SubStr(todo, 5, 2))
tres = Val(SubStr(todo, 1, 4))
if ( Arg1 = 0 .OR. uno = 0 .OR. dos = 0 )
bb = .F.
ELSE
IF ( dos <= 0 .OR. dos > 12 )
bb = .F.
ELSE
bisies = Local1[ dos ]
sanual = Str(tres, 4)
sanual2 = Val(sanual)
if ( dos = 2 .AND. Int(sanual2 / 4) * 4 = sanual2 )
bisies = bisies + 1
endif
ENDIF
if ( bb )
if ( uno <= 0 .OR. uno > bisies )
bb = .F.
endif
endif
endif
if ( !bb )
=MESSAGEBOX('ERROR EN FECHA DE NACIMIENTO',16+0,'Error')
else
wnumer6 = SUBSTR(Str(tres, 4),3,2)
if ( dos < 10 )
wnumer6 = wnumer6 + "0" + Str(dos, 1)
else
wnumer6 = wnumer6 + Str(dos, 2)
endif
if ( uno < 10 )
wnumer6 = wnumer6 + "0" + Str(uno, 1)
else
wnumer6 = wnumer6 + Str(uno, 2)
endif
ENDIF
Return bb
ENDFUNC
Function LOS3( Arg1, Arg2, Arg3 )
paterno = Trim(Arg1)
materno = Trim(Arg2)
nombre = Trim(Arg3)
wlos3 = alltrim(alltrim(Arg1) + " " + alltrim(Arg2) + " " + ;
alltrim(Arg3))
wlos3 = strtran(wlos3, " ", " ")
IF ( Len(wlos3) <= 6 )
Return .F.
ENDIF
Return .T.
ENDFUNC
PROCEDURE HOMONI()
valores = "0"
wbase = alltrim(alltrim(wpaterno) + " " + alltrim(wmaterno) +" " + alltrim(wnombre))
FOR x = 1 TO Len(wbase)
unok = SubStr(wbase, x, 1)
IF ( unok = " " )
unok = "*"
ENDIF
van = ascan(anex11, unok)
IF ( van > 0 )
valores = valores + anex12[ van ]
ELSE
valores = valores + "00"
ENDIF
NEXT
sumas = 0
FOR x = 1 TO Len(valores) - 1
prod1 = Val(SubStr(valores, x, 2))
prod2 = Val(SubStr(valores, x + 1, 1))
prod3 = prod1 * prod2
sumas = sumas + prod3
NEXT
zumass = Str(sumas, 10, 0)
zumass = right(zumass, 3)
zumas = Val(zumass)
solotres = zumas
cociente = Int(solotres / 34)
residuo = solotres - cociente * 34
IF ( cociente < 10 )
wrok = "0" + Str(cociente, 1)
ELSE
wrok = Str(cociente, 2)
ENDIF
van = ascan(anex21, wrok)
IF ( van > 0 )
homo = anex22[ van ]
ELSE
homo = "1"
ENDIF
IF ( residuo < 10 )
wrok = "0" + Str(residuo, 1)
ELSE
wrok = Str(residuo, 2)
ENDIF
van = ascan(anex21, wrok)
IF ( van > 0 )
homo = homo + anex22[ van ]
ELSE
homo = homo + "1"
ENDIF
wrfc = SubStr(wrfc, 1, 10) + homo
RETURN
ENDPROC
PROCEDURE DIGITO()
valores = ""
FOR x = 1 TO Len(wrfc)
unok = SubStr(wrfc, x, 1)
IF unok = " "
unok = "*"
ENDIF
van = ascan(anex31, unok)
IF van > 0
valores = valores + anex32[ van ]
ELSE
valores = valores + "00"
ENDIF
NEXT
sumas = 0
trece = 13
FOR x = 1 TO 12
prod1 = Val(SubStr(valores, x * 2 - 1, 2))
prod3 = prod1 * trece
sumas = sumas + prod3
trece = trece - 1
NEXT
cociente = Int(sumas / 11)
residuo = Int(sumas) - cociente * 11
IF residuo = 0
dijito = "0"
ELSE
valor = 11 - residuo
IF ( valor = 10 )
dijito = "A"
ELSE
entrer = Str(valor, 10, 0)
dijito = right(entrer, 1)
ENDIF
ENDIF
wrfc = wrfc + dijito
RETURN
ENDPROC
|
y aqui esta en C#
Cita:
/// <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);
}
}
|
saludos.
|