MI SELLO ESTA MAL FORMADO...

Para quienes programan Visual Basic aqui esta la solucion

MI SELLO ESTA MAL FORMADO...

Notapor danielambda » Mié Nov 23, 2011 11:02 am

Hola gente del grupo, esta es la primera vez que visito su sitio, pues apenas comencé con esto de la facturación electrónica. He desarrollado un sistema en vb.net 2008 para la facturación. Como verán pues estoy obligado a emitir CFDi y el xml pues obviamente en versión 3, y pues estoy contratando los servicios de un proveedor para timbrar (PAC) su nombre es FEL. bueno pues, ellos requieren que envíe en una cadena enorme mi xml, o sea que mi xml lo convierta a tipo String, (ESO YA ES PRUEBA SUPERADA), para hacer las digestiones sha1 y todo eso, utilizo el openssl y lo ejecuto de la siguiente manera:

Dim process As New Process
process.StartInfo.WindowStyle = ProcessWindowStyle.Minimized
process.StartInfo.FileName = "C:\OpenSSL\bin\openssl.exe" 'le ponemos el nombre del archivo q hara la encriptacion (la ruta del openssl.exe)
process.StartInfo.Arguments = "dgst -SHA1 " & s.App_Path() & "cadena.txt" 'le madamos solo un parametro. (el nombre del archivo .txt q contiene la cadena original)
process.StartInfo.WorkingDirectory = "C:\OpenSSL\bin" 'esto es para poner el direcctorio inicial en el q iniciara el proceso
process.StartInfo.UseShellExecute = False 'esto es para decirle q no usaremos el shell del sistema operativo
process.StartInfo.ErrorDialog = False 'esto es para omitir cualquier mensaje de error del proceso a ejecutar
process.StartInfo.RedirectStandardOutput = True 'esto es para decirle q vamos a escribir (o utiliar) el resultado de la secuencia (o sea el resultado encriptado)
process.Start() 'iniciamos el proceso
Dim codificado As String 'creamos una varaible q almacenara el resultado encriptado
codificado = process.StandardOutput.ReadToEnd 'el resultado del parametro "dgst -SHA1 d:\cadena.txt" se almacena en esta variable
process.WaitForExit() 'le decimos q se espere el proceso

bueno eso es a grandes rasgos, como en vb.net te permite la depuracion paso a paso, he depurado paso a paso todas las intrucciones del openssl que utilizo, y las he ido comparando con el openssl ejecutandolo desde modo consola, de modo que requiero ver si me arroja los mismos resultados, y pues efectivamente, siempre me arroja los mismo resultados, ya sea en la codificacion de la cadena original, cuando genera la cadena del certificado, ya he revisado que no se contengan saltos de carro, que mi xml contenga toda la informacion que debe de contener y mi cadena original contenga los datos correctos. De hecho cuando valido mi xml en el portal del sat, me muestra una cadena original y esa misma la comparo con la que yo genero desde mi sistema, y resulta que es exactamente la misma, pero me sigue diciendo que mi sello esta mal formado o es invalido. Alguien podria ayudarme con este problema??? si requieren mas datos o algo así con mucho gusto se los hago llegar a la brevedad.
No se fracasa si existe un comienzo...
danielambda
 
Mensajes: 3
Registrado: Mié Nov 23, 2011 10:44 am

Re: MI SELLO ESTA MAL FORMADO...

Notapor cbr_net » Jue Dic 01, 2011 11:14 pm

Hola Daniela,

El sello digital es una combinacion de la cadena original y el certificado aplicando el algoritmo de encriptacion SHA1 (2011), ahora en tu digestion no veo la obtencion de tu certificado solo beo que intentas obtener el sello solo con la cadena original.

Aqui en el foro esta la explicacion de como puedes formar el sello digital.


Saludos
cbr_net
 
Mensajes: 101
Registrado: Mar Nov 23, 2010 3:08 pm
Ubicación: Puebla

Re: MI SELLO ESTA MAL FORMADO...

Notapor danielambda » Vie Dic 02, 2011 11:27 pm

hola!!! gracias por responder!!!, (creí que nunca nadie lo haría). En efecto, lo que me comentas es muy cierto, mira, te pongo mi código completo con el cual estoy generando mi sello digital, y de antemano agradezco mucho mucho la atención prestada. (con respecto a lo de los demás foros pues no he encontrado información suficiente o mas bien no le he comprendido del toda esa información, tal vez no soy muy perspicaz o no me se dar cuenta, o bien no he encontrado el post adecuado, de verdad que no quiero levantar un tema antiguo, espero puedan ayudarme, cualquier información adicional que requieran que aporte, con mucho gusto a la brevedad se los haré llegar).

...............................EN ESTA PARTE SE EXPLICA COMO GENERO LOS ARCHIVOS(.cer.pem y .key.pem) Y LAS DEMAS ACCIONES (fecha de vencimiento, cadena del certificado, etc)

