FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Veri*Factu
Posts: 318
Joined: Fri Jan 14, 2022 08:37 AM
Re: Veri*Factu
Posted: Mon Dec 16, 2024 08:30 PM
Hola Antonio,

Dos cosas:

- Veo que has puesto los tags sin NameSpace. Entiendo que cómo estamos creando el .xml, a pelillo, sí hace falta ponerlos
- Lo habitual en el .xml será que contenga varias facturas, así que hay que poner otros tags de superior nivel

Pego aquí un ejemplo generado con soapui que incluye la definicion del registro de Alta y el registro de Anulacion. Supongo que ambos tipos de registros pueden incluirse en un mismo envío con lo cual necesitamos dos subdivisiones (dos funciones) del .xml, una para el alta y otra para la anulacion
Code (fw): Select all Collapse
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sum="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd" xmlns:sum1="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd" xmlns:xd="http://www.w3.org/2000/09/xmldsig#">
   <soapenv:Header/>
   <soapenv:Body>
      <sum:RegFactuSistemaFacturacion>
         <sum:Cabecera>
            <sum1:ObligadoEmision>
               <sum1:NombreRazon>?</sum1:NombreRazon>
               <sum1:NIF>?</sum1:NIF>
            </sum1:ObligadoEmision>
            <!--Optional:-->
            <sum1:Representante>
               <sum1:NombreRazon>?</sum1:NombreRazon>
               <sum1:NIF>?</sum1:NIF>
            </sum1:Representante>
            <!--Optional:-->
            <sum1:RemisionVoluntaria>
               <!--Optional:-->
               <sum1:FechaFinVeriFactu>?</sum1:FechaFinVeriFactu>
               <!--Optional:-->
               <sum1:Incidencia>?</sum1:Incidencia>
            </sum1:RemisionVoluntaria>
            <!--Optional:-->
            <sum1:RemisionRequerimiento>
               <sum1:RefRequerimiento>?</sum1:RefRequerimiento>
               <!--Optional:-->
               <sum1:FinRequerimiento>?</sum1:FinRequerimiento>
            </sum1:RemisionRequerimiento>
         </sum:Cabecera>
         <!--1 to 1000 repetitions:-->
         <sum:RegistroFactura>
            <!--You have a CHOICE of the next 2 items at this level-->
            <sum1:RegistroAlta>
               <sum1:IDVersion>?</sum1:IDVersion>
               <sum1:IDFactura>
                  <sum1:IDEmisorFactura>?</sum1:IDEmisorFactura>
                  <sum1:NumSerieFactura>?</sum1:NumSerieFactura>
                  <sum1:FechaExpedicionFactura>?</sum1:FechaExpedicionFactura>
               </sum1:IDFactura>
               <!--Optional:-->
               <sum1:RefExterna>?</sum1:RefExterna>
               <sum1:NombreRazonEmisor>?</sum1:NombreRazonEmisor>
               <!--Optional:-->
               <sum1:Subsanacion>?</sum1:Subsanacion>
               <!--Optional:-->
               <sum1:RechazoPrevio>?</sum1:RechazoPrevio>
               <sum1:TipoFactura>?</sum1:TipoFactura>
               <!--Optional:-->
               <sum1:TipoRectificativa>?</sum1:TipoRectificativa>
               <!--Optional:-->
               <sum1:FacturasRectificadas>
                  <!--1 to 1000 repetitions:-->
                  <sum1:IDFacturaRectificada>
                     <sum1:IDEmisorFactura>?</sum1:IDEmisorFactura>
                     <sum1:NumSerieFactura>?</sum1:NumSerieFactura>
                     <sum1:FechaExpedicionFactura>?</sum1:FechaExpedicionFactura>
                  </sum1:IDFacturaRectificada>
               </sum1:FacturasRectificadas>
               <!--Optional:-->
               <sum1:FacturasSustituidas>
                  <!--1 to 1000 repetitions:-->
                  <sum1:IDFacturaSustituida>
                     <sum1:IDEmisorFactura>?</sum1:IDEmisorFactura>
                     <sum1:NumSerieFactura>?</sum1:NumSerieFactura>
                     <sum1:FechaExpedicionFactura>?</sum1:FechaExpedicionFactura>
                  </sum1:IDFacturaSustituida>
               </sum1:FacturasSustituidas>
               <!--Optional:-->
               <sum1:ImporteRectificacion>
                  <sum1:BaseRectificada>?</sum1:BaseRectificada>
                  <sum1:CuotaRectificada>?</sum1:CuotaRectificada>
                  <!--Optional:-->
                  <sum1:CuotaRecargoRectificado>?</sum1:CuotaRecargoRectificado>
               </sum1:ImporteRectificacion>
               <!--Optional:-->
               <sum1:FechaOperacion>?</sum1:FechaOperacion>
               <sum1:DescripcionOperacion>?</sum1:DescripcionOperacion>
               <!--Optional:-->
               <sum1:FacturaSimplificadaArt7273>?</sum1:FacturaSimplificadaArt7273>
               <!--Optional:-->
               <sum1:FacturaSinIdentifDestinatarioArt61d>?</sum1:FacturaSinIdentifDestinatarioArt61d>
               <!--Optional:-->
               <sum1:Macrodato>?</sum1:Macrodato>
               <!--Optional:-->
               <sum1:EmitidaPorTerceroODestinatario>?</sum1:EmitidaPorTerceroODestinatario>
               <!--Optional:-->
               <sum1:Tercero>
                  <sum1:NombreRazon>?</sum1:NombreRazon>
                  <!--You have a CHOICE of the next 2 items at this level-->
                  <sum1:NIF>?</sum1:NIF>
                  <sum1:IDOtro>
                     <!--Optional:-->
                     <sum1:CodigoPais>?</sum1:CodigoPais>
                     <sum1:IDType>?</sum1:IDType>
                     <sum1:ID>?</sum1:ID>
                  </sum1:IDOtro>
               </sum1:Tercero>
               <!--Optional:-->
               <sum1:Destinatarios>
                  <!--1 to 1000 repetitions:-->
                  <sum1:IDDestinatario>
                     <sum1:NombreRazon>?</sum1:NombreRazon>
                     <!--You have a CHOICE of the next 2 items at this level-->
                     <sum1:NIF>?</sum1:NIF>
                     <sum1:IDOtro>
                        <!--Optional:-->
                        <sum1:CodigoPais>?</sum1:CodigoPais>
                        <sum1:IDType>?</sum1:IDType>
                        <sum1:ID>?</sum1:ID>
                     </sum1:IDOtro>
                  </sum1:IDDestinatario>
               </sum1:Destinatarios>
               <!--Optional:-->
               <sum1:Cupon>?</sum1:Cupon>
               <sum1:Desglose>
                  <!--1 to 12 repetitions:-->
                  <sum1:DetalleDesglose>
                     <!--Optional:-->
                     <sum1:Impuesto>?</sum1:Impuesto>
                     <!--Optional:-->
                     <sum1:ClaveRegimen>?</sum1:ClaveRegimen>
                     <!--You have a CHOICE of the next 2 items at this level-->
                     <sum1:CalificacionOperacion>?</sum1:CalificacionOperacion>
                     <sum1:OperacionExenta>?</sum1:OperacionExenta>
                     <!--Optional:-->
                     <sum1:TipoImpositivo>?</sum1:TipoImpositivo>
                     <sum1:BaseImponibleOimporteNoSujeto>?</sum1:BaseImponibleOimporteNoSujeto>
                     <!--Optional:-->
                     <sum1:BaseImponibleACoste>?</sum1:BaseImponibleACoste>
                     <!--Optional:-->
                     <sum1:CuotaRepercutida>?</sum1:CuotaRepercutida>
                     <!--Optional:-->
                     <sum1:TipoRecargoEquivalencia>?</sum1:TipoRecargoEquivalencia>
                     <!--Optional:-->
                     <sum1:CuotaRecargoEquivalencia>?</sum1:CuotaRecargoEquivalencia>
                  </sum1:DetalleDesglose>
               </sum1:Desglose>
               <sum1:CuotaTotal>?</sum1:CuotaTotal>
               <sum1:ImporteTotal>?</sum1:ImporteTotal>
               <sum1:Encadenamiento>
                  <!--You have a CHOICE of the next 2 items at this level-->
                  <sum1:PrimerRegistro>?</sum1:PrimerRegistro>
                  <sum1:RegistroAnterior>
                     <sum1:IDEmisorFactura>?</sum1:IDEmisorFactura>
                     <sum1:NumSerieFactura>?</sum1:NumSerieFactura>
                     <sum1:FechaExpedicionFactura>?</sum1:FechaExpedicionFactura>
                     <sum1:Huella>?</sum1:Huella>
                  </sum1:RegistroAnterior>
               </sum1:Encadenamiento>
               <sum1:SistemaInformatico>
                  <sum1:NombreRazon>?</sum1:NombreRazon>
                  <!--You have a CHOICE of the next 2 items at this level-->
                  <sum1:NIF>?</sum1:NIF>
                  <sum1:IDOtro>
                     <!--Optional:-->
                     <sum1:CodigoPais>?</sum1:CodigoPais>
                     <sum1:IDType>?</sum1:IDType>
                     <sum1:ID>?</sum1:ID>
                  </sum1:IDOtro>
                  <sum1:NombreSistemaInformatico>?</sum1:NombreSistemaInformatico>
                  <sum1:IdSistemaInformatico>?</sum1:IdSistemaInformatico>
                  <sum1:Version>?</sum1:Version>
                  <sum1:NumeroInstalacion>?</sum1:NumeroInstalacion>
                  <sum1:TipoUsoPosibleSoloVerifactu>?</sum1:TipoUsoPosibleSoloVerifactu>
                  <sum1:TipoUsoPosibleMultiOT>?</sum1:TipoUsoPosibleMultiOT>
                  <sum1:IndicadorMultiplesOT>?</sum1:IndicadorMultiplesOT>
               </sum1:SistemaInformatico>
               <sum1:FechaHoraHusoGenRegistro>?</sum1:FechaHoraHusoGenRegistro>
               <!--Optional:-->
               <sum1:NumRegistroAcuerdoFacturacion>?</sum1:NumRegistroAcuerdoFacturacion>
               <!--Optional:-->
               <sum1:IdAcuerdoSistemaInformatico>?</sum1:IdAcuerdoSistemaInformatico>
               <sum1:TipoHuella>?</sum1:TipoHuella>
               <sum1:Huella>?</sum1:Huella>
               <!--Optional:-->
               <xd:Signature Id="?">
                  <xd:SignedInfo Id="?">
                     <xd:CanonicalizationMethod Algorithm="?">
                        e
                        <!--You may enter ANY elements at this point-->
                        gero
                     </xd:CanonicalizationMethod>
                     <xd:SignatureMethod Algorithm="?">
                        cum
                        <!--Optional:-->
                        <xd:HMACOutputLength>?</xd:HMACOutputLength>
                        sonoras
                        <!--You may enter ANY elements at this point-->
                        aeoliam
                     </xd:SignatureMethod>
                     <!--1 or more repetitions:-->
                     <xd:Reference Id="?" URI="?" Type="?">
                        <!--Optional:-->
                        <xd:Transforms>
                           <!--1 or more repetitions:-->
                           <xd:Transform Algorithm="?">
                              quae
                              <!--You have a CHOICE of the next 2 items at this level-->
                              <!--You may enter ANY elements at this point-->
                              <xd:XPath>?</xd:XPath>
                              ventos
                           </xd:Transform>
                        </xd:Transforms>
                        <xd:DigestMethod Algorithm="?">
                           verrantque
                           <!--You may enter ANY elements at this point-->
                           temperat
                        </xd:DigestMethod>
                        <xd:DigestValue>cid:157794525561</xd:DigestValue>
                     </xd:Reference>
                  </xd:SignedInfo>
                  <xd:SignatureValue Id="?">cid:1690578518962</xd:SignatureValue>
                  <!--Optional:-->
                  <xd:KeyInfo Id="?">
                     per
                     <!--You have a CHOICE of the next 8 items at this level-->
                     <xd:KeyName>?</xd:KeyName>
                     <xd:KeyValue>
                        turbine
                        <!--You have a CHOICE of the next 3 items at this level-->
                        <xd:DSAKeyValue>
                           <xd:P>cid:1711707281655</xd:P>
                           <xd:Q>cid:481201118711</xd:Q>
                           <!--Optional:-->
                           <xd:G>cid:10611753232</xd:G>
                           <xd:Y>cid:1626111862696</xd:Y>
                           <!--Optional:-->
                           <xd:J>cid:1004230167824</xd:J>
                           <xd:Seed>cid:1162600426329</xd:Seed>
                           <xd:PgenCounter>cid:1261683778659</xd:PgenCounter>
                        </xd:DSAKeyValue>
                        <xd:RSAKeyValue>
                           <xd:Modulus>cid:1469002496253</xd:Modulus>
                           <xd:Exponent>cid:859317294610</xd:Exponent>
                        </xd:RSAKeyValue>
                        <!--You may enter ANY elements at this point-->
                        circum
                     </xd:KeyValue>
                     <xd:RetrievalMethod URI="?" Type="?">
                        <!--Optional:-->
                        <xd:Transforms>
                           <!--1 or more repetitions:-->
                           <xd:Transform Algorithm="?">
                              regemque
                              <!--You have a CHOICE of the next 2 items at this level-->
                              <!--You may enter ANY elements at this point-->
                              <xd:XPath>?</xd:XPath>
                              nimborum
                           </xd:Transform>
                        </xd:Transforms>
                     </xd:RetrievalMethod>
                     <xd:X509Data>
                        <!--You have a CHOICE of the next 6 items at this level-->
                        <xd:X509IssuerSerial>
                           <xd:X509IssuerName>?</xd:X509IssuerName>
                           <xd:X509SerialNumber>?</xd:X509SerialNumber>
                        </xd:X509IssuerSerial>
                        <xd:X509SKI>cid:1604072216124</xd:X509SKI>
                        <xd:X509SubjectName>?</xd:X509SubjectName>
                        <xd:X509Certificate>cid:534264511089</xd:X509Certificate>
                        <xd:X509CRL>cid:300236998953</xd:X509CRL>
                        <!--You may enter ANY elements at this point-->
                     </xd:X509Data>
                     <xd:PGPData>
                        <!--You have a CHOICE of the next 2 items at this level-->
                        <xd:PGPKeyID>cid:734311530325</xd:PGPKeyID>
                        <!--Optional:-->
                        <xd:PGPKeyPacket>cid:703929686148</xd:PGPKeyPacket>
                        <!--You may enter ANY elements at this point-->
                        <xd:PGPKeyPacket>cid:786902941464</xd:PGPKeyPacket>
                        <!--You may enter ANY elements at this point-->
                     </xd:PGPData>
                     <xd:SPKIData>
                        <xd:SPKISexp>cid:1242727609185</xd:SPKISexp>
                        <!--You may enter ANY elements at this point-->
                     </xd:SPKIData>
                     <xd:MgmtData>?</xd:MgmtData>
                     <!--You may enter ANY elements at this point-->
                     fremunt
                  </xd:KeyInfo>
                  <!--Zero or more repetitions:-->
                  <xd:Object Id="?" MimeType="?" Encoding="?">
                     foedere
                     <!--You may enter ANY elements at this point-->
                     ferant
                  </xd:Object>
               </xd:Signature>
            </sum1:RegistroAlta>
            <sum1:RegistroAnulacion>
               <sum1:IDVersion>?</sum1:IDVersion>
               <sum1:IDFactura>
                  <sum1:IDEmisorFacturaAnulada>?</sum1:IDEmisorFacturaAnulada>
                  <sum1:NumSerieFacturaAnulada>?</sum1:NumSerieFacturaAnulada>
                  <sum1:FechaExpedicionFacturaAnulada>?</sum1:FechaExpedicionFacturaAnulada>
               </sum1:IDFactura>
               <!--Optional:-->
               <sum1:RefExterna>?</sum1:RefExterna>
               <!--Optional:-->
               <sum1:SinRegistroPrevio>?</sum1:SinRegistroPrevio>
               <!--Optional:-->
               <sum1:RechazoPrevio>?</sum1:RechazoPrevio>
               <!--Optional:-->
               <sum1:GeneradoPor>?</sum1:GeneradoPor>
               <!--Optional:-->
               <sum1:Generador>
                  <sum1:NombreRazon>?</sum1:NombreRazon>
                  <!--You have a CHOICE of the next 2 items at this level-->
                  <sum1:NIF>?</sum1:NIF>
                  <sum1:IDOtro>
                     <!--Optional:-->
                     <sum1:CodigoPais>?</sum1:CodigoPais>
                     <sum1:IDType>?</sum1:IDType>
                     <sum1:ID>?</sum1:ID>
                  </sum1:IDOtro>
               </sum1:Generador>
               <sum1:Encadenamiento>
                  <!--You have a CHOICE of the next 2 items at this level-->
                  <sum1:PrimerRegistro>?</sum1:PrimerRegistro>
                  <sum1:RegistroAnterior>
                     <sum1:IDEmisorFactura>?</sum1:IDEmisorFactura>
                     <sum1:NumSerieFactura>?</sum1:NumSerieFactura>
                     <sum1:FechaExpedicionFactura>?</sum1:FechaExpedicionFactura>
                     <sum1:Huella>?</sum1:Huella>
                  </sum1:RegistroAnterior>
               </sum1:Encadenamiento>
               <sum1:SistemaInformatico>
                  <sum1:NombreRazon>?</sum1:NombreRazon>
                  <!--You have a CHOICE of the next 2 items at this level-->
                  <sum1:NIF>?</sum1:NIF>
                  <sum1:IDOtro>
                     <!--Optional:-->
                     <sum1:CodigoPais>?</sum1:CodigoPais>
                     <sum1:IDType>?</sum1:IDType>
                     <sum1:ID>?</sum1:ID>
                  </sum1:IDOtro>
                  <sum1:NombreSistemaInformatico>?</sum1:NombreSistemaInformatico>
                  <sum1:IdSistemaInformatico>?</sum1:IdSistemaInformatico>
                  <sum1:Version>?</sum1:Version>
                  <sum1:NumeroInstalacion>?</sum1:NumeroInstalacion>
                  <sum1:TipoUsoPosibleSoloVerifactu>?</sum1:TipoUsoPosibleSoloVerifactu>
                  <sum1:TipoUsoPosibleMultiOT>?</sum1:TipoUsoPosibleMultiOT>
                  <sum1:IndicadorMultiplesOT>?</sum1:IndicadorMultiplesOT>
               </sum1:SistemaInformatico>
               <sum1:FechaHoraHusoGenRegistro>?</sum1:FechaHoraHusoGenRegistro>
               <sum1:TipoHuella>?</sum1:TipoHuella>
               <sum1:Huella>?</sum1:Huella>
               <!--Optional:-->
               <xd:Signature Id="?">
                  <xd:SignedInfo Id="?">
                     <xd:CanonicalizationMethod Algorithm="?">
                        profundum
                        <!--You may enter ANY elements at this point-->
                        sceptra
                     </xd:CanonicalizationMethod>
                     <xd:SignatureMethod Algorithm="?">
                        et
                        <!--Optional:-->
                        <xd:HMACOutputLength>?</xd:HMACOutputLength>
                        turbine
                        <!--You may enter ANY elements at this point-->
                        iovis
                     </xd:SignatureMethod>
                     <!--1 or more repetitions:-->
                     <xd:Reference Id="?" URI="?" Type="?">
                        <!--Optional:-->
                        <xd:Transforms>
                           <!--1 or more repetitions:-->
                           <xd:Transform Algorithm="?">
                              flammato
                              <!--You have a CHOICE of the next 2 items at this level-->
                              <!--You may enter ANY elements at this point-->
                              <xd:XPath>?</xd:XPath>
                              speluncis
                           </xd:Transform>
                        </xd:Transforms>
                        <xd:DigestMethod Algorithm="?">
                           profundum
                           <!--You may enter ANY elements at this point-->
                           bella
                        </xd:DigestMethod>
                        <xd:DigestValue>cid:1085730955294</xd:DigestValue>
                     </xd:Reference>
                  </xd:SignedInfo>
                  <xd:SignatureValue Id="?">cid:293982713997</xd:SignatureValue>
                  <!--Optional:-->
                  <xd:KeyInfo Id="?">
                     nubibus
                     <!--You have a CHOICE of the next 8 items at this level-->
                     <xd:KeyName>?</xd:KeyName>
                     <xd:KeyValue>
                        flammas
                        <!--You have a CHOICE of the next 3 items at this level-->
                        <xd:DSAKeyValue>
                           <xd:P>cid:214292880720</xd:P>
                           <xd:Q>cid:1227813663222</xd:Q>
                           <!--Optional:-->
                           <xd:G>cid:13824133043</xd:G>
                           <xd:Y>cid:1243910579088</xd:Y>
                           <!--Optional:-->
                           <xd:J>cid:492279340888</xd:J>
                           <xd:Seed>cid:1357677455119</xd:Seed>
                           <xd:PgenCounter>cid:1489448324499</xd:PgenCounter>
                        </xd:DSAKeyValue>
                        <xd:RSAKeyValue>
                           <xd:Modulus>cid:137681429226</xd:Modulus>
                           <xd:Exponent>cid:367138859443</xd:Exponent>
                        </xd:RSAKeyValue>
                        <!--You may enter ANY elements at this point-->
                        ac
                     </xd:KeyValue>
                     <xd:RetrievalMethod URI="?" Type="?">
                        <!--Optional:-->
                        <xd:Transforms>
                           <!--1 or more repetitions:-->
                           <xd:Transform Algorithm="?">
                              hoc
                              <!--You have a CHOICE of the next 2 items at this level-->
                              <!--You may enter ANY elements at this point-->
                              <xd:XPath>?</xd:XPath>
                              rapidum
                           </xd:Transform>
                        </xd:Transforms>
                     </xd:RetrievalMethod>
                     <xd:X509Data>
                        <!--You have a CHOICE of the next 6 items at this level-->
                        <xd:X509IssuerSerial>
                           <xd:X509IssuerName>?</xd:X509IssuerName>
                           <xd:X509SerialNumber>?</xd:X509SerialNumber>
                        </xd:X509IssuerSerial>
                        <xd:X509SKI>cid:1458261262390</xd:X509SKI>
                        <xd:X509SubjectName>?</xd:X509SubjectName>
                        <xd:X509Certificate>cid:900472804471</xd:X509Certificate>
                        <xd:X509CRL>cid:853807643670</xd:X509CRL>
                        <!--You may enter ANY elements at this point-->
                     </xd:X509Data>
                     <xd:PGPData>
                        <!--You have a CHOICE of the next 2 items at this level-->
                        <xd:PGPKeyID>cid:1431285563718</xd:PGPKeyID>
                        <!--Optional:-->
                        <xd:PGPKeyPacket>cid:188885434417</xd:PGPKeyPacket>
                        <!--You may enter ANY elements at this point-->
                        <xd:PGPKeyPacket>cid:494088434823</xd:PGPKeyPacket>
                        <!--You may enter ANY elements at this point-->
                     </xd:PGPData>
                     <xd:SPKIData>
                        <xd:SPKISexp>cid:1724923742318</xd:SPKISexp>
                        <!--You may enter ANY elements at this point-->
                     </xd:SPKIData>
                     <xd:MgmtData>?</xd:MgmtData>
                     <!--You may enter ANY elements at this point-->
                     ac
                  </xd:KeyInfo>
                  <!--Zero or more repetitions:-->
                  <xd:Object Id="?" MimeType="?" Encoding="?">
                     caelumque
                     <!--You may enter ANY elements at this point-->
                     speluncis
                  </xd:Object>
               </xd:Signature>
            </sum1:RegistroAnulacion>
         </sum:RegistroFactura>
      </sum:RegFactuSistemaFacturacion>
   </soapenv:Body>
