Bom dia,
estou desenvolvendo a emissão de NFS-e para prefeitura de SP e toda a comunicação com o WS deles é feita via XML assinado.
No meu método de transmissão, faço a construção do documento XML de envio, assino e transmito para prefeitura, o retorno é OK, porém, para efeito de envio de e-mail e impressão de DANFE, realizo consecutivamente a consulta ao WS do lote enviado no mesmo modelo, construo o XML de consulta, assino e transmito. Porém a prefeitura me retorna que a nota é rejeitada por erro de calculo.
No sistema tenho uma funcionalidade que atualizo o status das NFs, que executa o mesmo método de consulta supracitado, este método monta um XML idêntico ao enviado na consulta do passo acima, porém quando assino ele tem o valor de assinatura diferente, e quando é transmitido à prefeitura, este é aceito. Notei que ambos os XMLs assinados divergem apenas nas tags DigestValue e SignatureValue, estes foram assinados por um mesmo método. Não consigo identificar o que pode ocorrer pelo digestValue modificar e consequentemente a assinatura também.
Segue o trecho de código que gera a assinatura de consulta errada:
Document xmlEnvio = this.getNfseXmlService().marshal(envio, municipio);
LogUtil.debugDumpXML(logger, "XML para envio", xmlEnvio);
Document xmlEnvioAssinado = this.getNfseComunicacaoService().assinaLoteSp(xmlEnvio);
LogUtil.debugDumpXML(logger, "XML assinado para envio", xmlEnvioAssinado);
this.getNfseGravacaoService().gravacaoXmlEnvio(docs, xmlEnvioAssinado);/*
* Já este trecho de código irá enviar o xml anteriormente gerado para a
* prefeitura de São Paulo
*/
logger.info("Enviando o RPS para a prefeitura.");// Envia o RPS para a prefeitura
RetornoNfse<RetornoEnvioLoteRPS> retEnvio = this.getNfseComunicacaoService()
.recepicionarPedidoEnvioLoteRPS(xmlEnvioAssinado, municipio, tpAmb);
NFeLogUtil.traceDump(logger, "Retorno do envio", retEnvio);
this.getNfseGravacaoService().gravacaoRetornoEnvioRpsSP(docs, retEnvio);
this.validaRetorno(retEnvio);
logger.debug("Montando a consulta de RPS com o protocolo recebido.");
PedidoConsultaLote consulta = factory.createPedidoConsultaLote();
consulta.setCabecalho(factory.createPedidoConsultaLoteCabecalho());
consulta.getCabecalho().setCPFCNPJRemetente(factory.createTpCPFCNPJ());
consulta.getCabecalho().getCPFCNPJRemetente().setCNPJ(envio.getCabecalho().getCPFCNPJRemetente().getCNPJ());
consulta.getCabecalho().setNumeroLote(retEnvio.getElemento().getCabecalho().getInformacoesLote().getNumeroLote());
consulta.getCabecalho().setVersao(envio.getCabecalho().getVersao());
logger.info("Consultando o lote de RPS.");
Document xmlConsulta = this.getNfseXmlService().marshal(consulta, municipio);
Document xmlConsultaAssinado = this.getNfseComunicacaoService().assinaLoteSp(xmlConsulta);
A assinatura é realizada pelo seguinte trecho de código:
List<Reference> refList = newReferenceList(elementToSign);
SignedInfo signedInfo = newSignedInfo(refList);
KeyInfo keyInfo = keyInfoBuilder.newKeyInfo(certificate);
logger.info("CONSTRUÇÃO DSC: {}, privatekey: {}, parentelement: {}",
new Object[]{ parentElement, privateKey});
DOMSignContext dsc = new DOMSignContext(privateKey, parentElement);
XMLSignature signature = signatureFactory.newXMLSignature(signedInfo, keyInfo);
logger.info("Assinatura: {}, keyInfo: {}, dsc: {}, signature: {}",
new Object[]{ signature, keyInfo, dsc, signature });
signature.sign(dsc);
logger.debug(" Primeiro digest value encontrado é {}.", ((Reference) signature.getSignedInfo().getReferences().get(0)).getDigestValue());