Dim cerPen As String = Mid(archivoImagen.FileName, 1, archivoImagen.FileName.Length - 4)
'CREAMOS EL CERTIFICADO .PEM (blahblahblahblah.CER.PEM)
'C:\OpenSSL\bin>openssl dgst -sign D:\Cer_Sellos\aaa010101aaa_CSD_01.key.pem D:\codificado.txt | openssl enc -base64 -A > D:\sello.txt
Dim process4 As New Process
process4.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
process4.StartInfo.FileName = "C:\OpenSSL\bin\openssl.exe" 'le ponemos el nombre del archivo q hara la encriptacion (la ruta del openssl.exe)
process4.StartInfo.Arguments = " x509 -inform DER -in " & Me.txtRutaCer.Text & " -outform PEM -out " & Me.txtRutaCer.Text & ".pem " 'le madamos solo un parametro.
process4.StartInfo.WorkingDirectory = "C:\OpenSSL\bin" 'esto es para poner el direcctorio inicial en el q iniciara el proceso
process4.StartInfo.UseShellExecute = False 'esto es para decirle q no usaremos el shell del sistema operativo
process4.StartInfo.ErrorDialog = True 'esto es para omitir cualquier mensaje de error del proceso a ejecutar
process4.StartInfo.RedirectStandardOutput = True 'esto es para decirle q vamos a escribir (o utiliar) el resultado de la secuencia (o sea el resultado encriptado)

process4.Start() 'iniciamos el proceso

process4.WaitForExit() 'le decimos q se espere el proceso

Sub consultarDatosCertificado(ByVal rutaCerPen As String)

If System.IO.File.Exists(rutaCerPen) Then
Dim desde As String = ""
Dim hasta As String = ""
'ejecutamos la instruccion openssl para extraer la vigencia del certificado (desde hasta)
'C:\OpenSSL\bin>openssl.exe x509 -in D:\Cer_Sellos\aaa010101aaa_CSD_01.cer.pem -noout -dates
Dim process As New Process
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
process.StartInfo.FileName = "C:\OpenSSL\bin\openssl.exe" 'le ponemos el nombre del archivo q hara la encriptacion (la ruta del openssl.exe)
process.StartInfo.Arguments = "x509 -in " & rutaCerPen & " -noout -dates "
process.StartInfo.WorkingDirectory = "C:\OpenSSL\bin" 'esto es para poner el direcctorio inicial en el q iniciara el proceso
process.StartInfo.UseShellExecute = False 'esto es para decirle q no usaremos el shell del sistema operativo
process.StartInfo.ErrorDialog = False 'esto es para omitir cualquier mensaje de error del proceso a ejecutar
process.StartInfo.RedirectStandardOutput = True 'esto es para decirle q vamos a escribir (o utiliar) el resultado de la secuencia (o sea el resultado encriptado)
process.Start() 'iniciamos el proceso
Dim codificado As String 'creamos una varaible q almacenara el resultado encriptado
codificado = process.StandardOutput.ReadToEnd 'el resultado del parametro "dgst -SHA1 d:\cadena.txt" se almacena en esta variable
process.WaitForExit() 'le decimos q se espere el proceso

desde = s.QuitaChars(RTrim(codificado), wB64 & ":= ")
hasta = s.QuitaChars(RTrim(Mid(codificado, 36)), wB64 & ":= ")
Me.txtDesdeCer.Text = desde
Me.txtHastaCer.Text = hasta
Me.txtVigDesde.Text = s.GetDateGS(Me.txtDesdeCer.Text)
Me.txtVigHasta.Text = s.GetDateGS(Me.txtHastaCer.Text)

'ejecutamos la instruccion openssl para extraer el serial del certificado
'C:\OpenSSL\bin>openssl.exe x509 -in D:\Cer_Sellos\aaa010101aaa_CSD_01.cer.pem -noout -serial
'C:\OpenSSL\bin>openssl.exe x509 -in D:\Cer_Sellos\aaa010101aaa_CSD_01.cer.pem -serial
Dim process2 As New Process
process2.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
process2.StartInfo.FileName = "C:\OpenSSL\bin\openssl.exe" 'le ponemos el nombre del archivo q hara la encriptacion (la ruta del openssl.exe)
process2.StartInfo.Arguments = "x509 -in " & rutaCerPen & " -noout -serial "
process2.StartInfo.WorkingDirectory = "C:\OpenSSL\bin" 'esto es para poner el direcctorio inicial en el q iniciara el proceso
process2.StartInfo.UseShellExecute = False 'esto es para decirle q no usaremos el shell del sistema operativo
process2.StartInfo.ErrorDialog = False 'esto es para omitir cualquier mensaje de error del proceso a ejecutar
process2.StartInfo.RedirectStandardOutput = True 'esto es para decirle q vamos a escribir (o utiliar) el resultado de la secuencia (o sea el resultado encriptado)
process2.Start() 'iniciamos el proceso
codificado = process2.StandardOutput.ReadToEnd 'el resultado del parametro "dgst -SHA1 d:\cadena.txt" se almacena en esta variable
process2.WaitForExit() 'le decimos q se espere el proceso

Me.txtSerieCer.Text = s.FormateaSerie(codificado)

