From 6e9e98da39bf0096a74c4f15b3d123335e5c4a57 Mon Sep 17 00:00:00 2001
From: Nielson <nielson.truesoft@gmail.com>
Date: Mon, 11 May 2020 16:03:16 -0300
Subject: [PATCH] =?UTF-8?q?Adicionando=20possibilidade=20de=20validar=20ou?=
 =?UTF-8?q?=20n=C3=A3o=20o=20XML=20ao=20emitir=20nota?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../nfe400/webservices/WSFacade.java          |  13 +-
 .../nfe400/webservices/WSLoteEnvio.java       | 247 ++++++++++--------
 2 files changed, 145 insertions(+), 115 deletions(-)

diff --git a/src/main/java/com/fincatto/documentofiscal/nfe400/webservices/WSFacade.java b/src/main/java/com/fincatto/documentofiscal/nfe400/webservices/WSFacade.java
index 5061e847d..1e582569c 100755
--- a/src/main/java/com/fincatto/documentofiscal/nfe400/webservices/WSFacade.java
+++ b/src/main/java/com/fincatto/documentofiscal/nfe400/webservices/WSFacade.java
@@ -60,18 +60,25 @@ public WSFacade(final NFeConfig config) throws KeyManagementException, Unrecover
      * Faz o envio de lote para a Sefaz.
      *
      * @param lote o lote a ser enviado para a Sefaz
+     * @param validarXML - boolean indicando se deve haver validação XSD com o XML a ser enviado
      * @return dados do lote retornado pelo webservice, alem do lote assinado
      * @throws Exception caso nao consiga gerar o xml ou problema de conexao com o sefaz
      */
