Ir para conteúdo
  • Cadastre-se

dev botao

ACBrNFe - Rejeição: Assinatura difere do calculado


Emerson Teixeira
  • Este tópico foi criado há 3304 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Recommended Posts

  • Consultores

Pessoal,

  Desculpa cair de gaiato nessa questão aqui, mas desse último jeito, se o texto tiver o #13#10, não vai ficar o #13 pra trás depois da alteração se for compilado no Windows?

AjustarQuebrasLinhas('ACBr'+sLineBreak+'Rocks!!'); // result = 'ACBr'+#13+';Rocks!!'

Pergunto isso pois nos softwares normalmente que vejo, o padrão para quebra de linha é a constante sLineBreak. Essa constante no Delphi é #13#10.

Editado por EMBarbosa

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
Link para o comentário
Compartilhar em outros sites

  • Moderadores

Elton, é por isso que o Daniel nivelou antes o sLineBreak para somente F:

function AjustarQuebrasLinhas(const ATexto: String; NovaQuebraDeLinha: String = ';'): String;
begin
  Result := Trim(ATexto);
  
  if Result <> '' then
  begin
    // aqui se a quebra de linha for diferente de #10(F) o #13#10(sLineBreak) e transformado somente em #10
    if sLineBreak <> LF then
      Result := StringReplace(Result, sLineBreak, LF, [rfReplaceAll]); 
	  
    // aqui a nova quebra de linha e alterada para o que o usuário deseja
    Result := StringReplace(Result, LF, NovaQuebraDeLinha, [rfReplaceAll]);
  end
end;
Editado por Régys Silveira
  • Curtir 2

Equipe ACBr

Régys Borges da Silveira

http://www.regys.com.br

certificacao delphicertificacao delphi
Link para o comentário
Compartilhar em outros sites

  • Fundadores

Talvez seja melhor definirmos um novo nome para o método... Hoje na ACBrUtil já existe:

procedure QuebrarLinha(const Alinha: string; const ALista: TStringList;  const QuoteChar: char = '"'; Delimiter: char = ';');

{-----------------------------------------------------------------------------
  Quebra amigável de Linhas de um <Texto>, em um determinado numero de <Colunas>,
  respeitando o espaço existente entre as palavras. Permite especificar um
  separador diferente de espaço em <CaracterQuebrar>
 ---------------------------------------------------------------------------- } 
function QuebraLinhas(const Texto: String; const Colunas: Integer;  const CaracterQuebrar : AnsiChar = ' '): String;

{-----------------------------------------------------------------------------
  Quebra Linhas grandes no máximo de Colunas especificado, ou caso encontre
  uma quebra de Linha (CR ou CR+LF)
  Retorna uma String usando o #10 como separador de Linha
  Se <NumMaxLinhas> for especificado, para ao chegar no Limite de Linhas
  Se <PadLinhas> for True, Todas as linhas terão o mesmo tamanho de Colunas
    com espaços a esquerda se necessário.
 ---------------------------------------------------------------------------- }
function AjustaLinhas(Texto: AnsiString; Colunas: Integer ;  NumMaxLinhas: Integer = 0; PadLinhas: Boolean = False): AnsiString;

 

 

 

 

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

  • Consultores

Elton, é por isso que o Daniel nivelou antes o sLineBreak para somente F:

Hmmm... Acho que eu vacilei aqui na hora de entender o código... devia ser fome :D

Só espero que ninguém use o #13 para quebrar linhas... porque daí vai acontecer o inverso do que eu disse antes.

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
Link para o comentário
Compartilhar em outros sites

  • Fundadores

Sim.. mas nessa caso seria um erro, conforme descrevi nesse post

 

Apenas uma sugestão... CR (#13) não é sinônimo de quebra de linha (Carriage Return)

LF (#10) sim... é a quebra de Linha (Line Feed)

No Linux a quebra de linha é apenas LF ou #10

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

  • Consultores

Verdade Daniel... Mas o Windows aceita isso em mensagens. Tipo

ShowMessage('linha1'+#13+'linha2')

Já vi tanto código assim, que as vezes fico com medo de muitos usuários ACBr utilizarem...

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
Link para o comentário
Compartilhar em outros sites

  • 1 mês depois ...

Pessoal, desculpe ser recorrente na questão, mas estou enfrentando o mesmo problema.

Atualizei os componentes com o trunk2 e após isso a minha rotina de emissão de NFe não está funcionando corretamente.

O pessoal comentou que não se deve alterar o XML antes de enviar, no entanto a minha rotina altera o componente antes do envio, e na versão do trunk isso funciona.

Rotina :

>> grava a nota no banco com valor aleatório para o campo cNF; (o cliente pode gravar várias notas e depois emitir aleatoriamente, por isso não recebe o número direto)

>> Enviar consiste em ler os dados no banco, carregar o componente, alterar o número e enviar;

>> Nesse passo se eu não usar a função ACBrNFe1.NotasFiscais.GerarNFe o número que atribuo para cNF não é alterado, permanece o nro aleatório gravado e a nota é emitda, porém se uso a função eu recebo a Rejeição: Assinatura difere do calculado mas neste caso o número cNF no XML.

Alguém teria alguma sugestão ?

Ah! Neste processo em nenhum momento é usado alguma outra função do componente (assinar,validar,....)

Link para o comentário
Compartilhar em outros sites

  • Consultores

Bom dia,

A minha aplicação permite que o usuário lance diversas notas e depois escolhe a que deseja enviar para a SEFAZ.

Quando os dados da nota vão ser gravados no banco de dados o cNF (código da NF conforme manual deve ser um numero aleatório) é gerado e salvo no banco de dados também.

Quando o usuário seleciona a nota para Emitir (enviar para SEFAZ) é executado uma rotina que lê os dados do banco de dados e alimenta o componente e é nessa rotina que tenho a seguinte linha:

   Ide.cNF   := DM_VEN.NotasNFChave.AsInteger;

O campo NFChave da Tabela Notas é o que contem o numero aleatório gerado no momento da gravação da nota no banco de dados.

Depois de alimentar o componente mando executar os métodos Assinar, Validar e Enviar.

O Assinar se encarrega de gerar o XML e assinar o mesmo.

Desta forma nunca tive problema com rejeição de assinatura diferente do calculado.

Consultor SAC ACBr

Italo Giurizzato Junior
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

Analista de Sistemas / Araraquara-SP

Araraquara - A era dos Trólebus

Link para o comentário
Compartilhar em outros sites

Bom dia,

A minha aplicação permite que o usuário lance diversas notas e depois escolhe a que deseja enviar para a SEFAZ.

Quando os dados da nota vão ser gravados no banco de dados o cNF (código da NF conforme manual deve ser um numero aleatório) é gerado e salvo no banco de dados também.

Quando o usuário seleciona a nota para Emitir (enviar para SEFAZ) é executado uma rotina que lê os dados do banco de dados e alimenta o componente e é nessa rotina que tenho a seguinte linha:

   Ide.cNF   := DM_VEN.NotasNFChave.AsInteger;

O campo NFChave da Tabela Notas é o que contem o numero aleatório gerado no momento da gravação da nota no banco de dados.

Depois de alimentar o componente mando executar os métodos Assinar, Validar e Enviar.

O Assinar se encarrega de gerar o XML e assinar o mesmo.

Desta forma nunca tive problema com rejeição de assinatura diferente do calculado.

Obrigado por responder Italo, mas preciso pedir desculpas pois confundi os campos, o campo alterado é o nNF, o número da nota. 

Na sequencia >> Alimentar componente com info do banco>> alterar número  >> Assinar >> Validar >> Enviar  a nota é emitida, no entanto o número nNF não é alterado ele passa com o que foi carregado do banco

 

Link para o comentário
Compartilhar em outros sites

Italo, consegui solucionar o problema, ocorre que eu tinha uma rotina antes da emissão a qual continha ACBrNFe1.NotasFiscais.Validar e que servia única e exclusivamente para testar o preenchimento, se passasse por esta, era chamada a thread que atribui o nNF correto para a nota, valida novamente e faz a sua emissão, no entanto notei que na atualização do componente na procedure NotaFiscal.Validar do ACBrNFeNotasFiscais.pas há a seguinte implementação :

  AXML := FXMLAssinado;

  if EstaVazio(AXML) then
  begin
    Assinar;
    AXML := FXMLAssinado;
  end;

ocorre que na primeira validação ainda com o nNF provisório o FXMLAssinado está vazio, assim ele é assinado como está.

Após este passo há duas situações :

1- XML validado com nNF provisório : mesmo alterando o campo ACBrNFe1...Ide.nNF e chamado as procedures Validar e/ou Assinar o XML é gerado com o nNF provisório e emitido com este, não importando o que está no componente. 

2 - XML validado com nNF provisório, alterado o nNF do componente e usado o comando ACBrNFe1.NotasFiscais.GerarNFe : aqui é que ocorre o retorno 297, pelo meu entendimento o FXMLAssinado contém o nNF provisório e não foi alterado com as informações atribuídas ao ACBrNFe1, no caso o nNF do componente continha o número que eu atualizai e o tag nNF do FXMLAssinado continha o número provisório.

 

 

 

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Não consegui compreender a sua colocação...

O componente assina o XML, se o bloco de assinatura não estiver presente... caso contrário ele não será validado, uma vez que o bloco de assinatura é obrigatório...

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

Não consegui compreender a sua colocação...

O componente assina o XML, se o bloco de assinatura não estiver presente... caso contrário ele não será validado, uma vez que o bloco de assinatura é obrigatório...

Daniel, deixa ver se consigo te explicar melhor o processo :

1º caso : Rejeição 297

1.1 leitura da tabela de notas e carrega o componente (nNF provisório)

1.2 ACBRNFe.Validar  //somente para testar o preenchimento dos campos, neste ponto o XML já é assinado

1.3 atribuo o nNF correto com a devida validação de numeração

1.4 ACBRNFe.Gerar 

1.5 ACBRNFe.Validar // valida novamente

1.6  ACBRNFe.Enviar // Rejeição 297

 

2º caso : Emite, mas há diferença entre a informação do componente ACBrNFe e o XML gerado (usando o debug no componente)

2.1 leitura da tabela de notas e carrega o componente //nNF provisório

2.2 ACBRNFe.Validar //somente para testar o preenchimento dos campos, neste ponto o XML já é assinado com número provisório 

2.3 atribuo o nNF correto com a devida validação de numeração

2.4 ACBRNFe.Validar // aqui como aquela string FXMLAssinado já tem um valor pois já passou aqui no passo 2.2 o XML não é assinado novamente

2.5  ACBRNFe.Enviar // aqui eu tenho o campo nNF do componente com o valor correto, mas no XML da variável FXMLAssinado o tag nNF possui ainda o nro provisório.

 

3º caso : Emite e com todas as informações corretas

3.1 leitura da tabela de notas e carrega o componente //nNF provisório

3.2 atribuo o nNF correto com a devida validação de numeração

3.3 ACBRNFe.Validar //  XML é assinado com número correto 

3.4  ACBRNFe.Enviar // aqui eu tenho o campo nNF do componente e o tag nNF em FXMLAssinado possuem o mesmo número;

 

Link para o comentário
Compartilhar em outros sites

  • Consultores

Boa tarde,

Você gera o XML e assina com um numero de nota provisório e submete ao validador do componente para saber se os dados estão corretos ou não.

Se ocorrer erro na validação o usuário não vai ter que efetuar a correção?

Com certeza que sim, então porque você não atribui o numero correto da nota de uma vez?

Lembre-se que o numero da nota, ou seja, o campo nNF é usado para compor a chave da NF-e e seu conteúdo é usado para calcular o DisgestValue da assinatura.

Eu compreendo o que você fez, o usuário lança varias possíveis vendas e a medida que elas vão se concretizando emiti-se a nota e a numeração tem que ser sequencial.

Muito bem, em vez do usuário lançar uma venda, ele lançaria um orçamento que possui uma numeração sequencial, caso este se concretize é gerado a nota com a sua numeração própria.

No meu entendimento no que diz respeito a validação esta tem que ser feita na entrada dos dados.

Se você validar cada informação digitada as chances do validador do componente acusar algum erro é quase zero.

Consultor SAC ACBr

Italo Giurizzato Junior
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

Analista de Sistemas / Araraquara-SP

Araraquara - A era dos Trólebus

Link para o comentário
Compartilhar em outros sites

Boa tarde,

Você gera o XML e assina com um numero de nota provisório e submete ao validador do componente para saber se os dados estão corretos ou não.

Se ocorrer erro na validação o usuário não vai ter que efetuar a correção?

Com certeza que sim, então porque você não atribui o numero correto da nota de uma vez?

Lembre-se que o numero da nota, ou seja, o campo nNF é usado para compor a chave da NF-e e seu conteúdo é usado para calcular o DisgestValue da assinatura.

Eu compreendo o que você fez, o usuário lança varias possíveis vendas e a medida que elas vão se concretizando emiti-se a nota e a numeração tem que ser sequencial.

Muito bem, em vez do usuário lançar uma venda, ele lançaria um orçamento que possui uma numeração sequencial, caso este se concretize é gerado a nota com a sua numeração própria.

No meu entendimento no que diz respeito a validação esta tem que ser feita na entrada dos dados.

Se você validar cada informação digitada as chances do validador do componente acusar algum erro é quase zero.

Italo, na verdade o meu processo de emissão teve muitos "remendos" ao logo dos tempos onde estes processos de geração e emissão haviam estavam com vários passos desnecessários, hoje no preenchimento de nota já tem todas as validações necessárias.

Não quero de forma alguma reclamar do componente ou das alterações (que foram muito bem implementadas) só quis mostrar o exemplo para o caso de mais pessoas estarem cometendo os mesmo erros que eu. 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

  • Fundadores

Acredito que essa modificação não seja necessária...

Observe que em procedure TGerador.wCampo, será aplicado esse replace para todo tipo String

 

    tcStr:
      begin
        // remover as quebras de linha e trocar por ;, porque a quebra de linha causa erros de assinatura
        ConteudoProcessado := ChangeLineBreak( Trim( VarToStr(valor) ), ';');
        EstaVazio := ConteudoProcessado = '';
      end;  

 

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

  • Moderadores

Acredito que essa modificação não seja necessária...

Observe que em procedure TGerador.wCampo, será aplicado esse replace para todo tipo String

 

    tcStr:
      begin
        // remover as quebras de linha e trocar por ;, porque a quebra de linha causa erros de assinatura
        ConteudoProcessado := ChangeLineBreak( Trim( VarToStr(valor) ), ';');
        EstaVazio := ConteudoProcessado = '';
      end;  

 

Consultei o log e percebi que minha versão dos fontes era anterior a essa alteração.

Assim que possível farei a atualização dos fontes e informarei o resultado.

Obrigado.

Equipe ACBr BigWings
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

 

Link para o comentário
Compartilhar em outros sites

  • 3 semanas depois ...

Bom dia Emerson,

Depois do XML ter sido assinado, ele foi alterado e depois enviado?

Boa tarde Italo,

Cai justamente neste caso, alterei o XML já assinado, executo a sequencia abaixo e retorna esta rejeição. Como faço para remover a assinatura antiga ? Pesquisei bastante mas não encontrei. Obrigado.

                              if (icStat = 539) then  //Duplicada
                              begin
                                 ACBrNFe1.NotasFiscais.Items[0].NFe.Ide.tpEmis := teNormal;
                                 ACBrNFe1.NotasFiscais.Items[0].NFe.Ide.xJust := '';
                                 ACBrNFe1.NotasFiscais.Items[0].NFe.Ide.dhCont := 0;
                                 ACBrNFe1.NotasFiscais.GerarNFe;
                                 ACBrNFe1.NotasFiscais.Assinar;
                                 ACBrNFe1.NotasFiscais.Validar;
                              end;
                              ACBrNFe1.Enviar(1,False,True);

 

Link para o comentário
Compartilhar em outros sites

  • Consultores

Boa tarde Gilson,

Como assim se retornar que a nota enviada já existe na SEFAZ você altera o tipo de emissão e envia novamente?

Não entendi nada o que você esta fazendo.

Outra coisa você só remove a assinado executando um Clear e alimentando o componente novamente do zero.

Consultor SAC ACBr

Italo Giurizzato Junior
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

Analista de Sistemas / Araraquara-SP

Araraquara - A era dos Trólebus

Link para o comentário
Compartilhar em outros sites

Boa tarde Gilson,

Como assim se retornar que a nota enviada já existe na SEFAZ você altera o tipo de emissão e envia novamente?

Não entendi nada o que você esta fazendo.

Outra coisa você só remove a assinado executando um Clear e alimentando o componente novamente do zero.

Bom dia Italo,

Vou explicar. Estou tratando um caso de contingência que peguei ontem, a NFCe é enviada e autorizada pela SEFAZ (33150932582702000117650020000102861000492897), porém durante o retorno a internet cai, o sistema identifica pelo código de erro e prepara o XML de contingência (33150932582702000117650020000102869000492892).

No momento do envio do XML em contingência recebo a rejeição 539 (duplicada com chave diferente), aqui começa o exemplo que te enviei, altero o tpEmis := teNormal, xJust := '' e .dhCont := 0,  executo as funções GerarNFe, Assinar, Validar e Enviar. Se não desse a rejeição por assinatura diferente eu receberia o erro 204 (duplicada com a mesma chave) e executaria a função ACBrNFe1.Consultar; para gravar o protNFe no meu XML.

Este procedimento eu encontrei aqui mesmo no fórum. Se tiver um melhor para este caso, desde já te agradeço por compartilhar.   

                                 

Link para o comentário
Compartilhar em outros sites

Calma ai amigo Gilson, quando você envia uma nf(ece), e os dados de retorno não são salvos, ou não são atualizados por falta de energia elétrica, acredito que esta nota enviada e "não atualizada" não pode ser novamente enviada por contingencia, explico. Não é a falta de energia local que vai impedir a recepção pela SEFAZ, isso porquê, a nota foi enviada, então, deve ser consultada ou em ultimo caso, fazer uma nova nota em modo de contingencia, e cancelar a anterior quando a energia elétrica for restabelecida. Caso contrário, vai dar duplicidade mesmo.

  • Curtir 1

_____________

Prates, Agnaldo

Link para o comentário
Compartilhar em outros sites

  • Este tópico foi criado há 3304 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora
×
×
  • Criar Novo...

Informação Importante

Colocamos cookies em seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies, caso contrário, assumiremos que você está bem para continuar.

The popup will be closed in 10 segundos...