Skip to content

Commit b5ac6b2

Browse files
authored
Merge pull request #73 from adrbarros/master
Ajustes para Obter URL QrCode versão 3
2 parents bdce2c9 + 7b69a8e commit b5ac6b2

File tree

5 files changed

+56
-70
lines changed

5 files changed

+56
-70
lines changed

DFe.Utils/Assinatura/CertificadoDigital.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,19 @@ public static X509Certificate2 ObterCertificado(ConfiguracaoCertificado configur
196196
return CacheCertificado[keyCertificado];
197197
}
198198

199+
/// <summary>
200+
/// Obtém a assinatura do certificado digital no formato PKCS#1, baseado em um array de bytes passado como Argumento [value].
201+
/// </summary>
202+
/// <param name="configuracaoCertificado"></param>
203+
/// <param name="value"></param>
204+
/// <returns></returns>
205+
public static byte[] ObterAssinaturaPkcs1(ConfiguracaoCertificado configuracaoCertificado, byte[] value)
206+
{
207+
X509Certificate2 certificado = ObterCertificado(configuracaoCertificado);
208+
using (RSA rsa = certificado.GetRSAPrivateKey())
209+
return rsa.SignData(value, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
210+
}
211+
199212
public static void ClearCache()
200213
{
201214
CacheCertificado.Clear();

NFe.AppTeste/MainWindow.xaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,19 @@
233233
IsEnabled="{Binding CfgServico.ModeloDocumento, ConverterParameter={x:Static flags:ModeloDocumento.NFCe}, Converter={StaticResource EnumParaBool}}">
234234
<Grid Margin="0,5,0,0">
235235
<Grid.ColumnDefinitions>
236-
<ColumnDefinition Width="150" />
237-
<ColumnDefinition Width="*" />
236+
<ColumnDefinition Width="100" />
237+
<ColumnDefinition Width="100"/>
238+
<ColumnDefinition Width="100"/>
238239
</Grid.ColumnDefinitions>
239240
<RadioButton Grid.Column="0" Content="Versão 1.0"
240241
HorizontalAlignment="Left" VerticalAlignment="Center"
241242
IsChecked="{Binding ConfiguracaoDanfeNfce.VersaoQrCode, ConverterParameter={x:Static nfeUtils:VersaoQrCode.QrCodeVersao1}, Converter={StaticResource EnumParaBool}}" />
242243
<RadioButton Grid.Column="1" Content="Versão 2.0"
243244
HorizontalAlignment="Left" VerticalAlignment="Center"
244245
IsChecked="{Binding ConfiguracaoDanfeNfce.VersaoQrCode, ConverterParameter={x:Static nfeUtils:VersaoQrCode.QrCodeVersao2}, Converter={StaticResource EnumParaBool}}" />
246+
<RadioButton Grid.Column="2" Content="Versão 3.0"
247+
HorizontalAlignment="Center" VerticalAlignment="Center"
248+
IsChecked="{Binding ConfiguracaoDanfeNfce.VersaoQrCode, ConverterParameter={x:Static nfeUtils:VersaoQrCode.QrCodeVersao3}, Converter={StaticResource EnumParaBool}}" />
245249
</Grid>
246250
</GroupBox>
247251

NFe.AppTeste/MainWindow.xaml.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
using static System.Net.Mime.MediaTypeNames;
4646
using System.Text;
4747
using System.Security.Cryptography;
48+
using DFe.Utils.Assinatura;
4849

4950
namespace NFe.AppTeste
5051
{
@@ -348,7 +349,7 @@ private void BtnInsucessoEntrega_Click(object sender, RoutedEventArgs e)
348349
Funcoes.Mensagem(ex.Message, "Erro", MessageBoxButton.OK);
349350
}
350351
}
351-
352+
352353
private void BtnCancInsucessoEntrega_Click(object sender, RoutedEventArgs e)
353354
{
354355
const string titulo = "Cancelar Insucesso Entrega NFe";
@@ -464,7 +465,7 @@ private void BtnComprovanteEntrega_Click(object sender, RoutedEventArgs e)
464465
: _configuracoes.Emitente.CNPJ;
465466

466467
var retornoComprovante = servicoNFe.RecepcaoEventoComprovanteEntrega(Convert.ToInt32(idlote),
467-
Convert.ToInt16(sequenciaEvento), cpfcnpj, chave, dhEntrega, nDoc, xNome, hashComprovante,
468+
Convert.ToInt16(sequenciaEvento), cpfcnpj, chave, dhEntrega, nDoc, xNome, hashComprovante,
468469
dhHashComprovante, latGps, longGps, DFe.Classes.Entidades.Estado.SP);
469470

470471
TrataRetorno(retornoComprovante);
@@ -736,7 +737,7 @@ private Classes.NFe ObterNfeValidada(VersaoServico versaoServico, ModeloDocument
736737
nfe.infNFeSupl = new infNFeSupl();
737738
if (versaoServico == VersaoServico.Versao400)
738739
nfe.infNFeSupl.urlChave = nfe.infNFeSupl.ObterUrlConsulta(nfe, _configuracoes.ConfiguracaoDanfeNfce.VersaoQrCode);
739-
nfe.infNFeSupl.qrCode = nfe.infNFeSupl.ObterUrlQrCode(nfe, _configuracoes.ConfiguracaoDanfeNfce.VersaoQrCode, configuracaoCsc.CIdToken, configuracaoCsc.Csc);
740+
nfe.infNFeSupl.qrCode = nfe.infNFeSupl.ObterUrlQrCode(nfe, _configuracoes.ConfiguracaoDanfeNfce.VersaoQrCode, configuracaoCsc.CIdToken, configuracaoCsc.Csc, _configuracoes.CfgServico.Certificado);
740741
}
741742

742743
nfe.Valida();
@@ -1431,7 +1432,7 @@ protected virtual dest GetDestinatario(VersaoServico versao, ModeloDocumento mod
14311432
};
14321433
dest.xNome = "NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL"; //Obrigatório para NFe e opcional para NFCe
14331434
dest.enderDest = GetEnderecoDestinatario(); //Obrigatório para NFe e opcional para NFCe
1434-
1435+
14351436
//if (versao == VersaoServico.Versao200)
14361437
// dest.IE = "ISENTO";
14371438
if (versao == VersaoServico.Versao200) return dest;
@@ -1803,8 +1804,8 @@ protected virtual List<pag> GetPagamento(ICMSTot icmsTot, VersaoServico versao)
18031804
{
18041805
detPag = new List<detPag>
18051806
{
1806-
new detPag {tPag = FormaPagamento.fpCreditoEmLoja, vPag = valorPagto},
1807-
new detPag {tPag = FormaPagamento.fpCreditoEmLoja, vPag = icmsTot.vNF - valorPagto}
1807+
new detPag {tPag = FormaPagamento.fpDinheiro, vPag = valorPagto},
1808+
new detPag {tPag = FormaPagamento.fpCheque, vPag = icmsTot.vNF - valorPagto}
18081809
}
18091810
}
18101811
};
@@ -2230,6 +2231,6 @@ private void BtnCancelarNFeSubstituicao_OnClick(object sender, RoutedEventArgs e
22302231
}
22312232
}
22322233

2233-
2234+
22342235
}
22352236
}

NFe.Danfe.AppTeste.Fast/MainWindow.xaml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,16 @@
122122
<Grid>
123123
<RadioButton Content="Versão 1"
124124
HorizontalAlignment="Left" VerticalAlignment="Top"
125-
Margin="8,5,0,0"
126-
IsChecked="{Binding ConfiguracaoDanfeNfce.VersaoQrCode, ConverterParameter={x:Static nfeUtils:VersaoQrCode.QrCodeVersao1}, Converter={StaticResource EnumParaBool}}" />
125+
Margin="10,5,0,0"
126+
IsChecked="{Binding ConfiguracaoDanfeNfce.VersaoQrCode, ConverterParameter={x:Static nfeUtils:VersaoQrCode.QrCodeVersao1}, Converter={StaticResource EnumParaBool}}" Width="90" />
127127
<RadioButton Content="Versão 2"
128128
HorizontalAlignment="Left" VerticalAlignment="Top"
129-
Margin="138,5,0,0"
130-
IsChecked="{Binding ConfiguracaoDanfeNfce.VersaoQrCode, ConverterParameter={x:Static nfeUtils:VersaoQrCode.QrCodeVersao2}, Converter={StaticResource EnumParaBool}}" />
129+
Margin="110,5,0,0"
130+
IsChecked="{Binding ConfiguracaoDanfeNfce.VersaoQrCode, ConverterParameter={x:Static nfeUtils:VersaoQrCode.QrCodeVersao2}, Converter={StaticResource EnumParaBool}}" Width="90"/>
131+
<RadioButton Content="Versão 3"
132+
HorizontalAlignment="Left" VerticalAlignment="Top"
133+
Margin="210,5,0,0"
134+
IsChecked="{Binding ConfiguracaoDanfeNfce.VersaoQrCode, ConverterParameter={x:Static nfeUtils:VersaoQrCode.QrCodeVersao3}, Converter={StaticResource EnumParaBool}}" Width="90"/>
131135
</Grid>
132136
</GroupBox>
133137
</StackPanel>

