ESTRUTURA CORRETA PARA GERAÇÃO DO QRCOD NO XML
Bom dia rapaziada estou enfrentando um problema na montagem da estrutura do QRCod no xml, minhas tentativas não surtiram efeito até agora vou posta como estou fazendo e se puderem me da uma ajuda, Uso a Sefaz Mato grosso.Função que gera o xml
Private Function CriarXmlNFCe(dados As DadosNFCeCompletos) As String
Try
Dim ns = XNamespace.Get("http://www.portalfiscal.inf.br/nfe")
' Garantir série e número
If dados.Serie <= 0 AndAlso Not String.IsNullOrEmpty(strEmitenteSerieBanco) Then
Integer.TryParse(strEmitenteSerieBanco, dados.Serie)
End If
If dados.NumeroNF <= 0 AndAlso Not String.IsNullOrEmpty(strEmitenteProximoNumero) Then
Integer.TryParse(strEmitenteProximoNumero, dados.NumeroNF)
dados.NumeroNFCe = dados.NumeroNF
End If
' Construir infNFe
Dim infNFe = New XElement(ns + "infNFe",
New XAttribute("Id", $"NFe{dados.ChaveAcesso}"),
New XAttribute("versao", "4.00"),
CriarIde(ns, dados),
CriarEmitente(ns, dados),
CriarDestinatario(ns, dados),
CriarItens(ns, dados),
CriarTotal(ns, dados),
CriarTransporte(ns),
CriarPagamento(ns, dados),
CriarInformacoesAdicionais(ns, dados)
)
' Documento inicial
Dim xmlFinal As New XDocument(
New XDeclaration("1.0", "UTF-8", "yes"),
New XElement(ns + "NFe", infNFe)
)
' Ajustar apenas dhEmi (não sobrescrever tpEmis!)
Dim ideEl = infNFe.Elements().FirstOrDefault(Function(e) e.Name.LocalName = "ide")
If ideEl IsNot Nothing Then
Dim dhEmiEl = ideEl.Elements().FirstOrDefault(Function(e) e.Name.LocalName = "dhEmi")
If dhEmiEl IsNot Nothing Then
dhEmiEl.Value = DateTimeOffset.Now.ToString("yyyy-MM-ddTHH:mm:sszzz")
End If
End If
' Assinar XML
Dim assinatura As New AssinaturaDigitalMelhorada()
' CRÍTICO: Obter string assinada e NÃO parsear de volta para XDocument para evitar quebra de assinatura
Dim xmlAssinadoString As String = assinatura.AssinarXml(xmlFinal.ToString(SaveOptions.DisableFormatting), "infNFe")
' QR Code
Dim chave = dados.ChaveAcesso
Dim tpAmbNode = xmlFinal.Descendants().FirstOrDefault(Function(e) e.Name.LocalName = "tpAmb")
Dim tpAmb As String = If(tpAmbNode IsNot Nothing, tpAmbNode.Value.Trim(), "1")
Dim tpEmisNode = xmlFinal.Descendants().FirstOrDefault(Function(e) e.Name.LocalName = "tpEmis")
Dim tpEmis As String = If(tpEmisNode IsNot Nothing, tpEmisNode.Value.Trim(), "1")
Dim idTokenRaw = stremitenteIDCSC
Dim apenasDigitos = New String((If(idTokenRaw, "")).Where(AddressOf Char.IsDigit).ToArray())
Dim idToken As String = NormalizarIdToken(apenasDigitos)
Dim csc = strEmitenteCodigoCSC
Dim uf = dados.Emitente.UF.ToUpper().Trim()
' Ajuste URL para Mato Grosso (MT) - Versão 2.0
Dim baseUrl As String = If(tpAmb = "2", "https://homologacao.sefaz.mt.gov.br", "https://www.sefaz.mt.gov.br")
Dim pathOnline = "/nfce/consultanfce"
Dim pathOffline = "/nfce/consultanfce"
Dim versao As String = "2"
Dim qrCodeUrl As String
_logger.LogInfo($"[DEBUG QRCODE] Contingencia (Flag): {dados.EmitidaEmContingencia}, tpEmis (XML): {tpEmis}")
' Validar consistência
If dados.EmitidaEmContingencia AndAlso tpEmis = "1" Then
_logger.LogWarning("[ALERTA] Inconsistência detectada: Flag Contingência=TRUE mas tpEmis=1. Forçando QR Code Online para manter consistência com XML.")
ElseIf Not dados.EmitidaEmContingencia AndAlso tpEmis = "9" Then
_logger.LogWarning("[ALERTA] Inconsistência detectada: Flag Contingência=FALSE mas tpEmis=9. Forçando QR Code Offline para manter consistência com XML.")
End If
' USAR tpEmis DO XML PARA DECIDIR FORMATO DO QR CODE
If tpEmis = "9" Then
' Contingência Offline (tpEmis=9): Requer dados da assinatura (DigestValue) e dhEmi (Dia)
Dim startDigest = xmlAssinadoString.IndexOf("") + 13
Dim endDigest = xmlAssinadoString.IndexOf("")
If startDigest < 13 OrElse endDigest < 0 Then
Throw New Exception("DigestValue não encontrado no XML assinado (necessário para QR Code Offline)")
End If
Dim digValBase64 = xmlAssinadoString.Substring(startDigest, endDigest - startDigest)
Dim digestBytes = Convert.FromBase64String(digValBase64)
Dim sbHex As New StringBuilder()
For Each b As Byte In digestBytes
sbHex.Append(b.ToString("X2"))
Next
Dim digValHex = sbHex.ToString()
' Extrair dhEmi completo do XML assinado
Dim startDhEmi = xmlAssinadoString.IndexOf("") + 7
Dim endDhEmi = xmlAssinadoString.IndexOf("")
If startDhEmi < 7 OrElse endDhEmi < 0 Then
Throw New Exception("dhEmi não encontrado no XML (necessário para QR Code Offline)")
End If
Dim dhEmiCompleta = xmlAssinadoString.Substring(startDhEmi, endDhEmi - startDhEmi).Trim()
' Para QR Code V2 Offline, usar apenas o DIA (dd)
Dim diaEmissao = dhEmiCompleta.Substring(8, 2)
Dim valorTotal = dados.ValorTotal.ToString("F2", CultureInfo.InvariantCulture)
' Gerar Hash com o DIA
Dim hash = GerarHashQRCodeOffline(chave, versao, tpAmb, diaEmissao, valorTotal, digValHex, idToken, csc)
qrCodeUrl = $"{baseUrl}{pathOffline}?p={chave}|{versao}|{tpAmb}|{diaEmissao}|{valorTotal}|{digValHex}|{idToken}|{hash}"
Else
' Normal (tpEmis=1): QR Code Online simples
Dim hash = GerarHashQRCode(chave, versao, tpAmb, idToken, csc)
qrCodeUrl = $"{baseUrl}{pathOnline}?p={chave}|{versao}|{tpAmb}|{idToken}|{hash}"
End If
_logger.LogInfo($"[DEBUG QRCODE] URL Gerada: {qrCodeUrl}")
Dim urlChaveBase = $"{baseUrl}{pathOnline}"
' Criar infNFeSupl usando XElement para garantir namespace correto, depois converter para string
Dim infSupl As New XElement(ns + "infNFeSupl",
New XElement(ns + "qrCode", qrCodeUrl),
New XElement(ns + "urlChave", urlChaveBase)
)
Dim infSuplString = infSupl.ToString(SaveOptions.DisableFormatting)
' Inserir infNFeSupl via manipulação de string para PRESERVAR ASSINATURA
' Local: APÓS e ANTES de <Signature
' A assinatura geralmente vem logo após
Dim posInfNFeEnd = xmlAssinadoString.IndexOf("")
If posInfNFeEnd > -1 Then
posInfNFeEnd += 9 ' Comprimento de
' Inserir logo após
xmlAssinadoString = xmlAssinadoString.Insert(posInfNFeEnd, infSuplString)
Else
' Fallback (não deve acontecer)
Throw New Exception("Elemento não encontrado para inserção do QR Code")
End If
' Atualiza a propriedade UltimoXmlAssinado
UltimoXmlAssinado = xmlAssinadoString
_logger.LogSuccess("XML assinado e pronto para envio à SEFAZ")
Return xmlAssinadoString
Catch ex As Exception
_logger.LogError($"Erro em CriarXmlNFCe: {ex.Message}")
Throw New Exception("Falha ao gerar XML da NFC-e", ex)
End Try
End Function
Private Function CriarXmlNFCe(dados As DadosNFCeCompletos) As String
Try
Dim ns = XNamespace.Get("http://www.portalfiscal.inf.br/nfe")
' Garantir série e número
If dados.Serie <= 0 AndAlso Not String.IsNullOrEmpty(strEmitenteSerieBanco) Then
Integer.TryParse(strEmitenteSerieBanco, dados.Serie)
End If
If dados.NumeroNF <= 0 AndAlso Not String.IsNullOrEmpty(strEmitenteProximoNumero) Then
Integer.TryParse(strEmitenteProximoNumero, dados.NumeroNF)
dados.NumeroNFCe = dados.NumeroNF
End If
' Construir infNFe
Dim infNFe = New XElement(ns + "infNFe",
New XAttribute("Id", $"NFe{dados.ChaveAcesso}"),
New XAttribute("versao", "4.00"),
CriarIde(ns, dados),
CriarEmitente(ns, dados),
CriarDestinatario(ns, dados),
CriarItens(ns, dados),
CriarTotal(ns, dados),
CriarTransporte(ns),
CriarPagamento(ns, dados),
CriarInformacoesAdicionais(ns, dados)
)
' Documento inicial
Dim xmlFinal As New XDocument(
New XDeclaration("1.0", "UTF-8", "yes"),
New XElement(ns + "NFe", infNFe)
)
' Ajustar apenas dhEmi (não sobrescrever tpEmis!)
Dim ideEl = infNFe.Elements().FirstOrDefault(Function(e) e.Name.LocalName = "ide")
If ideEl IsNot Nothing Then
Dim dhEmiEl = ideEl.Elements().FirstOrDefault(Function(e) e.Name.LocalName = "dhEmi")
If dhEmiEl IsNot Nothing Then
dhEmiEl.Value = DateTimeOffset.Now.ToString("yyyy-MM-ddTHH:mm:sszzz")
End If
End If
' Assinar XML
Dim assinatura As New AssinaturaDigitalMelhorada()
' CRÍTICO: Obter string assinada e NÃO parsear de volta para XDocument para evitar quebra de assinatura
Dim xmlAssinadoString As String = assinatura.AssinarXml(xmlFinal.ToString(SaveOptions.DisableFormatting), "infNFe")
' QR Code
Dim chave = dados.ChaveAcesso
Dim tpAmbNode = xmlFinal.Descendants().FirstOrDefault(Function(e) e.Name.LocalName = "tpAmb")
Dim tpAmb As String = If(tpAmbNode IsNot Nothing, tpAmbNode.Value.Trim(), "1")
Dim tpEmisNode = xmlFinal.Descendants().FirstOrDefault(Function(e) e.Name.LocalName = "tpEmis")
Dim tpEmis As String = If(tpEmisNode IsNot Nothing, tpEmisNode.Value.Trim(), "1")
Dim idTokenRaw = stremitenteIDCSC
Dim apenasDigitos = New String((If(idTokenRaw, "")).Where(AddressOf Char.IsDigit).ToArray())
Dim idToken As String = NormalizarIdToken(apenasDigitos)
Dim csc = strEmitenteCodigoCSC
Dim uf = dados.Emitente.UF.ToUpper().Trim()
' Ajuste URL para Mato Grosso (MT) - Versão 2.0
Dim baseUrl As String = If(tpAmb = "2", "https://homologacao.sefaz.mt.gov.br", "https://www.sefaz.mt.gov.br")
Dim pathOnline = "/nfce/consultanfce"
Dim pathOffline = "/nfce/consultanfce"
Dim versao As String = "2"
Dim qrCodeUrl As String
_logger.LogInfo($"[DEBUG QRCODE] Contingencia (Flag): {dados.EmitidaEmContingencia}, tpEmis (XML): {tpEmis}")
' Validar consistência
If dados.EmitidaEmContingencia AndAlso tpEmis = "1" Then
_logger.LogWarning("[ALERTA] Inconsistência detectada: Flag Contingência=TRUE mas tpEmis=1. Forçando QR Code Online para manter consistência com XML.")
ElseIf Not dados.EmitidaEmContingencia AndAlso tpEmis = "9" Then
_logger.LogWarning("[ALERTA] Inconsistência detectada: Flag Contingência=FALSE mas tpEmis=9. Forçando QR Code Offline para manter consistência com XML.")
End If
' USAR tpEmis DO XML PARA DECIDIR FORMATO DO QR CODE
If tpEmis = "9" Then
' Contingência Offline (tpEmis=9): Requer dados da assinatura (DigestValue) e dhEmi (Dia)
Dim startDigest = xmlAssinadoString.IndexOf("") + 13
Dim endDigest = xmlAssinadoString.IndexOf("")
If startDigest < 13 OrElse endDigest < 0 Then
Throw New Exception("DigestValue não encontrado no XML assinado (necessário para QR Code Offline)")
End If
Dim digValBase64 = xmlAssinadoString.Substring(startDigest, endDigest - startDigest)
Dim digestBytes = Convert.FromBase64String(digValBase64)
Dim sbHex As New StringBuilder()
For Each b As Byte In digestBytes
sbHex.Append(b.ToString("X2"))
Next
Dim digValHex = sbHex.ToString()
' Extrair dhEmi completo do XML assinado
Dim startDhEmi = xmlAssinadoString.IndexOf("") + 7
Dim endDhEmi = xmlAssinadoString.IndexOf("")
If startDhEmi < 7 OrElse endDhEmi < 0 Then
Throw New Exception("dhEmi não encontrado no XML (necessário para QR Code Offline)")
End If
Dim dhEmiCompleta = xmlAssinadoString.Substring(startDhEmi, endDhEmi - startDhEmi).Trim()
' Para QR Code V2 Offline, usar apenas o DIA (dd)
Dim diaEmissao = dhEmiCompleta.Substring(8, 2)
Dim valorTotal = dados.ValorTotal.ToString("F2", CultureInfo.InvariantCulture)
' Gerar Hash com o DIA
Dim hash = GerarHashQRCodeOffline(chave, versao, tpAmb, diaEmissao, valorTotal, digValHex, idToken, csc)
qrCodeUrl = $"{baseUrl}{pathOffline}?p={chave}|{versao}|{tpAmb}|{diaEmissao}|{valorTotal}|{digValHex}|{idToken}|{hash}"
Else
' Normal (tpEmis=1): QR Code Online simples
Dim hash = GerarHashQRCode(chave, versao, tpAmb, idToken, csc)
qrCodeUrl = $"{baseUrl}{pathOnline}?p={chave}|{versao}|{tpAmb}|{idToken}|{hash}"
End If
_logger.LogInfo($"[DEBUG QRCODE] URL Gerada: {qrCodeUrl}")
Dim urlChaveBase = $"{baseUrl}{pathOnline}"
' Criar infNFeSupl usando XElement para garantir namespace correto, depois converter para string
Dim infSupl As New XElement(ns + "infNFeSupl",
New XElement(ns + "qrCode", qrCodeUrl),
New XElement(ns + "urlChave", urlChaveBase)
)
Dim infSuplString = infSupl.ToString(SaveOptions.DisableFormatting)
' Inserir infNFeSupl via manipulação de string para PRESERVAR ASSINATURA
' Local: APÓS e ANTES de <Signature
' A assinatura geralmente vem logo após
Dim posInfNFeEnd = xmlAssinadoString.IndexOf("")
If posInfNFeEnd > -1 Then
posInfNFeEnd += 9 ' Comprimento de
' Inserir logo após
xmlAssinadoString = xmlAssinadoString.Insert(posInfNFeEnd, infSuplString)
Else
' Fallback (não deve acontecer)
Throw New Exception("Elemento não encontrado para inserção do QR Code")
End If
' Atualiza a propriedade UltimoXmlAssinado
UltimoXmlAssinado = xmlAssinadoString
_logger.LogSuccess("XML assinado e pronto para envio à SEFAZ")
Return xmlAssinadoString
Catch ex As Exception
_logger.LogError($"Erro em CriarXmlNFCe: {ex.Message}")
Throw New Exception("Falha ao gerar XML da NFC-e", ex)
End Try
End Function
https://www.vbmania.com.br/forum/abrir/fonte-nfc-e-consulta-envio-e-q---503706
Faça seu login para responder