</soapenv:Envelope>
Posts: 318
Joined: Fri Jan 14, 2022 08:37 AM
Re: Veri*Factu
Posted: Mon Dec 16, 2024 08:37 PM
FiveWiDi wrote:Hola a todos,

Ya se tienen algunas piezas del puzzle.

Creo que falta una, ¿Cómo leen Ustedes un XML?

Yo tengo una función pero creo que no es una solución muy ortodoxa, aunque funciona muy bien. El único requisito es saber a priori que Tag son iterativos.

Ya que usar la clase para crear un XML me costó entenderla, pensé que para leerlo me costaría también, por lo que opté por lo que me es fácil, y cuando quiero leer un XML paso su contenido a una array.

Me creé una función LoadXML() que devuelve una Array de arrays tridimensionales, cada array de esta array tiene:
-una cadena del path del tag completo
-el valor que tiene ese tag
-una array de arrays bidimensionales con el atributo y su valor (si tiene atributos)

Defino previamente aTagIter (son los Tags iterativos) que és una array de array bidimensionales, para Verifactu:
Code (fw): Select all Collapse
Local aTagIter  := { { "/env:Envelope/env:Body/tikR:RespuestaRegFactuSistemaFacturacion/tikR:RespuestaLinea/", 0 }, ;
                     { "/env:Envelope/env:Body/tikR:RespuestaRegFactuSistemaFacturacion/tikR:RespuestaLinea/tikR:CodigoErrorRegistro/", 0 }, ;
                     { "/env:Envelope/env:Body/tikR:RespuestaRegFactuSistemaFacturacion/tikR:RespuestaLinea/tikR:DescripcionErrorRegistro/", 0 } ;
                   }