NFe.Utils/InformacoesSuplementares/ExtinfNFeSupl.cs

Lines changed: 21 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1+
using DFe.Classes.Entidades;
2+
using DFe.Classes.Flags;
3+
using DFe.Utils;
4+
using DFe.Utils.Assinatura;
5+
using NFe.Classes;
6+
using NFe.Classes.Informacoes.Identificacao.Tipos;
17
using System;
28
using System.Collections.Generic;
39
using System.Linq;
410
using System.Security.Cryptography;
511
using System.Security.Cryptography.X509Certificates;
612
using System.Text;
7-
using DFe.Classes.Entidades;
8-
using DFe.Classes.Flags;
9-
using DFe.Utils;
10-
using NFe.Classes;
11-
using NFe.Classes.Informacoes.Identificacao.Tipos;
1213

1314
namespace NFe.Utils.InformacoesSuplementares
1415
{
@@ -358,7 +359,7 @@ public static string ObterUrlConsulta(this infNFeSupl infNFeSupl, Classes.NFe nf
358359
/// <summary>
359360
/// Obtém a URL para montagem do QR-Code
360361
/// </summary>
361-
public static string ObterUrlQrCode(this infNFeSupl infNFeSupl, Classes.NFe nfe, VersaoQrCode versaoQrCode, string cIdToken, string csc)
362+
public static string ObterUrlQrCode(this infNFeSupl infNFeSupl, Classes.NFe nfe, VersaoQrCode versaoQrCode, string cIdToken, string csc, ConfiguracaoCertificado _cfgCertificado = null)
362363
{
363364
Func<string, string> msgErro = parametro => $"O {parametro} não foi informado!";
364365

@@ -376,7 +377,7 @@ public static string ObterUrlQrCode(this infNFeSupl infNFeSupl, Classes.NFe nfe,
376377
case VersaoQrCode.QrCodeVersao2:
377378
return ObterUrlQrCode2(infNFeSupl, nfe, cIdToken, csc, versaoServico);
378379
case VersaoQrCode.QrCodeVersao3:
379-
throw new ArgumentOutOfRangeException("versaoQrCode", versaoQrCode, "Para versão 3.0 do QR-Code utilize a função ObterUrlQrCode3");
380+
return ObterUrlQrCode3(infNFeSupl, nfe, versaoServico, _cfgCertificado);
380381
default:
381382
throw new ArgumentOutOfRangeException("versaoQrCode", versaoQrCode, null);
382383
}
@@ -495,32 +496,22 @@ public static string ObterUrlQrCode2ComParametro(this infNFeSupl infNFeSupl, Tip
495496
/// <summary>
496497
/// Obtém a URL para uso no QR-Code, versão 3.0 - leiaute 4.00+
497498
/// </summary>
498-
public static string ObterUrlQrCode3(infNFeSupl infNFeSupl, Classes.NFe nfe, VersaoServico versaoServico, X509Certificate2 certificadoDigital, Encoding encoding = null)
499+
public static string ObterUrlQrCode3(this infNFeSupl infNFeSupl, Classes.NFe nfe, VersaoServico versaoServico, ConfiguracaoCertificado cfgCertificado, Encoding encoding = null)
499500
{
500-
const string pipe = "|";
501+
if (cfgCertificado == null || string.IsNullOrWhiteSpace(cfgCertificado.Serial))
502+
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.");
501503

502-
// Chave de Acesso da NFC-e
503-
var chave = nfe.infNFe.Id.Substring(3);
504-
// Versão do QR-Code
505-
var versaoQrCode = 3;
506-
// Identificação do Ambiente (1 – Produção, 2 – Homologação)
507-
var ambiente = (int)nfe.infNFe.ide.tpAmb;
504+
const string pipe = "|";
508505

509-
// Monta os parâmetros base
510-
var dadosBase = string.Concat(
511-
chave, pipe,
512-
versaoQrCode, pipe,
513-
ambiente
514-
);
506+
string chave = nfe.infNFe.Id.Substring(3);
507+
int versaoQrCode = 3;
508+
int ambiente = (int)nfe.infNFe.ide.tpAmb;
509+
string dadosBase = string.Concat(chave, pipe, versaoQrCode, pipe, ambiente);
515510

516511
if (nfe.infNFe.ide.tpEmis == TipoEmissao.teOffLine)
517512
{
518-
// Dia da emissão
519-
var diaEmi = nfe.infNFe.ide.dhEmi.Day.ToString("D2");
520-
// Valor total da NFC-e
521-
var valorNfce = nfe.infNFe.total.ICMSTot.vNF.ToString("0.00").Replace(',', '.');
522-
523-
// tp_idDest e idDest
513+
string diaEmi = nfe.infNFe.ide.dhEmi.Day.ToString("D2");
514+
string valorNfce = nfe.infNFe.total.ICMSTot.vNF.ToString("0.00").Replace(',', '.');
524515
string tp_idDest = string.Empty;
525516
string idDest = string.Empty;
526517
if (nfe.infNFe.dest != null)
@@ -542,44 +533,17 @@ public static string ObterUrlQrCode3(infNFeSupl infNFeSupl, Classes.NFe nfe, Ver
542533
}
543534
}
544535

545-
// Monta os parâmetros base
546-
dadosBase = string.Concat(dadosBase, pipe,
547-
diaEmi, pipe,
548-
valorNfce, pipe,
549-
tp_idDest, pipe,
550-
idDest
551-
);
536+
dadosBase = string.Concat(dadosBase, pipe, diaEmi, pipe, valorNfce, pipe, tp_idDest, pipe, idDest);
552537

553538
if (encoding == null)
554539
encoding = Encoding.UTF8;
555540

556-
if (certificadoDigital == null)
557-
throw new ArgumentNullException(nameof(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.");
558-
559-
// Assinatura SHA-1 dos parâmetros COM uso do certificado digital
560-
var assinatura = Convert.ToBase64String(CreateSignaturePkcs1(certificadoDigital, encoding.GetBytes(dadosBase)));
541+
string assinatura = Convert.ToBase64String(CertificadoDigital.ObterAssinaturaPkcs1(cfgCertificado, encoding.GetBytes(dadosBase)));
561542
dadosBase = string.Concat(dadosBase, pipe, assinatura);
562543
}
563544

564-
// Monta a URL base (ja com ?p= ao final)
565-
var url = ObterUrlQrCode2ComParametro(infNFeSupl, nfe.infNFe.ide.tpAmb, nfe.infNFe.ide.cUF, versaoServico);
566-
545+
string url = ObterUrlQrCode2ComParametro(infNFeSupl, nfe.infNFe.ide.tpAmb, nfe.infNFe.ide.cUF, versaoServico);
567546
return string.Concat(url, dadosBase);
568547
}
569-
570-
private static byte[] CreateSignaturePkcs1(X509Certificate2 certificado, byte[] Value)
571-
{
572-
var rsa = certificado.GetRSAPrivateKey();
573-
574-
RSAPKCS1SignatureFormatter rsaF = new RSAPKCS1SignatureFormatter(rsa);
575-
576-
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
577-
578-
byte[] hash = sha1.ComputeHash(Value);
579-
580-
rsaF.SetHashAlgorithm("SHA1");
581-
582-
return rsaF.CreateSignature(hash);
583-
}
584548
}
585549
}

0 commit comments

Comments
 (0)