No artigo “Assinatura Digital para NF-e”, abordamos e exemplificamos os aspectos envolvidos no uso de certificados digitais da CertiSign para assinatura dos arquivos de Nota Fiscal Eletrônica (NF-e) gerados
A NFe é um documento emitido e armazenado eletronicamente, com validade jurídica
garantida por processo de assinatura digital. O principal objetivo da
implantação desta nova modalidade é o acompanhamento em tempo real das operações
comercias pelo Fisco e a substituição do modelo atual de emissão de documentos
fiscais em papel, de forma a simplificar uma série de obrigações do
contribuinte. Maiores informações podem ser obtidas através do portal nacional
em
www.nfe.fazenda.gov.br
Seguindo a linha de publicações voltadas às soluções para NFe damos continuidade
a esta série mantendo o foco no processo de assinatura digital, desta vez para
assinatura de NFe em massa e criação de lotes de NFe. Para realizar o processo
de assinatura utilizamos a assinaturaNFe32dll.dll.
Para o entendimento desse artigo, partiremos do princípio de que o leitor já
possui o conhecimento de como gerar e assinar uma NFe, abordado nos artigos
“Certificação Digital para NF-e” e “Assinatura Digital para NF-e”.
Assinatura em massa de NFe e criação de Lotes
De acordo com o manual de integração da NFe disponibilizado no portal oficial em
www.nfe.fazenda.gov.br somente
arquivos de Lote de NFe podem ser transmitidos, ou seja, mesmo que se deseje
transmitir apenas uma única NFe teremos de criar um lote contendo a mesma para
que seja possível transmiti-la.
Um arquivo de lote de NFe pode conter de 1 até 50 NFe e deve ter tamanho máximo
de 500Kbytes, e somente os arquivos de NFe devem ser assinados, o lote em si não
é assinado.
Para demonstrar como é fácil assinar uma NFe, utilizaremos a
assinaturaNFe32dll.dll e o aplicativo demo que acompanha a mesma, e pode ser
obtido a partir do site
http://www.igara.com.br/produto.php?cod_produto=114
Após o download, executamos o aplicativo Demo_EnviNFe_.exe (Figura 01) contido
na pasta de Geracao_XML/PL005a/enviNFe e selecionamos o caminho dos arquivos a
serem assinados através da árvore de pastas apresentada à esquerda da tela. À
direita podem ser visualizados os arquivos contidos na pasta escolhida.
Selecione quais arquivos de NFe devem ser assinados, caso não tenha nenhum
arquivo de NFe disponível é possível gerá-los com base no demo disponível na
pasta Geracao_XML/PL005a/nfe. Para selecionar mais de uma, segure a tecla Ctrl e
clique sobre os arquivos desejados.
Uma vez selecionados os arquivos da NFe, é possível:
· Assinar digitalmente todos os arquivos de NFe selecionados;
· Criar um lote contendo todas as notas selecionadas; Para o
uso desta opção parte-se do princípio que os arquivos de NFe selecionados já se
encontram assinados.
· Assinar todos os arquivos de NFe e logo em seguida criar um
lote com todas as notas selecionadas;

Figura 01 – Aplicativo EnviNFe
Para apenas assinar as notas selecionadas, clique no botão “Assinar Arquivos
Selecionados”. Será mostrada ao usuário uma caixa de seleção (Figura 02) onde
deve ser escolhido o Certificado Digital a ser utilizado. Selecione o
certificado e clique em OK. Caso esteja utilizando o eToken da CertiSign, ou
outro certificado A3, uma janela será exibida (Figura 03) solicitando a senha
para uso do certificado.

Figura 02 – Caixa de seleção de certificado