Así es como leo la respuesta a los envíos que hago a Verifactu:
Code (fw): Select all Collapse
//----------------------------------------------------------------------------/
FUNCTION LoadXml( hFile, cBDPathFull, aTagIter )

Local oXmlDoc, oXmlIter
Local lAbreaqui := .F.
//Local oTagActual, oTagLast, aRoots := {}
Local oTagActual, oTagLast := {}

Local litetagA  := ""
Local litetagB  := ""
Local nContador := 0
Local aXml      := {}
Local cDummy    := ""

/* Tag iteratius i sumatori de iteracions trovades.
   L'estructura de l'array es:
   - 1er. element el tag que pot ser iteratiu
   - 2on. element el número de iteració del tag.
*/

/*
Local aTagIter  := { {"/Document/CstmrDrctDbtInitn/PmtInf/", 0}, ;
                     {"/Document/CstmrDrctDbtInitn/PmtInf/DrctDbtTxInf/", 0}, ;
                     {"/Document/CstmrDrctDbtInitn/PmtInf/DrctDbtTxInf/Dbtr/PstlAdr/AdrLine/", 0} }
*/

//Msgnowait( AMPAarra, GetTrad("Atenció!"), GetTrad("Llegint el fitxer: ") + cBDPathFull )


// Cal ordenar la array per a que es puguin controlar correctament les iteracions.
aTagIter := Asort( aTagIter,,, { |x, y| x[1] < y[1] } )

If hFile = 0
    hFile    = FOpen( cBDPathFull )
    lAbreaqui := .T.
EndIf

oXmlDoc  = TXmlDocument():New( hFile )
oXmlIter = TXmlIterator():New( oXmlDoc:oRoot )

oTagActual := oTagLast := Nil
   
litetagA := "/"
   
while ( oTagActual := oXmlIter:Next() ) != nil

    //Traza( 1, "oTagActual:Depth()-oTagActual:cName=", oTagActual:Depth(), "-", oTagActual:cName )

    If oTagLast != nil
      
        if oTagLast:Depth() < oTagActual:Depth()
            litetagA := litetagA + oTagActual:cName + "/"
        endif

        if oTagLast:Depth() > oTagActual:Depth()
            //Traza( 1, "litetagA=", litetagA )
            litetagB := "/"
            For nContador := 1 To ( oTagActual:Depth() - 1 )
                litetagB := litetagB + StrToken( litetagA, nContador, "/" ) + "/"
            EndFor
            litetagA := litetagB
            If Empty(oTagActual:cName)
                litetagA := litetagA + "/"
              Else
                litetagA := litetagA + oTagActual:cName + "/"
            EndIf
            //litetagA := CheckItera( litetagA, aTagIter )
        endif

        if oTagLast:Depth() == oTagActual:Depth()
            //Traza( 1, "litetagA=", litetagA )
            litetagB := "/"
            For nContador := 1 To ( oTagActual:Depth() - 1 )
                litetagB := litetagB + StrToken( litetagA, nContador, "/" ) + "/"
            EndFor
            litetagA := litetagB
            If Empty(oTagActual:cName)
                litetagA := litetagA + "/"
              Else
                litetagA := litetagA + oTagActual:cName + "/"
            EndIf
            //litetagA := CheckItera( litetagA, aTagIter )
        endif
        
        litetagA := CheckItera( litetagA, aTagIter )

      else
      
        If .Not. Empty(oTagActual:cName)
            litetagA := litetagA + oTagActual:cName + "/"
        EndIf
        
        //Traza( 1, "litetagA=", litetagA )
    endif
    
    //litetagA := CheckItera( litetagA, aTagIter )

    // Aquí es captura el TAG, el seu valor y els atributs si en té.
    // exemple: { "/Document/CstmrDrctDbtInitn/PmtInf<1>/DrctDbtTxInf<2>/Dbtr/PstlAdr/AdrLine<1>/", "BARCINO, 29 P-D - SELVA NEGRA", {} }
    //          { "/Document/CstmrDrctDbtInitn/PmtInf<1>/DrctDbtTxInf<2>/Dbtr/PstlAdr/AdrLine<2>/", "08750 Vallirana", {} }

    // Es captura el TAG si té data o si hi han atributs del TAG.
    If .Not. Empty( oTagActual:cData ) .or. Len( oTagActual:aAttributes ) > 0
        AADD( aXml, { litetagA, oTagActual:cData, {} } )
    
        HEval( oTagActual:aAttributes,;
               { | cKey, cData | AADD( ATail( aXml )[3], { cKey, cData } ) } )
    EndIf

    /* En aquesta traza s'enregistren els TAG i els seus valors.
       ------------------------------------------------------ */
    /*
    cDummy := ""
    HEval( oTagActual:aAttributes,;
           { | cKey, cData | cDummy := cDummy + cKey + ":" + cData + "-" } )

    If .Not. Empty( oTagActual:cData ) .or. Len( oTagActual:aAttributes ) > 0
        Traza( 1, "litetagA=", litetagA, "..", oTagActual:cData, "..", cDummy, "..", Len( ATail( aXml )[3]) )
    EndIf
    */
           
    //Traza( 1, "" )
      
    oTagLast = oTagActual
end

If lAbreaqui
    FClose( hFile )
EndIf

//EndMsgNoWait( AMPAarra )

// Podem ordenar l'array... però crec que no serà necessari.
//aXml := Asort( aXml,,, { |x, y| x[1] < y[1] } )

//Traza( 1 , aXml )

Return aXml
//----------------------------------------------------------------------------//
FUNCTION CheckItera( litetagA, aTagIter )

/* litetagA es reb acabat en '/'.

   Aquesta funció es llença al moment d'afegir un node de XML a litetagA, i 
   es comprova si aquest nou node afegit és iteratiu, i si és el cas s'el
   numera. A la resta de nodes que arriberien a 'penjar' d'ell s'els posa
   el numeral a '0', doncs es tractaria d'una nova captura de nodes iteratius.
   
   Per a que la possada a zero de les iteracions que penjen de la que
   estem examinant, cal que aTagIter estigui ordenada ascendentment.
   ------------------------------------------------------------------------ */

Local cCadena     := litetagA
Local nContadorA  := 0
Local nContadorB  := 0
Local PosA        := 0
Local PosB        := 0
Local LenaTagIter := 0
Local LencCadena  := 0

Do While (PosA := AT( "<", cCadena) ) > 0
    //Traza( 1 , "a-cCadena=", cCadena ) 
    PosB := AT( ">", cCadena )
    cCadena := Left( cCadena, PosA - 1 ) + SubStr( cCadena, PosB + 1 )
    //Traza( 1 , "b-cCadena=", cCadena )
