Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Envío de registros y sus respuestas (https://www.clubdelphi.com/foros/forumdisplay.php?f=66)
-   -   Funcion verificacion registros de alta C# (https://www.clubdelphi.com/foros/showthread.php?t=97431)

bmfranky 25-04-2025 14:14:58

Funcion verificacion registros de alta C#
 
1 Archivos Adjunto(s)
Hola, he creado una funcion que consulta los registros de facturacion, antes de enviarlos a la AEAT, devuelve cualquier error que haya en ellos.
Esoy haciendo uso del servicio creado para verificar los no verificables antes de almacenarlos que han abilitado la AEAT, aqui la descripcion.
Hay que importar la clase que define la respuesta del registro, simplemente eliminando la extension .txt
Código:

      /// <summary>
        /// checa la estructura del registro de alta
        /// </summary>
        /// <param name="alta"> Es el registro a comprobar , usa tambien  Program.certificado, Program.passcertificado Son el certificado y su pasword para realizar el envio</param>
        /// <param name="vervose"> por defecto true, muestra inmediatamente el mensaje de error en un message box </param>
        /// <returns>Devuelve true si ha ocurrido un error, tambien devuelve en un string Program.RespuestaServidor la respuesta formateada y en Program.devuelto un objeto RespuestaValContenidoFactuSistemaFacturacionType.</returns>
        public bool checaRegistro(RegistroFacturaType alta)
        {
            //Primero deserializamos el registro de facturacion.
            string facXml = "";
            try
            {
                XmlSerializer serializaFactura = new XmlSerializer(typeof(RegistroFacturaType));
                using (var xmlw = new StringWriter())
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Indent = true;
                    settings.Encoding = Encoding.UTF8;
                    using (XmlWriter writter = XmlWriter.Create(xmlw, settings))
                    {
                        serializaFactura.Serialize(writter, alta);
                        facXml = xmlw.ToString();
                    }

                }
            }
            catch
            { return true; }//fallamos al deserializar}
            //Eliminamos lo no necesario, solo debemos enviar el registro de alta.
            facXml = facXml.Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
            facXml = facXml.Replace("<RegistroFacturaType xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">", "");//Eliminamos la seccion
            facXml = facXml.Replace("</RegistroFacturaType>", "");
            //Creamos el XML Document Necesario para el envio asignandole el registro a enviar.
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(facXml.Replace("utf-16", "utf-8"));
            string responseFromServer;
            //Intentamos enviar a la web
            try
            {
                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://prewww1.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/ValRegistroNoVerifactu");//Asignamos la direccion de validacion           
                webRequest.ContentType = "text/xml;charset=\"utf-8\"";
                webRequest.Accept = "text/xml";
                webRequest.Method = "POST";
                //Cargamos el certificado para identificarnos en la aeat, verificando si es valido o esta caducado.
                X509Certificate2 certificate = new X509Certificate2(Program.certificado, Program.passcertificado); //requiere estas variables globales que contienen el certificado y su clave
                var tiempo = certificate.SubjectName;
                //Verificamos que no este anulado o erroneo.
                if (certificate == null)
                    throw new ArgumentNullException(
                        "El Certificado es Nulo. O el numero de serie en la configuracion es erroneo.");
                //verificamos que no este caducado.
                if (certificate.NotAfter < DateTime.Now)
                    throw new ArgumentNullException(
                      $"El Certificado esta caducado. NotAfter: {certificate.NotAfter}.");
                //Asignamos el Certificado.
                webRequest.ClientCertificates.Add(certificate);
                //Abrimos un stream a la direccion, para enviar el documento.
                using (Stream stream = webRequest.GetRequestStream())
                {
                    doc.Save(stream);
                }
                //Escuchamos la respuesta del servidor.
                HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
                string statusDescription = response.StatusDescription;
                //leemos la respuesta a un stream
                Stream dataStream = response.GetResponseStream();
                using (StreamReader reader = new StreamReader(dataStream))
                {
                    responseFromServer = reader.ReadToEnd();
                    reader.Close();
                    dataStream.Close();
                    response.Close();
                }
            }
            catch(Exception ex1) { return true; }// Fallo la conexion por algun motivo
            //Personalmente me gusta en formato indentado ai que lo modifico.
            XDocument Xdoc = XDocument.Parse(responseFromServer);
            Program.RespuestaServidor = Xdoc.ToString();// variable global en la que cargo la respuesta formateada para mostrar al usuario.
            //Finalmente intentamos crear el registro con el XML devuelto.
            XmlSerializer SerializaFactura = new XmlSerializer(typeof(RespuestaValContenidoFactuSistemaFacturacionType));
            try
            {
                //usamos un string reader para cargar la respuesta de internet
                using (var xmlw1 = new StringReader(responseFromServer))
                {
                    //  Sertializamos
                    using (XmlReader reader = XmlReader.Create(xmlw1))
                    {
                        Program.devuelto = SerializaFactura.Deserialize(reader) as RespuestaValContenidoFactuSistemaFacturacionType;// variable global en la que cargo el objeto completo de la respuesta
                    }
                }
            }
            catch(Exception Ex2) { return true; }//Fallamos al Serializar la respuesta
            try
            {
                RespuestaRegType reg = (RespuestaRegType)Program.devuelto.Item;
                if (reg.EstadoRegistro.ToString() != "Correcto")
                {
                  if(vervose)
                    MessageBox.Show(reg.DescripcionErrorRegistro, "Error: " + reg.CodigoErrorRegistro);
                    return true;
                }
            }
            catch
            {
                MessageBox.Show((string)Program.devuelto.Item);
                return true;
            }
            return false;
        }

Funciona perfecto, incluso verifica si te pasas de los 3000 en una F2.
Cita:

<tikR:RespuestaValContenidoFactuSistemaFacturacion xmlns:tikR="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/RespuestaValRegistNoVeriFactu.xsd" xmlns:tik="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd">
<tikR:RespuestaValidacion>
<tikR:IDFactura>
<tik:IDEmisorFactura>NIF</tik:IDEmisorFactura>
<tik:NumSerieFactura>VC1-25-100009</tik:NumSerieFactura>
<tik:FechaExpedicionFactura>25-04-2025</tik:FechaExpedicionFactura>
</tikR:IDFactura>
<tikR:Operacion>
<tik:TipoOperacion>Alta</tik:TipoOperacion>
</tikR:Operacion>
<tikR:EstadoRegistro>Incorrecto</tikR:EstadoRegistro>
<tikR:CodigoErrorRegistro>1150</tikR:CodigoErrorRegistro>
<tikR: DescripcionErrorRegistro>Cuando TipoFactura sea F2 y no este informado NumRegistroAcuerdoFacturacion o FacturaSinIdentifDestinatarioArt61d no sea S el sumatorio de BaseImponibleOimporteNoSujeto y CuotaRepercutida de todas las líneas de detalle no podrá ser superior a 3.000.</tikR: DescripcionErrorRegistro>
</tikR:RespuestaValidacion>
</tikR:RespuestaValContenidoFactuSistemaFacturacion>
La funcion devuelve true si se encuentra un error, entonces es cuando analizamos o el string o el objeto para saber que sucedio, si ponemos a true la opcin vervose, muestra el error en pantalla inmediatamente.

Otra prueba.
Cita:

<tikR:RespuestaValContenidoFactuSistemaFacturacion xmlns:tikR="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/RespuestaValRegistNoVeriFactu.xsd" xmlns:tik="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd">
<tikR:RespuestaValidacion>
<tikR:IDFactura>
<tik:IDEmisorFactura>NIF</tik:IDEmisorFactura>
<tik:NumSerieFactura>VC1-25-100009</tik:NumSerieFactura>
<tik:FechaExpedicionFactura>25-04-2026</tik:FechaExpedicionFactura>
</tikR:IDFactura>
<tikR:Operacion>
<tik:TipoOperacion>Alta</tik:TipoOperacion>
</tikR:Operacion>
<tikR:EstadoRegistro>Incorrecto</tikR:EstadoRegistro>
<tikR:CodigoErrorRegistro>1112</tikR:CodigoErrorRegistro>
<tikR: DescripcionErrorRegistro>El campo FechaExpedicionFactura es superior a la fecha actual.</tikR: DescripcionErrorRegistro>
</tikR:RespuestaValidacion>
</tikR:RespuestaValContenidoFactuSistemaFacturacion>
Si os interesa estoy creando uno igual para los registros de anulacion.

rci 25-04-2025 15:27:19

Cita:

Empezado por bmfranky (Mensaje 564048)
Hola, he creado una funcion que consulta los registros de facturacion, antes de enviarlos a la AEAT, devuelve cualquier error que haya en ellos.
Esoy haciendo uso del servicio creado para verificar los no verificables antes de almacenarlos que han abilitado la AEAT, aqui la descripcion.
Hay que importar la clase que define la respuesta del registro, simplemente eliminando la extension .txt
Código:

      /// <summary>
        /// checa la estructura del registro de alta
        /// </summary>
        /// <param name="alta"> Es el registro a comprobar , usa tambien  Program.certificado, Program.passcertificado Son el certificado y su pasword para realizar el envio</param>
        /// <param name="vervose"> por defecto true, muestra inmediatamente el mensaje de error en un message box </param>
        /// <returns>Devuelve true si ha ocurrido un error, tambien devuelve en un string Program.RespuestaServidor la respuesta formateada y en Program.devuelto un objeto RespuestaValContenidoFactuSistemaFacturacionType.</returns>
        public bool checaRegistro(RegistroFacturaType alta)
        {
            //Primero deserializamos el registro de facturacion.
            string facXml = "";
            try
            {
                XmlSerializer serializaFactura = new XmlSerializer(typeof(RegistroFacturaType));
                using (var xmlw = new StringWriter())
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Indent = true;
                    settings.Encoding = Encoding.UTF8;
                    using (XmlWriter writter = XmlWriter.Create(xmlw, settings))
                    {
                        serializaFactura.Serialize(writter, alta);
                        facXml = xmlw.ToString();
                    }

                }
            }
            catch
            { return true; }//fallamos al deserializar}
            //Eliminamos lo no necesario, solo debemos enviar el registro de alta.
            facXml = facXml.Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
            facXml = facXml.Replace("<RegistroFacturaType xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">", "");//Eliminamos la seccion
            facXml = facXml.Replace("</RegistroFacturaType>", "");
            //Creamos el XML Document Necesario para el envio asignandole el registro a enviar.
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(facXml.Replace("utf-16", "utf-8"));
            string responseFromServer;
            //Intentamos enviar a la web
            try
            {
                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://prewww1.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/ValRegistroNoVerifactu");//Asignamos la direccion de validacion           
                webRequest.ContentType = "text/xml;charset=\"utf-8\"";
                webRequest.Accept = "text/xml";
                webRequest.Method = "POST";
                //Cargamos el certificado para identificarnos en la aeat, verificando si es valido o esta caducado.
                X509Certificate2 certificate = new X509Certificate2(Program.certificado, Program.passcertificado); //requiere estas variables globales que contienen el certificado y su clave
                var tiempo = certificate.SubjectName;
                //Verificamos que no este anulado o erroneo.
                if (certificate == null)
                    throw new ArgumentNullException(
                        "El Certificado es Nulo. O el numero de serie en la configuracion es erroneo.");
                //verificamos que no este caducado.
                if (certificate.NotAfter < DateTime.Now)
                    throw new ArgumentNullException(
                      $"El Certificado esta caducado. NotAfter: {certificate.NotAfter}.");
                //Asignamos el Certificado.
                webRequest.ClientCertificates.Add(certificate);
                //Abrimos un stream a la direccion, para enviar el documento.
                using (Stream stream = webRequest.GetRequestStream())
                {
                    doc.Save(stream);
                }
                //Escuchamos la respuesta del servidor.
                HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
                string statusDescription = response.StatusDescription;
                //leemos la respuesta a un stream
                Stream dataStream = response.GetResponseStream();
                using (StreamReader reader = new StreamReader(dataStream))
                {
                    responseFromServer = reader.ReadToEnd();
                    reader.Close();
                    dataStream.Close();
                    response.Close();
                }
            }
            catch(Exception ex1) { return true; }// Fallo la conexion por algun motivo
            //Personalmente me gusta en formato indentado ai que lo modifico.
            XDocument Xdoc = XDocument.Parse(responseFromServer);
            Program.RespuestaServidor = Xdoc.ToString();// variable global en la que cargo la respuesta formateada para mostrar al usuario.
            //Finalmente intentamos crear el registro con el XML devuelto.
            XmlSerializer SerializaFactura = new XmlSerializer(typeof(RespuestaValContenidoFactuSistemaFacturacionType));
            try
            {
                //usamos un string reader para cargar la respuesta de internet
                using (var xmlw1 = new StringReader(responseFromServer))
                {
                    //  Sertializamos
                    using (XmlReader reader = XmlReader.Create(xmlw1))
                    {
                        Program.devuelto = SerializaFactura.Deserialize(reader) as RespuestaValContenidoFactuSistemaFacturacionType;// variable global en la que cargo el objeto completo de la respuesta
                    }
                }
            }
            catch(Exception Ex2) { return true; }//Fallamos al Serializar la respuesta
            try
            {
                RespuestaRegType reg = (RespuestaRegType)Program.devuelto.Item;
                if (reg.EstadoRegistro.ToString() != "Correcto")
                {
                  if(vervose)
                    MessageBox.Show(reg.DescripcionErrorRegistro, "Error: " + reg.CodigoErrorRegistro);
                    return true;
                }
            }
            catch
            {
                MessageBox.Show((string)Program.devuelto.Item);
                return true;
            }
            return false;
        }

Funciona perfecto, incluso verifica si te pasas de los 3000 en una F2.
La funcion devuelve true si se encuentra un error, entonces es cuando analizamos o el string o el objeto para saber que sucedio, si ponemos a true la opcin vervose, muestra el error en pantalla inmediatamente.

Otra prueba.

Si os interesa estoy creando uno igual para los registros de anulacion.

Muchas gracias compañero, es interesante, puede que lo pruebe.

Esto lo utilizas porque tu SIF también tendrá modo "No Veri*Factu"?

bmfranky 25-04-2025 19:43:59

Chequeo pre envio
 
Cita:

Empezado por rci (Mensaje 564049)
Muchas gracias compañero, es interesante, puede que lo pruebe.

Esto lo utilizas porque tu SIF también tendrá modo "No Veri*Factu"?

No, lo utilizo para verificar el registro de facturacion, antes incluso de cargar la factura para enviar, en fase de *Diseño de la misma, igual que la previsualizo sin numero de factura , ni dejo imprimir si no pasa las verificaciones, asi muestro el error y vuelvo a la pantalla de diseño, sin guardar el registro, porque aun estoy creandolo, dando pie a que se corrijan los errores antes de enviar nada.
Por ejemplo, si me confundo al escojer el tipo de iva o clave de regimen, pues vuelvo al menu de diseño de la factura, lo cambio y vuelvo a probar, que me indica que el nif no esta censado, pues lo modifico, etc..


Casi imposible enviar un registro de facturacion erroneo y como cada vez que intento enviar el registro, o en su caso encolarlo, como aun no he guardado nada me deja modificarlo, y siempre reasigno la fecha hora, pues adios al error "2004", por ejemplo.

Otro caso es que me diera que el registro ya existe, pues lanzo un verificacion de los registros enviados, se me ocurren muchas posibilidades.

No creo que eliminen el servicio, puesto que lo han creado para verficarlos antes de guardarlos en no verifactu, mientras permitan el no verifactu ahi estara.


La franja horaria es GMT +2. Ahora son las 09:20:39.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi