Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Ley antifraude 2021 (VERIFACTU) - Programas informáticos (https://www.clubdelphi.com/foros/showthread.php?t=95235)

seccion_31 01-10-2024 08:28:19

buenos dias pablog2k !

Cita:

RemClassRegistry.RegisterSerializeOptions(RegFactuSistemaFacturacion, [xoLiteralParam]);
gracias, incluso con ese cambio, sigue generando dos lineas.

¿Puedes postear x fa, tu importacion del wsdl ? a ver si con eso acertamos.

Saludos !

richidemola 01-10-2024 09:15:39

Os paso un ejemplo de XML que funciona, tendréis que cambiar algunas cosas, a saber:

NOMBRE_EMISOR_FACTURA: Es el nombre de la persona o empresa que emite la factura, debe ser el mismo que figura en el certificado electrónico con el que se firma el envío.
NIF_EMISOR_FACTURA: Es el nif de la persona o empresa que emite la factura, debe ser el mismo que figura en el certificado electrónico con el que se firma el envío.

NOMBRE_CLIENTE: Nombre del cliente, debe ser un nombre real.
NIF_CLIENTE: Es el nif del cliente, debe ser el nif real del nombre del cliente.
Ojo porque si te inventas los dos valores anteriores dará error aunque sea un nif válido, no te puedes inventar los dos valores anteriores.

NOMBRE_EMPRESA_SOFTWARE: Nombre de la empresa o persona que ha hecho el software de facturación, debe ser real.
NIF_EMPRESA_SOFTWARE: Nif de la empresa o persona que ha hecho el software de facturación, también debe ser real y el que corresponda con el nombre anterior.
Ojo porque si te inventas los dos valores anteriores dará error aunque sea un nif válido, no te puedes inventar los dos valores anteriores.

Código PHP:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd" xmlns:ns2="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd">
    <
SOAP-ENV:Body>
        <
ns2:RegFactuSistemaFacturacion>
            <
ns1:Cabecera>
                <
ns1:ObligadoEmision>
                    <
ns1:NombreRazon>NOMBRE_EMISOR_FACTURA</ns1:NombreRazon>
                    <
ns1:NIF>NIF_EMISOR_FACTURA</ns1:NIF>
                </
ns1:ObligadoEmision>
            </
ns1:Cabecera>
            <
ns2:RegistroFactura>
                <
ns2:RegistroAlta>
                    <
ns1:IDVersion>1.0</ns1:IDVersion>
                    <
ns1:IDFactura>
                        <
ns1:IDEmisorFactura>NIF_EMISOR_FACTURA</ns1:IDEmisorFactura>
                        <
ns1:NumSerieFactura>A022</ns1:NumSerieFactura>
                        <
ns1:FechaExpedicionFactura>08-09-2024</ns1:FechaExpedicionFactura>
                    </
ns1:IDFactura>
                    <
ns1:NombreRazonEmisor>NOMBRE_EMISOR_FACTURA</ns1:NombreRazonEmisor>
                    <
ns1:TipoFactura>F1</ns1:TipoFactura>
                    <
ns1:DescripcionOperacion>VENTA MERCADERIAS</ns1:DescripcionOperacion>
                    <
ns1:Destinatarios>
                        <
ns1:IDDestinatario>
                            <
ns1:NombreRazon>NOMBRE_CLIENTE</ns1:NombreRazon>
                            <
ns1:NIF>NIF_CLIENTE</ns1:NIF>
                        </
ns1:IDDestinatario>
                    </
ns1:Destinatarios>
                    <
ns1:Desglose>
                        <
ns1:DetalleDesglose>
                            <
ns1:ClaveRegimen>01</ns1:ClaveRegimen>
                            <
ns1:CalificacionOperacion>S1</ns1:CalificacionOperacion>
                            <
ns1:TipoImpositivo>21</ns1:TipoImpositivo>
                            <
ns1:BaseImponibleOimporteNoSujeto>100.00</ns1:BaseImponibleOimporteNoSujeto>
                            <
ns1:CuotaRepercutida>21.00</ns1:CuotaRepercutida>
                        </
ns1:DetalleDesglose>
                    </
ns1:Desglose>
                    <
ns1:CuotaTotal>21.00</ns1:CuotaTotal>
                    <
ns1:ImporteTotal>121.00</ns1:ImporteTotal>
                    <
ns1:Encadenamiento>
                        <
ns1:PrimerRegistro>S</ns1:PrimerRegistro>
                    </
ns1:Encadenamiento>
                    <
ns1:SistemaInformatico>
                        <
ns1:NombreRazon>NOMBRE_EMPRESA_SOFTWARE</ns1:NombreRazon>
                        <
ns1:NIF>NIF_EMPRESA_SOFTWARE</ns1:NIF>
                        <
ns1:NombreSistemaInformatico>SOFTWARE TPV DE PRUEBAS</ns1:NombreSistemaInformatico>
                        <
ns1:IdSistemaInformatico>7</ns1:IdSistemaInformatico>
                        <
ns1:Version>1.0</ns1:Version>
                        <
ns1:NumeroInstalacion>38</ns1:NumeroInstalacion>
                        <
ns1:TipoUsoPosibleSoloVerifactu>S</ns1:TipoUsoPosibleSoloVerifactu>
                        <
ns1:TipoUsoPosibleMultiOT>N</ns1:TipoUsoPosibleMultiOT>
                        <
ns1:IndicadorMultiplesOT>N</ns1:IndicadorMultiplesOT>
                    </
ns1:SistemaInformatico>
                    <
ns1:FechaHoraHusoGenRegistro>2024-10-01T09:05:00+02:00</ns1:FechaHoraHusoGenRegistro>
                    <
ns1:TipoHuella>01</ns1:TipoHuella>
                    <
ns1:Huella>DD127FF3CEE27D933D330BD718FFBD1D13B2876B14C3C3B2E3B329195</ns1:Huella>
                </
ns2:RegistroAlta>
            </
ns2:RegistroFactura>
        </
ns2:RegFactuSistemaFacturacion>
    </
SOAP-ENV:Body>
</
SOAP-ENV:Envelope

Y ya por si a alguien le interesa, este es el código que uso para enviar el fichero xml al web service hecho en php:

Código PHP:

$url 'no_puedo_poner_enlaces prewww1.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP'// URL del webservice
$pfxFile 'micertificado.pfx'// Ruta al archivo PFX del certificado electronico
$pfxPassword 'loquesea'// Contraseña del PFX del certificado electronico
$ch curl_init($url);
curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
curl_setopt($chCURLOPT_SSL_VERIFYPEERfalse);
curl_setopt($chCURLOPT_TIMEOUT30);
curl_setopt($chCURLOPT_POSTtrue);
curl_setopt($chCURLOPT_POSTFIELDS$xml);
curl_setopt($chCURLOPT_HTTPHEADER, array('Content-Type: application/xml',"SOAPAction: AltaFactuSistemaFacturacion"));
curl_setopt($chCURLOPT_SSLCERTTYPE'P12');
curl_setopt($chCURLOPT_SSLCERT$pfxFile);
curl_setopt($chCURLOPT_SSLCERTPASSWD$pfxPassword);
$response curl_exec($ch);
if (
curl_errno($ch)) {
    echo 
'Error: ' curl_error($ch);
} else {
    
print_r($response);
}
curl_close($ch); 

Espero que os sirva. Saludos.

keno_71 01-10-2024 09:20:14

Gracias Richidemola, lo probaré

pablog2k 01-10-2024 09:38:44

Cita:

Empezado por seccion_31 (Mensaje 557636)
buenos dias pablog2k !



gracias, incluso con ese cambio, sigue generando dos lineas.

¿Puedes postear x fa, tu importacion del wsdl ? a ver si con eso acertamos.

Saludos !

Hola, prefiero postearlo cuando consiga que me funcione todo, porque ahora me está dando problemas con los nodos IdDestinatario y DetalleDesglose .... :mad:

antoine0 01-10-2024 10:03:43

Cita:

Empezado por richidemola (Mensaje 557634)
Pues efectivamente, con +2:00 funciona y no me da el error, pero como dije en otro mensaje no lo entiendo entonces, ¿Cuándo pase el horario de verano no valdrá el +2 y hay que poner un +1 o que?

Sí. Después del 27 habrá que poner +01:00, o +00:00 si estás en Canarias.

Cita:

Existe algún sitio donde consultar la franja horaria en tiempo real?
A ver. Primero la hora del ordenador, también la hora de los señales GPS y NTP, y mucho otros, corren en hora UTc, también conocida como hora GMT (la que he marcado Z).
Por tanto lo más próximo adónde buscar para tal consulta es el propio ordenador, por qué tiene esta información.
Delphi lo expone a través de varias vías, por ejemplo System.DateUtils.TTimeZone (desde XE); probablemente usando
Código:

TTimeZone.Local.GetUtcOffset
.
A nivel de Windows, lo normal es que acabe en una llamada a GetTimeZoneInformation (antiguo pero suficiente para el propósito) o GetDynamicTimeZoneInformation (desde Vista, necesitará una versión no demasiada antigua de Delphi). Hay equivalente en los demás sistemas operativos.

Online hay un montón de sitios con esta información. Te recomiendo https://www.timeanddate.com/time en inglés, es corto pero acierta. Verás que los husos horarios son realmente una cosa de los políticos, aplicado por algunos laboratorios. Por tanto la respuesta correcta a tu pregunta es probablemente el Real Observatorio de la Armada.

pablog2k 01-10-2024 11:21:01

alguien me puede decir como habéis conseguido quitar los milisegundos en la fecha que se genera a partir de la variable TXSDateTime para rellenar el nodo FechaHoraHusoGenRegistro? o utilizáis otra tipo de variable?

espinete 01-10-2024 11:25:25

¿Pero entonces tenemos que darnos de alta en algún sitio para poder hacer los envíos? ¿Donde notificamos el NIF y/o el certificado para que admitan el envío de VeriFactu? No recuerdo haber leído nada de eso.

Cita:

Empezado por seccion_31 (Mensaje 557632)
buenos dias !

he consultado a la AEAT el problema del error:

4118 El NIF del titular no está autorizado a enviar información al sistema.

me han pedido el XML y el nif del certificado, antes de aplicar otros cambios voy a esperar a ver que dicen.

Saludos !

Como digo: este programa es la modificacion de aquel que deje en el foro para enviar 1 alta y 1 baja, que volvere a publicar una vez que funcione en pruebas.


pablog2k 01-10-2024 12:12:09

Cita:

Empezado por pablog2k (Mensaje 557646)
alguien me puede decir como habéis conseguido quitar los milisegundos en la fecha que se genera a partir de la variable TXSDateTime para rellenar el nodo FechaHoraHusoGenRegistro? o utilizáis otra tipo de variable?

me autorespondo, es utilizando el metodo XSToNative y poniendo 'a piñón' el valor que queramos

seccion_31 01-10-2024 12:20:06

La AEAT sobre el error 4118:

Cita:

Le confirmamos que no el problema no proviene por falta de autorización de ninguno de los NIFs incluidos en la presentación. En el fichero XML de respuesta podrá ver que la descripción del error 4118 es "Error técnico: la dirección no se corresponde con el fichero de entrada."

El error 4118 puede deberse al uso de un Endpoint incorrecto o un Envelope con errores. En su caso deben revisar el Envelope del fichero ya que no es correcto. Le recomendamos revisar los ejemplos de fichero incluidos en el documento "Documento de descripción de servicios web (v0.4.0) - Borrador" de la web de desarrolladores.
Saludos

espinete 01-10-2024 12:38:33

Tiene pinta de que el error va a estar en que nuestro XML tiene repetido el nodo "RegFactuSistemaFacturacion".

Al recibir el XML, AEAT intenta buscar dentro de ese nodo los datos de la factura, pero lo que encuentra es otro nodo "RegFactuSistemaFacturacion".

No soy un experto en XML ni sé cómo AEAT interpreta el archivo, pero me da que el problema puede estar ahi.

Otra cosa que he notado en mi XML con respecto al que publicaron recientemente es que el que yo genero tiene dos nodos de más:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body xmlns:NS1="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd">
.....
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

El otro XML que publicaron que sí se envía sin error no tiene esas dos líneas.

No sé qué hay que configurar en Delphi, o en el componente HTTPRIO, o en el wsdl importado, etc. para que no haga eso. Por si esa fuera la causa del problema.


Cita:

Empezado por seccion_31 (Mensaje 557653)
La AEAT sobre el error 4118:



Saludos


seccion_31 01-10-2024 12:53:39

Cita:

Tiene pinta de que el error va a estar en que nuestro XML tiene repetido el nodo "RegFactuSistemaFacturacion".
Si, tiene pinta de eso, pero creo que ayer envie un XML sin el nodo repetido y seguia diciendo lo mismo. ... (creo), en mi opinion, o estan mal importados los WSDL, mal creados, o delphi no los puede importar bien.

Probare mañana a enviar XMLS manuales, copiando algunos de los que han remitido por aqui.

Saludos!

pablog2k 01-10-2024 13:22:14

De los que habéis podido enviar, que hay que poner exactamente en el campo FechaHoraHusoGenRegistro ??
Porque he probado:
2024-10-01T13:17:13+01:00 (error)
2024-10-01T13:17:13+02:00 (error)
2024-10-01T12:17:13+01:00 (restando una hora para que aplique el +01:00, error)
2024-10-01T11:17:13+02:00 (restando dos horas para que aplique el +02:00, error)
2024-10-01T15:17:13+02:00 (sumando dos horas para que aplique el +02:00, error)

richidemola 01-10-2024 13:39:41

Cita:

Empezado por pablog2k (Mensaje 557657)
De los que habéis podido enviar, que hay que poner exactamente en el campo FechaHoraHusoGenRegistro ??
Porque he probado:
2024-10-01T13:17:13+01:00 (error)
2024-10-01T13:17:13+02:00 (error)
2024-10-01T12:17:13+01:00 (restando una hora para que aplique el +01:00, error)
2024-10-01T11:17:13+02:00 (restando dos horas para que aplique el +02:00, error)
2024-10-01T15:17:13+02:00 (sumando dos horas para que aplique el +02:00, error)

A mi me sirvió con el +02:00 porque el +01:00 me daba error, varios mensajes más arriba hablábamos del tema, lo que si que hago, para curarme en salud, es redondear los segundos, es decir, si son las 13:36:17 yo pongo 13:36:00 para ir siempre un poco por debajo de la hora de la aeat, ten en cuenta que el margen que acepta la aeat es de máximo 5 minutos por debajo de su hora.

Comprueba también que la hora de tu equipo, si es una aplicación de escritorio, es igual a la hora de la aeat, en mi caso como la aplicación funciona en navegador web cojo la hora del servidor web que es la misma hora que la de la aeat porque la hora del servidor web está sincronizada y no tengo que andar mirando la hora del PC.

Saludos.

sglorka 01-10-2024 14:01:45

Cita:

Empezado por pablog2k (Mensaje 557657)
De los que habéis podido enviar, que hay que poner exactamente en el campo FechaHoraHusoGenRegistro ??
Porque he probado:
2024-10-01T13:17:13+01:00 (error)
2024-10-01T13:17:13+02:00 (error)
2024-10-01T12:17:13+01:00 (restando una hora para que aplique el +01:00, error)
2024-10-01T11:17:13+02:00 (restando dos horas para que aplique el +02:00, error)
2024-10-01T15:17:13+02:00 (sumando dos horas para que aplique el +02:00, error)

Te sería más fácil ejecutar este curl si quieres
# curl "http://worldtimeapi.org/api/timezone/Europe/Madrid" si estás en península.
Te va a devolver, entre otras cosas, "datetime": "2024-10-01T13:56:54.849406+02:00". Esta fecha es la que tienes que informar en el FechaHoraHusoGenRegistro, indica la hora actual y el +2 hace referencia al horario de verano.

Si estás en las Islas Canarias ejecutas
# curl "http://worldtimeapi.org/api/timezone/Atlantic/Canary", donde obtenemos "datetime": "2024-10-01T12:55:50.103145+01:00", donde el +1 indica horario de verano ya que en las Islas hay una hora menos.

pablog2k 01-10-2024 14:08:25

Cita:

Empezado por sglorka (Mensaje 557659)
Te sería más fácil ejecutar este curl si quieres
# curl "http://worldtimeapi.org/api/timezone/Europe/Madrid" si estás en península.
Te va a devolver, entre otras cosas, "datetime": "2024-10-01T13:56:54.849406+02:00". Esta fecha es la que tienes que informar en el FechaHoraHusoGenRegistro, indica la hora actual y el +2 hace referencia al horario de verano.

Si estás en las Islas Canarias ejecutas
# curl "http://worldtimeapi.org/api/timezone/Atlantic/Canary", donde obtenemos "datetime": "2024-10-01T12:55:50.103145+01:00", donde el +1 indica horario de verano ya que en las Islas hay una hora menos.

pero no se supone que hay que enviar la fecha actual + 2 horas??? porque estamos en +02:00??
De todas formas mi problema no es obtener la fecha actual, es saber que narices están esperando...
he probado todas las maneras habidas y por haber, restando y sumando horas.... y nada (tus ejemplos tampoco me funcionaron ,ni con milisegundos ni sin milisegundos)

espinete 01-10-2024 14:15:29

Con el .pas generado al importar el WSDL como SOAP 1.2, solo tuve que añadir esta línea al .pas (gracias a pablog2k)

Código Delphi [-]
InvRegistry.RegisterInvokeOptions(TypeInfo(sfPortTypeVerifactu), ioLiteral);

La añadí justo después de la que viene por defecto:

Código Delphi [-]
InvRegistry.RegisterInvokeOptions(TypeInfo(sfPortTypeVerifactu), ioDocument);

Después de ese cambio, me daba otro error indicando que faltaba el campo "IDDestinatario", pero ese campo sí que estaba.
Lo que pasa es que en mi IDDestinatario había añadido el subnodo "IDOtro". Lo quité y ya pude hacer el envío.

Ahora bien, el envío me devuelve "Incorrecto", así que ahora tendré que ir poco a poco buscando los motivos, pero al menos el error anterior ya no me da. Supongo que ahora tendré que buscar en la respuesta (RespuestaBaseType) las causas de error que devuelve la AEAT.


Cita:

Empezado por seccion_31 (Mensaje 557655)
Si, tiene pinta de eso, pero creo que ayer envie un XML sin el nodo repetido y seguia diciendo lo mismo. ... (creo), en mi opinion, o estan mal importados los WSDL, mal creados, o delphi no los puede importar bien.

Probare mañana a enviar XMLS manuales, copiando algunos de los que han remitido por aqui.

Saludos!


sglorka 01-10-2024 14:35:18

Cita:

Empezado por pablog2k (Mensaje 557660)
pero no se supone que hay que enviar la fecha actual + 2 horas??? porque estamos en +02:00??
De todas formas mi problema no es obtener la fecha actual, es saber que narices están esperando...
he probado todas las maneras habidas y por haber, restando y sumando horas.... y nada (tus ejemplos tampoco me funcionaron ,ni con milisegundos ni sin milisegundos)

Mis ejemplos no te funcionaron porque han sido generados en Canarias UTC+1 en horario de verano.
Si miras esta página de Wikipedia https://es.wikipedia.org/wiki/UTC%2B...opedia%20libre
podrás ver que España se rige en la zona horaria UTC+1 ya que tiene una hora más que las situadas en el meridiano de Greenwich.
Como además, tenemos una hora adelantada debido al cambio horario de verano, entonces la hora de expresa como UTC+2. Cuando se vuelva a cambiar la hora a la de invierno, atrasaremos una y volveremos a UTC+1. En Canarias sería UTC+0.
De todas maneras, como el ordenador donde va estar tu programa debe tener conexión a Internet sí o sí, debes tener activada la sincronización horaria con el reloj de Microsoft o cualquier otro, cualquier librería de cualquier lenguaje puede obtener la hora del sistema y expresarla en formato Iso8601 que es la que nos atañe.

espinete 01-10-2024 14:36:11

Para poder ver el detalle del error, hay que hacer el envío usando "RespuestaRegFactuSistemaFacturacionType" para la respuesta, en vez de "RespuestaBaseType".

Por lo que el envío usando HTTPRIO hay que hacerlo así:

Código Delphi [-]
res := RespuestaRegFactuSistemaFacturacionType.Create;
SistemaFacturacion.RespuestaRegFactuSistemaFacturacion(res) := SistemaFacturacion.GetsfPortTypeVerifactu(false, 'https://prewww1.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP', Form1.HTTPRIO1).RegFactuSistemaFacturacion(veriFactu);
Solo así puedo ver el array de errores que devuelve Hacienda.

espinete 01-10-2024 14:50:29

ChatGPT me hizo un favor:

XSDatetime.FractionalSeconds := 0;

Con eso se elimina el .000 de la fecha/hora

Cita:

Empezado por pablog2k (Mensaje 557646)
alguien me puede decir como habéis conseguido quitar los milisegundos en la fecha que se genera a partir de la variable TXSDateTime para rellenar el nodo FechaHoraHusoGenRegistro? o utilizáis otra tipo de variable?


pablog2k 01-10-2024 15:00:15

Increíble pero cierto.....
resulta que estaba poniendo como pruebas la fecha de una factura de hace unos días..... y no se puede hacer eso
tienes que poner la fecha de facturas de HOY para los envíos de hoy .....
ya podrían indicarlo claramente en el mensaje de error , en vez de decir todo el rato El valor del campo FechaHoraHusoGenRegistro no está dentro del umbral establecido sobre la fecha del sistema de la AEAT
:(


La franja horaria es GMT +2. Ahora son las 13:09:29.

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