def validar(self, xml, nome_xsd = None): '''Função que valida um XML usando lxml do Python via arquivo XSD no diretório xsd/<pacote>/<nó_xml>.xsd''' # Realiza o parser sobre o xml, identificado como string se iniciar por '<', senão é identificado como nome de arquivo if type(xml) == str: if xml[0] == '<': xml = PoleXML.importar(xml) else: xml = PoleXML.importar(open(xml).read()) # Para este sistema com lxml funcionar foi preciso trocar em tiposBasico_v1.03.xsd {0,} por * # Obeter a versão do primeiro ou segundo nó versao = xml('', 1)['versao'] or xml('', 1)('', 1)['versao'] # O padrão de nome de arquivos xsd é iniciar com letras minúsculas, # mantendo maiúsuclas iniciais de palavras, assim foi preciso desse # trecho de código para passar para músculas iniciais maiúsculas if nome_xsd is None: nome = '' temp = xml('', 1)._XML__nome for i in range(len(temp)): if temp[i].isupper(): nome += temp[i].lower() else: break nome += temp[i:] else: nome = nome_xsd # Caminho do arquivo XSD #print nome_xsd, self.__raiz , '/xsd/' , self.__pacote , '/' , nome , '_v' , versao , '.xsd' arquivo_xsd = os.path.join(self.__raiz, 'xsd', self.__pacote, nome + '_v' + versao + '.xsd') # Verifica a validade do xml self.erros = PoleXML.validar(xml, arquivo_xsd) return len(self.erros) == 0
def validar(self, xml, nome_xsd=None): '''Função que valida um XML usando lxml do Python via arquivo XSD no diretório xsd/<pacote>/<nó_xml>.xsd''' # Realiza o parser sobre o xml, identificado como string se iniciar por '<', senão é identificado como nome de arquivo if type(xml) == str: if xml[0] == '<': xml = PoleXML.importar(xml) else: xml = PoleXML.importar(open(xml).read()) # Para este sistema com lxml funcionar foi preciso trocar em tiposBasico_v1.03.xsd {0,} por * # Obeter a versão do primeiro ou segundo nó versao = xml('', 1)['versao'] or xml('', 1)('', 1)['versao'] # O padrão de nome de arquivos xsd é iniciar com letras minúsculas, # mantendo maiúsuclas iniciais de palavras, assim foi preciso desse # trecho de código para passar para músculas iniciais maiúsculas if nome_xsd is None: nome = '' temp = xml('', 1)._XML__nome for i in range(len(temp)): if temp[i].isupper(): nome += temp[i].lower() else: break nome += temp[i:] else: nome = nome_xsd # Caminho do arquivo XSD #print nome_xsd, self.__raiz , '/xsd/' , self.__pacote , '/' , nome , '_v' , versao , '.xsd' arquivo_xsd = os.path.join(self.__raiz, 'xsd', self.__pacote, nome + '_v' + versao + '.xsd') # Verifica a validade do xml self.erros = PoleXML.validar(xml, arquivo_xsd) return len(self.erros) == 0
def servico(self, nome_wsdl, xml, nome_xsd = None): # Validar xml para envio if not self.validar(xml, nome_xsd): erros = "Erro(s) no XML: " for erro in self.erros: erros += erro['type_name'] + ': ' + erro['message'] raise ValueError(erros) # Criar meio de transporte criptografado transporte = suds.transport.http.HttpTransport() transporte.urlopener = urllib2.build_opener(https_ssl(key_file = self.__chave, cert_file = self.__certificado, ca_file = self.__certificadoras)) # Carrega o wsdl da estrutura de arquivos <raiz>/wsdl/<uf>/<nome_wsdl>.wsdl arquivo_wsdl = 'file://' + self.__raiz + '/wsdl/' + self.__sefaz + '/' + self.__str_ambiente + '/' + str(nome_wsdl) + '.wsdl' wsdl = suds.client.Client(arquivo_wsdl, transport = transporte) # Configurar o ambiente do SOAP wsdl.options.cache.clear() ns_anterior = suds.bindings.binding.envns suds.bindings.binding.envns = ('SOAP-ENV', 'http://www.w3.org/2003/05/soap-envelope') # Cria uma função do primeiro serviço, primeira URL (port) e primeiro método, visto que são únicos funcao = suds.client.Method(wsdl, wsdl.wsdl.services[0].ports[0].methods.values()[0]) # Configura o cabeçalho e retorno em XML - Na versão do servidor não tem o parâmetro prettyxml, então tem que comentá-lo para rodar lá wsdl.set_options(soapheaders = self.__cabecalho(wsdl, xml('', 1)['versao']), retxml = True, prettyxml = True) # Executa a função e coleta o resultado em XML resultado = funcao(suds.sax.parser.Parser().parse(string = PoleXML.serializar(xml)).root()) #resultado = funcao(PoleXML.exportar(xml, -1)) #print repr(PoleXML.importar(resultado)) # Voltando o ambiente do SOAP suds.bindings.binding.envns = ns_anterior # Retornar o resultado na forma da classe XML, somente o corpo do envelope Soap return PoleXML.importar(resultado).Envelope.Body('', 1)
def consultar_distribuicao_dfe(self, ultimo_nsu=0, nsu=None, chave=None): # Usar sefaz = 'AN' (ambiente nacional) if self.__sefaz == 'AN': ws = self else: ws = Webservice(self.__cnpj, self.__ambiente, self.__uf, 'AN', self.__raiz, self.__pacote, self.__contingencia) requisicao = PoleXML.XML() distDFeInt = requisicao.nfeDadosMsg.distDFeInt distDFeInt['xmlns'] = 'http://www.portalfiscal.inf.br/nfe' distDFeInt['versao'] = '1.01' if chave else '1.35' distDFeInt.tpAmb = self.__ambiente distDFeInt.cUFAutor = UFS_IBGE[self.__uf] distDFeInt.CNPJ = self.__cnpj if chave: distDFeInt.consChNFe.chNFe = chave elif nsu: distDFeInt.consNSU.NSU = "%015i" % nsu else: distDFeInt.distNSU.ultNSU = "%015i" % ultimo_nsu retorno = ws.servico('NfeDistribuicaoDFe', requisicao, versao_wsdl='1.00') lote = retorno.nfeDistDFeInteresseResult.retDistDFeInt.loteDistDFeInt for num_doc in range(1, lote('docZip', 0) + 1): doc = PoleXML.importar( zlib.decompress(str(lote.docZip(num_doc)).decode('base64'), 16 + zlib.MAX_WBITS)) # for gZip header lote.docZip = None, num_doc lote.docZip += doc, num_doc return retorno
def servico(self, nome_wsdl, xml, nome_xsd=None, versao_wsdl=None): # Validar xml para envio if not self.validar(xml, nome_xsd): erros = "Erro(s) no XML: " for erro in self.erros: erros += erro['type_name'] + ': ' + erro['message'] raise ValueError(erros) # Versões do XML e do WSDL versao_xml = xml('', 1)['versao'] or xml('', 1)('', 1)['versao'] if not versao_wsdl: versao_wsdl = versao_xml # Carrega o wsdl da estrutura de arquivos pela versão do WSDL # <raiz>/wsdl/<sefaz>/<ambiente>/<versao>/<nome_wsdl>.wsdl arquivo_wsdl = os.path.join(self.__raiz, 'wsdl', self.__sefaz, self.__str_ambiente, versao_wsdl, nome_wsdl + '.wsdl') # Se não encontrou pela versão do WSDL especificada, vai pela do XML if not os.path.exists(arquivo_wsdl): arquivo_wsdl = os.path.join( self.__raiz, 'wsdl', self.__sefaz, self.__str_ambiente, versao_xml, nome_wsdl + '.wsdl') arquivo_wsdl = 'file://' + arquivo_wsdl # Criar meio de transporte criptografado transporte = suds.transport.http.HttpTransport() transporte_ssl = (https_ssl_mt if (self.__sefaz == 'MT' or (sys.version_info.major == 2 and sys.version_info.minor < 7)) else https_ssl) transporte.urlopener = urllib2.build_opener( transporte_ssl(key_file=self.__chave, cert_file=self.__certificado, ca_file=self.__certificadoras)) wsdl = suds.client.Client(arquivo_wsdl, transport=transporte) # Configurar o ambiente do SOAP 1.2 wsdl.options.cache.clear() ns_anterior = suds.bindings.binding.envns suds.bindings.binding.envns = ( 'soap12', 'http://www.w3.org/2003/05/soap-envelope') # Cria uma função do primeiro serviço, primeira URL (port) # e primeiro método, visto que são únicos funcao = suds.client.Method(wsdl, wsdl.wsdl. services[0].ports[0].methods.values()[0]) # Configura os headers http para SOAP 1.2, o cabeçalho e retorno em XML wsdl.set_options(soapheaders=self.__cabecalho(wsdl, versao_xml), headers={'Content-Type': 'application/soap+xml; charset=utf-8'}, retxml=True) # Na versão do servidor não tem o parâmetro prettyxml, # então tem que comentá-lo para rodar lá if sys.version_info.major > 2 or sys.version_info.minor > 6: wsdl.set_options(prettyxml=True) # Executa a função e coleta o resultado em XML resultado = funcao(suds.sax.parser.Parser().parse( string=PoleXML.serializar(xml)).root()) # Voltando o ambiente do SOAP suds.bindings.binding.envns = ns_anterior # Retornar o resultado na forma da classe XML, # somente o corpo do envelope Soap return PoleXML.importar(resultado).Envelope.Body('', 1)
def servico(self, nome_wsdl, xml, nome_xsd=None, versao_wsdl=None): # Validar xml para envio if not self.validar(xml, nome_xsd): erros = "Erro(s) no XML: " for erro in self.erros: erros += erro['type_name'] + ': ' + erro['message'] raise ValueError(erros) # Versões do XML e do WSDL versao_xml = xml('', 1)['versao'] or xml('', 1)('', 1)['versao'] if not versao_wsdl: versao_wsdl = versao_xml # Carrega o wsdl da estrutura de arquivos pela versão do WSDL # <raiz>/wsdl/<sefaz>/<ambiente>/<versao>/<nome_wsdl>.wsdl arquivo_wsdl = os.path.join(self.__raiz, 'wsdl', self.__sefaz, self.__str_ambiente, versao_wsdl, nome_wsdl + '.wsdl') # Se não encontrou pela versão do WSDL especificada, vai pela do XML if not os.path.exists(arquivo_wsdl): arquivo_wsdl = os.path.join(self.__raiz, 'wsdl', self.__sefaz, self.__str_ambiente, versao_xml, nome_wsdl + '.wsdl') arquivo_wsdl = 'file://' + arquivo_wsdl # Criar meio de transporte criptografado transporte = suds.transport.http.HttpTransport() transporte_ssl = (https_ssl_mt if (self.__sefaz == 'MT' or (sys.version_info.major == 2 and sys.version_info.minor < 7)) else https_ssl) transporte.urlopener = urllib2.build_opener( transporte_ssl(key_file=self.__chave, cert_file=self.__certificado, ca_file=self.__certificadoras)) wsdl = suds.client.Client(arquivo_wsdl, transport=transporte) # Configurar o ambiente do SOAP 1.2 wsdl.options.cache.clear() ns_anterior = suds.bindings.binding.envns suds.bindings.binding.envns = ( 'soap12', 'http://www.w3.org/2003/05/soap-envelope') # Cria uma função do primeiro serviço, primeira URL (port) # e primeiro método, visto que são únicos funcao = suds.client.Method( wsdl, wsdl.wsdl.services[0].ports[0].methods.values()[0]) # Configura os headers http para SOAP 1.2, o cabeçalho e retorno em XML wsdl.set_options( soapheaders=self.__cabecalho(wsdl, versao_xml), headers={'Content-Type': 'application/soap+xml; charset=utf-8'}, retxml=True) # Na versão do servidor não tem o parâmetro prettyxml, # então tem que comentá-lo para rodar lá if sys.version_info.major > 2 or sys.version_info.minor > 6: wsdl.set_options(prettyxml=True) # Executa a função e coleta o resultado em XML resultado = funcao(suds.sax.parser.Parser().parse( string=PoleXML.serializar(xml)).root()) # Voltando o ambiente do SOAP suds.bindings.binding.envns = ns_anterior # Retornar o resultado na forma da classe XML, # somente o corpo do envelope Soap return PoleXML.importar(resultado).Envelope.Body('', 1)
def enviar_nfe(self, xml): # Realiza o parser sobre nfe, identificada como string se iniciar por '<', senão é identificada como nome de arquivo if type(xml) == str: if xml[0] == '<': xml = PoleXML.importar(xml) else: xml = PoleXML.importar(open(xml).read()) if not isinstance(xml, PoleXML.XML): raise TypeError('A NFe em XML precisa ser passada como string XML, string com o nome do arquivo com o XML ou instância de PoleXML.XML!') # Assina a NFe self.assinar(xml.NFe.infNFe) # Cria envelope de lote para a NFe lote_nfe = PoleXML.XML() lote_nfe.enviNFe['xmlns'] = 'http://www.portalfiscal.inf.br/nfe' lote_nfe.enviNFe['versao'] = '2.00' lote_nfe.enviNFe.idLote = datetime.datetime.now().strftime('%y%m%d%H%M%S%f')[:15] lote_nfe.enviNFe += xml # Envia a NFe return self.servico('NfeRecepcao2', lote_nfe)
def enviar_nfe(self, xml): # Realiza o parser sobre nfe, identificada como string se iniciar por '<', senão é identificada como nome de arquivo if type(xml) == str: if xml[0] == '<': xml = PoleXML.importar(xml) else: xml = PoleXML.importar(open(xml).read()) if not isinstance(xml, PoleXML.XML): raise TypeError( 'A NFe em XML precisa ser passada como string XML, string com o nome do arquivo com o XML ou instância de PoleXML.XML!' ) # Assina a NFe self.assinar(xml.NFe.infNFe) # Cria envelope de lote para a NFe lote_nfe = PoleXML.XML() lote_nfe.enviNFe['xmlns'] = 'http://www.portalfiscal.inf.br/nfe' lote_nfe.enviNFe['versao'] = '2.00' lote_nfe.enviNFe.idLote = datetime.datetime.now().strftime( '%y%m%d%H%M%S%f')[:15] lote_nfe.enviNFe += xml # Envia a NFe return self.servico('NfeRecepcao2', lote_nfe)
def servico(self, nome_wsdl, xml, nome_xsd=None): # Validar xml para envio if not self.validar(xml, nome_xsd): erros = "Erro(s) no XML: " for erro in self.erros: erros += erro['type_name'] + ': ' + erro['message'] raise ValueError(erros) # Criar meio de transporte criptografado transporte = suds.transport.http.HttpTransport() transporte.urlopener = urllib2.build_opener( https_ssl(key_file=self.__chave, cert_file=self.__certificado, ca_file=self.__certificadoras)) # Carrega o wsdl da estrutura de arquivos <raiz>/wsdl/<uf>/<nome_wsdl>.wsdl arquivo_wsdl = 'file://' + self.__raiz + '/wsdl/' + self.__sefaz + '/' + self.__str_ambiente + '/' + str( nome_wsdl) + '.wsdl' wsdl = suds.client.Client(arquivo_wsdl, transport=transporte) # Configurar o ambiente do SOAP wsdl.options.cache.clear() ns_anterior = suds.bindings.binding.envns suds.bindings.binding.envns = ( 'SOAP-ENV', 'http://www.w3.org/2003/05/soap-envelope') # Cria uma função do primeiro serviço, primeira URL (port) e primeiro método, visto que são únicos funcao = suds.client.Method( wsdl, wsdl.wsdl.services[0].ports[0].methods.values()[0]) # Configura o cabeçalho e retorno em XML - Na versão do servidor não tem o parâmetro prettyxml, então tem que comentá-lo para rodar lá wsdl.set_options(soapheaders=self.__cabecalho(wsdl, xml('', 1)['versao']), retxml=True, prettyxml=True) # Executa a função e coleta o resultado em XML resultado = funcao(suds.sax.parser.Parser().parse( string=PoleXML.serializar(xml)).root()) #resultado = funcao(PoleXML.exportar(xml, -1)) #print repr(PoleXML.importar(resultado)) # Voltando o ambiente do SOAP suds.bindings.binding.envns = ns_anterior # Retornar o resultado na forma da classe XML, somente o corpo do envelope Soap return PoleXML.importar(resultado).Envelope.Body('', 1)