If IsDate(txtVigHasta.Text) = True Then
If CDate(txtVigHasta.Text) < Date.Now Then
txtVigHasta.BackColor = Color.Red
txtVigHasta.Focus()
s.errror("El certificado ha caducado")
End If
End If
Me.txtRutaCerPem.Text = rutaCerPen
'EXTRAEMOS LA CADENA DEL CERTIFICADO MIIE/TCCA+WgAwIBAgIUMzAwMDEwMDAwMDAxMDAwMDA4MDAwDQYJKoZIh ......
'C:\OpenSSL\bin>openssl.exe x509 -inform DER -outform PEM -in D:\Cer_Sellos\aaa010101aaa_CSD_01.cer
Dim process5 As New Process
process5.StartInfo.WindowStyle = ProcessWindowStyle.Minimized
process5.StartInfo.FileName = "C:\OpenSSL\bin\openssl.exe" 'le ponemos el nombre del archivo q hara la encriptacion (la ruta del openssl.exe)
process5.StartInfo.Arguments = "x509 -inform DER -outform PEM -in " & Me.txtRutaCer.Text & "" 'le madamos solo un parametro.
process5.StartInfo.WorkingDirectory = "C:\OpenSSL\bin" 'esto es para poner el direcctorio inicial en el q iniciara el proceso
process5.StartInfo.UseShellExecute = False 'esto es para decirle q no usaremos el shell del sistema operativo
process5.StartInfo.ErrorDialog = False 'esto es para omitir cualquier mensaje de error del proceso a ejecutar
process5.StartInfo.RedirectStandardOutput = True 'esto es para decirle q vamos a escribir (o utiliar) el resultado de la secuencia (o sea el resultado encriptado)

process5.Start() 'iniciamos el proceso

process5.WaitForExit() 'le decimos q se espere el proceso
Dim CertificadoCadena As String 'creamos una varaible q almacenara el resultado encriptado
CertificadoCadena = process5.StandardOutput.ReadToEnd
CertificadoCadena = Mid(CertificadoCadena, 28)

Dim oSW As New StreamWriter("D:\certificado.txt")
oSW.WriteLine(CertificadoCadena)
oSW.Flush()
oSW.Close()
'quitamos los guiones
Dim RespCertificadoCadena As String = ""
Dim valor As Integer
For i As Integer = 0 To CertificadoCadena.Length - 1
valor = Asc(CertificadoCadena.Chars(i))
If valor > 31 And CertificadoCadena.Chars(i) <> "-" And CertificadoCadena.Chars(i) <> Chr(10) And CertificadoCadena.Chars(i) <> " " Then
RespCertificadoCadena = RespCertificadoCadena & CertificadoCadena.Chars(i)
End If
Next
Me.txtCertificadoE.Text = Mid(RespCertificadoCadena, 1, RespCertificadoCadena.Length - 14)
Else
s.errror("No se genero el archivo .pem, vuelva a seleccionar el certificado")
Me.txtRutaCer.Text = ""
Me.txtDesdeCer.Text = ""
Me.txtHastaCer.Text = ""
Me.txtVigDesde.Text = ""
Me.txtVigHasta.Text = ""
txtVigHasta.BackColor = Color.White
Me.txtSerieCer.Text = ""
Exit Sub
End If


End Sub

'CREAMOS EL ARCHIVO .KEY.PEN
Dim process2 As New Process
process2.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
process2.StartInfo.FileName = "C:\OpenSSL\bin\openssl.exe" 'le ponemos el nombre del archivo q hara la encriptacion (la ruta del openssl.exe)
process2.StartInfo.Arguments = "pkcs8 -inform DER -in " & Me.txtRutaLlave.Text & " -passin pass:" & password & " -outform PEM -out " & Me.txtRutaLlave.Text & ".pem" 'le madamos solo un parametro.
process2.StartInfo.WorkingDirectory = s.App_Path() 'esto es para poner el direcctorio inicial en el q iniciara el proceso
process2.StartInfo.UseShellExecute = False 'esto es para decirle q no usaremos el shell del sistema operativo
process2.StartInfo.ErrorDialog = False 'esto es para omitir cualquier mensaje de error del proceso a ejecutar
process2.StartInfo.RedirectStandardOutput = True 'esto es para decirle q vamos a escribir (o utiliar) el resultado de la secuencia (o sea el resultado encriptado)
process2.Start() 'iniciamos el proceso
process2.WaitForExit() 'le decimos q se espere el proceso

Function modulosCerKey() As Boolean
Dim modulusCer As String
Dim modulusKey As String
'ejecutamos el MODULOS PARA REVISAR Q EL CERTIFICADO CORRESPONDE CON LA LLAVE PRIVADA
Dim process3 As New Process
process3.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
process3.StartInfo.FileName = "C:\OpenSSL\bin\openssl.exe" 'le ponemos el nombre del archivo q hara la encriptacion (la ruta del openssl.exe)
process3.StartInfo.Arguments = "x509 -in " & Me.txtRutaCerPem.Text & " -noout -modulus " 'le madamos solo un parametro.
process3.StartInfo.WorkingDirectory = s.App_Path() 'esto es para poner el direcctorio inicial en el q iniciara el proceso
process3.StartInfo.UseShellExecute = False 'esto es para decirle q no usaremos el shell del sistema operativo
process3.StartInfo.ErrorDialog = False 'esto es para omitir cualquier mensaje de error del proceso a ejecutar
process3.StartInfo.RedirectStandardOutput = True 'esto es para decirle q vamos a escribir (o utiliar) el resultado de la secuencia (o sea el resultado encriptado)
process3.Start() 'iniciamos el proceso
modulusCer = process3.StandardOutput.ReadToEnd 'extraemos le resutado (modulus)
process3.WaitForExit() 'le decimos q se espere el proceso
modulusCer = Mid(modulusCer, 9)

