Proceso de autenticación automática contra el SII
Recuerdo cuando comencé con mis desarrollos orientados a la facturación electrónica en Chile, que la experiencia que existía al respecto tenía sus bases en desarrollos efectuados en JAVA a los cuales debíamos ceñirnos para poder crear los nuestros. Esto significaba que o nos cambiábamos a plataformas JAVA o nos dábamos el trabajo de implementar las rutinas en lenguajes como VB 6.0.
De esta experiencia recuerdo varios dolores de cabeza e interminables horas de pruebas de firmas y envío. Gracias a la evolución de los lenguajes de desarrollo de Microsoft como en este caso C#, se ha podido simplificar mucho mas tales procesos. Sin embargo una cosa es saber cómo construir una clase orientada a la Facturación electrónica y otra muy distinta es como diseñar una aplicación que nos permita generar el flujo de la misma. Por esta razón escribo este blog, pues quisiera compartir algunos tips del proceso para que aquellos que inician en esto, pueda extraer algo de mi conocimiento del tema.
Bueno les dejo entonces algunas anotaciones separadas por conceptos, espero les sirvan y me puedan aportar algún comentario.
De esta experiencia recuerdo varios dolores de cabeza e interminables horas de pruebas de firmas y envío. Gracias a la evolución de los lenguajes de desarrollo de Microsoft como en este caso C#, se ha podido simplificar mucho mas tales procesos. Sin embargo una cosa es saber cómo construir una clase orientada a la Facturación electrónica y otra muy distinta es como diseñar una aplicación que nos permita generar el flujo de la misma. Por esta razón escribo este blog, pues quisiera compartir algunos tips del proceso para que aquellos que inician en esto, pueda extraer algo de mi conocimiento del tema.
Bueno les dejo entonces algunas anotaciones separadas por conceptos, espero les sirvan y me puedan aportar algún comentario.
MODULO I: Como autenticarse contra el SII de forma automática.
- Crear clase Proxy para conectarse al SIIDescribe como confeccionar la clase proxy de .Net para realizar la conección al SII, describe la función de la semilla entregada por este origenismo y como utilizarla para realizar la autenticación contra el SII.
-
Cómo obtener semilla del SII desde la clase proxy.
Describe cómo recuperar la semilla del SII utilizando la clase generada en .Net (proxy). - Cómo firmar la semilla del SIIIndica una vez obtenida la semilla cómo construir el documento xml para ser firmado y posteriormente enviado al SII. Muestra las posibles respuestas desde el SII indicando el estado de la autenticación del usuario actual.
- Cómo Recuperar el token del SII
Indica como recuperar el token del SII utlilizando la semilla firmada
Marcelo, estoy tratando de comenzar con el tema de la factura electronica, he estado programando en visual basic 6.0 y quisiera crear un archivo de texto con la factura generada en ese lenguaje y desde ahi programar la factura electronica desde visual basic .net 2010 (Lenguaje VB), que es lo primero que debo aprender ?, puedo realizar pruebas sin necesidad de estar etapa de certificación ?.. la idea primero es dominar todas las herramientas necesarias y luego comenzar a programar el módulo.
ResponderEliminarde antemano muchas gracias
Saludos
Que tal Marcelo.
ResponderEliminarSoy yo de nuevo, Oliver;D.
Ocurre que voy a poner manos la obra a fin de lograr autenticar contra el SII usando sus WS y Java como lenguaje. Ya baje toda la informacion y estoy usando como cliente de pruebas SOAPUI con el cual ya me conecto y obtengo la semilla.
Mi consulta es si conoces alguna herramienta que me permita firmar la semilla "al vuelo" y luego enviar el xml de entrada al SII posteriormente con https://palena.sii.cl/DTEWS/GetTokenFromSeed.jws?WSDL
Lo que pretendo es evitar picar codigo hasta no estar seguro de que entendi el flujo. Por favor dame tu opinion, respecto si es posible mi idea o debere comenzar a generar las clases para una prueba programatica.
Muchas gracias por tu ayuda!
Oliver
Oliver,
EliminarLamentablemente no conozco ningan app que te permita realizar esto que me dices on the fly. La verdad es que el sistema esta pensado para que apliques el algoritomo de forma tal que demuestres al SII que conoces el metodo para firmar y autenticarte correctamente. Ahora bien yo no estoy muy familiarizado con JAVA, asi que es perfectamente posible que me equivoque. De todas formas el codigo de autenticación en C# puede ayudarte al momento de crear tu app.
Atte,
Marcelo Rojas R.
Grupo Desarrollo Hefesto.Fe
Hola Oliver, encontraste alguna solución para firmar la semilla?
EliminarAnaligia,
EliminarPuedes llamarme para que veamos como solucinar tu problema con la semilla.
Atte.
Marcelo Rojas Rojas
997800285
Estimado Marcelo:
ResponderEliminarNada más que reiterar mis agradecimientos por tu excelente blog e invaluable ayuda. Como te comente telefónicamente acá en provincia (Los Ángeles, Octava Región), loa información no es muy aclaratoria que digamos a eso sumar lo difícil de encontrar a alguien que te guié. Por lo cual tu blog ha sidi de infinita utilidad en este proceso.
Saludos cordiales,
Víctor Rivera
Estimado Marcelo, te agradezco por compartir tus conocimientos con los demas, eso es algo de la vieja escuela que ya no suele verse, te hago una consulta :
ResponderEliminarSolo pueden hacer pruebas quienes esten con una empresa en periodo de certificacion, o cualquiera puede hacer pruebas de envio y consulta de DTEs?
Gracias y saludos.
Marcelo. Tengo una pregunta que demuestra que estoy recién empezando con esto y que ando un poco perdido. Disculpa entonces si es muy básica y gracias de antemano. (Por cierto, esta pregunta la hice en el SII y me respondieron "vea la documentación").
ResponderEliminarSuponiendo que ya pude consumir los web services semilla-token,¿qué hago ahora con el token? ¿Tengo que pasarlo a los dte en algún punto?
Si voy a generar 20 facturas en el día, ¿tengo que ir cada vez a autenticarme y por lo tanto "añado" un token diferente a cada dte? ¿O voy una sola vez y "añado" el mismo token a todos los dte? ¿O uso el mismo token para todos los dte que envíe en sus 2 minutos de validez? ¿Dónde va esa información en el envío? (Estoy usando el verbo "añadir", pero creo que no voy por buen camino).
Te reitero los agradecimientos, la verdad es que va siendo más fácil seguir tu blog que ver los documentos del SII.
Estimado Colega
EliminarRespondiendo a tu pregunta, cuando tengas el token puedes utilizarlo para enviar uno o varios DTEs. Recuerda en todo caso que el envio tiene un limite de DTEs (2000). Puedes en todo caso pedir un token por cada uno de los DTEs.
El token va en el formato rfc que te permite hacer un upload automatico al SII.
Si necesitas mas ayuda escribeme a Abaddon.1974@gmail.com
Atte.
Marcelo Rojas Rojas
Ah, en el RFC. Yo pensé que iba en un campo del xml. Muchas gracias, te pasaste.
ResponderEliminardispongo de clase de conexion a SII hecha en VB.net 2010 en base a lo expuesto en este blog.....quien la desee se contacta por este medio.
ResponderEliminarHola Nelson,
EliminarMe gustaria que me compartieras la clase para poder guiarme, ya que encuentro este tema muy complicado aun. Estoy desarrollando en Java, pero puedo entender la sintaxis de visual. Gracias de antemano.
Saludos, un abrazo.
Hola Nelson
Eliminarsoy nuevo en esto de la factura electronica, hay muy poca informacion y cada vez me confundo mas , quiero hacer algo en vb6 o vb.net , me gustaria si me puedes compartir la clase de conexion para empezar por algo
saludos
Estimado,
EliminarEn la página http://lenguajedemaquinas.blogspot.cl/2013/02/conectarse-automaticamente-al-sii.html
En Crear archivo proxy encontrarás el link para bajar las clases de conexion al SII
Atte.
Marcelo Rojas Rojas
clase conexion al sii. 1 de 4
Eliminar'Clase de autentificación ante SII en VB.net (2010) por Nelson Agurto Pavez.(nelsonagurtop@gmail.com)
'liberado para su uso citando al autor y desarrollado en base a código en C# de Marcelo Rojas.
'Luego de crear y poner nombre a la solución se deben agregar las referencias a los servicios web que se necesitaran
' estos son para pedir la semilla y el otro para pedir el token
' para eso deben irse a menu-->Proyecto-->Agregar Referencias de Servicio...
'les aparece una ventana, pinchan en boton "Avanzadas..." (abajo a la izquierda) y luego en la ventana siguiente en
'click en boton "Agregar referencia web...", en la nueva ventana deben insertar la URL del WebServer (WS) para pedir la semilla, y luego click en el boton
'verde de ir que esta al costado.....con eso se conectaran al WS, deben desactivar el antivirus o firewall para ello, si aún les dice que
'hay problemas de seguridad, deben darle autorización manual cuando se los pida.
'Finalmente deben darle nombre a la referencia ..en este caso le puese SemillaSii y boton "Agregar Referencia"
'Lo mismo para pedir el token, deben crear su referencia web con los pasos de arriba solo cambiando la URL del WS
'Nota, si estan probando la aplicación y aparece un msgbox que dice que no se pudo conectar al servidor Nogal....
'deben editar el archivo wsl que crea la referencia web (estan en la ventana de Explorador de soluciones) y cambiar a mano donde diga nogal por maullin.... (me quebre dos hrs. la cabeza con ese error)
'tb editen el archivo App.config, tb cambien nogal por maullin
Imports System
Imports System.Xml
Imports System.Security
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates
clase conexion al sii. 2 de 4
EliminarPublic Function PidoSemillaToken() As String
'inicio pidiendo semilla
Try
RespuestaSemilla = pidosemilla.getSeed()
SemillaXml.LoadXml(RespuestaSemilla)
NodoSemilla = SemillaXml.SelectSingleNode("//SEMILLA")
NodoEstadoSemilla = SemillaXml.SelectSingleNode("//ESTADO")
'saco valor semilla del xml
Dim Semilla = NodoSemilla.ChildNodes.Item(0).InnerText
'saco valor estado semilla del xml
Dim EstadoSemilla = NodoEstadoSemilla.ChildNodes.Item(0).InnerText
'control de errores de semilla
If RespuestaSemilla = "" Then
MsgBox("Problemas al extraer semilla desde SII !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf Semilla = "" Then
MsgBox("Problemas al extraer semilla desde SII !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoSemilla = "-1" Then
MsgBox("No se registro línea en el Archivo de Configuración !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoSemilla = "-2" Then
MsgBox("ERROR de RETORNO, NO PUEDE CREAR SEMILLA!!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoSemilla = "00" Then
'MsgBox("Semilla Obtenida, firmo y pido Token!!", MsgBoxStyle.Exclamation)
' Exit Sub
End If
'FirmarSemilla
Semi_Firmada = FirmarSemilla(Semilla, cn) 'voy a funcion firmarsemilla con dos parametros, valor semilla y nombre de certificado
'region Recuperar TOKEN
'Suponiendo que el objeto XmlDocument ( XMLDOM ) contenga la semilla firmada, esta debería ser la forma de recuperar
'el valor string.
SemillaFirmada.LoadXml(Semi_Firmada) 'convierto el string de semilla firmada en un documento xml
Firmada = SemillaFirmada.OuterXml ' extraigo solo los valores string para pasar al metodo getToken
RespuestaToken = pidotoken.getToken(Firmada) ' pido el token y paso su parametro, que es la semilla firmada
TokenXml.LoadXml(RespuestaToken)
NodoToken = TokenXml.SelectSingleNode("//TOKEN")
NodoEstadoToken = TokenXml.SelectSingleNode("//ESTADO")
NodoGlosaToken = TokenXml.SelectSingleNode("//GLOSA")
'saco valor token del xml
Dim Token = NodoToken.ChildNodes.Item(0).InnerText
'saco valor estado token del xml
Dim EstadoToken = NodoEstadoToken.ChildNodes.Item(0).InnerText
'saco valor glosa token del xml
Dim GlosaToken = NodoGlosaToken.ChildNodes.Item(0).InnerText
continuacion funcion pidosemillatoken()
Eliminar'control de errores de Token
If EstadoToken = "01" Then
MsgBox("XML Inválido (IOException), función valSignedXml !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "02" Then
MsgBox("XML Inválido (SAXException), función valSignedXml !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "03" Then
MsgBox("XML Inválido (ParserConfigurationException), función valSignedXml !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "04" Then
MsgBox("XML Inválido, elemento Signature no existe, función valSignedXml !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "05" Then
MsgBox("XML Inválido, firma invalida, función valSignedXml !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "06" Then
MsgBox("XML Inválido, elemento Semilla no existe, función getSeed !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "07" Then
MsgBox("ERROR (MessageException). !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "08" Then
MsgBox("PARAMETROS INCORRECTOS,TIME-OUT DEL SEED, NO GENERA TOKEN func:CreaToken, NO PUEDO ACT. SEED CON TOKEN, TIME-OUT del SEED, NO Existe SEED !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "09" Then
MsgBox("ERROR (MessageException). !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "10" Then
MsgBox("ERROR RETORNO DATOS, NO PUEDO CREAR O ACT. TOKEN !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "11" Then
MsgBox("XML Inválido, elemento Certificado no existe, función getCertificado !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "12" Then
MsgBox("ERROR (12) (MessageException) !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "21" Then
MsgBox("Firma invalida( La llave pública no coincide con la del certificado). !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "-3" Then
MsgBox("Error en Autenticación !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "-7" Then
MsgBox("Error (12) parse ERROR en Validación del RUT (verificar que el usuario se encuentre registrado en el SII con la opción de autenticación mediante Certificado Digital !!", MsgBoxStyle.Critical)
Return Nothing
Exit Function
ElseIf EstadoToken = "00" Then
MsgBox("Token Obtenido, conexión establecida !!", MsgBoxStyle.Exclamation)
' ' con eso ya estamos autenticados en el portal del SII.
End If
Return Token
Catch ex As Exception
MsgBox(ex.ToString())
Return Nothing 'Exit Function
End Try
End Function
funcion firmarsemilla()
Eliminar'Firmo la semilla para poder validarla en el SII
Public Function FirmarSemilla(ByVal seed As String, ByVal cn As String) As String
'Construyo el cuerpo del documento en formato string.
Dim cert As Certificado = New Certificado()
Dim resultado As String = Nothing
Dim body As String
' Firmo la semilla.
Try
body = "" 'blanqueo para asegurar el string desde cero
'saco los ceros iniciales a la semilla
body = Format("{0}", Double.Parse(seed).ToString())
'esta linea no esta en el codigo de Marcelo Rojas hecha en c# sin ella no funciona la autentificación con vb.net
body = "" & body & ""
resultado = FirmarDocumentoSemilla(body, cert.ObtenerCertificado(cn))
Return resultado
Catch ex As Exception
MsgBox(ex.ToString())
resultado = Nothing
Return resultado
End Try
End Function
Este comentario ha sido eliminado por el autor.
Eliminar'Firmar el documento xml semilla
EliminarPublic Function FirmarDocumentoSemilla(ByVal documento As String, ByVal certificado As X509Certificate2) As String
Dim bResult As Boolean = False
Dim pCertContext As IntPtr = IntPtr.Zero
Dim key As RSA = Nothing
Dim doc As XmlDocument = Nothing
Dim signedXml As SignedXml = Nothing
Dim reference As Reference = Nothing
Dim trns As XmlDsigC14NTransform = Nothing
Dim env As XmlDsigEnvelopedSignatureTransform = Nothing
Dim keyInfo As KeyInfo = Nothing
Dim xmlDigitalSignature As XmlElement = Nothing
Dim cert As X509Certificate2 = Nothing
Dim pass As SecureString = Nothing
Dim XMLSignature As Signature
Try
' Creo un nuevo documento xml y defino sus caracteristicas
doc = New XmlDocument
doc.PreserveWhitespace = False
'MsgBox(documento)
doc.LoadXml(documento)
'Creo el objeto XMLSignature.
signedXml = New SignedXml(doc)
'Agrego la clave privada al objeto xmlSignature.
signedXml.SigningKey = certificado.PrivateKey
'Obtengo el objeto signature desde el objeto SignedXml.
XMLSignature = signedXml.Signature
'Creo una referencia al documento que va a firmarse 'si la referencia es "" se firmara todo el documento
reference = New Reference
reference.Uri = ""
' Add an enveloped transformation to the reference.
env = New XmlDsigEnvelopedSignatureTransform
reference.AddTransform(env)
'Agrego el objeto referenciado al objeto firma.
signedXml.AddReference(reference)
'Agregue RSAKeyValue KeyInfo ( requerido para el SII ).
keyInfo = New KeyInfo
keyInfo.AddClause(New RSAKeyValue(certificado.PrivateKey))
'Agregar información del certificado x509
keyInfo.AddClause(New KeyInfoX509Data(certificado))
'Agregar KeyInfo al objeto Signature
XMLSignature.KeyInfo = keyInfo
'Creo la firma
signedXml.ComputeSignature()
' Recupero la representacion xml de la firma
xmlDigitalSignature = signedXml.GetXml()
'Agrego la representacion xml de la firma al documento xml
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))
'Limpio el documento xml de la declaracion xml ( Opcional, pero para nuestro proceso es valido )
If TypeOf doc.FirstChild Is XmlDeclaration Then
doc.RemoveChild(doc.FirstChild)
End If
Return doc.InnerXml
Catch e As CryptographicException
MsgBox(e.Source & ". " & e.Message)
Return Nothing
End Try
End Function
ultimo. comienzo de la clase conexión....ojo con el cierre de la clase, debe ir despues de la funcion firmardocumentosemilla()
EliminarPublic Class ConexionSII
Const cn = "Nelson Enrique Agurto Pavez" 'nombre del certificado a usar-------> se saca del repositorio de certificados instalados en el pc
Dim RespuestaSemilla, RespuestaToken, Semi_Firmada, Firmada, Semilla, EstadoSemilla, Token, EstadoToken, GlosaToken As String
Dim SemillaXml As XmlDocument = New XmlDocument()
Dim TokenXml As XmlDocument = New XmlDocument()
Dim SemillaFirmada As XmlDocument = New XmlDocument()
Dim NodoSemilla, NodoEstadoSemilla, NodoToken, NodoEstadoToken, NodoGlosaToken As XmlNode
Dim pidosemilla As New SemillaSii.CrSeedService()
Dim pidotoken As New TokenSii.GetTokenFromSeedService()
Estimado Marcelo,
ResponderEliminarTe quiero agradecer por toda la información y tu experiencia que nos compartes a todos quienes visitamos tu blog. Gracias a ello estoy entendiendo un poco mas de este complejo sistema de facturación electronica. Estoy recién empezando con este tema, pero con tu blog entiendo mucho mejor los conceptos luego de leer la documentación del SII.
Saludos y Feliz año nuevo.
Estimado, Marcelo agradecido por tu ayuda con el tema de la facturación electronica la cual es muy dificil encontrar información de como empezar a desarrollar dicha aplicación, y sobre todo en .net.
ResponderEliminarEstimado, Nelson agradecido por los ejemplos mencionados anteriormente la cual nos provee de unas rutinas para poder empezar.
ResponderEliminarde antemano muchas gracias a todos por compartir sus conocimiento y la experiencia que han adquirido y tener la paciencia para poder publicarlos y poder enseñar a los que comenzamos en el tema de la facturación electronica.
Hola tu me podrias ayudar con mi proyecto de Facturacion electronica
ResponderEliminarhola, hemos desaarrollado un sistema de facuracion electronica en java, ha funcionado bastante bien, el problema lo tenemos cuando nos autenticamos en el SII, cada vez que el SII cambia su certificado no
ResponderEliminarpodemos obtener token, debemos recuperar el certificado del sii, actualizarlo de manera local en las librerias de java y podemos operar, esto nos pasa una vez a año. de que otra manera me puedo autenticar con java con el sii, para evitar este problema, gracias
Estimado Ernesto
EliminarMe gustaria charlar contigo acerca de este tema favor llamamrme al 224042279
Marcelo Rojas Rojas