Figura 03 – Seleção do eToken e senha
De forma resumida, o código do evento OnClick do botão “Assinar Arquivos
Selecionados” implementa um loop nos arquivos selecionados e faz uma chamada da
função fncAssinarXML assinando sequencialmente cada um dos arquivos
selecionados.
A seguir apresentado código que mostra como é simples realizar o processo de
assinatura em massa com o trecho de código relativo ao evento OnClick do botão
citado.
|
procedure TForm1.Button2Click(Sender:
TObject);
var
i: integer;
nfe_STR: TStrings;
antes, depois: TTime;
begin
//Se nenhuma NFe selecionada
if FileListBox1.SelCount <= 0 then
begin
ShowMessage('Nenhum arquivo de NFe selecionado' + #13 +
'Selecione pelo menos um
arquivo de NFe para assinar');
Exit;
end;
antes := now;
//inicializa o progressbar
ProgressBar1.Position := 0;
ProgressBar1.Step := 1;
ProgressBar1.max := FileListBox1.SelCount;
//cria objeto da nota
nfe_STR := TStringList.Create;
nfe_STR.Clear;
//Faz loop nas notas selecionadas assinando-as
for i := 0 to FileListBox1.Items.Count - 1 do
begin
if FileListBox1.Selected[i] then //se o arquivo estiver
selecionado
begin
//carrega para a variável
nfe_STR.LoadFromFile(DirectoryListBox1.Directory
+ '\' + FileListBox1.Items.Strings[i]);
//assina nota
nfe_STR.Text := fncAssinarXML(nfe_STR);
//salva nota assinada
nfe_STR.SaveToFile(DirectoryListBox1.Directory +
FileListBox1.Items.Strings[i]);
//incrementa progressbar
ProgressBar1.StepIt;
end;
end;
//libera memoria da nota
nfe_STR.Free;
depois := now;
//mostra mensagem de nota salva e calcula tempo gasto para assiná-la
Showmessage('Assinatura Concluída' + #13#10 +
'Tempo Total (seg): ' + inttostr(SecondsBetween(antes, depois)) + #13#10
+
'Tempo Médio (seg): ' + formatfloat('0.00', SecondsBetween(antes,
depois)/FileListBox1.SelCount));
end; |
Como o objetivo da aplicação é assinar várias notas de uma só vez, não teria
sentido se o usuário fosse solicitado a selecionar o certificado e digitar a
senha a cada nota durante o loop principal da aplicação. Visando eliminar este
trabalho, é possível marcar a opção “Usar este certificado como padrão e não
perguntar novamente” na tela de seleção de certificados, para que a caixa de
seleção não seja mais exibida e todas as suas notas sejam assinadas com o
certificado selecionado.
Esse recurso é disponibilizado pela assinaturaNFe32dll.dll e pode ser utilizado
em qualquer aplicativo que use a mesma.
Ao selecionar a opção para não mais perguntar sobre o certificado, é criado na
mesma pasta da assinaturaNFe32dll.dll, um arquivo chamado “DefCertificado.res”.
Esse arquivo armazena qual o índice do certificado na lista. Caso queira que a
caixa de seleção de certificados volte a aparecer basta apagar o arquivo “DefCertificado.res”.
O procedimento de apagar o arquivo pode ser feito tanto manualmente pelo
usuário, como pelo aplicativo que está utilizando a assinaturaNFe32dll.dll. A
seguir é apresentada uma proposta de código que permite excluir o arquivo
“DefCertificado.res” a partir do clique em um botão da sua aplicação.
|
procedure TForm1.Button3Click(Sender:
TObject);
var
myfilename: String;
begin
try
//Configura o diretório onde se encontra o arquivo que armazena o índice
//Da forma que está implementada aqui só funciona se a dll estiver
localizada no mesmo diretório do .exe
myfilename := ExtractFilePath(application.ExeName) + '\DefCertificado.res';
//testa se arquivo existe
if fileexists(myfilename) then
begin
//exclue o arquivo q armazena o índice
//Usuário logado no windows deve ter permissões sobre o
diretório e o arquivo em questão
DeleteFile(myfilename);
showmessage('Arquivo' + myfilename + 'excluído. O sistema
voltará a solicitar que o usuário selecione o
certificado desejado para a
assinatura');
end;
except
showmessage('Erro durante exclusão do arquivo ' + myfilename)
end;
end; |
Agora que já vimos como realizar o processo de assinatura em massa de
arquivos de NFe, vamos gerar um lote a partir dos arquivos que foram assinados.
Para criar um lote de NFe, selecione as notas desejadas e clique no botão “Gerar
lotes dos arquivos assinados”. Vale lembrar que só é possível gerar lotes
contendo arquivos de NFe já assinados.
Conforme já dito anteriormente o lote é necessário para que seja possível
transmitir suas notas, pois não é possível transmitir notas individualmente sem
que as mesmas estejam contidas em um lote. Elas precisam ser agrupadas em lotes,
para depois serem enviadas. Mesmo que deseje enviar apenas uma nota, essa deve
estar dentro de um lote.
Conforme descrito no manual de integração (Figura 4), a estrutura de um lote é
muito simples e consiste em uma concatenação de todos os arquivos XML que vão
formá-lo e a adição de um cabeçalho e um rodapé.

Figura 04 – Estrutura do arquivo de lote conforme manual de integração
No cabeçalho do lote o conteúdo do campo “versão” é fixo e deverá ser conforme
valor apresentado na tabela (Figura 05) também disponibilizada no manual de
integração da NFe.

Figura 05 – Valor do campo versão do arquivo de lote
Ainda conforme a tabela que define a estrutura do arquivo de lote (Figura 04)
temos que o campo ‘id”, identificador de controle do envio do lote é um número
seqüencial auto-incremental sendo a responsabilidade de gerar e controlar este
número exclusiva do contribuinte.
Assim espera-se que o cabeçalho do lote gerado seja algo conforme mostrado a
seguir.
|
<?xml version="1.0" encoding="UTF-8" ?>
<enviNFe xmlns=http://www.portalfiscal.inf.br/nfe xmlns:ds=http://www.w3.org/2000/09/xmldsig#
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.portalfiscal.inf.br/nfe
enviNFe_v1.10.xsd" versao="1.10">
<idLote>000000000000001</idLote>
|
Algumas UFs rejeitam os parâmetros de NameSpace informados no cabeçalho anterior, podendo o mesmo ser gerado da seguinte forma alternativa.
|
<?xml version="1.0" encoding="UTF-8"
?>
<enviNFe xmlns=http://www.portalfiscal.inf.br/nfe xsi:schemaLocation="http://www.portalfiscal.inf.br/nfe
enviNFe_v1.10.xsd" versao="1.10">
<idLote>000000000000001</idLote> |
Segundo o manual
de integração do contribuinte, cada arquivo XML só pode possuir uma única
declaração do cabeçalho “<?xml version="1.0" encoding="UTF-8"?>”, ou seja, nas
situações onde um documento XML pode conter outros dentro do mesmo, arquivos de
lote por exemplo, apenas o lote pode conter a tag em questão, removendo dos XML
de todas as outras notas essa tag.
Sendo assim, ao realizar a concatenação de todos os arquivos
XML de NFe selecionados para compor o lote é muito importante retirar dos
arquivos somente o conteúdo a partir da tag “<NFe”, excluindo qualquer coisa que
venha antes (Figura 06).

Figura 06 – Arquivo
de NFe. Remoção do conteúdo antes da tag “<NFe”
Ao final da concatenação a aplicação deve somente incluir o
rodapé “</enviNFe>” que finaliza o arquivo de lote fechando a tag que foi aberta
no cabeçalho.
Aseguir temos o código do evento OnClick do botão “Gerar
lotes dos arquivos assinados” que executa os procedimentos descritos
anteriormente.
|
procedure TForm1.Button5Click(Sender: TObject);
var
F: TextFile;
i: integer;
nfe_STR: TStrings;
buf: String;
antes, depois: TTime;
begin
//Se nenhuma NFe selecionada
if FileListBox1.SelCount <= 0 then
begin
ShowMessage('Nenhum arquivo de NFe selecionado' + #13 +
'Selecione pelo menos um arquivo de NFe para integrar o novo
lote');
Exit;
end;
//Nº máximo de Notas por lote é 50
if FileListBox1.SelCount > 50 then
begin
ShowMessage('O lote não pode possuir mais de 50 notas' + #13
+
'Retire algumas notas e tente novamente');
Exit;
end;
antes := now;
//inicializa o progressbar
ProgressBar1.Position := 0;
ProgressBar1.Step := 1;
ProgressBar1.max := FileListBox1.SelCount;
//cria objeto da nota
nfe_STR := TStringList.Create;
nfe_STR.Clear;
AssignFile(F, DirectoryListBox1.Directory + '\' + copy(ValueListEditor76.Values['idLote'],
4, 44) + '-env-lot.xml');
Rewrite(F);
//cria cabeçalho do lote
Write(F, '<?xml version="1.0" encoding="UTF-8"?>');
if FormataCampo(ValueListEditor76, 'versao', 'N', 4) then
Write(F, '<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.portalfiscal.inf.br/nfe
enviNFe_v1.10.xsd" versao="' + ValueListEditor76.Values['versao'] + '">');
if FormataCampo(ValueListEditor76, 'idLote', 'N', 15) then
Write(F, '<idLote>' + ValueListEditor76.Values['idLote'] +
'</idLote>');
//Faz loop nas notas selecionadas assinando-as
for i := 0 to FileListBox1.Items.Count - 1 do
begin
if FileListBox1.Selected[i] then //se o arquivo estiver
selecionado
begin
nfe_STR.LoadFromFile(DirectoryListBox1.Directory
+ '\' + FileListBox1.Items.Strings[i]);
//Adiciona todas as notas ao buffer
buf := copy(nfe_STR.text, pos('<NFe',
nfe_STR.text), length(nfe_STR.text));
Write(F, buf);
ProgressBar1.StepIt;
end;
end;
//fecha rodapé de lote
Write(F, '</enviNFe>');
//libera arquivo
CloseFile(F);
depois := now;
//mostra mensagem de nota salva e calcula tempo gasto para assiná-la
Showmessage('Geração do Lote Concluída' + #13#10 +
'Tempo Total (seg): ' + inttostr(SecondsBetween(antes, depois)) + #13#10
+
'Tempo Médio (seg): ' + formatfloat('0.00', SecondsBetween(antes, depois)/FileListBox1.SelCount));
end; |
Para agilizar
ainda mais o processo de assinatura em massa de notas, podemos usar o botão
“Assinar e Gerar Lote dos arquivos selecionados”. Esse botão junta a
funcionalidade de assinatura em massa e geração de lote em apenas um click
facilitando ainda mais o processo.
O código do evento OnClick desse botão é simplesmente a
junção do código dos outros dois botões apresentados anteriormente, como pode
ser visto a seguir.
|
procedure TForm1.Button61Click(Sender: TObject);
var
i: integer;
nfe_STR: TStrings;
F: TextFile;
F_Temp: File of Byte;
buf, myfilename: String;
antes, depois: TTime;
Tamanho_Lote: Double;
begin
//Se nenhuma NFe selecionada
if FileListBox1.SelCount <= 0 then
begin
ShowMessage('Nenhum arquivo de NFe selecionado' + #13 +
'Selecione pelo menos um arquivo de NFe para integrar o novo
lote');
Exit;
end;
//Nº máximo de Notas por lote é 50
if FileListBox1.SelCount > 50 then
begin
ShowMessage('O lote não pode possuir mais de 50 notas' + #13
+
'Retire algumas notas e tente novamente');
Exit;
end;
antes := now;
//Inicializa o progressbar
ProgressBar1.Position := 0;
ProgressBar1.Step := 1;
ProgressBar1.max := FileListBox1.SelCount;
//cria o objeto da nota
nfe_STR := TStringList.Create;
nfe_STR.Clear;
myfilename := DirectoryListBox1.Directory + '\' + copy(ValueListEditor76.Values['idLote'],
4, 44) + '-env-lot.xml';
AssignFile(F, myfilename);
Rewrite(F);
//cria cabeçalho do lote
Write(F, '<?xml version="1.0" encoding="UTF-8"?>');
if FormataCampo(ValueListEditor76, 'versao', 'N', 4) then
Write(F, '<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.portalfiscal.inf.br/nfe
enviNFe_v1.10.xsd" versao="' + ValueListEditor76.Values['versao'] + '">');
if FormataCampo(ValueListEditor76, 'idLote', 'N', 15) then //Número
seqüencial auto-incremental.
Responsabilidade exclusiva do contribuinte
Write(F, '<idLote>' + ValueListEditor76.Values['idLote'] + '</idLote>');
//Faz loop nas notas selecionadas assinando-as
for i := 0 to FileListBox1.Items.Count - 1 do
begin
if FileListBox1.Selected[i] then //se arquivo selecionado
begin
//carrega arquivo para variável
nfe_STR.LoadFromFile(DirectoryListBox1.Directory
+ '\' + FileListBox1.Items.Strings[i]);
//assina nota
nfe_STR.Text := fncAssinarXML(nfe_STR);
//adiciona ao buffer do lote
buf := copy(nfe_STR.text, pos('<NFe',
nfe_STR.text), length(nfe_STR.text));
//Escreve no arquivo
Write(F, buf);
ProgressBar1.StepIt;
end;
end;
//fecha o rodapé do lote
Write(F, '</enviNFe>');
//libera arquivo
CloseFile(F);
//Verifica tamanho do lote criado. Arquivo de lote não pode ser maior que
500KB
AssignFile(F_Temp, myfilename);
Reset(F_Temp);
Tamanho_Lote := FileSize(F_Temp)/1000;
if Tamanho_Lote > 500 then
ShowMessage('Arquivo de lote é maior que tamanho máximo
permitido' + #13 +
'Seu tamanho máximo é de 500KB.');
//libera memória do objeto da nota
nfe_STR.Free;
depois := now;
//mostra mensagem de nota salva e calcula tempo gasto para gerar lote e
assiná-la
Showmessage('Assinatura e Geração do Lote Concluída' + #13#10 +
'Tempo Total (seg): ' + inttostr(SecondsBetween(antes, depois)) + #13#10
+
'Tempo Médio (seg): ' + formatfloat('0.00', SecondsBetween(antes,
depois)/FileListBox1.SelCount));
end; |
Observe que dos
trechos de código mostrados para geração do lote, apenas algumas linhas são
necessárias para assinar a nota e gerar o lote, o restante das linhas executam
funções secundárias, como atualizar progressbar e mostrar mensagens na tela, ou
seja, o processo de assinatura e geração de lote são muito simples e de fácil
implementação em qualquer aplicação.
Testes de performance mostraram que o processo de assinatura
em massa de um grande volume de NFe utilizando certificados A1 é ligeiramente
mais rápido do que utilizando certificados A3. Tipicamente o tempo médio de
assinatura utilizando certificados A3 é da ordem de 3 segundos para cada NFe
enquanto com certificados A1 os tempos obtidos foram da ordem de 2 segundos.
Importante lembrar que este valores estão condicionados a
aspectos de configuração da máquina, como memória disponível, processamento etc.
Caso haja a necessidade de grande performance, com a
assinatura de um volume realmente muito grande de notas em um curto espaço de
tempo é possível ainda se adotar hardwares específicos, chamados de HSM - Host
Security Module, que atualmente permitem assinar até 175 notas por segundo como
é o caso do equipamento Net D-Fence da True Access Consulting apresentado a
seguir.

Figura 07 – Solução
True Access para assinatura digital de grande performance.
Conclusão
Com este artigo abordamos conceitos gerais sobre
assinatura digital em massa e geração de lotes no que tange a NF-e, e vimos como
é fácil assinar e gerar tais documentos. A NF-e já é uma realidade, e muito em
breve todos serão obrigados a adotar este novo formato. Mesmo as empresas não
obrigadas, estão interessadas em ter seus sistemas atualizados para trabalhar
nesta nova modalidade de emissão de documentos fiscais.
Demos continuidade à nossa série de artigos sobre NFe, e
desta vez, demonstramos como realizar de forma simples e prática a assinatura
digital em massa e criação de lotes a partir da sua aplicação, com o uso da
assinaturaNFe32dll.dll, apresentamos resultados de performance de certificados
A1 e A3 obtidos através de testes com a solução proposta bem como indicamos
trouxemos ao conhecimento do leitor o uso dos equipamentos HSM para assinatura
de grandes volumes de NFe em um curto espaço de tempo. De agora em diante,
assinar uma Nota Fiscal Eletrônica e gerar o lote é questão
apenas de chamar uma função e indicar os arquivos a serem assinados e que irão
compor o lote, simples assim!
Victory Fernandes é Professor
do Departamento de Engenharia da UNIFACS, Engenheiro Mestrando em Redes de
Computadores, e desenvolvedor sócio da TKS Software - Soluções de Automação e
Softwares Dedicados. Pode ser contatado em
victory@igara.com.br , ou através dos sites www.igara.com.br –
www.igara.com.br/victory
Fellipe Capolupo é estudante de Engenharia Elétrica da UNIFACS –
Universidade Salvador e desenvolvedor da TKS Software - Soluções de Automação e
Softwares Dedicados. Pode ser contatado em
capolupofellipe@yahoo.com.br
|