Dim process4 As New Process
process4.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
process4.StartInfo.FileName = "C:\OpenSSL\bin\openssl.exe" 'le ponemos el nombre del archivo q hara la encriptacion (la ruta del openssl.exe)
process4.StartInfo.Arguments = "rsa -in " & Me.txtRutaLlave.Text & ".pem -noout -modulus " 'le madamos solo un parametro.
process4.StartInfo.WorkingDirectory = s.App_Path() 'esto es para poner el direcctorio inicial en el q iniciara el proceso
process4.StartInfo.UseShellExecute = False 'esto es para decirle q no usaremos el shell del sistema operativo
process4.StartInfo.ErrorDialog = False 'esto es para omitir cualquier mensaje de error del proceso a ejecutar
process4.StartInfo.RedirectStandardOutput = True 'esto es para decirle q vamos a escribir (o utiliar) el resultado de la secuencia (o sea el resultado encriptado)
process4.Start() 'iniciamos el proceso
modulusKey = process4.StandardOutput.ReadToEnd 'extraemos le resutado (modulus)
process4.WaitForExit() 'le decimos q se espere el proceso
modulusKey = Mid(modulusKey, 9)

If modulusCer <> modulusKey Then
Return False
Else
Return True

End If
End Function

---------------------EN LA PARTE SIGUIENTE VA AHORA LO DE LA FORMACION DEL SELLO CON LA CADENA ORIGINAL Y TODO LO DEMAS

'A continuacion guardaremos la cadena en un archivo con su formato UTF-8 como lo pide SAT -------------------------------------
System.IO.File.WriteAllText(s.App_Path() & "cadena.txt", cadena_original, System.Text.Encoding.UTF8)

'CREAMOS EL SELLO
'C:\OpenSSL\bin>openssl dgst -SHA1 -sign D:\Cer_Sellos\aaa010101aaa_CSD_01.key.pem D:\codificado.txt | openssl enc -base64 -A > D:\sello.txt
Dim process3 As New Process
process3.StartInfo.WindowStyle = ProcessWindowStyle.Minimized
process3.StartInfo.FileName = "C:\OpenSSL\bin\openssl.exe" 'le ponemos el nombre del archivo q hara la encriptacion (la ruta del openssl.exe)
process3.StartInfo.Arguments = "dgst -sha1 -sign " & direccionLLavePem & " -out " & s.App_Path() & "sello.txt " & s.App_Path() & "cadena.txt " 'le madamos solo un parametro.
process3.StartInfo.WorkingDirectory = "C:\OpenSSL\bin" 'esto es para poner el direcctorio inicial en el q iniciara el proceso
process3.StartInfo.UseShellExecute = False 'esto es para decirle q no usaremos el shell del sistema operativo
process3.StartInfo.ErrorDialog = True 'esto es para omitir cualquier mensaje de error del proceso a ejecutar
process3.StartInfo.RedirectStandardOutput = True 'esto es para decirle q vamos a escribir (o utiliar) el resultado de la secuencia (o sea el resultado encriptado)

process3.Start() 'iniciamos el proceso
process3.WaitForExit() 'le decimos q se espere el proceso

Dim b64 As String = ""

'CONVERTIMOS EL RESULTADO A BASE64
Dim process33 As New Process
process33.StartInfo.WindowStyle = ProcessWindowStyle.Minimized
process33.StartInfo.FileName = "C:\OpenSSL\bin\openssl.exe" 'le ponemos el nombre del archivo q hara la encriptacion (la ruta del openssl.exe)
process33.StartInfo.Arguments = "enc -base64 -in " & s.App_Path() & "sello.txt -out " & s.App_Path() & "b64.txt " 'le madamos solo un parametro.
process33.StartInfo.WorkingDirectory = "C:\OpenSSL\bin" 'esto es para poner el direcctorio inicial en el q iniciara el proceso
process33.StartInfo.UseShellExecute = False 'esto es para decirle q no usaremos el shell del sistema operativo
process33.StartInfo.ErrorDialog = True 'esto es para omitir cualquier mensaje de error del proceso a ejecutar
process33.StartInfo.RedirectStandardOutput = True 'esto es para decirle q vamos a escribir (o utiliar) el resultado de la secuencia (o sea el resultado encriptado)

process33.Start() 'iniciamos el proceso
process33.WaitForExit() 'le decimos q se espere el proceso

'AQUI LEEMOS EL RESULTADO DE BASE64
Dim objReader As New StreamReader(s.App_Path() & "b64.txt")
Dim sLine As String = ""
Dim arrText As New ArrayList()

sLine = objReader.ReadToEnd

'AQUI LE QUITAMOS LOS RETORNOS DE CARRO
For i As Integer = 0 To sLine.Length - 1
If sLine.Chars(i) <> Chr(10) Then
b64 = b64 & sLine.Chars(i)
End If
Next


LISTO, ESO ES TODO EL CODIGO, ESPERO PUEDAN AYUDARME, Y REPITO, SI NECESITAN CUALQUIER EXPLICACIÓN CON RESPECTO A MI CODIGO, PUEDEN PREGUNTAR CON CONFIANZA, QUEDO A SUS ORDENES Y COMENTARIOS... :) :D ;)
No se fracasa si existe un comienzo...
danielambda
 