End

If ( nContadorA := ASCan( aTagIter, { |aVal| aVal[1] = cCadena } ) ) > 0
    
    /* Poso la resta d'elements iteratius que penjen del que estem examinant a zero (0).
       ------------------------------------------------------------------------------ */
    LenaTagIter := Len(aTagIter)
    LencCadena  := Len(cCadena)
    
    For nContadorB := ( nContadorA + 1 ) To LenaTagIter
        If cCadena = Left( aTagIter[nContadorB][1], LencCadena )
            aTagIter[nContadorB][2] := 0
        EndIf
    EndFor

    aTagIter[ nContadorA ][2] ++
    cCadena :=  Left( litetagA, Len(litetagA) - 1 ) + "<" + AllTrim(Str(aTagIter[ nContadorA ][2], 10,0)) + ">/"
    
  Else
    cCadena   := litetagA
EndIf

Return cCadena
//----------------------------------------------------------------------------//
Prueben a pasarle a LoadXML() un fichero XML y vean el array que les devuelve, hacer un AT() nos facilita recuperar el valor que lleva ese Tag.

Con mucho gusto compartiría mi código, pero no lo tengo tan bien estructurado para aislarlo del programa donde se utiliza, hay demasiadas llamadas a funciones que utilizo para otras cosas.

Si que puedo compartir parte de él y como he resuelto situaciones que voy detectando.

Saludos,

Hola FiveWIDI,

Gracias por tu aporte.

Hay una funcion, no sé si es del core o de contribs que se llama xml2hash() y que hace el trabajo sucio de convertir el xml en hash con lo cual hace la información muy accesible.
Yo la he usado con éxito con el tema del SII.

Salu2
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Veri*Factu
Posted: Wed Dec 18, 2024 08:13 PM

Antonio,

If I read correctly, your last post is the first code of a new class that can be used to create the XML invoices in a correct way. I tested and indeed, it is working.

I would like to help, but my programming skills are not that good. I can test however and share ideas ))))

Do you need more XML info's (fields that are used in the Belgium/Holland xml files ?

Once the XML is made, I will be nessesary to upload it to Peppol (at least in Belgium) but I believe also in the rest of EU.

I participate here in a project for a company that sell invoice system in the cloud. (No impact on the code or see source). My part is using my software to generate

a csv with all data needed to make a invoice. There systhem will import the CSV and process them to a XML. They then will send it to a secure Peppol account.

The business model of them will be to pay a yearly fee for the CSV module and also the Peppol account. You can only connect to Peppol by a official partner and that cannot be me since i'm a end user.

There will be so many users because everybody with a own made program, exel invoice etc.... can make a CVS to upload. XML programming will be more complex, but a MUST for FWin, so keep on working.

Marc Venken

Using: FWH 23.08 with Harbour
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Veri*Factu
Posted: Wed Dec 18, 2024 09:49 PM
Dear Marc,

Many thanks for your feedback

We already have a Class TXml that creates the invoice XML. Next is to complete the invoice details as needed.

Then we will sign it and send it. With the feedback and help from all surely we can do it :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Veri*Factu
Posted: Fri Dec 20, 2024 03:56 PM
I would like to try a other approuch. Looking at some Xml invoices, you see that they are not the same, but the items used are always named the same . (some have more items)

