Imports System.IO Imports System.Xml Imports System.Xml.Serialization Imports System.Xml.XPath Imports System.Xml.Xsl Imports DigitalData.Modules.Interfaces.Exceptions Imports DigitalData.Modules.Logging Imports GdPicture14 Public Class ZUGFeRDInterface Private _logConfig As LogConfig Private _logger As Logger Public Enum ErrorType NoValidFile NoZugferd NoValidZugferd MissingProperties End Enum Public ReadOnly Property FileGroup As FileGroups Public ReadOnly Property PropertyValues As PropertyValues Public Sub New(LogConfig As LogConfig, GDPictureKey As String) _logConfig = LogConfig _logger = _logConfig.GetLogger() FileGroup = New FileGroups(_logConfig) PropertyValues = New PropertyValues(_logConfig) Try Dim oLicenseManager As New LicenseManager oLicenseManager.RegisterKEY(GDPictureKey) Catch ex As Exception _logger.Warn("GDPicture License could not be registered!") _logger.Error(ex) End Try End Sub ''' ''' Validates a ZUGFeRD File and extracts the XML Document from it ''' ''' ''' ''' Public Function ExtractZUGFeRDFileWithGDPicture(Path As String) As Object Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Path) If IsNothing(oXmlDocument) Then Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.") End If Return SerializeZUGFeRDDocument(oXmlDocument) End Function ''' ''' Validates a ZUGFeRD File and extracts the XML Document from it ''' ''' ''' ''' Public Function ExtractZUGFeRDFileWithGDPicture(Stream As Stream) As Object Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Stream) If IsNothing(oXmlDocument) Then Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.") End If Return SerializeZUGFeRDDocument(oXmlDocument) End Function ''' ''' Validates a ZUGFeRD File and extracts the XML Document from it ''' ''' ''' ''' Public Function ValidateZUGFeRDFileWithGDPicture(Stream As Stream) As XPathDocument Dim oEmbedExtractor = New PDFEmbeds(_logConfig) Dim oAllowedExtensions = New List(Of String) From {"xml"} Try Dim oFiles = oEmbedExtractor.Extract(Stream, oAllowedExtensions) ' Attachments are in this case the files that are embedded into a pdf file, ' like for example the zugferd-invoice.xml file Return HandleEmbeddedFiles(oFiles) Catch ex As ZUGFeRDExecption ' Don't log ZUGFeRD Exceptions here, they should be handled by the calling code. ' It also produces misleading error messages when checking if an attachment is a zugferd file. Throw ex Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Function ValidateZUGFeRDFileWithGDPicture(Path As String) As XPathDocument Dim oEmbedExtractor = New PDFEmbeds(_logConfig) Dim oAllowedExtensions = New List(Of String) From {"xml"} Try Dim oFiles = oEmbedExtractor.Extract(Path, oAllowedExtensions) ' Attachments are in this case the files that are embedded into a pdf file, ' like for example the zugferd-invoice.xml file Return HandleEmbeddedFiles(oFiles) Catch ex As ZUGFeRDExecption ' Don't log ZUGFeRD Exceptions here, they should be handled by the calling code. ' It also produces misleading error messages when checking if an attachment is a zugferd file. Throw ex Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Private Function HandleEmbeddedFiles(Results As List(Of PDFEmbeds.EmbeddedFile)) As XPathDocument Dim oXmlDocument As XPathDocument If Results Is Nothing Then Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil die Attachments nicht gelesen werden konnten.") End If If Results.Count = 0 Then Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil sie keine Attachments enthält.") End If Dim oValidFilenames As New List(Of String) From { PDFEmbeds.ZUGFERD_XML_FILENAME.ToUpper, PDFEmbeds.FACTUR_X_XML_FILENAME_DE.ToUpper, PDFEmbeds.FACTUR_X_XML_FILENAME_FR.ToUpper } ' Find the first file which filename matches the valid filenames for embedded invoice files Dim oFoundResult As PDFEmbeds.EmbeddedFile = Results. Where(Function(result) oValidFilenames.Contains(result.FileName.ToUpper)). FirstOrDefault() If oFoundResult Is Nothing Then Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil die zugferd-invoice.xml nicht gefunden wurde.") End If Try Using oStream As New MemoryStream(oFoundResult.FileContents) oXmlDocument = New XPathDocument(oStream) End Using Return oXmlDocument Catch ex As ZUGFeRDExecption ' Don't log ZUGFeRD Exceptions here, they should be handled by the calling code. ' It also produces misleading error messages when checking if an attachment is a zugferd file. Throw ex Catch ex As Exception _logger.Error(ex) Throw New ZUGFeRDExecption(ErrorType.NoValidZugferd, "Datei ist eine ungültige ZUGFeRD Datei.") End Try End Function Public Function SerializeZUGFeRDDocument(Document As XPathDocument) As Object Try Dim oNavigator As XPathNavigator = Document.CreateNavigator() Dim oReader As XmlReader Dim oResult = Nothing Dim oTypes As New List(Of Type) From { GetType(ZUGFeRD.Version1_0.CrossIndustryDocumentType), GetType(ZUGFeRD.Version2_0.CrossIndustryInvoiceType), GetType(ZUGFeRD.Version2_1_1.CrossIndustryInvoiceType), GetType(ZUGFeRD.Version2_2_FacturX.CrossIndustryInvoiceType) } For Each oType In oTypes _logger.Debug("Trying Type [{0}]", oType.FullName) Dim oSerializer As New XmlSerializer(oType) Try oReader = oNavigator.ReadSubtree() oResult = oSerializer.Deserialize(oReader) _logger.Debug("Serializing with type [{0}] succeeded", oType.FullName) Exit For Catch ex As Exception _logger.Debug("Serializing with type [{0}] failed", oType.FullName) _logger.Debug(ex.Message) _logger.Error(ex.InnerException?.Message) End Try Next If oResult Is Nothing Then Throw New ApplicationException("No Types matched the given document. Document could not be serialized.") End If Return oResult Catch ex As Exception _logger.Error(ex) Throw New ZUGFeRDExecption(ErrorType.NoValidZugferd, "Datei ist eine ungültige ZUGFeRD Datei.") End Try End Function End Class