diff --git a/CTe.Servicos/Enderecos/Helpers/UrlHelper.cs b/CTe.Servicos/Enderecos/Helpers/UrlHelper.cs
index bb252184d..827cd2a1e 100644
--- a/CTe.Servicos/Enderecos/Helpers/UrlHelper.cs
+++ b/CTe.Servicos/Enderecos/Helpers/UrlHelper.cs
@@ -269,7 +269,7 @@ private static UrlCTe UrlProducao(ConfiguracaoServico configuracaoServico)
CteStatusServico = @"https://cte.fazenda.mg.gov.br/cte/services/CTeStatusServicoV4",
CteRecepcaoOs = @"https://cte.fazenda.mg.gov.br/cte/services/CTeRecepcaoOSV4",
CteRecepcaoGtve = @"https://cte.fazenda.mg.gov.br/cte/services/CTeRecepcaoGTVeV4",
- QrCode = @"https://cte.fazenda.mg.gov.br/portalcte/sistema/qrcode.xhtml"
+ QrCode = @"https://portalcte.fazenda.mg.gov.br/portalcte/sistema/qrcode.xhtml"
};
}
@@ -281,7 +281,7 @@ private static UrlCTe UrlProducao(ConfiguracaoServico configuracaoServico)
CteInutilizacao = @"https://cte.fazenda.mg.gov.br/cte/services/CteInutilizacao",
CteRecepcaoEvento = @"https://cte.fazenda.mg.gov.br/cte/services/RecepcaoEvento",
CteConsulta = @"https://cte.fazenda.mg.gov.br/cte/services/CteConsulta",
- QrCode = @"https://cte.fazenda.mg.gov.br/portalcte/sistema/qrcode.xhtml",
+ QrCode = @"https://portalcte.fazenda.mg.gov.br/portalcte/sistema/qrcode.xhtml",
CTeDistribuicaoDFe = "https://www1.cte.fazenda.gov.br/CTeDistribuicaoDFe/CTeDistribuicaoDFe.asmx"
};
case Estado.PR:
@@ -488,7 +488,7 @@ private static UrlCTe UrlHomologacao(ConfiguracaoServico configuracaoServico)
CteStatusServico = @"https://hcte.fazenda.mg.gov.br/cte/services/CTeStatusServicoV4",
CteRecepcaoOs = @"https://hcte.fazenda.mg.gov.br/cte/services/CTeRecepcaoOSV4",
CteRecepcaoGtve = @"https://hcte.fazenda.mg.gov.br/cte/services/CTeRecepcaoGTVeV4",
- QrCode = @"https://cte.fazenda.mg.gov.br/portalcte/sistema/qrcode.xhtml"
+ QrCode = @"https://portalcte.fazenda.mg.gov.br/portalcte/sistema/qrcode.xhtml"
};
}
diff --git a/DFe.Utils/Assinatura/AssinaturaDigital.cs b/DFe.Utils/Assinatura/AssinaturaDigital.cs
index 3c099e3b7..097acf2fb 100644
--- a/DFe.Utils/Assinatura/AssinaturaDigital.cs
+++ b/DFe.Utils/Assinatura/AssinaturaDigital.cs
@@ -116,5 +116,18 @@ public static byte[] ObterHashSha1Bytes(byte[] dados)
return sha1HashBytes;
}
}
+
+ ///
+ /// Obtém a assinatura do certificado digital no formato PKCS#1, baseado em um array de bytes passado como Argumento [value].
+ ///
+ ///
+ ///
+ ///
+ public static byte[] ObterAssinaturaPkcs1(ConfiguracaoCertificado configuracaoCertificado, byte[] value)
+ {
+ X509Certificate2 certificado = CertificadoDigital.ObterCertificado(configuracaoCertificado);
+ using (RSA rsa = certificado.GetRSAPrivateKey())
+ return rsa.SignData(value, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
+ }
}
}
\ No newline at end of file
diff --git a/NFe.AppTeste/MainWindow.xaml b/NFe.AppTeste/MainWindow.xaml
index 7a793539b..f0250500c 100644
--- a/NFe.AppTeste/MainWindow.xaml
+++ b/NFe.AppTeste/MainWindow.xaml
@@ -233,8 +233,9 @@
IsEnabled="{Binding CfgServico.ModeloDocumento, ConverterParameter={x:Static flags:ModeloDocumento.NFCe}, Converter={StaticResource EnumParaBool}}">
-
-
+
+
+
+
diff --git a/NFe.AppTeste/MainWindow.xaml.cs b/NFe.AppTeste/MainWindow.xaml.cs
index 1409fa640..e12a965ae 100644
--- a/NFe.AppTeste/MainWindow.xaml.cs
+++ b/NFe.AppTeste/MainWindow.xaml.cs
@@ -1,4 +1,4 @@
-/********************************************************************************/
+/********************************************************************************/
/* Projeto: Biblioteca ZeusNFe */
/* Biblioteca C# para emissão de Nota Fiscal Eletrônica - NFe e Nota Fiscal de */
/* Consumidor Eletrônica - NFC-e (http://www.nfe.fazenda.gov.br) */
@@ -381,7 +381,7 @@ private void BtnInsucessoEntrega_Click(object sender, RoutedEventArgs e)
Funcoes.Mensagem(ex.Message, "Erro", MessageBoxButton.OK);
}
}
-
+
private void BtnCancInsucessoEntrega_Click(object sender, RoutedEventArgs e)
{
const string titulo = "Cancelar Insucesso Entrega NFe";
@@ -497,7 +497,7 @@ private void BtnComprovanteEntrega_Click(object sender, RoutedEventArgs e)
: _configuracoes.Emitente.CNPJ;
var retornoComprovante = servicoNFe.RecepcaoEventoComprovanteEntrega(Convert.ToInt32(idlote),
- Convert.ToInt16(sequenciaEvento), cpfcnpj, chave, dhEntrega, nDoc, xNome, hashComprovante,
+ Convert.ToInt16(sequenciaEvento), cpfcnpj, chave, dhEntrega, nDoc, xNome, hashComprovante,
dhHashComprovante, latGps, longGps, DFe.Classes.Entidades.Estado.SP);
TrataRetorno(retornoComprovante);
@@ -769,7 +769,7 @@ private Classes.NFe ObterNfeValidada(VersaoServico versaoServico, ModeloDocument
nfe.infNFeSupl = new infNFeSupl();
if (versaoServico == VersaoServico.Versao400)
nfe.infNFeSupl.urlChave = nfe.infNFeSupl.ObterUrlConsulta(nfe, _configuracoes.ConfiguracaoDanfeNfce.VersaoQrCode);
- nfe.infNFeSupl.qrCode = nfe.infNFeSupl.ObterUrlQrCode(nfe, _configuracoes.ConfiguracaoDanfeNfce.VersaoQrCode, configuracaoCsc.CIdToken, configuracaoCsc.Csc);
+ nfe.infNFeSupl.qrCode = nfe.infNFeSupl.ObterUrlQrCode(nfe, _configuracoes.ConfiguracaoDanfeNfce.VersaoQrCode, configuracaoCsc.CIdToken, configuracaoCsc.Csc, _configuracoes.CfgServico.Certificado);
}
nfe.Valida();
@@ -1464,7 +1464,7 @@ protected virtual dest GetDestinatario(VersaoServico versao, ModeloDocumento mod
};
dest.xNome = "NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL"; //Obrigatório para NFe e opcional para NFCe
dest.enderDest = GetEnderecoDestinatario(); //Obrigatório para NFe e opcional para NFCe
-
+
//if (versao == VersaoServico.Versao200)
// dest.IE = "ISENTO";
if (versao == VersaoServico.Versao200) return dest;
@@ -1836,8 +1836,8 @@ protected virtual List GetPagamento(ICMSTot icmsTot, VersaoServico versao)
{
detPag = new List
{
- new detPag {tPag = FormaPagamento.fpCreditoEmLoja, vPag = valorPagto},
- new detPag {tPag = FormaPagamento.fpCreditoEmLoja, vPag = icmsTot.vNF - valorPagto}
+ new detPag {tPag = FormaPagamento.fpDinheiro, vPag = valorPagto},
+ new detPag {tPag = FormaPagamento.fpCheque, vPag = icmsTot.vNF - valorPagto}
}
}
};
diff --git a/NFe.Classes/Informacoes/Detalhe/gCred.cs b/NFe.Classes/Informacoes/Detalhe/gCred.cs
index 425aef414..e4945858a 100644
--- a/NFe.Classes/Informacoes/Detalhe/gCred.cs
+++ b/NFe.Classes/Informacoes/Detalhe/gCred.cs
@@ -30,12 +30,12 @@ public decimal? vCredPresumido
public bool ShouldSerializepCredPresumido()
{
- return _pCredPresumido.HasValue && _pCredPresumido > 0;
+ return _pCredPresumido.HasValue;
}
public bool ShouldSerializevCredPresumido()
{
- return _vCredPresumido.HasValue && _vCredPresumido > 0;
+ return _vCredPresumido.HasValue;
}
}
}
diff --git a/NFe.Danfe.AppTeste.Fast/MainWindow.xaml b/NFe.Danfe.AppTeste.Fast/MainWindow.xaml
index d10e6babf..cbd75fdf1 100644
--- a/NFe.Danfe.AppTeste.Fast/MainWindow.xaml
+++ b/NFe.Danfe.AppTeste.Fast/MainWindow.xaml
@@ -122,12 +122,16 @@
+ Margin="10,5,0,0"
+ IsChecked="{Binding ConfiguracaoDanfeNfce.VersaoQrCode, ConverterParameter={x:Static nfeUtils:VersaoQrCode.QrCodeVersao1}, Converter={StaticResource EnumParaBool}}" Width="90" />
+ Margin="110,5,0,0"
+ IsChecked="{Binding ConfiguracaoDanfeNfce.VersaoQrCode, ConverterParameter={x:Static nfeUtils:VersaoQrCode.QrCodeVersao2}, Converter={StaticResource EnumParaBool}}" Width="90"/>
+
diff --git a/NFe.Danfe.Base/NFe/NFeRetrato.frx b/NFe.Danfe.Base/NFe/NFeRetrato.frx
index e12986475..799aedef4 100644
--- a/NFe.Danfe.Base/NFe/NFeRetrato.frx
+++ b/NFe.Danfe.Base/NFe/NFeRetrato.frx
@@ -1444,7 +1444,7 @@ namespace FastReport
-
+
diff --git a/NFe.Utils/Enums.cs b/NFe.Utils/Enums.cs
index b72e16980..adc5b1f5a 100644
--- a/NFe.Utils/Enums.cs
+++ b/NFe.Utils/Enums.cs
@@ -50,6 +50,10 @@ public enum VersaoQrCode
QrCodeVersao1 = 100,
[Description("Versão 2.0 do QR-Code")]
- QrCodeVersao2 = 2
+ QrCodeVersao2 = 2,
+
+ [Description("Versão 3.0 do QR-Code")]
+ QrCodeVersao3 = 3,
+
}
}
\ No newline at end of file
diff --git a/NFe.Utils/Excecoes/ValidacaoSchemaException.cs b/NFe.Utils/Excecoes/ValidacaoSchemaException.cs
index e06d36927..a7591ee1b 100644
--- a/NFe.Utils/Excecoes/ValidacaoSchemaException.cs
+++ b/NFe.Utils/Excecoes/ValidacaoSchemaException.cs
@@ -48,6 +48,12 @@ public class ValidacaoSchemaException : Exception
/// Houve erros de validação de schema XSD
///
///
- public ValidacaoSchemaException(string message) : base(string.Format("Erros na validação:\n {0}", message)) {}
+ public ValidacaoSchemaException(string message, string xmlString) : base(
+ $"Erros na validação:\n {message}")
+ {
+ XmlString = xmlString;
+ }
+
+ public string XmlString { get; private set; }
}
}
diff --git a/NFe.Utils/InformacoesSuplementares/ExtinfNFeSupl.cs b/NFe.Utils/InformacoesSuplementares/ExtinfNFeSupl.cs
index b205f8887..3e1506b3a 100644
--- a/NFe.Utils/InformacoesSuplementares/ExtinfNFeSupl.cs
+++ b/NFe.Utils/InformacoesSuplementares/ExtinfNFeSupl.cs
@@ -37,8 +37,10 @@
using DFe.Classes.Entidades;
using DFe.Classes.Flags;
using DFe.Utils;
+using DFe.Utils.Assinatura;
using NFe.Classes;
using NFe.Classes.Informacoes.Identificacao.Tipos;
+using System.Text;
namespace NFe.Utils.InformacoesSuplementares
{
@@ -127,7 +129,7 @@ private static List CarregarUrls()
{Estado.RR, versao3E4, "https://www.sefaz.rr.gov.br/nfce/servlet/qrcode"},
{Estado.MG, versao3E4, "https://portalsped.fazenda.mg.gov.br/portalnfce/sistema/qrcode.xhtml"}
};
- adicionarUrls(TipoAmbiente.Producao, TipoUrlConsultaPublica.UrlQrCode, new[] { VersaoQrCode.QrCodeVersao1, VersaoQrCode.QrCodeVersao2 }, urlsQrCodeProducaoQrCode1E2);
+ adicionarUrls(TipoAmbiente.Producao, TipoUrlConsultaPublica.UrlQrCode, new[] { VersaoQrCode.QrCodeVersao1, VersaoQrCode.QrCodeVersao2, VersaoQrCode.QrCodeVersao3 }, urlsQrCodeProducaoQrCode1E2);
var urlsQrCodeProducaoQrCode1 = new TupleList
{
@@ -149,7 +151,7 @@ private static List CarregarUrls()
{Estado.TO, versao4, "http://apps.sefaz.to.gov.br/portal-nfce/qrcodeNFCe"},
{Estado.SC, versao4, "https://sat.sef.sc.gov.br/nfce/consulta"}
};
- adicionarUrls(TipoAmbiente.Producao, TipoUrlConsultaPublica.UrlQrCode, new[] { VersaoQrCode.QrCodeVersao2 }, urlsQrCodeProducaoQrCode2);
+ adicionarUrls(TipoAmbiente.Producao, TipoUrlConsultaPublica.UrlQrCode, new[] { VersaoQrCode.QrCodeVersao2, VersaoQrCode.QrCodeVersao3 }, urlsQrCodeProducaoQrCode2);
#endregion
@@ -181,7 +183,7 @@ private static List CarregarUrls()
{Estado.TO, versao3E4, "http://apps.sefaz.to.gov.br/portal-nfce-homologacao/qrcodeNFCe"},
{Estado.MG, versao3E4, "https://portalsped.fazenda.mg.gov.br/portalnfce/sistema/qrcode.xhtml"}
};
- adicionarUrls(TipoAmbiente.Homologacao, TipoUrlConsultaPublica.UrlQrCode, new[] { VersaoQrCode.QrCodeVersao1, VersaoQrCode.QrCodeVersao2 }, urlsQrCodeHomologacaoQrCode1E2);
+ adicionarUrls(TipoAmbiente.Homologacao, TipoUrlConsultaPublica.UrlQrCode, new[] { VersaoQrCode.QrCodeVersao1, VersaoQrCode.QrCodeVersao2, VersaoQrCode.QrCodeVersao3 }, urlsQrCodeHomologacaoQrCode1E2);
var urlsQrCodeHomologacaoQrCode1 = new TupleList
{
@@ -199,7 +201,7 @@ private static List CarregarUrls()
{Estado.SP, versao4, "https://www.homologacao.nfce.fazenda.sp.gov.br/qrcode"},
{Estado.SC, versao4, "https://hom.sat.sef.sc.gov.br/nfce/consulta"},
};
- adicionarUrls(TipoAmbiente.Homologacao, TipoUrlConsultaPublica.UrlQrCode, new[] { VersaoQrCode.QrCodeVersao2 }, urlsQrCodeHomologacaoQrCode2);
+ adicionarUrls(TipoAmbiente.Homologacao, TipoUrlConsultaPublica.UrlQrCode, new[] { VersaoQrCode.QrCodeVersao2, VersaoQrCode.QrCodeVersao3 }, urlsQrCodeHomologacaoQrCode2);
#endregion
@@ -306,8 +308,8 @@ private static List CarregarUrls()
{Estado.RR, versao3E4, "www.sefaz.rr.gov.br/nfce/consulta"}
};
- adicionarUrls(TipoAmbiente.Homologacao, TipoUrlConsultaPublica.UrlConsulta, new[] { VersaoQrCode.QrCodeVersao2 }, urlsConsultaHomologacaoEProducao2);
- adicionarUrls(TipoAmbiente.Producao, TipoUrlConsultaPublica.UrlConsulta, new[] { VersaoQrCode.QrCodeVersao2 }, urlsConsultaHomologacaoEProducao2);
+ adicionarUrls(TipoAmbiente.Homologacao, TipoUrlConsultaPublica.UrlConsulta, new[] { VersaoQrCode.QrCodeVersao2, VersaoQrCode.QrCodeVersao3 }, urlsConsultaHomologacaoEProducao2);
+ adicionarUrls(TipoAmbiente.Producao, TipoUrlConsultaPublica.UrlConsulta, new[] { VersaoQrCode.QrCodeVersao2, VersaoQrCode.QrCodeVersao3 }, urlsConsultaHomologacaoEProducao2);
#endregion
@@ -326,7 +328,7 @@ private static List CarregarUrls()
{Estado.SC, versao3E4, "https://sat.sef.sc.gov.br/nfce/consulta" }
};
- adicionarUrls(TipoAmbiente.Producao, TipoUrlConsultaPublica.UrlConsulta, new[] { VersaoQrCode.QrCodeVersao2 }, urlsConsultaProducao2);
+ adicionarUrls(TipoAmbiente.Producao, TipoUrlConsultaPublica.UrlConsulta, new[] { VersaoQrCode.QrCodeVersao2, VersaoQrCode.QrCodeVersao3 }, urlsConsultaProducao2);
#endregion
@@ -345,7 +347,7 @@ private static List CarregarUrls()
{Estado.SC, versao3E4, "https://hom.sat.sef.sc.gov.br/nfce/consulta" }
};
- adicionarUrls(TipoAmbiente.Homologacao, TipoUrlConsultaPublica.UrlConsulta, new[] { VersaoQrCode.QrCodeVersao2 }, urlsConsultaHomologacao2);
+ adicionarUrls(TipoAmbiente.Homologacao, TipoUrlConsultaPublica.UrlConsulta, new[] { VersaoQrCode.QrCodeVersao2, VersaoQrCode.QrCodeVersao3 }, urlsConsultaHomologacao2);
#endregion
@@ -388,7 +390,7 @@ public static string ObterUrlConsulta(this infNFeSupl infNFeSupl, Classes.NFe nf
///
/// Obtém a URL para montagem do QR-Code
///
- public static string ObterUrlQrCode(this infNFeSupl infNFeSupl, Classes.NFe nfe, VersaoQrCode versaoQrCode, string cIdToken, string csc)
+ public static string ObterUrlQrCode(this infNFeSupl infNFeSupl, Classes.NFe nfe, VersaoQrCode versaoQrCode, string cIdToken, string csc, ConfiguracaoCertificado _cfgCertificado = null)
{
Func msgErro = parametro => $"O {parametro} não foi informado!";
@@ -405,6 +407,8 @@ public static string ObterUrlQrCode(this infNFeSupl infNFeSupl, Classes.NFe nfe,
return ObterUrlQrCode1(infNFeSupl, nfe, cIdToken, csc, versaoServico);
case VersaoQrCode.QrCodeVersao2:
return ObterUrlQrCode2(infNFeSupl, nfe, cIdToken, csc, versaoServico);
+ case VersaoQrCode.QrCodeVersao3:
+ return ObterUrlQrCode3(infNFeSupl, nfe, versaoServico, _cfgCertificado);
default:
throw new ArgumentOutOfRangeException("versaoQrCode", versaoQrCode, null);
}
@@ -430,7 +434,7 @@ private static string ObterUrlQrCode1(infNFeSupl infNFeSupl, Classes.NFe nfe, st
if (nfe.infNFe.dest != null)
cDest = "&cDest=" + nfe.infNFe.dest.CPF + nfe.infNFe.dest.CNPJ + nfe.infNFe.dest.idEstrangeiro;
- //Passo 3: Substituir os valores (“dhEmi” e “digVal”) nos parâmetros;
+ //Passo 3: Substituir os valores ("dhEmi" e "digVal") nos parâmetros;
var dadosBase =
"chNFe=" + nfe.infNFe.Id.Substring(3) +
"&nVersao=100" +
@@ -519,5 +523,58 @@ public static string ObterUrlQrCode2ComParametro(this infNFeSupl infNFeSupl, Tip
url += parametro;
return url;
}
+
+ ///
+ /// Obtém a URL para uso no QR-Code, versão 3.0 - leiaute 4.00+
+ ///
+ public static string ObterUrlQrCode3(this infNFeSupl infNFeSupl, Classes.NFe nfe, VersaoServico versaoServico, ConfiguracaoCertificado cfgCertificado, Encoding encoding = null)
+ {
+ if (cfgCertificado == null || string.IsNullOrWhiteSpace(cfgCertificado.Serial))
+ throw new ArgumentNullException("CertificadoDigital", "Para gerar a assinatura do QR-Code versão 3.0 EM CONTINGENCIA é necessário informar o certificado digital utilizado na assinatura da NFC-e, verificar Número de Série e Senha.");
+
+ const string pipe = "|";
+
+ string chave = nfe.infNFe.Id.Substring(3);
+ int versaoQrCode = 3;
+ int ambiente = (int)nfe.infNFe.ide.tpAmb;
+ string dadosBase = string.Concat(chave, pipe, versaoQrCode, pipe, ambiente);
+
+ if (nfe.infNFe.ide.tpEmis == TipoEmissao.teOffLine)
+ {
+ string diaEmi = nfe.infNFe.ide.dhEmi.Day.ToString("D2");
+ string valorNfce = nfe.infNFe.total.ICMSTot.vNF.ToString("0.00").Replace(',', '.');
+ string tp_idDest = string.Empty;
+ string idDest = string.Empty;
+ if (nfe.infNFe.dest != null)
+ {
+ if (!string.IsNullOrEmpty(nfe.infNFe.dest.idEstrangeiro))
+ {
+ tp_idDest = "3";
+ idDest = nfe.infNFe.dest.idEstrangeiro.Trim();
+ }
+ else if (!string.IsNullOrEmpty(nfe.infNFe.dest.CPF) && nfe.infNFe.dest.CPF.Length == 11)
+ {
+ tp_idDest = "2";
+ idDest = nfe.infNFe.dest.CPF.Replace(".", "").Replace("/", "").Replace("-", "").Trim();
+ }
+ else if (!string.IsNullOrEmpty(nfe.infNFe.dest.CNPJ) && nfe.infNFe.dest.CNPJ.Length == 14)
+ {
+ tp_idDest = "1";
+ idDest = nfe.infNFe.dest.CNPJ.Replace(".", "").Replace("/", "").Replace("-", "").Trim();
+ }
+ }
+
+ dadosBase = string.Concat(dadosBase, pipe, diaEmi, pipe, valorNfce, pipe, tp_idDest, pipe, idDest);
+
+ if (encoding == null)
+ encoding = Encoding.UTF8;
+
+ string assinatura = Convert.ToBase64String(AssinaturaDigital.ObterAssinaturaPkcs1(cfgCertificado, encoding.GetBytes(dadosBase)));
+ dadosBase = string.Concat(dadosBase, pipe, assinatura);
+ }
+
+ string url = ObterUrlQrCode2ComParametro(infNFeSupl, nfe.infNFe.ide.tpAmb, nfe.infNFe.ide.cUF, versaoServico);
+ return string.Concat(url, dadosBase);
+ }
}
}
diff --git a/NFe.Utils/Validacao/Validador.cs b/NFe.Utils/Validacao/Validador.cs
index cf30b2ae7..01375c877 100644
--- a/NFe.Utils/Validacao/Validador.cs
+++ b/NFe.Utils/Validacao/Validador.cs
@@ -206,7 +206,7 @@ public static string[] Valida(ServicoNFe servicoNFe, VersaoServico versaoServico
}
if (falhas.Length > 0)
- throw new ValidacaoSchemaException($"Ocorreu o seguinte erro durante a validação XML: {Environment.NewLine}{falhas}");
+ throw new ValidacaoSchemaException($"Ocorreu o seguinte erro durante a validação XML: {Environment.NewLine}{falhas}", stringXml);
return falhas.ToString().Trim().Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
}