Skip to content

Commit

Permalink
Merge pull request #660 from nielsonjr/fix/validar_xml_opcional
Browse files Browse the repository at this point in the history
Validação opcional XSD no envio do lote
  • Loading branch information
fincatto authored Jun 13, 2020
2 parents b48989c + 584f11a commit 557f8b6
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

0 comments on commit 557f8b6

Please sign in to comment.