diff --git a/DFe.Testes/Gerais/ObterIdTestes.cs b/DFe.Testes/Gerais/ObterIdTestes.cs new file mode 100644 index 000000000..2733d6e47 --- /dev/null +++ b/DFe.Testes/Gerais/ObterIdTestes.cs @@ -0,0 +1,61 @@ +using DFe.Classes.Entidades; +using DFe.Classes.Flags; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NFe.Classes.Servicos.Tipos; +using NFe.Utils.Evento; +using NFe.Utils.Inutilizacao; + +namespace DFe.Testes.Gerais +{ + /// + /// Vetores ouro do Id assinável de evento (infEvento/@Id) e de inutilização (infInut/@Id). + /// + /// Esses Ids também são calculados internamente pelos métodos que assinam (ServicosNFe). Se o formato + /// divergir, o digest da assinatura não bate e o SEFAZ rejeita — por isso os valores esperados aqui são + /// literais do layout, e não o resultado do próprio método. + /// + /// + [TestClass] + public class ObterIdTestes + { + /// Chave de NF-e (modelo 55) com CNPJ alfanumérico, conforme NT Conjunta 2025.001 + private const string ChaveNFe = "522507PC3D315K000193550010000000011000000018"; + + /// Chave de NFC-e (modelo 65), 100% numérica + private const string ChaveNFCe = "23190811820016000167650010000000221100000227"; + + private const string CnpjNumerico = "11820016000167"; + private const string CnpjAlfanumerico = "PC3D315K000193"; + + [TestMethod] + [DataRow(NFeTipoEvento.TeNfeCancelamento, ChaveNFe, 1, "ID110111" + ChaveNFe + "01", + DisplayName = "Cancelamento, chave com CNPJ alfanumérico")] + [DataRow(NFeTipoEvento.TeNfeCartaCorrecao, ChaveNFe, 2, "ID110110" + ChaveNFe + "02", + DisplayName = "Carta de Correção, 2ª sequência")] + [DataRow(NFeTipoEvento.TeMdCienciaDaOperacao, ChaveNFCe, 1, "ID210210" + ChaveNFCe + "01", + DisplayName = "Ciência da Operação, chave numérica")] + [DataRow(NFeTipoEvento.TeMdCienciaDaOperacao, ChaveNFCe, 11, "ID210210" + ChaveNFCe + "11", + DisplayName = "Sequência com 2 dígitos não recebe zero à esquerda")] + public void ObterIdEvento_SegueOLayout(NFeTipoEvento tpEvento, string chNFe, int nSeqEvento, string esperado) + { + Assert.AreEqual(esperado, Extevento.ObterId(tpEvento, chNFe, nSeqEvento)); + } + + [TestMethod] + [DataRow(ModeloDocumento.NFe, CnpjNumerico, 1, 1, 10, + "ID3525" + CnpjNumerico + "55" + "001" + "000000001" + "000000010", + DisplayName = "NF-e, modelo 55")] + [DataRow(ModeloDocumento.NFCe, CnpjNumerico, 1, 1, 10, + "ID3525" + CnpjNumerico + "65" + "001" + "000000001" + "000000010", + DisplayName = "NFC-e, modelo 65")] + [DataRow(ModeloDocumento.NFe, CnpjAlfanumerico, 12, 5, 5, + "ID3525" + CnpjAlfanumerico + "55" + "012" + "000000005" + "000000005", + DisplayName = "CNPJ alfanumérico, faixa de um número só")] + public void ObterIdInutilizacao_SegueOLayout(ModeloDocumento modelo, string cnpj, int serie, + int numeroInicial, int numeroFinal, string esperado) + { + Assert.AreEqual(esperado, + ExtinutNFe.ObterId(Estado.SP, 25, cnpj, modelo, serie, numeroInicial, numeroFinal)); + } + } +} diff --git a/NFe.Servicos/ServicosNFe.cs b/NFe.Servicos/ServicosNFe.cs index e6f4534ca..6474fdf7e 100644 --- a/NFe.Servicos/ServicosNFe.cs +++ b/NFe.Servicos/ServicosNFe.cs @@ -675,6 +675,23 @@ public RetornoRecepcaoEvento RecepcaoEventoManifestacaoDestinatario(int idlote, return retorno; } + /// + /// Envia eventos do tipo "Manifestação do destinatário" já assinado. + /// + /// + /// + /// + /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca + /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id + /// que já estiver preenchido. + /// + /// + public RetornoRecepcaoEvento RecepcaoEventoManifestacaoDestinatario(int idlote, List eventos, bool assinar = false) + { + var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoManifestacaoDestinatario, _cFgServico.VersaoRecepcaoEventoManifestacaoDestinatario, assinar); + return retorno; + } + /// /// Envia um evento do tipo "EPEC" /// @@ -816,6 +833,23 @@ public RetornoRecepcaoEvento RecepcaoEventoInsucessoEntrega(int idlote, return retorno; } + /// + /// Envia eventos do tipo "Insucesso na Entrega da NF-e" já assinado. + /// + /// + /// + /// + /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca + /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id + /// que já estiver preenchido. + /// + /// + public RetornoRecepcaoEvento RecepcaoEventoInsucessoEntrega(int idlote, List eventos, bool assinar = false) + { + var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoInsucessoEntregaNFe, _cFgServico.VersaoRecepcaoEventoInsucessoEntrega, assinar); + return retorno; + } + /// /// Serviço para cancelamento insucesso na entrega /// @@ -868,6 +902,23 @@ public RetornoRecepcaoEvento RecepcaoEventoCancInsucessoEntrega(int idlote, return retorno; } + /// + /// Envia eventos do tipo "Cancelamento do Insucesso na Entrega da NF-e" já assinado. + /// + /// + /// + /// + /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca + /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id + /// que já estiver preenchido. + /// + /// + public RetornoRecepcaoEvento RecepcaoEventoCancInsucessoEntrega(int idlote, List eventos, bool assinar = false) + { + var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoCancInsucessoEntregaNFe, _cFgServico.VersaoRecepcaoEventoInsucessoEntrega, assinar); + return retorno; + } + /// /// Recepção do Evento de Comprovante de Entrega /// @@ -937,6 +988,23 @@ public RetornoRecepcaoEvento RecepcaoEventoComprovanteEntrega(int idlote, return retorno; } + /// + /// Envia eventos do tipo "Comprovante de Entrega da NF-e" já assinado. + /// + /// + /// + /// + /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca + /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id + /// que já estiver preenchido. + /// + /// + public RetornoRecepcaoEvento RecepcaoEventoComprovanteEntrega(int idlote, List eventos, bool assinar = false) + { + var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoComprovanteEntregaNFe, _cFgServico.VersaoRecepcaoEventoComprovanteEntrega, assinar); + return retorno; + } + /// /// Serviço para cancelamento comprovante de entrega /// @@ -990,6 +1058,23 @@ public RetornoRecepcaoEvento RecepcaoEventoCancComprovanteEntrega(int idlote, return retorno; } + /// + /// Envia eventos do tipo "Cancelamento do Comprovante de Entrega da NF-e" já assinado. + /// + /// + /// + /// + /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca + /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id + /// que já estiver preenchido. + /// + /// + public RetornoRecepcaoEvento RecepcaoEventoCancComprovanteEntrega(int idlote, List eventos, bool assinar = false) + { + var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoCancComprovanteEntregaNFe, _cFgServico.VersaoRecepcaoEventoComprovanteEntrega, assinar); + return retorno; + } + /// /// Recepção do Evento de Conciliação Financeira @@ -1041,6 +1126,23 @@ public RetornoRecepcaoEvento RecepcaoEventoConciliacaoFinanceira(int idlote, return retorno; } + /// + /// Envia eventos do tipo "Conciliação Financeira da NF-e" já assinado. + /// + /// + /// + /// + /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca + /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id + /// que já estiver preenchido. + /// + /// + public RetornoRecepcaoEvento RecepcaoEventoConciliacaoFinanceira(int idlote, List eventos, bool assinar = false) + { + var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoConciliacaoFinanceiraNFe, _cFgServico.VersaoRecepcaoEventoConciliacaoFinanceira, assinar); + return retorno; + } + /// /// Serviço para cancelamento Conciliação Financeira /// @@ -1092,6 +1194,23 @@ public RetornoRecepcaoEvento RecepcaoEventoCancConciliacaoFinanceira(int idlote, return retorno; } + /// + /// Envia eventos do tipo "Cancelamento da Conciliação Financeira da NF-e" já assinado. + /// + /// + /// + /// + /// false (padrão) para transmitir os eventos exatamente como vieram, já assinados; true para a biblioteca + /// calcular o Id e assinar cada evento com o certificado desta instância de ServicosNFe, sobrescrevendo o Id + /// que já estiver preenchido. + /// + /// + public RetornoRecepcaoEvento RecepcaoEventoCancConciliacaoFinanceira(int idlote, List eventos, bool assinar = false) + { + var retorno = RecepcaoEvento(idlote, eventos, ServicoNFe.RecepcaoEventoCancConciliacaoFinanceiraNFe, _cFgServico.VersaoRecepcaoEventoConciliacaoFinanceira, assinar); + return retorno; + } + /// /// Recepção do Evento de Perecimento, perda, roubo ou furto durante o transporte contratado pelo fornecedor /// diff --git a/NFe.Utils/Evento/Extevento.cs b/NFe.Utils/Evento/Extevento.cs index c278d6745..70e3668e5 100644 --- a/NFe.Utils/Evento/Extevento.cs +++ b/NFe.Utils/Evento/Extevento.cs @@ -2,6 +2,7 @@ using System.Security.Cryptography.X509Certificates; using DFe.Utils; using NFe.Classes.Servicos.Evento; +using NFe.Classes.Servicos.Tipos; using NFe.Utils.Assinatura; namespace NFe.Utils.Evento @@ -18,6 +19,23 @@ public static string ObterXmlString(this evento pedEvento) return FuncoesXml.ClasseParaXmlString(pedEvento); } + /// + /// Obtém o Id de um evento (infEvento/@Id): literal "ID" + tpEvento + chNFe + nSeqEvento com 2 dígitos + /// + /// Uso opcional, para quando o evento for montado fora da biblioteca — por exemplo, para assinar com o + /// certificado numa máquina cliente e depois transmitir com a sobrecarga que recebe o evento já + /// assinado. Os métodos que assinam internamente continuam calculando o Id sozinhos. + /// + /// + /// Código do evento + /// Chave de acesso da NF-e vinculada ao evento + /// Sequencial do evento para o mesmo tipo de evento + /// Retorna o conteúdo do atributo infEvento/@Id + public static string ObterId(NFeTipoEvento tpEvento, string chNFe, int nSeqEvento) + { + return "ID" + ((int)tpEvento) + chNFe + nSeqEvento.ToString().PadLeft(2, '0'); + } + /// /// Assina um objeto evento /// diff --git a/NFe.Utils/Inutilizacao/ExtinutNFe.cs b/NFe.Utils/Inutilizacao/ExtinutNFe.cs index 9f00c220d..79b8e544d 100644 --- a/NFe.Utils/Inutilizacao/ExtinutNFe.cs +++ b/NFe.Utils/Inutilizacao/ExtinutNFe.cs @@ -1,5 +1,7 @@ using System; using System.Security.Cryptography.X509Certificates; +using DFe.Classes.Entidades; +using DFe.Classes.Flags; using DFe.Utils; using NFe.Classes.Servicos.Inutilizacao; using NFe.Utils.Assinatura; @@ -29,6 +31,36 @@ public static string ObterXmlString(this inutNFe pedInutilizacao) return FuncoesXml.ClasseParaXmlString(pedInutilizacao); } + /// + /// Obtém o Id de um pedido de inutilização (infInut/@Id): literal "ID" + cUF + ano com 2 dígitos + CNPJ + + /// modelo + série com 3 dígitos + número inicial e número final com 9 dígitos + /// + /// Uso opcional, para quando o pedido for montado fora da biblioteca — por exemplo, para assinar com o + /// certificado numa máquina cliente e depois transmitir com já feito, via a + /// sobrecarga que recebe o inutNFe pronto. O método que assina internamente continua calculando o Id + /// sozinho. + /// + /// + /// Código da UF do solicitante + /// Ano de inutilização da numeração + /// CNPJ do emitente + /// Modelo do documento + /// Série + /// Número inicial a ser inutilizado + /// Número final a ser inutilizado + /// Retorna o conteúdo do atributo infInut/@Id + public static string ObterId(Estado cUF, int ano, string cnpj, ModeloDocumento modelo, int serie, + int numeroInicial, int numeroFinal) + { + var numId = string.Concat((int)cUF, ano.ToString("D2"), + cnpj, (int)modelo, + serie.ToString().PadLeft(3, '0'), + numeroInicial.ToString().PadLeft(9, '0'), + numeroFinal.ToString().PadLeft(9, '0')); + + return "ID" + numId; + } + /// /// Assina um objeto inutNFe ///