Buscar en este blog

jueves, 28 de febrero de 2013

Autenticación Automática contra el SII


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.

MODULO I: Como autenticarse contra el SII de forma automática.




27 comentarios:

  1. 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.

    de antemano muchas gracias

    Saludos

    ResponderEliminar
  2. Que tal Marcelo.
    Soy 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


    ResponderEliminar
    Respuestas
    1. Oliver,

      Lamentablemente 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

      Eliminar
    2. Hola Oliver, encontraste alguna solución para firmar la semilla?

      Eliminar
    3. Analigia,

      Puedes llamarme para que veamos como solucinar tu problema con la semilla.

      Atte.
      Marcelo Rojas Rojas
      997800285

      Eliminar
  3. Estimado Marcelo:

    Nada 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

    ResponderEliminar
  4. 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 :
    Solo 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.

    ResponderEliminar
  5. 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").

    Suponiendo 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.

    ResponderEliminar
    Respuestas
    1. Estimado Colega

      Respondiendo 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

      Eliminar
  6. Ah, en el RFC. Yo pensé que iba en un campo del xml. Muchas gracias, te pasaste.

    ResponderEliminar
  7. dispongo 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.

    ResponderEliminar
    Respuestas
    1. Hola Nelson,

      Me 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.

      Eliminar
    2. Hola Nelson
      soy 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

      Eliminar
    3. Estimado,

      En 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

      Eliminar
    4. clase conexion al sii. 1 de 4
      '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

      Eliminar
    5. clase conexion al sii. 2 de 4
      Public 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

      Eliminar
    6. continuacion funcion pidosemillatoken()
      '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

      Eliminar
    7. funcion firmarsemilla()
      '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

      Eliminar
    8. Este comentario ha sido eliminado por el autor.

      Eliminar
    9. 'Firmar el documento xml semilla
      Public 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

      Eliminar
    10. ultimo. comienzo de la clase conexión....ojo con el cierre de la clase, debe ir despues de la funcion firmardocumentosemilla()
      Public 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()

      Eliminar
  8. Estimado Marcelo,

    Te 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.

    ResponderEliminar
  9. 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.

    ResponderEliminar
  10. Estimado, Nelson agradecido por los ejemplos mencionados anteriormente la cual nos provee de unas rutinas para poder empezar.
    de 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.

    ResponderEliminar
  11. Hola tu me podrias ayudar con mi proyecto de Facturacion electronica

    ResponderEliminar
  12. hola, 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
    podemos 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

    ResponderEliminar
    Respuestas
    1. Estimado Ernesto

      Me gustaria charlar contigo acerca de este tema favor llamamrme al 224042279

      Marcelo Rojas Rojas

      Eliminar