I take a random xml invoice that is compliant with the norm we need to use (we all recive already xml invoices from companys)

The Fwin function FW_XmlView( hFile ) will give all items from the invoice.
Option 2 : read with tXml

Put all items in a dbf and once map these items with dbf items from customers, invoices etc. for all items needed.

ID = Customer->ID
ISSUEDATE = Invoice->DATUM
etc...

Once created, this dbf will be called while invoicing and it will loop from 1 to xxx and process the invoice data into a Xml
The part with the invoice lines (detail) will be a second loop.

I think this can work. The final dbf can always be updated with extra items or changes.

What do you think ?? This code is only the code to show the items. Rest is not programmed yet
Code (fw): Select all Collapse
#include "fivewin.ch"

ANNOUNCE RDDSYS
REQUEST OrdKeyNo, OrdKeyCount, OrdCreate, OrdKeyGoto
REQUEST DBFCDX, DBFFPT, DBFDBT

FUNCTION Main()

   LOCAL oWnd
   LOCAL oBar
   LOCAL cTitle := "Testing Software module"

   PUBLIC lDebug:= .f.
   RDDSETDEFAULT("DBFCDX")
   DEFINE WINDOW oWnd TITLE cTitle

   DEFINE BUTTONBAR oBar OF oWnd 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar;
      CENTER;
      PROMPT "Test";
      ACTION xmlreader()

   ACTIVATE WINDOW oWnd;
      MAXIMIZED

   RETURN Nil

function Xmlreader()
   local aMail:={},nTel:= 1, i, aData:={}
   local hFile    := FOpen( "armor.xml" ) // random xmlfile
   Local aStruct := {}
   Local oXmlDoc  := TXmlDocument():New( hFile )
   Local oXmlIter := TXmlIterator():New( oXmlDoc:oRoot ), oTagActual
   Local cKleur, cHex, cId

   FW_XmlView( hFile )

   nTel = 1
   while .T.
      oTagActual = oXmlIter:Next()
      If oTagActual != nil
         aadd(aMail ,{oTagActual:cName,oTagActual:cData} )
         aadd(aData,oTagActual)
         //  Make code to fill a DBF (Xbrowse) with items and also with dbf customer and invoice mapped data
      Else
         Exit
      Endif
   End

   xbrowser(aMail)
   xbrowser(aData)

   FClose( hFile )
   close all
return nil
Marc Venken

Using: FWH 23.08 with Harbour
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Veri*Factu
Posted: Fri Dec 20, 2024 04:04 PM

Off cource, when the Veri*Factu is ready to publish, I need to change my way.

Marc Venken

Using: FWH 23.08 with Harbour
Posts: 309
Joined: Wed Mar 28, 2018 04:38 PM
Re: Veri*Factu
Posted: Wed Jan 29, 2025 07:26 AM
Buenos días.

Nuevas publicaciones de la AEAT al respecto de Verifactu:

https://www.agenciatributaria.es/AEAT.desarrolladores/Desarrolladores/Desarrolladores.html
--------

¿ Y porque no ?

¿ And why not ?
Posts: 73
Joined: Wed Oct 12, 2005 06:58 PM
Re: Veri*Factu
Posted: Fri Feb 07, 2025 05:34 PM

No se qué estoy haciendo mal. Intento compilar estos ejemplos de Antonio incluyendo los ficheros de cabecera que tienen como "include" y no me encuentra unas funciones.


Lines 6139, Functions/Procedures 4

Generating C source output to 'MainYFun.c'... Done.

Embarcadero C++ 7.00 for Win32 Copyright (c) 1993-2015 Embarcadero Technologies, Inc.

MainYFun.c:

Turbo Incremental Link 6.70 Copyright (c) 1997-2014 Embarcadero Technologies, Inc.

Error: Unresolved external '_HB_FUN_HB_XMLDOCUMENT' referenced from C:\HARBPROG__NUEVA_VERIFACT\CODIGO\A_LINARES\ULTIMO\MAINYFUN.OBJ

Error: Unresolved external '_HB_FUN_HB_XMLNODE' referenced from C:\HARBPROG__NUEVA_VERIFACT\CODIGO\A_LINARES\ULTIMO\MAINYFUN.OBJ

Error: Unresolved external '_HB_FUN_HB_CURLEASYINIT' referenced from C:\HARBPROG__NUEVA_VERIFACT\CODIGO\A_LINARES\ULTIMO\MAINYFUN.OBJ

Error: Unresolved external '_HB_FUN_HB_CURLEASYSETOPT' referenced from C:\HARBPROG__NUEVA_VERIFACT\CODIGO\A_LINARES\ULTIMO\MAINYFUN.OBJ

Error: Unresolved external '_HB_FUN_HB_CURLEASYPERFORM' referenced from C:\HARBPROG__NUEVA_VERIFACT\CODIGO\A_LINARES\ULTIMO\MAINYFUN.OBJ

Error: Unresolved external '_HB_FUN_HB_CURLEASYCLEANUP' referenced from C:\HARBPROG__NUEVA_VERIFACT\CODIGO\A_LINARES\ULTIMO\MAINYFUN.OBJ

Error: Unable to perform link

  • Linking errors *

Si alguno puede ver qué me falta y me lo dice se lo agradeceré. Un saludo y muchas gracias por enseñar al que no sabe.

Saludos

julio@cepedaserinf.es
FiveWin 25.06 + Harbour 3.2.0dev (r2503251254), BCC 7 Windows 11
Posts: 410
Joined: Sun Jan 31, 2010 03:30 PM
Re: Veri*Factu
Posted: Thu Mar 06, 2025 01:57 AM

Buena noche...

Antonio es posible obtener el harbour y la version de c, con las lib externas para probar

FUNCTION EnviarFactura(cUrl, cSignedXmlFile)

oCurl := hb_curlEasyInit()

Dado que yo uso : xharbour comercial

Gracias

JONSSON RUSSI

Colombia

Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Veri*Factu
Posted: Fri Mar 07, 2025 06:09 AM
Pido disculpas, este es el código correcto para que construya bien, no está probado:
#include "hbcurl.ch"