-    public NFLoteEnvioRetornoDados enviaLote(final NFLoteEnvio lote) throws Exception {
+    public NFLoteEnvioRetornoDados enviaLote(final NFLoteEnvio lote, boolean validarXML) throws Exception {
         if (lote.getIndicadorProcessamento().equals(NFLoteIndicadorProcessamento.PROCESSAMENTO_SINCRONO) && lote.getNotas().size() > 1) {
             throw new IllegalArgumentException("Apenas uma nota permitida no modo sincrono!");
         } else if (lote.getNotas().size() == 0) {
             throw new IllegalArgumentException("Nenhuma nota informada no envio do Lote!");
         }
-        return this.wsLoteEnvio.enviaLote(lote);
+        return this.wsLoteEnvio.enviaLote(lote, validarXML);
+    }
+    
+    public NFLoteEnvioRetornoDados enviaLote(final NFLoteEnvio lote) throws Exception {
+        return enviaLote(lote, true);
     }
     
+    
+    
     public NFLoteEnvio getLoteAssinado(final NFLoteEnvio lote) throws Exception {
         return this.wsLoteEnvio.getLoteAssinado(lote);
     }
@@ -98,7 +105,7 @@ public NFLoteEnvioRetorno enviaLoteAssinado(final String loteAssinadoXml, final
      * @throws Exception caso nao consiga gerar o xml ou problema de conexao com o sefaz
      */
     public NFeAutorizacao4Stub.NfeResultMsg getNfeResultMsg(final String loteAssinadoXml, final DFModelo modelo) throws Exception {
-        return this.wsLoteEnvio.comunicaLoteRaw(loteAssinadoXml, modelo);
+        return this.wsLoteEnvio.comunicaLoteRaw(loteAssinadoXml, modelo, true);
     }
     
     /**
diff --git a/src/main/java/com/fincatto/documentofiscal/nfe400/webservices/WSLoteEnvio.java b/src/main/java/com/fincatto/documentofiscal/nfe400/webservices/WSLoteEnvio.java
index 184f51d42..00c91ce0c 100644
--- a/src/main/java/com/fincatto/documentofiscal/nfe400/webservices/WSLoteEnvio.java
+++ b/src/main/java/com/fincatto/documentofiscal/nfe400/webservices/WSLoteEnvio.java
@@ -29,116 +29,139 @@
 import java.util.Iterator;
 
 class WSLoteEnvio implements DFLog {
-    
-    private static final String NFE_ELEMENTO = "NFe";
-    private final NFeConfig config;
-    
-    WSLoteEnvio(final NFeConfig config) {
-        this.config = config;
-    }
-    
-    NFLoteEnvioRetorno enviaLoteAssinado(final String loteAssinadoXml, final DFModelo modelo) throws Exception {
-        return this.comunicaLote(loteAssinadoXml, modelo);
-    }
-    
-    NFLoteEnvioRetornoDados enviaLote(final NFLoteEnvio lote) throws Exception {
-        final NFLoteEnvio loteAssinado = this.getLoteAssinado(lote);
-        final NFLoteEnvioRetorno loteEnvioRetorno = this.comunicaLote(loteAssinado.toString(), loteAssinado.getNotas().get(0).getInfo().getIdentificacao().getModelo());
-        return new NFLoteEnvioRetornoDados(loteEnvioRetorno, loteAssinado);
-    }
-    
-    /**
-     * Retorna o Lote assinado.
-     */
-    NFLoteEnvio getLoteAssinado(final NFLoteEnvio lote) throws Exception {
-        // adiciona a chave e o dv antes de assinar
-        for (final NFNota nota : lote.getNotas()) {
-            final NFGeraChave geraChave = new NFGeraChave(nota);
-            nota.getInfo().getIdentificacao().setCodigoRandomico(StringUtils.defaultIfBlank(nota.getInfo().getIdentificacao().getCodigoRandomico(), geraChave.geraCodigoRandomico()));
-            nota.getInfo().getIdentificacao().setDigitoVerificador(geraChave.getDV());
-            nota.getInfo().setIdentificador(geraChave.getChaveAcesso());
-        }
-        // assina o lote
-        final String documentoAssinado = new DFAssinaturaDigital(this.config).assinarDocumento(lote.toString());
-        final NFLoteEnvio loteAssinado = this.config.getPersister().read(NFLoteEnvio.class, documentoAssinado);
-        
-        // verifica se nao tem NFCe junto com NFe no lote e gera qrcode (apos assinar mesmo, eh assim)
-        int qtdNF = 0, qtdNFC = 0;
-        for (final NFNota nota : loteAssinado.getNotas()) {
-            switch (nota.getInfo().getIdentificacao().getModelo()) {
-                case NFE:
-                    qtdNF++;
-                    break;
-                case NFCE:
-                    NFGeraQRCode20 geraQRCode = getNfGeraQRCode20(nota);
-    
-                    nota.setInfoSuplementar(new NFNotaInfoSuplementar());
-                    nota.getInfoSuplementar().setUrlConsultaChaveAcesso(geraQRCode.urlConsultaChaveAcesso());
-                    nota.getInfoSuplementar().setQrCode(geraQRCode.getQRCode());
-                    qtdNFC++;
-                    break;
-                default:
-                    throw new IllegalArgumentException(String.format("Modelo de nota desconhecida: %s", nota.getInfo().getIdentificacao().getModelo()));
-            }
-        }
-        // verifica se todas as notas do lote sao do mesmo modelo
-        if ((qtdNF > 0) && (qtdNFC > 0)) {
-            throw new IllegalArgumentException("Lote contendo notas de modelos diferentes!");
-        }
-        return loteAssinado;
-    }
-    
-    private NFGeraQRCode20 getNfGeraQRCode20(NFNota nota) {
-        if (NFTipoEmissao.EMISSAO_NORMAL.equals(nota.getInfo().getIdentificacao().getTipoEmissao())) {
-            return new NFGeraQRCodeEmissaoNormal20(nota, this.config);
-        } else if (NFTipoEmissao.CONTIGENCIA_OFFLINE.equals(nota.getInfo().getIdentificacao().getTipoEmissao())) {
-            return new NFGeraQRCodeContingenciaOffline20(nota, this.config);
-        } else {
-            throw new IllegalArgumentException("QRCode 2.0 Tipo Emissao nao implementado: " + nota.getInfo().getIdentificacao().getTipoEmissao().getDescricao());
-        }
-    }
-    
-    private NFLoteEnvioRetorno comunicaLote(final String loteAssinadoXml, final DFModelo modelo) throws Exception {
-        final NfeResultMsg autorizacaoLoteResult = comunicaLoteRaw(loteAssinadoXml, modelo);
-        final NFLoteEnvioRetorno loteEnvioRetorno = this.config.getPersister().read(NFLoteEnvioRetorno.class, autorizacaoLoteResult.getExtraElement().toString());
-        this.getLogger().debug(loteEnvioRetorno.toString());
-        return loteEnvioRetorno;
-    }
-
-    public NfeResultMsg comunicaLoteRaw(String loteAssinadoXml, DFModelo modelo) throws Exception {
-        // valida o lote assinado, para verificar se o xsd foi satisfeito, antes de comunicar com a sefaz
-        XMLValidador.validaLote400(loteAssinadoXml);
-
-        // envia o lote para a sefaz
-        final OMElement omElement = this.nfeToOMElement(loteAssinadoXml);
-
-        final NFeAutorizacao4Stub.NfeDadosMsg dados = new NFeAutorizacao4Stub.NfeDadosMsg();
-        dados.setExtraElement(omElement);
-
-        // define o tipo de emissao
-        final NFAutorizador400 autorizador = NFAutorizador400.valueOfTipoEmissao(this.config.getTipoEmissao(), this.config.getCUF());
-
-        final String endpoint = DFModelo.NFE.equals(modelo) ? autorizador.getNfeAutorizacao(this.config.getAmbiente()) : autorizador.getNfceAutorizacao(this.config.getAmbiente());
-        if (endpoint == null) {
-            throw new IllegalArgumentException("Nao foi possivel encontrar URL para Autorizacao " + modelo.name() + ", autorizador " + autorizador.name());
-        }
-
-        return new NFeAutorizacao4Stub(endpoint).nfeAutorizacaoLote(dados);
-    }
-
-    private OMElement nfeToOMElement(final String documento) throws XMLStreamException {
-        final XMLInputFactory factory = XMLInputFactory.newInstance();
-        factory.setProperty(XMLInputFactory.IS_COALESCING, false);
-        final XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(documento));
-        final StAXOMBuilder builder = new StAXOMBuilder(reader);
-        final OMElement ome = builder.getDocumentElement();
-        final Iterator<?> children = ome.getChildrenWithLocalName(WSLoteEnvio.NFE_ELEMENTO);
-        while (children.hasNext()) {
-            final OMElement omElement = (OMElement) children.next();
-            if ((omElement != null) && (WSLoteEnvio.NFE_ELEMENTO.equals(omElement.getLocalName()))) {
-                omElement.addAttribute("xmlns", NFeConfig.NAMESPACE, null);
-            }
-        }
-        return ome;
-    }
+
+	private static final String NFE_ELEMENTO = "NFe";
+	private final NFeConfig config;
+
+	WSLoteEnvio(final NFeConfig config) {
+		this.config = config;
+	}
+
+	NFLoteEnvioRetorno enviaLoteAssinado(final String loteAssinadoXml, final DFModelo modelo) throws Exception {
+		return this.comunicaLote(loteAssinadoXml, modelo);
+	}
+
+	NFLoteEnvioRetornoDados enviaLote(final NFLoteEnvio lote, boolean validarXML) throws Exception {
+		final NFLoteEnvio loteAssinado = this.getLoteAssinado(lote);
+		final NFLoteEnvioRetorno loteEnvioRetorno = this.comunicaLote(loteAssinado.toString(),
+				loteAssinado.getNotas().get(0).getInfo().getIdentificacao().getModelo(), validarXML);
+		return new NFLoteEnvioRetornoDados(loteEnvioRetorno, loteAssinado);
+	}
+	
+	NFLoteEnvioRetornoDados enviaLote(final NFLoteEnvio lote) throws Exception {
+		return this.enviaLote(lote, true);
+	}
+
+	/**
+	 * Retorna o Lote assinado.
+	 */
+	NFLoteEnvio getLoteAssinado(final NFLoteEnvio lote) throws Exception {
+		// adiciona a chave e o dv antes de assinar
+		for (final NFNota nota : lote.getNotas()) {
+			final NFGeraChave geraChave = new NFGeraChave(nota);
+			nota.getInfo().getIdentificacao().setCodigoRandomico(StringUtils.defaultIfBlank(
+					nota.getInfo().getIdentificacao().getCodigoRandomico(), geraChave.geraCodigoRandomico()));
+			nota.getInfo().getIdentificacao().setDigitoVerificador(geraChave.getDV());
+			nota.getInfo().setIdentificador(geraChave.getChaveAcesso());
+		}
+		// assina o lote
+		final String documentoAssinado = new DFAssinaturaDigital(this.config).assinarDocumento(lote.toString());
+		final NFLoteEnvio loteAssinado = this.config.getPersister().read(NFLoteEnvio.class, documentoAssinado);
+
+		// verifica se nao tem NFCe junto com NFe no lote e gera qrcode (apos assinar
+		// mesmo, eh assim)
+		int qtdNF = 0, qtdNFC = 0;
+		for (final NFNota nota : loteAssinado.getNotas()) {
+			switch (nota.getInfo().getIdentificacao().getModelo()) {
+			case NFE:
+				qtdNF++;
+				break;
+			case NFCE:
+				NFGeraQRCode20 geraQRCode = getNfGeraQRCode20(nota);
+
+				nota.setInfoSuplementar(new NFNotaInfoSuplementar());
+				nota.getInfoSuplementar().setUrlConsultaChaveAcesso(geraQRCode.urlConsultaChaveAcesso());
+				nota.getInfoSuplementar().setQrCode(geraQRCode.getQRCode());
+				qtdNFC++;
+				break;
+			default:
+				throw new IllegalArgumentException(String.format("Modelo de nota desconhecida: %s",
+						nota.getInfo().getIdentificacao().getModelo()));
+			}
+		}
+		// verifica se todas as notas do lote sao do mesmo modelo
+		if ((qtdNF > 0) && (qtdNFC > 0)) {
+			throw new IllegalArgumentException("Lote contendo notas de modelos diferentes!");
+		}
+		return loteAssinado;
+	}
+
+	private NFGeraQRCode20 getNfGeraQRCode20(NFNota nota) {
+		if (NFTipoEmissao.EMISSAO_NORMAL.equals(nota.getInfo().getIdentificacao().getTipoEmissao())) {
+			return new NFGeraQRCodeEmissaoNormal20(nota, this.config);
+		} else if (NFTipoEmissao.CONTIGENCIA_OFFLINE.equals(nota.getInfo().getIdentificacao().getTipoEmissao())) {
+			return new NFGeraQRCodeContingenciaOffline20(nota, this.config);
+		} else {
+			throw new IllegalArgumentException("QRCode 2.0 Tipo Emissao nao implementado: "
+					+ nota.getInfo().getIdentificacao().getTipoEmissao().getDescricao());
+		}
+	}
+
+	private NFLoteEnvioRetorno comunicaLote(final String loteAssinadoXml, final DFModelo modelo, boolean validarXML)
+			throws Exception {
+		final NfeResultMsg autorizacaoLoteResult = comunicaLoteRaw(loteAssinadoXml, modelo, validarXML);
+		final NFLoteEnvioRetorno loteEnvioRetorno = this.config.getPersister().read(NFLoteEnvioRetorno.class,
+				autorizacaoLoteResult.getExtraElement().toString());
+		this.getLogger().debug(loteEnvioRetorno.toString());
+		return loteEnvioRetorno;
+	}
+
+	private NFLoteEnvioRetorno comunicaLote(final String loteAssinadoXml, final DFModelo modelo) throws Exception {
+		return this.comunicaLote(loteAssinadoXml, modelo, true);
+	}
+
+	NfeResultMsg comunicaLoteRaw(final String loteAssinadoXml, final DFModelo modelo, boolean validarXML)
+			throws Exception {
+
+		if (validarXML) {
+			// valida o lote assinado, para verificar se o xsd foi satisfeito, antes de
+			// comunicar com a sefaz
+			XMLValidador.validaLote400(loteAssinadoXml);
+		}
+
+		// envia o lote para a sefaz
+		final OMElement omElement = this.nfeToOMElement(loteAssinadoXml);
+
+		final NFeAutorizacao4Stub.NfeDadosMsg dados = new NFeAutorizacao4Stub.NfeDadosMsg();
+		dados.setExtraElement(omElement);
+
+		// define o tipo de emissao
+		final NFAutorizador400 autorizador = NFAutorizador400.valueOfTipoEmissao(this.config.getTipoEmissao(),
+				this.config.getCUF());
+
+		final String endpoint = DFModelo.NFE.equals(modelo) ? autorizador.getNfeAutorizacao(this.config.getAmbiente())
+				: autorizador.getNfceAutorizacao(this.config.getAmbiente());
+		if (endpoint == null) {
+			throw new IllegalArgumentException("Nao foi possivel encontrar URL para Autorizacao " + modelo.name()
+					+ ", autorizador " + autorizador.name());
+		}
+
+		return new NFeAutorizacao4Stub(endpoint).nfeAutorizacaoLote(dados);
+	}
+
+	private OMElement nfeToOMElement(final String documento) throws XMLStreamException {
+		final XMLInputFactory factory = XMLInputFactory.newInstance();
+		factory.setProperty(XMLInputFactory.IS_COALESCING, false);
+		final XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(documento));
+		final StAXOMBuilder builder = new StAXOMBuilder(reader);
+		final OMElement ome = builder.getDocumentElement();
+		final Iterator<?> children = ome.getChildrenWithLocalName(WSLoteEnvio.NFE_ELEMENTO);
+		while (children.hasNext()) {
+			final OMElement omElement = (OMElement) children.next();
+			if ((omElement != null) && (WSLoteEnvio.NFE_ELEMENTO.equals(omElement.getLocalName()))) {
+				omElement.addAttribute("xmlns", NFeConfig.NAMESPACE, null);
+			}
+		}
+		return ome;
+	}
 }