diff --git a/README.md b/README.md index af27e0f..88fbcac 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -Atenção este repositório já esta em desenvolvimento para a versão 4.00, para a versão 3.10 utilize a última release, [0.3](https://github.com/leotada/PyNFe/releases/tag/0.3). +Atenção este repositório já esta em desenvolvimento para a versão NF-e 4.00, para a versão 3.10 utilize a última [release](https://github.com/leotada/PyNFe/releases). ----------- Visão Geral @@ -19,12 +19,10 @@ NFS-e padrão Abrasf para autorizadores Ginfes e Betha. Dependências ------------ -- Java 8u51 - - para a geração da DANFE - lxml - biblioteca de leitura e gravação de arquivos XML, de alta performance e fácil de implementar. -- xmlsec1 e openssl (instalado no SO) +- signxml - assinatura e validação do XML - pyopenssl - biblioteca para manuseio do certificado digital diff --git a/pynfe/__init__.py b/pynfe/__init__.py index 7d3cab9..3e48912 100644 --- a/pynfe/__init__.py +++ b/pynfe/__init__.py @@ -1,5 +1,5 @@ def get_version(): - return '0.2' + return '0.4' __version__ = get_version() __author__ = 'Marinho Brandao, Junior Tada, Leonardo Tada' diff --git a/pynfe/entidades/notafiscal.py b/pynfe/entidades/notafiscal.py index 3c3a8a5..bc3b757 100644 --- a/pynfe/entidades/notafiscal.py +++ b/pynfe/entidades/notafiscal.py @@ -56,10 +56,26 @@ class NotaFiscal(Entidade): data_saida_entrada = None # - Forma de pagamento (obrigatorio - seleciona de lista) - NF_FORMAS_PAGAMENTO - forma_pagamento = int() + # Removido na NF-e 4.00 + # forma_pagamento = int() # - Tipo de pagamento - # 01=Dinheiro 02=Cheque 03=Cartão de Crédito 04=Cartão de Débito 05=Crédito Loja 10=Vale Alimentação 11=Vale Refeição 12=Vale Presente 13=Vale Combustível 99=Outros + """ + Obrigatório o preenchimento do Grupo Informações de Pagamento para NF-e e NFC-e. + Para as notas com finalidade de Ajuste ou Devolução o campo Forma de Pagamento deve ser preenchido com 90=Sem Pagamento. + 01=Dinheiro + 02=Cheque + 03=Cartão de Crédito + 04=Cartão de Débito + 05=Crédito Loja + 10=Vale Alimentação + 11=Vale Refeição + 12=Vale Presente + 13=Vale Combustível + 14=Duplicata Mercantil + 90= Sem pagamento + 99=Outros + """ tipo_pagamento = int() # - Forma de emissao (obrigatorio - seleciona de lista) - NF_FORMAS_EMISSAO @@ -78,6 +94,7 @@ class NotaFiscal(Entidade): 2=Operação não presencial, pela Internet; 3=Operação não presencial, Teleatendimento; 4=NFC-e em operação com entrega a domicílio; + 5=Operação presencial, fora do estabelecimento; 9=Operação não presencial, outros. """ indicador_presencial = int() @@ -171,6 +188,11 @@ class NotaFiscal(Entidade): # - Total do IPI (somente leitura) totais_icms_total_ipi = Decimal() + # - Valor Total do IPI devolvido + # Deve ser informado quando preenchido o Grupo Tributos Devolvidos na emissão de nota finNFe=4 (devolução) nas operações com não contribuintes do IPI. + # Corresponde ao total da soma dos campos id:UA04. + totais_icms_total_ipi_dev = Decimal() + # - PIS (somente leitura) totais_icms_pis = Decimal() @@ -224,10 +246,32 @@ class NotaFiscal(Entidade): # - Valor aproximado total de tributos federais, estaduais e municipais. totais_tributos_aproximado = Decimal() + # - Valor Total do FCP (Fundo de Combate à Pobreza) + totais_fcp = Decimal() + + # - Valor total do ICMS relativo Fundo de Combate à Pobreza (FCP) da UF de destino + totais_fcp_destino = Decimal() + + # - Valor Total do FCP (Fundo de Combate à Pobreza) retido por substituição tributária + totais_fcp_st = Decimal() + + # - Valor Total do FCP retido anteriormente por Substituição Tributária + totais_fcp_st_ret = Decimal() + + # - Valor total do ICMS Interestadual para a UF de destino + totais_icms_inter_destino = Decimal() + + # - Valor total do ICMS Interestadual para a UF do remetente + totais_icms_inter_remetente = Decimal() + # Transporte # - Modalidade do Frete (obrigatorio - seleciona de lista) - MODALIDADES_FRETE - # - 0 - Por conta do emitente - # - 1 - Por conta do destinatario + # 0=Contratação do Frete por conta do Remetente (CIF); + # 1=Contratação do Frete por conta do Destinatário (FOB); + # 2=Contratação do Frete por conta de Terceiros; + # 3=Transporte Próprio por conta do Remetente; + # 4=Transporte Próprio por conta do Destinatário; + # 9=Sem Ocorrência de Transporte. transporte_modalidade_frete = int() # - Transportador (seleciona de Transportadoras) @@ -343,10 +387,18 @@ class NotaFiscal(Entidade): self.totais_icms_total_desconto += obj.desconto # self.totais_icms_total_ii += # tem que entender o cálculo self.totais_icms_total_ipi += obj.ipi_valor_ipi + self.totais_icms_total_ipi_dev += obj.ipi_valor_ipi_dev self.totais_icms_pis += obj.pis_valor self.totais_icms_cofins += obj.cofins_valor self.totais_icms_outras_despesas_acessorias += obj.outras_despesas_acessorias self.totais_icms_total_nota += obj.valor_total_bruto + # - Valor Total do FCP (Fundo de Combate à Pobreza) + self.totais_fcp += obj.fcp_valor + self.totais_fcp_destino += obj.fcp_destino_valor + self.totais_fcp_st += obj.fcp_st_valor + self.totais_fcp_st_ret += obj.fcp_st_ret_valor + self.totais_icms_inter_destino += obj.icms_inter_destino_valor + self.totais_icms_inter_remetente += obj.icms_inter_remetente_valor ## TODO calcular impostos aproximados #self.totais_tributos_aproximado += obj.tributos return obj @@ -530,7 +582,7 @@ class NotaFiscalProduto(Entidade): # - Tributos # - ICMS # - Situacao tributaria (obrigatorio - seleciona de lista) - ICMS_TIPOS_TRIBUTACAO - icms_situacao_tributaria = str() + icms_modalidade = str() # - Origem (obrigatorio - seleciona de lista) - ICMS_ORIGENS icms_origem = int() @@ -559,9 +611,17 @@ class NotaFiscalProduto(Entidade): icms_motivo_desoneracao = int() # - ICMS ST - # - Modalidade de determinacao da BC ICMS ST (seleciona de lista) - ICMS_MODALIDADES + # - Modalidade de determinacao da BC ICMS ST + # 0=Preço tabelado ou máximo sugerido; + # 1=Lista Negativa (valor); + # 2=Lista Positiva (valor); + # 3=Lista Neutra (valor); + # 4=Margem Valor Agregado (%); + # 5=Pauta (valor); icms_st_modalidade_determinacao_bc = str() + # - Percentual da margem de valor Adicionado do ICMS ST + icms_st_percentual_adicional = Decimal() # - Percentual reducao da BC ICMS ST icms_st_percentual_reducao_bc = Decimal() @@ -574,6 +634,13 @@ class NotaFiscalProduto(Entidade): # - Valor do ICMS ST icms_st_valor = Decimal() + fcp_valor = Decimal() + fcp_destino_valor = Decimal() + fcp_st_valor = Decimal() + fcp_st_ret_valor = Decimal() + icms_inter_destino_valor = Decimal() + icms_inter_remetente_valor = Decimal() + # - IPI # - Situacao tributaria (seleciona de lista) - IPI_TIPOS_TRIBUTACAO ipi_situacao_tributaria = str() @@ -619,6 +686,9 @@ class NotaFiscalProduto(Entidade): # - Valor do IPI ipi_valor_ipi = Decimal() + # - Valor do IPI Devolvido + ipi_valor_ipi_dev = Decimal() + # - PIS # - PIS # - Situacao tributaria (obrigatorio - seleciona de lista) - PIS_TIPOS_TRIBUTACAO diff --git a/pynfe/processamento/comunicacao.py b/pynfe/processamento/comunicacao.py index 280caab..3fd3238 100644 --- a/pynfe/processamento/comunicacao.py +++ b/pynfe/processamento/comunicacao.py @@ -69,10 +69,7 @@ class ComunicacaoSefaz(Comunicacao): raiz.append(nota_fiscal) # Monta XML para envio da requisição - xml = self._construir_xml_status_pr( - cabecalho=self._cabecalho_soap(metodo='NfeAutorizacao'), metodo='NfeAutorizacao', dados=raiz - ) - + xml = self._construir_xml_soap('NFeAutorizacao4', raiz) # Faz request no Servidor da Sefaz retorno = self._post(url, xml) @@ -133,10 +130,7 @@ class ComunicacaoSefaz(Comunicacao): etree.SubElement(raiz, 'nRec').text = numero # Monta XML para envio da requisição - xml = self._construir_xml_status_pr( - cabecalho=self._cabecalho_soap(metodo='NfeRetAutorizacao'), metodo='NfeRetAutorizacao', dados=raiz - ) - + xml = self._construir_xml_soap('NFeRetAutorizacao4', raiz) return self._post(url, xml) def consulta_nota(self, modelo, chave): @@ -158,10 +152,7 @@ class ComunicacaoSefaz(Comunicacao): etree.SubElement(raiz, 'chNFe').text = chave # Monta XML para envio da requisição - xml = self._construir_xml_status_pr( - cabecalho=self._cabecalho_soap(metodo='NfeConsulta2'), metodo='NfeConsulta2', dados=raiz - ) - + xml = self._construir_xml_soap('NFeConsultaProtocolo4', raiz) return self._post(url, xml) def consulta_notas_cnpj(self, cnpj, nsu=0): @@ -200,10 +191,7 @@ class ComunicacaoSefaz(Comunicacao): etree.SubElement(raiz, 'ultNSU').text = str(nsu) # Monta XML para envio da requisição - xml = self._construir_xml_status_pr( - cabecalho=self._cabecalho_soap(metodo='NfeConsultaDest'), metodo='NfeConsultaDest', dados=raiz - ) - + xml = self._construir_xml_soap('NfeConsultaDest', raiz) return self._post(url, xml) def consulta_distribuicao(self, cnpj, nsu=0): @@ -237,10 +225,7 @@ class ComunicacaoSefaz(Comunicacao): # etree.SubElement(info, 'CPF').text = cpf # Monta XML para envio da requisição - xml = self._construir_xml_status_pr( - cabecalho=self._cabecalho_soap(metodo='CadConsultaCadastro2'), metodo='CadConsultaCadastro2', dados=raiz - ) - + xml = self._construir_xml_soap('CadConsultaCadastro4', raiz) # Chama método que efetua a requisição POST no servidor SOAP return self._post(url, xml) @@ -267,9 +252,7 @@ class ComunicacaoSefaz(Comunicacao): raiz = etree.Element('envEvento', versao='1.00', xmlns=NAMESPACE_NFE) etree.SubElement(raiz, 'idLote').text = str(id_lote) # numero autoincremental gerado pelo sistema raiz.append(evento) - xml = self._construir_xml_status_pr( - cabecalho=self._cabecalho_soap(metodo='RecepcaoEvento'), metodo='RecepcaoEvento', dados=raiz - ) + xml = self._construir_xml_soap('NFeRecepcaoEvento4', raiz) return self._post(url, xml) def status_servico(self, modelo): @@ -278,21 +261,13 @@ class ComunicacaoSefaz(Comunicacao): :param modelo: modelo é a string com tipo de serviço que deseja consultar, Ex: nfe ou nfce :return: """ - - url = self._get_url(modelo=modelo, consulta='STATUS') - + url = self._get_url(modelo, 'STATUS') # Monta XML do corpo da requisição raiz = etree.Element('consStatServ', versao=VERSAO_PADRAO, xmlns=NAMESPACE_NFE) etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente) etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()] etree.SubElement(raiz, 'xServ').text = 'STATUS' - - # Monta XML para envio da requisição - xml = self._construir_xml_status_pr( - cabecalho=self._cabecalho_soap(metodo='NfeStatusServico2'), metodo='NfeStatusServico2', dados=raiz - ) - - # Chama método que efetua a requisição POST no servidor SOAP + xml = self._construir_xml_soap('NFeStatusServico4', raiz) return self._post(url, xml) def download(self, cnpj, chave): @@ -315,11 +290,8 @@ class ComunicacaoSefaz(Comunicacao): etree.SubElement(raiz, 'CNPJ').text = str(cnpj) etree.SubElement(raiz, 'chNFe').text = str(chave) - # Monta XML para envio da requisição - xml = self._construir_xml_status_pr( - cabecalho=self._cabecalho_soap(metodo='NfeDownloadNF'), metodo='NfeDownloadNF', dados=raiz - ) - + # Monta XML para envio da requisição + xml = self._construir_xml_soap('NfeDownloadNF', raiz) return self._post(url, xml) def inutilizacao(self, modelo, cnpj, numero_inicial, numero_final, justificativa='', ano=None, serie='1'): @@ -374,10 +346,7 @@ class ComunicacaoSefaz(Comunicacao): xml = a1.assinar(raiz) # Monta XML para envio da requisição - xml = self._construir_xml_status_pr( - cabecalho=self._cabecalho_soap(metodo='NfeInutilizacao2'), metodo='NfeInutilizacao2', dados=xml - ) - + xml = self._construir_xml_soap('NFeInutilizacao4', xml) # Faz request no Servidor da Sefaz e retorna resposta return self._post(url, xml) @@ -492,35 +461,20 @@ class ComunicacaoSefaz(Comunicacao): etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()] return raiz - def _construir_xml_soap(self, cabecalho, metodo, dados): + def _construir_xml_soap(self, metodo, dados): """Mota o XML para o envio via SOAP""" - - raiz = etree.Element('{%s}Envelope' % NAMESPACE_SOAP, nsmap={'soap12': NAMESPACE_SOAP}) - c = etree.SubElement(raiz, '{%s}Header' % NAMESPACE_SOAP) - c.append(cabecalho) - body = etree.SubElement(raiz, '{%s}Body' % NAMESPACE_SOAP) - a = etree.SubElement(body, 'nfeDadosMsg', xmlns=NAMESPACE_METODO+metodo) - a.append(dados) - return raiz - - def _construir_xml_status_pr(self, cabecalho, metodo, dados): - u"""Mota o XML para o envio via SOAP""" - raiz = etree.Element('{%s}Envelope' % NAMESPACE_SOAP, nsmap={ - 'xsi': NAMESPACE_XSI, 'xsd': NAMESPACE_XSD,'soap': NAMESPACE_SOAP - }) - c = etree.SubElement(raiz, '{%s}Header' % NAMESPACE_SOAP) - c.append(cabecalho) + 'xsi': NAMESPACE_XSI, 'xsd': NAMESPACE_XSD,'soap': NAMESPACE_SOAP}) body = etree.SubElement(raiz, '{%s}Body' % NAMESPACE_SOAP) - a = etree.SubElement(body, 'nfeDadosMsg', xmlns=NAMESPACE_METODO + metodo) + a = etree.SubElement(body, 'nfeDadosMsg', xmlns=NAMESPACE_METODO+metodo) a.append(dados) return raiz def _post_header(self): - u"""Retorna um dicionário com os atributos para o cabeçalho da requisição HTTP""" + """Retorna um dicionário com os atributos para o cabeçalho da requisição HTTP""" return { - u'content-type': u'application/soap+xml; charset=utf-8;', - u'Accept': u'application/soap+xml; charset=utf-8;', + 'content-type': 'application/soap+xml; charset=utf-8;', + 'Accept': 'application/soap+xml; charset=utf-8;', } def _post(self, url, xml): @@ -538,19 +492,11 @@ class ComunicacaoSefaz(Comunicacao): etree.tostring(xml, encoding='unicode').replace('\n', '') ) xml = xml_declaration + xml - - # adapter para substituir ssl por tls - # s = requests.Session() - # s.mount(url, AdapterTLSV1()) - # print(xml) - # # print(self._post_header()) - # # Faz o request com o servidor - # result = s.post(url, xml, headers=self._post_header(), cert=chave_cert, verify=False, timeout=120) - # result.encoding = 'utf-8' - # return result + # debug dev 4.00 + print(xml) print(url) # Faz o request com o servidor - result = requests.post(url, xml, headers=self._post_header(), cert=chave_cert, verify=False, timeout=120) + result = requests.post(url, xml, headers=self._post_header(), cert=chave_cert, verify=False) result.encoding = 'utf-8' return result except requests.exceptions.RequestException as e: @@ -782,12 +728,3 @@ class ComunicacaoNfse(Comunicacao): raise Exception('Método não implementado no autorizador.') except Exception as e: raise e - -""" Adapter para conexão tls """ - -class AdapterTLSV1(HTTPAdapter): - def init_poolmanager(self, connections, maxsize, block=False): - self.poolmanager = PoolManager(num_pools=connections, - maxsize=maxsize, - block=block, - ssl_version=ssl.PROTOCOL_TLSv1_2) diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index 38c5e70..4ab5261 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -270,17 +270,51 @@ class SerializacaoXML(Serializacao): etree.SubElement(icms_item, 'vBCSTDest').text = '' # Informar o valor da BC do ICMS ST da UF destino etree.SubElement(icms_item, 'vICMSSTDest').text = '' # Informar o valor do ICMS ST da UF destino else: - # FIXME - ### OUTROS TIPOS DE ICMS + ### OUTROS TIPOS DE ICMS (00,10,20) + icms_item = etree.SubElement(icms, 'ICMS'+produto_servico.icms_modalidade) + etree.SubElement(icms_item, 'orig').text = str(produto_servico.icms_origem) + etree.SubElement(icms_item, 'CST').text = produto_servico.icms_modalidade + # Modalidade de determinação da BC do ICMS: 0=Margem Valor Agregado (%); 1=Pauta (Valor); 2=Preço Tabelado Máx. (valor); 3=Valor da operação. etree.SubElement(icms_item, 'modBC').text = str(produto_servico.icms_modalidade_determinacao_bc) - etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo) - etree.SubElement(icms_item, 'pICMS').text = str(produto_servico.icms_aliquota) - etree.SubElement(icms_item, 'vICMS').text = str(produto_servico.icms_valor) + # 00=Tributada integralmente. + if produto_servico.icms_modalidade == '00': + etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo) # Valor da BC do ICMS + etree.SubElement(icms_item, 'pICMS').text = str(produto_servico.icms_aliquota) # Alíquota do imposto + etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS + # 10=Tributada e com cobrança do ICMS por substituição tributária + elif produto_servico.icms_modalidade == '10': + etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo) # Valor da BC do ICMS + etree.SubElement(icms_item, 'pICMS').text = str(produto_servico.icms_aliquota) # Alíquota do imposto + etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS + # Modalidade de determinação da BC do ICMS ST + # 0=Preço tabelado ou máximo sugerido; 1=Lista Negativa (valor);2=Lista Positiva (valor);3=Lista Neutra (valor);4=Margem Valor Agregado (%);5=Pauta (valor); + etree.SubElement(icms_item, 'modBCST').text = str(produto_servico.icms_st_modalidade_determinacao_bc) + etree.SubElement(icms_item, 'pMVAST').text = str(produto_servico.icms_st_percentual_adicional) # Percentual da margem de valor Adicionado do ICMS ST + etree.SubElement(icms_item, 'pRedBCST').text = str(produto_servico.icms_st_percentual_reducao_bc) # APercentual da Redução de BC do ICMS ST + etree.SubElement(icms_item, 'vBCST ').text = str(produto_servico.icms_st_valor_base_calculo) + etree.SubElement(icms_item, 'pICMSST ').text = str(produto_servico.icms_st_aliquota) + etree.SubElement(icms_item, 'vICMSST ').text = str(produto_servico.icms_st_valor) + # 20=Com redução de base de cálculo + elif produto_servico.icms_modalidade == '20': + etree.SubElement(icms_item, 'pRedBC').text = str(produto_servico.icms_percentual_reducao_bc) # Percentual da Redução de BC + etree.SubElement(icms_item, 'vBC').text = '{:.2f}'.format(produto_servico.icms_valor_base_calculo or 0) # Valor da BC do ICMS + etree.SubElement(icms_item, 'pICMS').text = str(produto_servico.icms_aliquota) # Alíquota do imposto + etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS + # Impostos não implementados + else: + raise NotImplementedError + # ipi + # ipi = etree.SubElement(imposto, 'IPI') + # etree.SubElement(ipi, 'clEnq') = produto_servico.ipi_classe_enquadramento # Preenchimento conforme Atos Normativos editados pela Receita Federal (Observação 2) + # ipint = etree.SubElement(ipi, 'IPINT') + # # 01=Entrada tributada com alíquota zero 02=Entrada isenta 03=Entrada não-tributada 04=Entrada imune 05=Entrada com suspensão + # # 51=Saída tributada com alíquota zero 52=Saída isenta 53=Saída não-tributada 54=Saída imune 55=Saída com suspensão + # etree.SubElement(ipint, 'CST') = produto_servico.ipi_codigo_enquadramento # apenas nfe - pisnt = ('04','05','06','07','08','09') if modelo == 55: ## PIS + pisnt = ('04','05','06','07','08','09') pis = etree.SubElement(imposto, 'PIS') if produto_servico.pis_modalidade in pisnt: pis_item = etree.SubElement(pis, 'PISNT') @@ -378,7 +412,8 @@ class SerializacaoXML(Serializacao): etree.SubElement(ide, 'cUF').text = CODIGOS_ESTADOS[nota_fiscal.uf] etree.SubElement(ide, 'cNF').text = nota_fiscal.codigo_numerico_aleatorio etree.SubElement(ide, 'natOp').text = nota_fiscal.natureza_operacao - etree.SubElement(ide, 'indPag').text = str(nota_fiscal.forma_pagamento) + # Removido na NF-e 4.00 + # etree.SubElement(ide, 'indPag').text = str(nota_fiscal.forma_pagamento) etree.SubElement(ide, 'mod').text = str(nota_fiscal.modelo) etree.SubElement(ide, 'serie').text = nota_fiscal.serie etree.SubElement(ide, 'nNF').text = str(nota_fiscal.numero_nf) @@ -481,8 +516,18 @@ class SerializacaoXML(Serializacao): etree.SubElement(icms_total, 'vBC').text = '{:.2f}'.format(nota_fiscal.totais_icms_base_calculo) etree.SubElement(icms_total, 'vICMS').text = '{:.2f}'.format(nota_fiscal.totais_icms_total) etree.SubElement(icms_total, 'vICMSDeson').text = '{:.2f}'.format(nota_fiscal.totais_icms_desonerado) # Valor Total do ICMS desonerado + if nota_fiscal.totais_fcp: + etree.SubElement(icms_total, 'vFCP').text = '{:.2f}'.format(nota_fiscal.totais_fcp) + if nota_fiscal.totais_fcp_destino: + etree.SubElement(icms_total, 'vFCPUFDest').text = '{:.2f}'.format(nota_fiscal.totais_fcp_destino) + if nota_fiscal.totais_icms_inter_destino: + etree.SubElement(icms_total, 'vICMSUFDest').text = '{:.2f}'.format(nota_fiscal.totais_icms_inter_destino) + if nota_fiscal.totais_icms_inter_remetente: + etree.SubElement(icms_total, 'vICMSUFRemet').text = '{:.2f}'.format(nota_fiscal.totais_icms_remetente) etree.SubElement(icms_total, 'vBCST').text = '{:.2f}'.format(nota_fiscal.totais_icms_st_base_calculo) etree.SubElement(icms_total, 'vST').text = '{:.2f}'.format(nota_fiscal.totais_icms_st_total) + etree.SubElement(icms_total, 'vFCPST').text = '{:.2f}'.format(nota_fiscal.totais_fcp_st) + etree.SubElement(icms_total, 'vFCPSTRet').text = '{:.2f}'.format(nota_fiscal.totais_fcp_st_ret) etree.SubElement(icms_total, 'vProd').text = str(nota_fiscal.totais_icms_total_produtos_e_servicos) etree.SubElement(icms_total, 'vFrete').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_frete) etree.SubElement(icms_total, 'vSeg').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_seguro) @@ -491,6 +536,7 @@ class SerializacaoXML(Serializacao): # Tributos etree.SubElement(icms_total, 'vII').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_ii) etree.SubElement(icms_total, 'vIPI').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_ipi) + etree.SubElement(icms_total, 'vIPIDevol').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_ipi_dev) etree.SubElement(icms_total, 'vPIS').text = '{:.2f}'.format(nota_fiscal.totais_icms_pis) etree.SubElement(icms_total, 'vCOFINS').text = '{:.2f}'.format(nota_fiscal.totais_icms_cofins) @@ -499,13 +545,12 @@ class SerializacaoXML(Serializacao): if nota_fiscal.totais_tributos_aproximado: etree.SubElement(icms_total, 'vTotTrib').text = '{:.2f}'.format(nota_fiscal.totais_tributos_aproximado) + # Transporte + transp = etree.SubElement(raiz, 'transp') + etree.SubElement(transp, 'modFrete').text = str(nota_fiscal.transporte_modalidade_frete) + # Apenas NF-e if nota_fiscal.modelo == 55: - - # Transporte - transp = etree.SubElement(raiz, 'transp') - etree.SubElement(transp, 'modFrete').text = str(nota_fiscal.transporte_modalidade_frete) - # Transportadora if nota_fiscal.transporte_transportadora: transp.append(self._serializar_transportadora( @@ -548,26 +593,25 @@ class SerializacaoXML(Serializacao): for lacre in volume.lacres: etree.SubElement(lacres, 'nLacre').text = lacre.numero_lacre - # Somente NFC-e - """ Grupo obrigatório para a NFC-e, a critério da UF. Não informar para a NF-e (modelo 55). """ - if nota_fiscal.modelo == 65: - # Transporte - transp = etree.SubElement(raiz, 'transp') - etree.SubElement(transp, 'modFrete').text = str(9) - # Pagamento - pag = etree.SubElement(raiz, 'pag') - etree.SubElement(pag, 'tPag').text = str(nota_fiscal.tipo_pagamento).zfill(2) # 01=Dinheiro 02=Cheque 03=Cartão de Crédito 04=Cartão de Débito 05=Crédito Loja 10=Vale Alimentação 11=Vale Refeição 12=Vale Presente 13=Vale Combustível 99=Outros - etree.SubElement(pag, 'vPag').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_nota) - # Cartão NT2015.002 - cartao = etree.SubElement(pag, 'card') + # Pagamento + """ Obrigatório o preenchimento do Grupo Informações de Pagamento para NF-e e NFC-e. Para as notas com finalidade de Ajuste ou Devolução o +campo Forma de Pagamento deve ser preenchido com 90=Sem Pagamento. """ + pag = etree.SubElement(raiz, 'pag') + detpag = etree.SubElement(pag, 'detPag') + etree.SubElement(detpag, 'tPag').text = str(nota_fiscal.tipo_pagamento).zfill(2) + etree.SubElement(detpag, 'vPag').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_nota) + if nota_fiscal.tipo_pagamento == 3 or nota_fiscal.tipo_pagamento == 4: + cartao = etree.SubElement(detpag, 'card') """ Tipo de Integração do processo de pagamento com o sistema de automação da empresa: 1=Pagamento integrado com o sistema de automação da empresa (Ex.: equipamento TEF, Comércio Eletrônico); 2= Pagamento não integrado com o sistema de automação da empresa (Ex.: equipamento POS); """ etree.SubElement(cartao, 'tpIntegra').text = '2' #etree.SubElement(cartao, 'CNPJ').text = '' # Informar o CNPJ da Credenciadora de cartão de crédito / débito - #etree.SubElement(cartao, 'tBand').text = '' # 01=Visa 02=Mastercard 03=American Express 04=Sorocred 99=Outros + #etree.SubElement(cartao, 'tBand').text = '' # 01=Visa 02=Mastercard 03=American Express 04=Sorocred 05=Diners Club 06=Elo 07=Hipercard 08=Aura 09=Caba 99=Outros #etree.SubElement(cartao, 'cAut').text = '' # Identifica o número da autorização da transação da operação com cartão de crédito e/ou débito + # troco + # etree.SubElement(pag, 'vTroco').text = str('') # Informações adicionais if nota_fiscal.informacoes_adicionais_interesse_fisco or nota_fiscal.informacoes_complementares_interesse_contribuinte: @@ -658,22 +702,32 @@ class SerializacaoQrcode(object): url = url + '&cHashQRCode=' + url_hash.upper() - if uf.upper() == 'PR': + # url_chave - Texto com a URL de consulta por chave de acesso a ser impressa no DANFE NFC-e. + # Informar a URL da “Consulta por chave de acesso da NFC-e”. + # A mesma URL que deve estar informada no DANFE NFC-e para consulta por chave de acesso + lista_uf_padrao = ['PR', 'CE', 'RS', 'RJ', 'RO'] + if uf.upper() in lista_uf_padrao: qrcode = NFCE[uf.upper()]['QR'] + url + url_chave = NFCE[uf.upper()]['URL'] elif uf.upper() == 'SP': if tpamb == '1': qrcode = NFCE[uf.upper()]['HTTPS'] + 'www.' + NFCE[uf.upper()]['QR'] + url + url_chave = NFCE[uf.upper()]['HTTPS'] + 'www.' + NFCE[uf.upper()]['URL'] + url else: qrcode = NFCE[uf.upper()]['HTTPS'] + 'www.homologacao.' + NFCE[uf.upper()]['QR'] + url + url_chave = NFCE[uf.upper()]['HTTPS'] + 'www.homologacao.' + NFCE[uf.upper()]['URL'] + url + # AC, AM, RR, PA, else: if tpamb == '1': qrcode = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['QR'] + url + url_chave = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['URL'] + url else: qrcode = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['QR'] + url - + url_chave = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['URL'] + url # adicionta tag infNFeSupl com qrcode info = etree.Element('infNFeSupl') etree.SubElement(info, 'qrCode').text = '' + etree.SubElement(info, 'urlChave').text = url_chave nfe.insert(1, info) # correção da tag qrCode, retira caracteres pois e CDATA tnfe = etree.tostring(nfe, encoding='unicode') @@ -747,240 +801,3 @@ class SerializacaoNfse(object): return SerializacaoBetha().cancelar(nfse) else: raise Exception('Autorizador não suportado para cancelamento!') - - -class SerializacaoPipes(Serializacao): - """Serialização utilizada pela SEFAZ-SP para a importação de notas.""" - - def exportar(self, destino, **kwargs): - pass - - def _serializar_emitente(self, emitente, retorna_string=True): - - cod_municipio, municipio = obter_municipio_e_codigo( - dict(codigo=emitente.endereco_cod_municipio, - municipio=emitente.endereco_municipio), - emitente.endereco_uf - ) - - serial_emitente_list = [ - '\nC', - emitente.razao_social, - emitente.nome_fantasia, - emitente.inscricao_estadual, - emitente.inscricao_estadual_subst_tributaria, - emitente.inscricao_municipal, - emitente.cnae_fiscal, - emitente.codigo_de_regime_tributario, - '\nC02', - emitente.cnpj, - '\nC05', - emitente.endereco_logradouro, - emitente.endereco_numero, - emitente.endereco_complemento, - emitente.endereco_bairro, - cod_municipio, - municipio, - obter_uf_por_codigo(emitente.endereco_uf), - emitente.endereco_cep.replace('-',''), - emitente.endereco_pais, - obter_pais_por_codigo(emitente.endereco_pais), - emitente.endereco_telefone, - ] - - if retorna_string: - return '|'.join(map(str,serial_emitente_list)) - return serial_emitente_list - - def _serializar_cliente(self, cliente, retorna_string=True): - - cod_municipio, municipio = obter_municipio_e_codigo( - dict(codigo=cliente.endereco_cod_municipio, - municipio=cliente.endereco_municipio), - cliente.endereco_uf - ) - - serial_data = [ - '\nE', - cliente.razao_social, - '2', # indIEDest - cliente.inscricao_estadual, - cliente.inscricao_suframa, - '', # IM - cliente.email, - '\nE02' if cliente.tipo_documento == 'CNPJ' else '\nE03', - cliente.numero_documento, - '\nE05', - cliente.endereco_logradouro, - cliente.endereco_numero, - cliente.endereco_complemento, - cliente.endereco_bairro, - cod_municipio, - municipio, - obter_uf_por_codigo(cliente.endereco_uf), - cliente.endereco_cep.replace('-',''), - cliente.endereco_pais, - obter_pais_por_codigo(cliente.endereco_pais), - cliente.endereco_telefone - ] - - if retorna_string: - return '|'.join(map(str,serial_data)) - return serial_data - - def _serializar_produto_servico(self, produto_servico, retorna_string=True): - serial_data = [ - '\nI', - produto_servico.codigo, - produto_servico.ean, - produto_servico.descricao, - produto_servico.ncm, - produto_servico.ex_tipi, - produto_servico.cfop, - produto_servico.unidade_comercial, - formatar_decimal(produto_servico.quantidade_comercial), - formatar_decimal(produto_servico.valor_unitario_comercial), - formatar_decimal(produto_servico.valor_total_bruto), - produto_servico.ean_tributavel, - produto_servico.unidade_tributavel, - formatar_decimal(produto_servico.quantidade_tributavel), - formatar_decimal(produto_servico.valor_unitario_tributavel), - formatar_decimal(produto_servico.total_frete) if produto_servico.total_frete else '', - formatar_decimal(produto_servico.total_seguro) if produto_servico.total_seguro else '', - formatar_decimal(produto_servico.desconto) if produto_servico.desconto else '', - formatar_decimal(produto_servico.outras_despesas_acessorias) if produto_servico.outras_despesas_acessorias else '', - produto_servico.compoe_valor_total, - produto_servico.numero_pedido, - produto_servico.numero_do_item, - '', # nFCI - '\nM', #IMPOSTOS - '\nN', #ICMS - '\nN06', - produto_servico.icms_origem, - produto_servico.icms_modalidade_determinacao_bc, - produto_servico.icms_valor if produto_servico.icms_valor else '', - produto_servico.icms_motivo_desoneracao if produto_servico.icms_valor else '', - '\nQ', #PIS - '\nQ02', - produto_servico.pis_tipo_calculo, - formatar_decimal(produto_servico.pis_valor_base_calculo), - formatar_decimal(produto_servico.pis_aliquota_percentual), - formatar_decimal(produto_servico.pis_valor), - '\nS', #COFINS - '\nS02', - produto_servico.cofins_situacao_tributaria, - formatar_decimal(produto_servico.cofins_valor_base_calculo), - formatar_decimal(produto_servico.cofins_aliquota_percentual), - formatar_decimal(produto_servico.cofins_valor) - ] - - if retorna_string: - return '|'.join(map(str, serial_data)) - return serial_data - - def _serializar_nota_fiscal(self, nota_fiscal, retorna_string=True): - - cod_municipio, municipio = obter_municipio_e_codigo( - dict(codigo='', - municipio=nota_fiscal.municipio), - nota_fiscal.uf - ) - - if nota_fiscal.emitente.endereco_uf == nota_fiscal.cliente.endereco_uf: - id_dest = '1' - else: - id_dest = '2' - - tz = time.strftime("%z") - tz = "{}:{}".format(tz[:-2], tz[-2:]) - - serial_data = [ - 'A', - '3.10', - nota_fiscal.identificador_unico, - '\nB', - CODIGOS_ESTADOS.get(nota_fiscal.uf, nota_fiscal.uf), - nota_fiscal.codigo_numerico_aleatorio, - nota_fiscal.natureza_operacao, - nota_fiscal.forma_pagamento, - nota_fiscal.modelo, - nota_fiscal.serie, - nota_fiscal.numero_nf, - nota_fiscal.data_emissao.strftime('%Y-%m-%dT%H:%M:%S') + tz, - nota_fiscal.data_saida_entrada.strftime('%Y-%m-%dT%H:%M:%S') + tz, - nota_fiscal.tipo_documento, - id_dest, # idDest - cod_municipio, - nota_fiscal.tipo_impressao_danfe, - nota_fiscal.forma_emissao, - nota_fiscal.dv_codigo_numerico_aleatorio, - self._ambiente, - nota_fiscal.finalidade_emissao, - nota_fiscal.cliente_final, # indFinal - nota_fiscal.indicador_presencial, # indPres - nota_fiscal.processo_emissao, - '%s %s' % (self._nome_aplicacao, - nota_fiscal.versao_processo_emissao), - '', # dhCont - Data e Hora da entrada em contingência - '', # xJust - Justificativa da entrada em contingência - ] - - serial_data += self._serializar_emitente(nota_fiscal.emitente, - retorna_string=False) - serial_data += self._serializar_cliente(nota_fiscal.cliente, - retorna_string=False) - - # Produtos e serviços - produtos_servicos = enumerate(nota_fiscal.produtos_e_servicos, start=1) - for num, produto_servico in produtos_servicos: - num_produto = [ - '\nH', - num, # Número do produto na lista - '' - '' # End Pipe - ] - serial_data += num_produto - serial_data += self._serializar_produto_servico(produto_servico, - retorna_string=False) - - serial_data += [ - '\nW', #Valores totais NFe, - '\nW02', - formatar_decimal(nota_fiscal.totais_icms_base_calculo), - formatar_decimal(nota_fiscal.totais_icms_total), - '', # ICMSDeson - formatar_decimal(nota_fiscal.totais_icms_st_base_calculo), - formatar_decimal(nota_fiscal.totais_icms_st_total), - formatar_decimal(nota_fiscal.totais_icms_total_produtos_e_servicos), - formatar_decimal(nota_fiscal.totais_icms_total_frete), - formatar_decimal(nota_fiscal.totais_icms_total_seguro), - formatar_decimal(nota_fiscal.totais_icms_total_desconto), - formatar_decimal(nota_fiscal.totais_icms_total_ii), - formatar_decimal(nota_fiscal.totais_icms_total_ipi), - formatar_decimal(nota_fiscal.totais_icms_pis), - formatar_decimal(nota_fiscal.totais_icms_cofins), - formatar_decimal(nota_fiscal.totais_icms_outras_despesas_acessorias), - formatar_decimal(nota_fiscal.totais_icms_total_nota), - '', # vTotTrib - '\nX', - nota_fiscal.transporte_modalidade_frete, - '\nZ', - nota_fiscal.informacoes_adicionais_interesse_fisco, - nota_fiscal.informacoes_complementares_interesse_contribuinte, - '' # End Pipe - ] - - if retorna_string: - try: - return '|'.join(map(remover_acentos, serial_data)) - except TypeError as err: - enum_args = '\n'.join( - map( - lambda x: str(x[0]) + ' ' + str(x[1]), - enumerate(serial_data) - ) - ) - message = err.message + '\n' + enum_args - raise TypeError(message) - - return serial_data diff --git a/pynfe/utils/flags.py b/pynfe/utils/flags.py index ae99de7..7c1db9e 100644 --- a/pynfe/utils/flags.py +++ b/pynfe/utils/flags.py @@ -10,7 +10,7 @@ NAMESPACE_METODO = 'http://www.portalfiscal.inf.br/nfe/wsdl/' NAMESPACE_SOAP_NFSE = 'http://schemas.xmlsoap.org/soap/envelope/' NAMESPACE_BETHA = 'http://www.betha.com.br/e-nota-contribuinte-ws' -VERSAO_PADRAO = '3.10' +VERSAO_PADRAO = '4.00' VERSAO_QRCODE = '100' diff --git a/pynfe/utils/webservices.py b/pynfe/utils/webservices.py index 7d05fbe..80d3a19 100644 --- a/pynfe/utils/webservices.py +++ b/pynfe/utils/webservices.py @@ -3,6 +3,8 @@ @author: Junior Tada, Leonardo Tada """ +# http://nfce.encat.org/desenvolvedor/qrcode/ +# http://nfce.encat.org/consumidor/consulte-sua-nota/ url consulta por chave # Nfc-e NFCE = { 'RO': { @@ -12,10 +14,12 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': 'http://www.nfce.sefin.ro.gov.br/consultanfce/consulta.jsp?', + 'URL': 'http://www.nfce.sefin.ro.gov.br' }, 'AC': { 'QR': 'sefaznet.ac.gov.br/nfce?', + 'URL': 'sefaznet.ac.gov.br/nfce/consulta', 'HTTPS': 'http://www.', 'HOMOLOGACAO': 'http://hml.' }, @@ -29,6 +33,7 @@ NFCE = { 'INUTILIZACAO': 'nfce.sefaz.am.gov.br/nfce-services-nac/services/NfeInutilizacao2', 'EVENTOS': 'nfce.sefaz.am.gov.br/nfce-services-nac/services/RecepcaoEvento', 'QR': 'sefaz.am.gov.br/nfceweb/consultarNFCe.jsp?', + 'URL': 'sefaz.am.gov.br/nfceweb/formConsulta.do', 'HTTPS': 'http://sistemas.', 'HOMOLOGACAO': 'http://homnfce.' }, @@ -39,7 +44,10 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': '/nfce/servlet/qrcode?', + 'URL': '/nfce/servlet/wp_consulta_nfce', + 'HTTPS': 'https://www.sefaz.rr.gov.br', + 'HOMOLOGACAO': 'http://200.174.88.103:8080' }, 'PA': { 'STATUS': '', @@ -48,7 +56,10 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': 'view/consultas/nfce/nfceForm.seam?', + 'URL': 'view/consultas/nfce/consultanfce.seam', + 'HTTPS': 'https://appnfc.sefa.pa.gov.br/portal/', + 'HOMOLOGACAO': 'https://appnfc.sefa.pa.gov.br/portal-homologacao/' }, 'AP': { 'STATUS': '', @@ -57,7 +68,10 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': '/nfcep.php?', + 'URL': 'https://www.sefaz.ap.gov.br/sate/seg/SEGf_AcessarFuncao.jsp?cdFuncao=FIS_1261', + 'HTTPS': ' https://www.sefaz.ap.gov.br/nfce', + 'HOMOLOGACAO': 'https://www.sefaz.ap.gov.br/nfcehml' }, 'TO': { 'STATUS': '', @@ -85,7 +99,8 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': 'http://nfceh.sefaz.ce.gov.br/pages/ShowNFCe.html?', + 'URL': 'http://nfceh.sefaz.ce.gov.br/pages/consultaNota.jsf' }, 'RN': { #'QR': 'http://www.nfe.rn.gov.br/portal/consultarNFCe.jsp?', @@ -160,8 +175,16 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' - }, + 'QR': 'http://www4.fazenda.rj.gov.br/consultaNFCe/QRCode?', + 'URL': 'www.nfce.fazenda.rj.gov.br/consulta' + }, + # Os Web Services de homologação da NFC-e 4.00 são: + # https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeAutorizacao4.asmx + # https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeStatusServico4.asmx + # https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeConsultaProtocolo4.asmx + # https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeRetAutorizacao4.asmx + # https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeRecepcaoEvento4.asmx + # https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeInutilizacao4.asmx 'SP': { 'STATUS': 'nfce.fazenda.sp.gov.br/ws/nfestatusservico2.asmx', 'AUTORIZACAO': 'nfce.fazenda.sp.gov.br/ws/nfeautorizacao.asmx', @@ -170,6 +193,7 @@ NFCE = { 'INUTILIZACAO': 'nfce.fazenda.sp.gov.br/ws/nfeinutilizacao2.asmx', 'EVENTOS': 'nfce.fazenda.sp.gov.br/ws/recepcaoevento.asmx', 'QR': 'nfce.fazenda.sp.gov.br/NFCeConsultaPublica/Paginas/ConsultaQRCode.aspx?', + 'URL': 'nfce.fazenda.sp.gov.br/NFCeConsultaPublica/Paginas/ConsultaPublica.aspx', 'HTTPS': 'https://', 'HOMOLOGACAO': 'https://homologacao.' }, @@ -180,7 +204,8 @@ NFCE = { 'CHAVE': 'nfce.fazenda.pr.gov.br/nfce/NFeConsulta3', 'INUTILIZACAO': 'nfce.fazenda.pr.gov.br/nfce/NFeInutilizacao3', 'EVENTOS': 'nfce.fazenda.pr.gov.br/nfce/NFeRecepcaoEvento', - 'QR': 'http://www.dfeportal.fazenda.pr.gov.br/dfe-portal/rest/servico/consultaNFCe?', + 'QR': 'http://www.fazenda.pr.gov.br/nfce/qrcode?', + 'URL': 'http://www.fazenda.pr.gov.br', 'HTTPS': 'https://', 'HOMOLOGACAO': 'https://homologacao.' }, @@ -201,6 +226,7 @@ NFCE = { 'INUTILIZACAO': 'sefazrs.rs.gov.br/ws/nfeinutilizacao/nfeinutilizacao2.asmx', 'EVENTOS': 'sefazrs.rs.gov.br/ws/recepcaoevento/recepcaoevento.asmx', 'QR': 'https://www.sefaz.rs.gov.br/NFCE/NFCE-COM.aspx?', + 'URL': 'https://www.sefaz.rs.gov.br/NFCE/NFCE-COM.aspx', 'HTTPS': 'https://nfce.', 'HOMOLOGACAO': 'https://nfce-homologacao.' }, @@ -245,10 +271,12 @@ NFCE = { } # Nfe +# homologação => http://hom.nfe.fazenda.gov.br/PORTAL/WebServices.aspx +# produção => https://www.nfe.fazenda.gov.br/portal/webServices.aspx NFE = { # Alguns serviços são disponibilizados apenas pelo ambiente nacional 'AN': { - 'EVENTOS': 'nfe.fazenda.gov.br/RecepcaoEvento/RecepcaoEvento.asmx', # versao: 1.00 + 'EVENTOS': 'nfe.fazenda.gov.br/NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx', # versao: 4.00 'DISTRIBUICAO': 'nfe.fazenda.gov.br/NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx', 'DOWNLOAD': 'nfe.fazenda.gov.br/NfeDownloadNF/NfeDownloadNF.asmx', # versao: 2.00/3.10 'DESTINADAS': 'nfe.fazenda.gov.br/NFeConsultaDest/NFeConsultaDest.asmx', # versao: 2.00/3.10 @@ -270,12 +298,12 @@ NFE = { 'CADASTRO': 'https://sistemas.sefaz.ma.gov.br/wscadastro/CadConsultaCadastro2?wsdl' }, 'CE': { - 'STATUS': 'sefaz.ce.gov.br/nfe2/services/NfeStatusServico2?wsdl', - 'AUTORIZACAO': 'sefaz.ce.gov.br/nfe2/services/NfeAutorizacao?wsdl', - 'RECIBO': 'sefaz.ce.gov.br/nfe2/services/NfeRetAutorizacao?wsdl', - 'CHAVE': 'sefaz.ce.gov.br/nfe2/services/NfeConsulta2?wsdl', - 'INUTILIZACAO': 'sefaz.ce.gov.br/nfe2/services/NfeInutilizacao2?wsdl', - 'EVENTOS': 'sefaz.ce.gov.br/nfe2/services/RecepcaoEvento?wsdl', + 'STATUS': 'sefaz.ce.gov.br/nfe4/services/NFeStatusServico4?WSDL', + 'AUTORIZACAO': 'sefaz.ce.gov.br/nfe4/services/NFeAutorizacao4?WSDL', + 'RECIBO': 'sefaz.ce.gov.br/nfe4/services/NFeRetAutorizacao4?WSDL', + 'CHAVE': 'sefaz.ce.gov.br/nfe4/services/NFeConsultaProtocolo4?WSDL', + 'INUTILIZACAO': 'sefaz.ce.gov.br/nfe4/services/NFeInutilizacao4?WSDL', + 'EVENTOS': 'sefaz.ce.gov.br/nfe4/services/NFeRecepcaoEvento4?WSDL', 'CADASTRO': 'sefaz.ce.gov.br/nfe2/services/CadConsultaCadastro2?wsdl', 'DOWNLOAD': 'sefaz.ce.gov.br/nfe2/services/NfeDownloadNF?wsdl', 'HTTPS': 'https://nfe.', @@ -293,57 +321,57 @@ NFE = { 'HOMOLOGACAO': 'https://nfehomolog.' }, 'BA': { - 'STATUS': 'nfe.sefaz.ba.gov.br/webservices/NfeStatusServico/NfeStatusServico.asmx', - 'AUTORIZACAO': 'nfe.sefaz.ba.gov.br/webservices/NfeAutorizacao/NfeAutorizacao.asmx', - 'RECIBO': 'nfe.sefaz.ba.gov.br/webservices/NfeRetAutorizacao/NfeRetAutorizacao.asmx', - 'CHAVE': 'nfe.sefaz.ba.gov.br/webservices/NfeConsulta/NfeConsulta.asmx', - 'INUTILIZACAO': 'nfe.sefaz.ba.gov.br/webservices/NfeInutilizacao/NfeInutilizacao.asmx', - 'EVENTOS': 'nfe.sefaz.ba.gov.br/webservices/sre/recepcaoevento.asmx', - 'CADASTRO': 'nfe.sefaz.ba.gov.br/webservices/nfenw/CadConsultaCadastro2.asmx', + 'STATUS': 'nfe.sefaz.ba.gov.br/webservices/NFeStatusServico4/NFeStatusServico4.asmx', + 'AUTORIZACAO': 'nfe.sefaz.ba.gov.br/webservices/NFeAutorizacao4/NFeAutorizacao4.asmx', + 'RECIBO': 'nfe.sefaz.ba.gov.br/webservices/NFeRetAutorizacao4/NFeRetAutorizacao4.asmx', + 'CHAVE': 'nfe.sefaz.ba.gov.br/webservices/NFeConsultaProtocolo4/NFeConsultaProtocolo4.asmx', + 'INUTILIZACAO': 'nfe.sefaz.ba.gov.br/webservices/NFeInutilizacao4/NFeInutilizacao4.asmx', + 'EVENTOS': 'nfe.sefaz.ba.gov.br/webservices/NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx', + 'CADASTRO': 'nfe.sefaz.ba.gov.br/webservices/CadConsultaCadastro4/CadConsultaCadastro4.asmx', 'HTTPS': 'https://', 'HOMOLOGACAO': 'https://h' }, 'MG': { - 'STATUS': 'nfe.fazenda.mg.gov.br/nfe2/services/NfeStatus2', - 'AUTORIZACAO': 'nfe.fazenda.mg.gov.br/nfe2/services/NfeAutorizacao', - 'RECIBO': 'nfe.fazenda.mg.gov.br/nfe2/services/NfeRetAutorizacao', - 'CHAVE': 'nfe.fazenda.mg.gov.br/nfe2/services/NfeConsulta2', - 'INUTILIZACAO': 'nfe.fazenda.mg.gov.br/nfe2/services/NfeInutilizacao2', + 'STATUS': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeStatusServico4', + 'AUTORIZACAO': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeAutorizacao4', + 'RECIBO': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeRetAutorizacao4', + 'CHAVE': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeConsulta4', + 'INUTILIZACAO': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeInutilizacao4', 'EVENTOS': 'nfe.fazenda.mg.gov.br/nfe2/services/RecepcaoEvento', 'CADASTRO': 'nfe.fazenda.mg.gov.br/nfe2/services/cadconsultacadastro2', 'HTTPS': 'https://', 'HOMOLOGACAO': 'https://h' }, 'SP': { - 'STATUS': 'nfe.fazenda.sp.gov.br/ws/nfestatusservico2.asmx', - 'AUTORIZACAO': 'nfe.fazenda.sp.gov.br/ws/nfeautorizacao.asmx', - 'RECIBO': 'nfe.fazenda.sp.gov.br/ws/nferetautorizacao.asmx', - 'CHAVE': 'nfe.fazenda.sp.gov.br/ws/nfeconsulta2.asmx', - 'INUTILIZACAO': 'nfe.fazenda.sp.gov.br/ws/nfeinutilizacao2.asmx', - 'EVENTOS': 'nfe.fazenda.sp.gov.br/ws/recepcaoevento.asmx', - 'CADASTRO': 'nfe.fazenda.sp.gov.br/ws/cadconsultacadastro2.asmx', + 'STATUS': 'nfe.fazenda.sp.gov.br/ws/NFeStatusServico4.asmx', + 'AUTORIZACAO': 'nfe.fazenda.sp.gov.br/ws/nfeautorizacao4.asmx', + 'RECIBO': 'nfe.fazenda.sp.gov.br/ws/nferetautorizacao4.asmx', + 'CHAVE': 'nfe.fazenda.sp.gov.br/ws/nfeconsulta4.asmx', + 'INUTILIZACAO': 'nfe.fazenda.sp.gov.br/ws/nfeinutilizacao4.asmx', + 'EVENTOS': 'nfe.fazenda.sp.gov.br/ws/nferecepcaoevento4.asmx', + 'CADASTRO': 'nfe.fazenda.sp.gov.br/ws/cadconsultacadastro4.asmx', 'HTTPS': 'https://', 'HOMOLOGACAO': 'https://homologacao.' }, 'PR': { - 'STATUS': 'nfe.fazenda.pr.gov.br/nfe/NFeStatusServico3', # CONSULTA STATUS DO SERVICO - 'AUTORIZACAO': 'nfe.fazenda.pr.gov.br/nfe/NFeAutorizacao3', # AUTORIZACAO - 'RECIBO': 'nfe.fazenda.pr.gov.br/nfe/NFeRetAutorizacao3', # CONSULTA RECIBO - 'CHAVE': 'nfe.fazenda.pr.gov.br/nfe/NFeConsulta3', # CONSULTA CHAVE DE ACESSO - 'INUTILIZACAO': 'nfe.fazenda.pr.gov.br/nfe/NFeInutilizacao3', # INUTILIZAÇAO - 'EVENTOS': 'nfe.fazenda.pr.gov.br/nfe/NFeRecepcaoEvento', # REGISTRO DE EVENTOS - 'CADASTRO': 'nfe.fazenda.pr.gov.br/nfe/CadConsultaCadastro2', # CONSULTA CADASTRO + 'STATUS': 'nfe.sefa.pr.gov.br/nfe/NFeStatusServico4', # CONSULTA STATUS DO SERVICO + 'AUTORIZACAO': 'nfe.sefa.pr.gov.br/nfe/NFeAutorizacao4', # AUTORIZACAO + 'RECIBO': 'nfe.sefa.pr.gov.br/nfe/NFeRetAutorizacao4', # CONSULTA RECIBO + 'CHAVE': 'nfe.sefa.pr.gov.br/nfe/NFeConsultaProtocolo4', # CONSULTA CHAVE DE ACESSO + 'INUTILIZACAO': 'nfe.sefa.pr.gov.br/nfe/NFeInutilizacao4', # INUTILIZAÇAO + 'EVENTOS': 'nfe.sefa.pr.gov.br/nfe/NFeRecepcaoEvento4', # REGISTRO DE EVENTOS + 'CADASTRO': 'nfe.sefa.pr.gov.br/nfe/CadConsultaCadastro4', # CONSULTA CADASTRO 'HTTPS': 'https://', 'HOMOLOGACAO': 'https://homologacao.' }, # https://www.sefaz.rs.gov.br/site/MontaDuvidas.aspx?al=l_rel_end_ws_nfe 'RS': { - 'STATUS': 'sefazrs.rs.gov.br/ws/NfeStatusServico/NfeStatusServico2.asmx', - 'AUTORIZACAO': 'sefazrs.rs.gov.br/ws/NfeAutorizacao/NFeAutorizacao.asmx', - 'RECIBO': 'sefazrs.rs.gov.br/ws/NfeRetAutorizacao/NFeRetAutorizacao.asmx', - 'CHAVE': 'sefazrs.rs.gov.br/ws/NfeConsulta/NfeConsulta2.asmx', - 'INUTILIZACAO': 'sefazrs.rs.gov.br/ws/nfeinutilizacao/nfeinutilizacao2.asmx', - 'EVENTOS': 'sefazrs.rs.gov.br/ws/recepcaoevento/recepcaoevento.asmx', + 'STATUS': 'sefazrs.rs.gov.br/ws/NfeStatusServico/NfeStatusServico4.asmx', + 'AUTORIZACAO': 'sefazrs.rs.gov.br/ws/NfeAutorizacao/NFeAutorizacao4.asmx', + 'RECIBO': 'sefazrs.rs.gov.br/ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx', + 'CHAVE': 'sefazrs.rs.gov.br/ws/NfeConsulta/NfeConsulta4.asmx', + 'INUTILIZACAO': 'sefazrs.rs.gov.br/ws/nfeinutilizacao/nfeinutilizacao4.asmx', + 'EVENTOS': 'sefazrs.rs.gov.br/ws/recepcaoevento/recepcaoevento4.asmx', 'CADASTRO': 'https://cad.sefazrs.rs.gov.br/ws/cadconsultacadastro/cadconsultacadastro2.asmx', 'DOWNLOAD': 'sefazrs.rs.gov.br/ws/nfeDownloadNF/nfeDownloadNF.asmx', 'DESTINADAS': 'sefazrs.rs.gov.br/ws/nfeConsultaDest/nfeConsultaDest.asmx', @@ -351,12 +379,12 @@ NFE = { 'HOMOLOGACAO': 'https://nfe-homologacao.' }, 'MS': { - 'STATUS': 'nfe.fazenda.ms.gov.br/producao/services2/NfeStatusServico2', - 'AUTORIZACAO': 'nfe.fazenda.ms.gov.br/producao/services2/NfeAutorizacao', - 'RECIBO': 'nfe.fazenda.ms.gov.br/producao/services2/NfeRetAutorizacao', - 'CHAVE': 'nfe.fazenda.ms.gov.br/producao/services2/NfeConsulta2', - 'INUTILIZACAO': 'nfe.fazenda.ms.gov.br/producao/services2/NfeInutilizacao2', - 'EVENTOS': 'nfe.fazenda.ms.gov.br/producao/services2/RecepcaoEvento', + 'STATUS': 'nfe.ms.gov.br/ws/NFeStatusServico4', + 'AUTORIZACAO': 'nfe.ms.gov.br/ws/NFeAutorizacao4', + 'RECIBO': 'nfe.ms.gov.br/ws/NFeRetAutorizacao4', + 'CHAVE': 'nfe.ms.gov.br/ws/NFeConsultaProtocolo4', + 'INUTILIZACAO': 'nfe.ms.gov.br/ws/NFeInutilizacao4', + 'EVENTOS': 'nfe.ms.gov.br/ws/NFeRecepcaoEvento4', 'CADASTRO': 'nfe.fazenda.ms.gov.br/producao/services2/CadConsultaCadastro2', 'HTTPS': 'https://', 'HOMOLOGACAO': 'https://homologacao.' @@ -373,13 +401,13 @@ NFE = { 'HOMOLOGACAO': 'https://homologacao.' }, 'GO': { - 'STATUS': 'sefaz.go.gov.br/nfe/services/v2/NfeStatusServico2?wsdl', - 'AUTORIZACAO': 'sefaz.go.gov.br/nfe/services/v2/NfeAutorizacao?wsdl', - 'RECIBO': 'sefaz.go.gov.br/nfe/services/v2/NfeRetAutorizacao?wsdl', - 'CHAVE': 'sefaz.go.gov.br/nfe/services/v2/NfeConsulta2?wsdl', - 'INUTILIZACAO': 'sefaz.go.gov.br/nfe/services/v2/NfeInutilizacao2?wsdl', - 'EVENTOS': 'sefaz.go.gov.br/nfe/services/v2/RecepcaoEvento?wsdl', - 'CADASTRO': 'sefaz.go.gov.br/nfe/services/v2/CadConsultaCadastro2?wsdl', + 'STATUS': 'sefaz.go.gov.br/nfe/services/NFeStatusServico4?wsdl', + 'AUTORIZACAO': 'sefaz.go.gov.br/nfe/services/NFeAutorizacao4?wsdl', + 'RECIBO': 'sefaz.go.gov.br/nfe/services/NFeRetAutorizacao4?wsdl', + 'CHAVE': 'sefaz.go.gov.br/nfe/services/NFeConsultaProtocolo4?wsdl', + 'INUTILIZACAO': 'sefaz.go.gov.br/nfe/services/NFeInutilizacao4?wsdl', + 'EVENTOS': 'sefaz.go.gov.br/nfe/services/NFeRecepcaoEvento4?wsdl', + 'CADASTRO': 'sefaz.go.gov.br/nfe/services/CadConsultaCadastro4?wsdl', 'HTTPS': 'https://nfe.', 'HOMOLOGACAO': 'https://homolog.' }, @@ -395,12 +423,12 @@ NFE = { 'HOMOLOGACAO': 'https://hom.' }, 'SVRS': { - 'STATUS': 'svrs.rs.gov.br/ws/NfeStatusServico/NfeStatusServico2.asmx', - 'AUTORIZACAO': 'svrs.rs.gov.br/ws/NfeAutorizacao/NFeAutorizacao.asmx', - 'RECIBO': 'svrs.rs.gov.br/ws/NfeRetAutorizacao/NFeRetAutorizacao.asmx', - 'CHAVE': 'svrs.rs.gov.br/ws/NfeConsulta/NfeConsulta2.asmx', - 'INUTILIZACAO': 'svrs.rs.gov.br/ws/nfeinutilizacao/nfeinutilizacao2.asmx', - 'EVENTOS': 'svrs.rs.gov.br/ws/recepcaoevento/recepcaoevento.asmx', + 'STATUS': 'svrs.rs.gov.br/ws/NfeStatusServico/NfeStatusServico4.asmx', + 'AUTORIZACAO': 'svrs.rs.gov.br/ws/NfeAutorizacao/NFeAutorizacao4.asmx', + 'RECIBO': 'svrs.rs.gov.br/ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx', + 'CHAVE': 'svrs.rs.gov.br/ws/NfeConsulta/NfeConsulta4.asmx', + 'INUTILIZACAO': 'svrs.rs.gov.br/ws/nfeinutilizacao/nfeinutilizacao4.asmx', + 'EVENTOS': 'svrs.rs.gov.br/ws/recepcaoevento/recepcaoevento4.asmx', 'CADASTRO': 'https://cad.svrs.rs.gov.br/ws/cadconsultacadastro/cadconsultacadastro2.asmx', 'HTTPS': 'https://nfe.', 'HOMOLOGACAO': 'https://nfe-homologacao.'