function EnviarFactura( cUrl, cSignedXmlFile )

    local hCurl, cSoapRequest, cSoapResponse, cFacturaXml

    cFacturaXml = MemoRead( cSignedXmlFile )

    // Crear la solicitud SOAP
    cSoapRequest = ;
        '<?xml version="1.0" encoding="UTF-8"?>' + ;
        '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:veri="http://www.aeat.es/VeriFactu">' + ;
        '<soapenv:Header/>' + ;
        '<soapenv:Body>' + ;
        '<veri:EnviarFactura>' + ;
        '<veri:FacturaXML><![CDATA[' + cFacturaXml + ']]></veri:FacturaXML>' + ;
        '</veri:EnviarFactura>' + ;
        '</soapenv:Body>' + ;
        '</soapenv:Envelope>'

    hCurl = curl_easy_init()
    curl_easy_setopt( hCurl, HB_CURLOPT_URL, cUrl )
    curl_easy_setopt( hCurl, HB_CURLOPT_POSTFIELDS, cSoapRequest )
    curl_easy_setopt( hCurl, HB_CURLOPT_HTTPHEADER, { "Content-Type: text/xml", "SOAPAction: EnviarFactura" } )
    curl_easy_setopt( hCurl, HB_CURLOPT_SSLCERT, "ruta_certificado.pem" )
    curl_easy_setopt( hCurl, HB_CURLOPT_SSLCERTPASSWD, "password_certificado" )

    cSoapResponse = curl_easy_perform( hCurl )

    if Empty( cSoapResponse )
        MsgStop( "Error al enviar la factura." )
    else
        MsgInfo( "Respuesta del servidor: " + cSoapResponse )
    endif

    curl_easy_cleanup( hCurl )

return nil
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 410
Joined: Sun Jan 31, 2010 03:30 PM
Re: Veri*Factu
Posted: Fri Mar 07, 2025 03:33 PM

Antonio.. buen día

Ya lo pude compilar, el xml está bien armado (lo envió con soapUI y llega a la DIAN),

pero desde la app de ejemplo, me genera en "cSoapResponse" el codigo "58"... ahora lo probe con un certificado .p12 y también con un .pem (convertido el .p12)

Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Veri*Factu
Posted: Fri Mar 07, 2025 03:37 PM

Cual es el valor completo de cSoapResponse ?

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 410
Joined: Sun Jan 31, 2010 03:30 PM
Re: Veri*Factu
Posted: Fri Mar 07, 2025 05:12 PM

Antonio.. solo regresa ese valor... al correo le envié todo para que lo pueda ejecutar

Gracias

Posts: 410
Joined: Sun Jan 31, 2010 03:30 PM
Re: Veri*Factu
Posted: Fri Mar 07, 2025 05:42 PM

Se puede ver con algún método el xml final después de agregar el certificado ??

Posts: 410
Joined: Sun Jan 31, 2010 03:30 PM
Re: Veri*Factu
Posted: Thu Mar 13, 2025 12:18 PM
Buen dia..

Con el siguiente APP obtengo como respuesta este código : "58"...
Alguien usa esta clase : curl (curl_easy_init)

Gracias
JONSSON RUSSI
#include "FiveWin.ch"
#include "hbcurl.ch"

function main()

local cUrl := "https://vpfe.dian.gov.co/WcfDianCustomerServices.svc"
local cSignedXmlFile := "E:\TEMP\XML_FIRMADO\z006331767200025SP104100000250_fv_B64"
local cNomZip := "z006331767200025SP104100000250.zip"

EnviarFactura( cUrl, cSignedXmlFile,cNomZip )

return


function EnviarFactura( cUrl, cSignedXmlFile, cNomZip )

    local hCurl, cSoapRequest, cSoapResponse, cFacturaXml

    cFilCer := "E:\ZERUS\FIRMA_ELECTRONICA\CERT\CERTIFICADO_29.P12"
    cClaCer := "DeexTz0tttreuQrTu2Lj0" 

    cFacturaXml = MemoRead( cSignedXmlFile )

    // Crear la solicitud SOAP
    cSoapRequest = ;
        '<?xml version="1.0" encoding="UTF-8"?>' + ;
        '<soapenv:Envelope xmlns:soapenv=http://www.w3.org/2003/05/soap-envelope xmlns:wcf=http://wcf.dian.colombia>' + ;
        '<soapenv:Header/>'+;
        '<soapenv:Body>' + ;
        '<wcf:SendBillSync>' + ;
        '<wcf:fileName>' + cNomZip +'</wcf:fileName>' + ;
        '<wcf:contentFile>' + cFacturaXml + '</wcf:contentFile>' + ;
        '</wcf:SendBillSync>' + ;
        '</soapenv:Body>' + ;
        '</soapenv:Envelope>'

   HB_MEMOWRIT( "PRUEBA.XML", cSoapRequest )

    hCurl = curl_easy_init()
    curl_easy_setopt( hCurl, HB_CURLOPT_URL, cUrl )
    curl_easy_setopt( hCurl, HB_CURLOPT_POSTFIELDS, cSoapRequest )
    curl_easy_setopt( hCurl, HB_CURLOPT_HTTPHEADER, { "Content-Type: application/soap+xml; charset=utf-8", "SOAPAction: http://wcf.dian.colombia/IWcfDianCustomerServices/SendBillSync" } )
    curl_easy_setopt( hCurl, HB_CURLOPT_SSLCERT, cFilCer )
    curl_easy_setopt( hCurl, HB_CURLOPT_SSLCERTPASSWD, cClaCer )

    cSoapResponse = curl_easy_perform( hCurl )


    if Empty( cSoapResponse )
        MsgStop( "Error al enviar la factura." )
    else
        MsgInfo( "Respuesta del servidor: " + if(valtype(cSoapResponse)=="C",cSoapResponse,STR(cSoapResponse) ) )
    endif

    curl_easy_cleanup( hCurl )

return nil