Mensajes: 3
Registrado: Mié Nov 23, 2011 10:44 am

Re: MI SELLO ESTA MAL FORMADO...

Notapor cbr_net » Sab Dic 03, 2011 1:10 pm

Hola de nuevo,

Ok veo que tu codigo es bastante extenso, te recomendaria depurarlo un poco, veo algunas cosas que pudieran afectar el resultado de tu sello por ejemplo s.App_Path() ya que en lo personal he visto que en vb.net el App_path muchas veces varia o no se tiene acceso total, por consecuencia no encuentra estas rutas y no se genera el sello o bien se genera mal, en lo personal mi sistema hace lo siguiente:

1.- Valido la vigencia del certificado.
2.- Valido que la llave (.key) sea pareja del certificado, importantisimo por que de lo contrario nunca podras sellar correctamente (horas de trabajo :'( )
3.- Creo el XML "a mano" con los nodos requeridos (sin cadena de certificado y sin sello, solo para poder formar mi cadena original con el archivo xslt).
4.- En base al punto anterior obtengo mi cadena original.
5.- Aplico SHA1 "openssl.exe dgst -sha1 -sign " & RutaCFD & "llave.pem -out " & RutaCFD & "SelloBin.txt " & RutaCFD & "CO.txt"
6.- Transformo a base64 "openssl enc -base64 -in " & RutaCFD & "SelloBin.txt -out " & RutaCFD & "Sello.txt"
7.- Por ultimo a mi xml le agrego el sello y la cedena del certificado.

Como ves es algo muy similar a los que haces tu, lo que creo que esta fallando pueden ser tus rutas o bien la formacion de tu cadenao original, ya que en tu codigo no veo como la formas, pero si ocupas un ciclo (do, while, for, etc) no te lo recomiendo para nada, es mejor basarse en el estandar del xslt, por aquello del "error de dedo".

Si necesitas ayuda extra me puedes contactar por msn hoy estoy en la oficina hasta las 6:00 pm.

Saludos.
cbr_net
 
Mensajes: 101
Registrado: Mar Nov 23, 2010 3:08 pm
Ubicación: Puebla

MI SELLO ESTA MAL FORMADO...

Notapor danielambda » Dom Dic 04, 2011 10:30 pm

hola que tal, nuevamente gracias por responder, creo que ya se en donde podría estar mi error, lo que pasa es que mi sistema trabaja de manera distinta (tal vez ahi es donde esta el error) tu primero generas el archivo xml. y en base a ese generas tu cadena original, yo lo hago de manera contrario, genero mi cadena original, y después genero mi xml. Tal vez ahi es donde este mi problema, yo genero mi cadena original con los datos que tengo en mi windowsform, (PROGRAMO EN VB.NET) y lo voy concatenando, y despues genero mi xml con mis datos que también están en mi windows form, mira, te pongo la parte de mi codigo donde hago mi cadena original, y tambien te pongo mi codigo donde hago mi archivo xml.
'GENERAMOS LAS CADENA ORIGINAL CON ALGUNAS VARIABLES
'VOY A DECLARAR VARIABLES Y YA DESPUES LAS CONCATENO
'DECLARAMOS LAS VARABLES DEL ENCABEZADO
Dim version As String
Dim horafecha As String
Dim horafecha_2 As String
Dim tipo_transaccion As String
Dim forma_de_pago As String
Dim nombre_transaccion As String
Dim subtotal As String
Dim retenciones As String
Dim total As String

'DESPUES SIGUEN LOS DATOS DEL EMISOR PERO ESOS YA LOS TENEMOS EN LA BASE DE DATOS
'PERO A FUERZA NECESITAMOS CONCATENARLAS, ENTONCES LAS ASIGNAMOS A UNAS VARIABLES DE RESPALDO
Dim rfcER As String
Dim nombreER As String
Dim calleER As String
Dim noextER As String
Dim nointER As String
Dim coloniaER As String
Dim localidadER As String
Dim municipioER As String
Dim estadoER As String
Dim cpER As String
Dim paisER As String = "MÉXICO"

'AHORA LAS DEL RECEPTOR
Dim rfcR As String
Dim nombreR As String
Dim calleR As String
Dim noextR As String
Dim nointR As String
Dim coloniaR As String
Dim localidadR As String
Dim municipioR As String
Dim estadoR As String
Dim cpR As String
Dim paisr As String
'AHORA LOS DATOS DE LOS CONCEPTOS
Dim cantidad As String
Dim tipo As String
Dim descripcion As String
Dim precio_unitario As String
Dim total_prod As String
'AHORA LOS TRASLADOS
Dim concepto As String
Dim tasa As String
Dim total_impuesto As String

'YA TENIENDO TODOS LOS DATOS, AHORA PROCEDEMOS A GENERAR LA CADENA
'PRIMERO, LAS VARIABLES ESAS LES DAMOS VALOR (A LAS QUE LES HAGA FALTA)

Dim año As String = ""
Dim mes As String = ""
Dim dia As String = ""
Dim hora As String = ""
Dim minuto As String = ""
Dim segundo As String = ""
año = Format(Date.Now.Year, "00")
mes = Format(Date.Now.Month, "00")
dia = Format(Date.Now.Day, "00")
hora = Format(Date.Now.Hour, "00")
minuto = Format(Date.Now.Minute, "00")
segundo = Format(Date.Now.Second, "00")
horafecha_2 = año & "-" & mes & "-" & dia & "T" & hora & ":" & minuto & ":" & segundo

version = "|3.0"
horafecha = "|" & horafecha_2
tipo_transaccion = "|ingreso"
forma_de_pago = "|" & Me.ComboBox3.Text
If Me.CheckBox2.Checked = True Then
nombre_transaccion = "|Parcialidades"
Else
nombre_transaccion = "|Pago en una sola exhibición"
End If
subtotal = "|" & Format(CDbl(Me.txtsubtotal.Text), "0.0000")
Dim moneeeda As String
moneeeda = "|MXN"
retenciones = "|0.0000"
total = "|" & Format(CDbl(Me.txttotal.Text), "0.0000")
'LO CONCATENAMOS TODA ESTA PRIMERA PARTE EN UNA SOLA CADENA
Dim cadena_original_encabezado As String
cadena_original_encabezado = "|" & version & horafecha & tipo_transaccion & nombre_transaccion & subtotal & moneeeda & total
'HASTA AQUI YA TENEMOS EL ENCABEZADO LISTO PARA CONCATENAR
'AHORA GENERAMOS EL EMISIOR
rfcER = "|" & rfcE
nombreER = "|" & nombreE
calleER = "|" & calleE
noextER = "|" & noextE
coloniaER = "|" & coloniaE
municipioER = "|" & muicipioE
estadoER = "|" & estadoE
paisER = "|" & paisER
cpER = "|" & cpE
'GUARDAMOS TODO EN UNA SOLA CADENA
Dim cadena_original_emisior As String
cadena_original_emisior = rfcER & nombreER & calleER & noextER & nointER & coloniaER & localidadER & municipioER & estadoER & paisER & cpER & estadoER & paisER

'LISTO, AHORA EL RECEPTOR
rfcR = "|" & Me.txtRFC.Text
nombreR = "|" & Me.ComboBox2.Text
calleR = "|" & Me.txtDireccion.Text
noextR = "|" & Me.txtNumExt.Text
nointR = "|" & Me.txtnumInt.Text
coloniaR = "|" & Me.txtcolonia.Text
localidadR = "|" & Me.txtxLocalidad.Text
municipioR = "|" & Me.txtMunicipio.Text
estadoR = "|" & Me.txtLugar.Text
paisr = "|" & pais
cpR = "|" & Me.txtCP.Text
'LO GUARDAMOS EN UNA CADENA LO DEL RECEPTOR
Dim cadena_original_receptor As String
cadena_original_receptor = rfcR & nombreR & calleR & noextR & nointR & coloniaR & localidadR & municipioR & estadoR & paisr & cpR

'AHORA SOLO RESTAN LOS PRODUCTOS
Dim cadena_prod As String = ""
Dim zzzzZZZZ As Integer
For zzzzZZZZ = 0 To Me.GridVentas.RowCount - 1 Step 1
cantidad = "|" & Format(CDbl(Me.GridVentas.Item(3, zzzzZZZZ).Value), "0.0000")
tipo = "|" & Me.GridVentas.Item(4, zzzzZZZZ).Value
descripcion = "|" & Me.GridVentas.Item(1, zzzzZZZZ).Value
precio_unitario = "|" & Format(CDbl(Me.GridVentas.Item(5, zzzzZZZZ).Value), "0.0000")
total_prod = "|" & Format(CDbl(Me.GridVentas.Item(6, zzzzZZZZ).Value), "0.0000")
cadena_prod = cadena_prod & cantidad & descripcion & precio_unitario & total_prod
Next
'AHORA LO DE EL IMPUESTO, ESE ESTA FACILITO
concepto = "|IVA"
Dim tasaiva As Double
tasaiva = CDbl(ini.IniGet(s.App_Path() & "Config.ini", "IVA", "Clave1", ""))
tasaiva = tasaiva * 100
tasa = "|" & Format(tasaiva, "0.0000")
total_impuesto = "|" & Format(CDbl(Me.txtIVa.Text), "0.0000")
'LO CONCATENAMOS EN UNA SOLA CADENA DE IMPUESTOS
Dim cadena_original_impuesto As String
cadena_original_impuesto = concepto & tasa & total_impuesto & total_impuesto


'FIN TERMINAMOS TODO LO DE LOS DATOS NECESARIOS PARA LA CADENA ORIGINAL
'AHORA YA SOLO SE CONCATENA
cadena_original = cadena_original_encabezado & cadena_original_emisior & cadena_original_receptor & cadena_prod & cadena_original_impuesto & "||"
'QUITAMOS TODO LO QUE TENGA DOBLE ESPACIO: " " (doble espacio)
cadena_original = Replace(cadena_original, " ", " ")


'A continuacion guardaremos la cadena en un archivo con su formato UTF-8 como lo pide SAT -------------------------------------
System.IO.File.WriteAllText(s.App_Path() & "cadena.txt", cadena_original, System.Text.Encoding.UTF8)


'A continuacion GENERO EL XML.
Dim rz As String
rz = ini.IniGet(s.App_Path() & "Config.ini", "E-FACT", "Ruta", "")
Dim rut As String
If rz.Chars(rz.Length - 1) = "\" Then
rut = rz & "MiXML_Timbrado" & Me.txtFolio.Text & ".xml"
Else
rut = rz & "\MiXML_Timbrado" & Me.txtFolio.Text & ".xml"
End If
'ARMAMOS EL EQUIS EME ELE
Dim W As XmlTextWriter = New XmlTextWriter(rut, System.Text.Encoding.UTF8)
Dim xmldoc As New XmlDocument
W.Formatting = System.Xml.Formatting.Indented

Dim xmlString As String

W.WriteStartDocument()

W.WriteStartElement("cfdi:Comprobante")

W.WriteStartAttribute("xsi:schemaLocation")
W.WriteValue("http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv3.xsd")
W.WriteEndAttribute()

W.WriteStartAttribute("xmlns:xsi")
W.WriteValue("http://www.w3.org/2001/XMLSchema-instance")
W.WriteEndAttribute()

W.WriteStartAttribute("xmlns:cfdi")
W.WriteValue("http://www.sat.gob.mx/cfd/3")
W.WriteEndAttribute()



W.WriteStartAttribute("version")
W.WriteValue("3.0")
W.WriteEndAttribute()

W.WriteStartAttribute("serie") ' opcional
W.WriteValue("E123456789")
W.WriteEndAttribute()

W.WriteStartAttribute("folio")
W.WriteValue(Me.txtFolio.Text)
W.WriteEndAttribute()

W.WriteStartAttribute("fecha")
W.WriteValue(horafecha_2)
W.WriteEndAttribute()

W.WriteStartAttribute("sello")
W.WriteValue(b64)
W.WriteEndAttribute()

W.WriteStartAttribute("formaDePago")
'Aqui esta lo de el tipo de pago (ya sabes cabron lo del chetsbots)
W.WriteValue(Mid(nombre_transaccion, 2))
W.WriteEndAttribute()

W.WriteStartAttribute("noCertificado")
W.WriteValue(NoCertificadoR)
W.WriteEndAttribute()

W.WriteStartAttribute("certificado")
W.WriteValue(certificadoE)
W.WriteEndAttribute()

W.WriteStartAttribute("subTotal")
W.WriteValue(Format(CDbl(Me.txtsubtotal.Text), "0.0000"))
W.WriteEndAttribute()

W.WriteStartAttribute("Moneda")
W.WriteValue("MXN")
W.WriteEndAttribute()

W.WriteStartAttribute("total")
W.WriteValue(Format(CDbl(Me.txttotal.Text), "0.0000"))
W.WriteEndAttribute()

W.WriteStartAttribute("metodoDePago")
W.WriteValue(Me.ComboBox3.Text) 'DEL COMBO SELECCIONO LA TRANSACCION
W.WriteEndAttribute()

W.WriteStartAttribute("tipoDeComprobante")
W.WriteValue("ingreso") 'ingreso o egreso
W.WriteEndAttribute()

'nodo emisor......................................................

W.WriteStartElement("cfdi:Emisor")

W.WriteStartAttribute("rfc")
W.WriteValue(rfcE)
W.WriteEndAttribute()

W.WriteStartAttribute("nombre")
W.WriteValue(nombreE)
W.WriteEndAttribute()

'subnodo Direccion emisor

W.WriteStartElement("cfdi:DomicilioFiscal")

W.WriteStartAttribute("calle")
W.WriteValue(calleE)
W.WriteEndAttribute()

W.WriteStartAttribute("noExterior")
W.WriteValue(noextE)
W.WriteEndAttribute()

W.WriteStartAttribute("colonia")
W.WriteValue(coloniaE)
W.WriteEndAttribute()

W.WriteStartAttribute("municipio")
W.WriteValue(muicipioE)
W.WriteEndAttribute()

W.WriteStartAttribute("estado")
W.WriteValue(estadoE)
W.WriteEndAttribute()

W.WriteStartAttribute("pais")
W.WriteValue(Mid(paisER, 2))
W.WriteEndAttribute()

W.WriteStartAttribute("codigoPostal")
W.WriteValue(cpE)
W.WriteEndAttribute()

W.WriteEndElement() 'finaliza direccion

'subnodo ExpedidoEn

W.WriteStartElement("cfdi:ExpedidoEn")

W.WriteStartAttribute("estado")
W.WriteValue(estadoE)
W.WriteEndAttribute()

W.WriteStartAttribute("pais")
W.WriteValue(Mid(paisER, 2))
W.WriteEndAttribute()

W.WriteEndElement() 'finaliza expedido en

W.WriteEndElement() 'finaliza emisor

'nodo receptor....................................................

W.WriteStartElement("cfdi:Receptor")

W.WriteStartAttribute("rfc")
W.WriteValue(Me.txtRFC.Text)
W.WriteEndAttribute()

W.WriteStartAttribute("nombre")
W.WriteValue(Me.ComboBox2.Text)
W.WriteEndAttribute()

'subnodo direccion receptor

W.WriteStartElement("cfdi:Domicilio")

W.WriteStartAttribute("calle")
W.WriteValue(Me.txtDireccion.Text)
W.WriteEndAttribute()

W.WriteStartAttribute("noExterior")
W.WriteValue(Me.txtNumExt.Text)
W.WriteEndAttribute()

W.WriteStartAttribute("noInterior")
W.WriteValue(Me.txtnumInt.Text)
W.WriteEndAttribute()

W.WriteStartAttribute("colonia")
W.WriteValue(Me.txtcolonia.Text)
W.WriteEndAttribute()

W.WriteStartAttribute("localidad")
W.WriteValue(Me.txtxLocalidad.Text)
W.WriteEndAttribute()

W.WriteStartAttribute("municipio")
W.WriteValue(Me.txtMunicipio.Text)
W.WriteEndAttribute()

W.WriteStartAttribute("estado")
W.WriteValue(Me.txtLugar.Text)
W.WriteEndAttribute()

W.WriteStartAttribute("pais")
W.WriteValue(pais)
W.WriteEndAttribute()

W.WriteStartAttribute("codigoPostal")
W.WriteValue(Me.txtCP.Text)
W.WriteEndAttribute()

W.WriteEndElement() 'finaliza direccion receptor
W.WriteEndElement() 'finaliza receptor

'nodo CONCEPTOS....................................................

W.WriteStartElement("cfdi:Conceptos")

'Esto debe de ir en un Ciclo For o while...
'subNodo del la descripcion de los conceptos
For jj As Integer = 0 To Me.GridVentas.RowCount - 1
W.WriteStartElement("cfdi:Concepto")
W.WriteStartAttribute("cantidad") 'Cantidad
W.WriteValue(Format(CDbl(Me.GridVentas.Item(3, jj).Value), "0.0000"))
W.WriteEndAttribute()
W.WriteStartAttribute("descripcion") 'Descripcion
W.WriteValue(Me.GridVentas.Item(1, jj).Value)
W.WriteEndAttribute()
W.WriteStartAttribute("valorUnitario") 'ValorUnitario
W.WriteValue(Format(CDbl(Me.GridVentas.Item(5, jj).Value), "0.0000"))
W.WriteEndAttribute()
W.WriteStartAttribute("importe") 'importe
W.WriteValue(Format(CDbl(Me.GridVentas.Item(6, jj).Value), "0.0000"))
W.WriteEndAttribute()

W.WriteEndElement() 'finaliza elemento conceptos este va antes de terminar el ciclo for o while
Next

W.WriteEndElement() 'finaliza elemento conceptos (padre) este va fuera del ciclo for o while
'nodo IMPUESTOS....................................................

W.WriteStartElement("cfdi:Impuestos")

W.WriteStartAttribute("totalImpuestosTrasladados") 'totalImpuestosTrasladados
W.WriteValue(Format(CDbl(Me.txtIVa.Text), "0.0000"))
W.WriteEndAttribute()

W.WriteStartElement("cfdi:Traslados") 'Nodo Traslados
W.WriteStartElement("cfdi:Traslado") 'Nodo Traslado
W.WriteStartAttribute("impuesto") 'totalImpuestosTrasladados
W.WriteValue("IVA")
W.WriteEndAttribute()
W.WriteStartAttribute("tasa") 'taza
W.WriteValue(Format(tasaiva, "0.0000"))
W.WriteEndAttribute()
W.WriteStartAttribute("importe") 'totalImpuestosTrasladados
W.WriteValue(Format(CDbl(Me.txtIVa.Text), "0.0000"))
W.WriteEndAttribute()
W.WriteEndElement() 'finaliza elemento Transaldo
W.WriteEndElement() 'finaliza elemento Translados

W.WriteEndElement() 'finaliza elemento IMPUESTOS

'nodo COMPLEMENTO....................................................
W.WriteStartElement("cfdi:Complemento")

W.WriteEndElement() 'finaliza elemento comeplemento

W.WriteEndElement() 'finaliza comprobante
W.WriteEndDocument() 'finaliza documento


W.Flush()
W.Close()



entonces asi es como yo genero mis "cosas" mmm pero me gustaria saber como es que tu lo haces, me refiero a esa parte en la que utilizas el xslt. (la verdad es que esa parte no la comprendi) de antemano muchas muchas gracias..
NOTA: CON RESPECTO A LO DE s.App_Path() es un metodo que utilizo pero que bien traducido seria exactamente q eso
Public Function App_Path() As String
Return System.AppDomain.CurrentDomain.BaseDirectory()
End Function

esta funcion esta en una clase en la que estan todos mis metodos que utilizo
No se fracasa si existe un comienzo...
danielambda
 
Mensajes: 3
Registrado: Mié Nov 23, 2011 10:44 am

Re: MI SELLO ESTA MAL FORMADO...

Notapor cbr_net » Mié Dic 07, 2011 3:33 am

Ok, mira primero tienes que comprender que es un XSLT, te dejo una liga aqui: http://msdn.microsoft.com/es-es/library ... 0(v=sql.90).aspx

Depende de que lenjuage ocupes sera tu sintaxis.

Como te mencionaba si tu generacion de cadena original esta mal (que puedo apostar a que es eso) tu sello no se validara correctamente, te recomiendo implantes el metodo de creacion de tu CO desde el xslt, cualquier validador se basa en este estandar.

Saludos.
cbr_net
 
Mensajes: 101
Registrado: Mar Nov 23, 2010 3:08 pm
Ubicación: Puebla


Volver a Visual Basic

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado