Exemple #1
0
    def assinar(self, xml, retorna_string=False):
        # busca tag que tem id(reference_uri), logo nao importa se tem namespace
        reference = xml.find(".//*[@Id]").attrib['Id']
        #print('Referencia: ',reference)
        # retira acentos
        xml_str = remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False))
        xml = etree.fromstring(xml_str)

        signer = XMLSigner(
            method=signxml.methods.enveloped, signature_algorithm="rsa-sha1",
            digest_algorithm='sha1',
            c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')

        ns = {None: signer.namespaces['ds']}
        signer.namespaces = ns
        #print('Chave......: ',self.key)
        #print('*',200)
        #print('Certificado: ',self.cert)
        ref_uri = ('#%s' % reference) if reference else None
        signed_root = signer.sign(
            xml, key=self.key, cert=self.cert, reference_uri=ref_uri)

        ns = {'ns': NAMESPACE_SIG}
        # coloca o certificado na tag X509Data/X509Certificate
        tagX509Data = signed_root.find('.//ns:X509Data', namespaces=ns)
        etree.SubElement(tagX509Data, 'X509Certificate').text = self.cert
        #print('Assinatura: ',etree.tostring(signed_root, encoding="unicode", pretty_print=False) )
        if retorna_string:
            return etree.tostring(signed_root, encoding="unicode", pretty_print=False)
        else:
            return signed_root
Exemple #2
0
    def assinarLote(self, xml, retorna_string=True):
        "Assina nfse e lote"
        try:
            xml = self.assinarNfse(xml, retorna_string=False)
            xpath = './/ns1:LoteRps'
            tag = 'LoteRps'
            # define namespaces, pega do proprio xml
            namespaces = xml.nsmap
            # No raiz do XML de saida
            raiz = etree.Element('Signature', xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(siginfo, 'CanonicalizationMethod', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(siginfo, 'SignatureMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Tenta achar a tag
            ref = etree.SubElement(siginfo, 'Reference', URI='#' +
                                   xml.xpath(xpath, namespaces=namespaces)[0].attrib['Id'])
            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(ref, 'DigestMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            # posiciona tag Signature antes do LoteRps para assinar
            base = xml.xpath(xpath+'/..', namespaces=namespaces)[0]
            base.insert(0, raiz)

            # Escreve no arquivo depois de remover caracteres especiais
            with open('nfse.xml', 'w') as arquivo:
                texto = remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False))
                arquivo.write(texto)
            # assina lote
            subprocess.call(['xmlsec1', '--sign', '--pkcs12', self.certificado,
                             '--pwd', self.senha, '--crypto', 'openssl', '--output',
                             'nfse.xml', '--id-attr:Id', tag, 'nfse.xml'])

            # Reposiciona tag Signature apos LoteRps
            xml = etree.fromstring(open('nfse.xml', 'r').read())
            namespaces = xml.nsmap
            sig = xml.find('{http://www.w3.org/2000/09/xmldsig#}Signature')
            sig.getparent().remove(sig)
            xml.append(sig)

            if retorna_string:
                return etree.tostring(xml, encoding="unicode", pretty_print=False)
            else:
                return xml
        except Exception as e:
            raise e
Exemple #3
0
    def _serializar_evento(self, evento, tag_raiz="evento", retorna_string=False):

        # timezone Brasília -03:00
        tz = time.strftime("%z")
        tz = "{}:{}".format(tz[:-2], tz[-2:])
        # import ipdb
        # ipdb.set_trace()
        raiz = etree.Element(tag_raiz, versao="1.00", xmlns=NAMESPACE_NFE)
        e = etree.SubElement(raiz, "infEvento", Id=evento.identificador)
        etree.SubElement(e, "cOrgao").text = CODIGOS_ESTADOS[evento.uf.upper()]
        etree.SubElement(e, "tpAmb").text = str(self._ambiente)
        etree.SubElement(e, "CNPJ").text = evento.cnpj  # Empresas somente terão CNPJ
        # etree.SubElement(e, 'CPF').text = ''
        etree.SubElement(e, "chNFe").text = evento.chave
        etree.SubElement(e, "dhEvento").text = evento.data_emissao.strftime("%Y-%m-%dT%H:%M:%S") + tz
        etree.SubElement(e, "tpEvento").text = evento.tp_evento
        etree.SubElement(e, "nSeqEvento").text = str(evento.n_seq_evento)
        etree.SubElement(e, "verEvento").text = "1.00"
        det = etree.SubElement(e, "detEvento", versao="1.00")
        etree.SubElement(det, "descEvento").text = evento.descricao
        etree.SubElement(det, "nProt").text = evento.protocolo
        etree.SubElement(det, "xJust").text = evento.justificativa

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemple #4
0
    def _serializar_emitente(self, emitente, tag_raiz="emit", retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Dados do emitente
        etree.SubElement(raiz, "CNPJ").text = so_numeros(emitente.cnpj)
        etree.SubElement(raiz, "xNome").text = emitente.razao_social
        etree.SubElement(raiz, "xFant").text = emitente.nome_fantasia
        etree.SubElement(raiz, "IE").text = emitente.inscricao_estadual

        # Endereço
        endereco = etree.SubElement(raiz, "enderEmit")
        etree.SubElement(endereco, "xLgr").text = emitente.endereco_logradouro
        etree.SubElement(endereco, "nro").text = emitente.endereco_numero
        etree.SubElement(endereco, "xCpl").text = emitente.endereco_complemento
        etree.SubElement(endereco, "xBairro").text = emitente.endereco_bairro
        etree.SubElement(endereco, "cMun").text = emitente.endereco_municipio
        etree.SubElement(endereco, "xMun").text = obter_municipio_por_codigo(
            emitente.endereco_municipio, emitente.endereco_uf
        )
        etree.SubElement(endereco, "UF").text = emitente.endereco_uf
        etree.SubElement(endereco, "CEP").text = so_numeros(emitente.endereco_cep)
        etree.SubElement(endereco, "cPais").text = emitente.endereco_pais
        etree.SubElement(endereco, "xPais").text = obter_pais_por_codigo(emitente.endereco_pais)
        etree.SubElement(endereco, "fone").text = emitente.endereco_telefone

        if retorna_string:
            return etree.tostring(raiz, pretty_print=True)
        else:
            return raiz
    def _serializar_consulta(self, consulta, tag_raiz='Consulta', retorna_string=True):

        raiz = etree.Element(tag_raiz)

        etree.SubElement(raiz, 'ModeloDocumento').text = 'NFCe'
        etree.SubElement(raiz, 'Versao').text = self._versao
        etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(raiz, 'CnpjEmpresa').text = so_numeros(consulta.cnpj)
        etree.SubElement(raiz, 'CnpjEmissor').text = so_numeros(consulta.cnpj)

        if consulta.numero_inicial:
            etree.SubElement(raiz, 'NumeroInicial').text = str(consulta.numero_inicial)
        if consulta.numero_final:
            etree.SubElement(raiz, 'NumeroFinal').text = str(consulta.numero_final)
        etree.SubElement(raiz, 'Serie').text = str(consulta.serie)

        if consulta.chave_acesso:
            etree.SubElement(raiz, 'ChaveAcesso').text = str(consulta.chave_acesso)

        if consulta.data_inicial and consulta.data_final:
            etree.SubElement(
                raiz, 'DataEmissaoInicial').text = consulta.data_inicial.strftime("%Y-%m-%d")
            etree.SubElement(
                raiz, 'DataEmissaoFinal').text = consulta.data_final.strftime("%Y-%m-%d")

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
        def _serializar_permissoes(tag_raiz='Permissoes', retorna_string=True):
            raiz = etree.Element(tag_raiz)

            # Permissões referente ao módulo NFC-e
            p_nfce = etree.SubElement(raiz, 'PermissaoNFCe')
            etree.SubElement(p_nfce, 'Visualizar').text = "S"
            etree.SubElement(p_nfce, 'Baixar').text = "S"

            # Permissões gerais da aplicação
            p_geral = etree.SubElement(raiz, 'PermissoesGerais')
            etree.SubElement(p_geral, 'ImportarDocumentos').text = "N"
            etree.SubElement(p_geral, 'AlterarDadosDoUsuario').text = "S"
            etree.SubElement(p_geral, 'AlterarDadosDaEmpresa').text = "N"
            etree.SubElement(p_geral, 'AlterarMarcasDaEmpresa').text = "N"
            etree.SubElement(p_geral, 'AlterarCertificadosDaEmpresa').text = "S"
            etree.SubElement(p_geral, 'AlterarConfiguracoesParametros').text = "N"
            etree.SubElement(p_geral, 'CadastrarEmpresas').text = "N"
            etree.SubElement(p_geral, 'AlterarCaixasDeEmail').text = "S"
            etree.SubElement(p_geral, 'AlterarPermissoesDeUsuario').text = "S"
            etree.SubElement(p_geral, 'AdicionarNovosUsuarios').text = "S"
            etree.SubElement(p_geral, 'VisualizarChaveAcesso').text = "N"
            etree.SubElement(p_geral, 'VisualizarAcoesDeUsuarios').text = "S"
            etree.SubElement(p_geral, 'VisualizarQuantidadesEmitidas').text = "S"
            etree.SubElement(p_geral, 'VisualizarLicencas').text = "S"
            etree.SubElement(p_geral, 'ConfiguracaoSenha').text = "N"
            etree.SubElement(p_geral, 'GerarRelatorios').text = "S"
            etree.SubElement(p_geral, 'InutilizarDocumentos').text = "S"
            etree.SubElement(p_geral, 'FerramentasIntegracao').text = "N"

            if retorna_string:
                return etree.tostring(raiz, encoding="unicode", pretty_print=True)
            else:
                return raiz
        def _serializar_parametros_nfce(tag_raiz='NFCe', retorna_string=True):

            def _serializar_contingencia(tag_raiz='OrdemContingencia',
                                         retorna_string=True):
                raiz = etree.Element(tag_raiz)

                orderm = etree.SubElement(raiz, 'OrdemContingenciaItem')
                etree.SubElement(orderm, 'OrdemContingenciaNFCe').text = '0'

                if retorna_string:
                    return etree.tostring(raiz, encoding="unicode", pretty_print=True)
                else:
                    return raiz

            # Parâmetros referente ao módulo NFC-e
            raiz = etree.Element(tag_raiz)
            etree.SubElement(
                raiz, 'InutilizarAutomaticamenteDocumentosRejeitados').text = 'N'
            etree.SubElement(raiz, 'InutilizarPulosNumeracao').text = 'N'
            etree.SubElement(raiz, 'FormaRetornoPDFIntegracao').text = '3'
            etree.SubElement(raiz, 'FormaRetornoXMLIntegracao').text = '3'
            etree.SubElement(raiz, 'UltimoNSU').text = '000000000000000'
            etree.SubElement(raiz, 'IDTokenCscSEFAZ').text = empresa.token
            etree.SubElement(raiz, 'CscSEFAZ').text = empresa.csc
            etree.SubElement(raiz, 'PossuiLeituraX').text = 'S'
            etree.SubElement(raiz, 'PossuiGeracaoRelatorios').text = 'S'

            raiz.append(_serializar_contingencia(retorna_string=False))

            if retorna_string:
                return etree.tostring(raiz, encoding="unicode", pretty_print=True)
            else:
                return raiz
    def _serializar_evento(self, evento, tag_raiz='evento', retorna_string=False):

        # timezone Brasília -03:00
        tz = time.strftime("%z")
        tz = "{}:{}".format(tz[:-2], tz[-2:])
        raiz = etree.Element(tag_raiz, versao='1.00', xmlns=NAMESPACE_NFE)
        e = etree.SubElement(raiz, 'infEvento', Id=evento.identificador)
        etree.SubElement(e, 'cOrgao').text = CODIGOS_ESTADOS[evento.uf.upper()]
        etree.SubElement(e, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(e, 'CNPJ').text = evento.cnpj # Empresas somente terão CNPJ
        #etree.SubElement(evento, 'CPF').text = ''
        etree.SubElement(e, 'chNFe').text = evento.chave
        etree.SubElement(e, 'dhEvento').text = evento.data_emissao.strftime('%Y-%m-%dT%H:%M:%S') + tz
        etree.SubElement(e, 'tpEvento').text = evento.tp_evento
        etree.SubElement(e, 'nSeqEvento').text = str(evento.n_seq_evento)
        etree.SubElement(e, 'verEvento').text = '1.00'
        det = etree.SubElement(e, 'detEvento', versao='1.00')
        etree.SubElement(det, 'descEvento').text = evento.descricao
        etree.SubElement(det, 'nProt').text = evento.protocolo
        etree.SubElement(det, 'xJust').text = evento.justificativa

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
    def _serializar_evento(self, evento, tag_raiz='EnvioEvento', retorna_string=True):

        raiz = etree.Element(tag_raiz)

        etree.SubElement(raiz, 'ModeloDocumento').text = 'NFCe'
        etree.SubElement(raiz, 'Versao').text = self._versao

        # timezone Brasília -03:00
        tz = time.strftime("%z")

        event = etree.SubElement(raiz, 'Evento')
        etree.SubElement(event, 'NtfCnpjEmissor').text = so_numeros(evento.cnpj)
        etree.SubElement(event, 'NtfNumero').text = evento.numero
        etree.SubElement(event, 'NtfSerie').text = evento.serie
        etree.SubElement(event, 'tpAmb').text = str(self._ambiente)

        eve_info = etree.SubElement(event, 'EveInf')
        etree.SubElement(eve_info, 'EveDh').text = evento.data_emissao.strftime(
            '%Y-%m-%dT%H:%M:%S')
        etree.SubElement(eve_info, 'EveFusoHorario').text = "{}:{}".format(
            tz[:-2], tz[-2:])
        etree.SubElement(eve_info, 'EveTp').text = evento.tp_evento
        etree.SubElement(eve_info, 'EvenSeq').text = str(evento.n_seq_evento)

        eve_det = etree.SubElement(eve_info, 'Evedet')
        etree.SubElement(eve_det, 'EveDesc').text = evento.descricao
        etree.SubElement(eve_det, 'EvenProt').text = evento.protocolo
        etree.SubElement(eve_det, 'EvexJust').text = evento.justificativa

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemple #10
0
    def exportar(self, destino=None, retorna_string=False, limpar=True, **kwargs):
        """Gera o(s) arquivo(s) de Nota Fiscal eletronica no padrao oficial da SEFAZ
        e Receita Federal, para ser(em) enviado(s) para o webservice ou para ser(em)
        armazenado(s) em cache local.
        @param destino -
        @param retorna_string - Retorna uma string para debug.
        @param limpar - Limpa a fonte de dados para não gerar xml com dados duplicados.
        """
        try:
            # No raiz do XML de saida
            raiz = etree.Element("NFe", xmlns=NAMESPACE_NFE)

            # Carrega lista de Notas Fiscais
            notas_fiscais = self._fonte_dados.obter_lista(_classe=NotaFiscal, **kwargs)

            for nf in notas_fiscais:
                raiz.append(self._serializar_nota_fiscal(nf, retorna_string=False))
                # Grupo de informaçoes suplementares NT2015.002
                # Somente para NFC-e
                # if nf.modelo == 65:
                #     info = etree.Element('infNFeSupl')
                #     etree.SubElement(info, 'qrCode').text = ''
                #     raiz.append(info)

            if retorna_string:
                return etree.tostring(raiz, encoding="unicode", pretty_print=False)
            else:
                return raiz
        except Exception as e:
            raise e
        finally:
            if limpar:
                self._fonte_dados.limpar_dados()
Exemple #11
0
    def _serializar_cliente(self, cliente, tag_raiz='dest', retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Dados do cliente
        etree.SubElement(raiz, cliente.tipo_documento).text = so_numeros(cliente.numero_documento)
        etree.SubElement(raiz, 'xNome').text = cliente.razao_social
        etree.SubElement(raiz, 'IE').text = cliente.inscricao_estadual

        # Endereço
        endereco = etree.SubElement(raiz, 'enderDest')
        etree.SubElement(endereco, 'xLgr').text = cliente.endereco_logradouro
        etree.SubElement(endereco, 'nro').text = cliente.endereco_numero
        etree.SubElement(endereco, 'xCpl').text = cliente.endereco_complemento
        etree.SubElement(endereco, 'xBairro').text = cliente.endereco_bairro
        etree.SubElement(endereco, 'cMun').text = cliente.endereco_municipio
        etree.SubElement(endereco, 'xMun').text = obter_municipio_por_codigo(
                cliente.endereco_municipio, cliente.endereco_uf,
                )
        etree.SubElement(endereco, 'UF').text = cliente.endereco_uf
        etree.SubElement(endereco, 'CEP').text = so_numeros(cliente.endereco_cep)
        etree.SubElement(endereco, 'cPais').text = cliente.endereco_pais
        etree.SubElement(endereco, 'xPais').text = obter_pais_por_codigo(cliente.endereco_pais)
        etree.SubElement(endereco, 'fone').text = cliente.endereco_telefone

        if retorna_string:
            return etree.tostring(raiz, pretty_print=True)
        else:
            return raiz
Exemple #12
0
    def _serializar_emitente(self, emitente, tag_raiz='emit', retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Dados do emitente
        etree.SubElement(raiz, 'CNPJ').text = so_numeros(emitente.cnpj)
        etree.SubElement(raiz, 'xNome').text = emitente.razao_social
        etree.SubElement(raiz, 'xFant').text = emitente.nome_fantasia
        etree.SubElement(raiz, 'IE').text = emitente.inscricao_estadual

        # Endereço
        endereco = etree.SubElement(raiz, 'enderEmit')
        etree.SubElement(endereco, 'xLgr').text = emitente.endereco_logradouro
        etree.SubElement(endereco, 'nro').text = emitente.endereco_numero
        etree.SubElement(endereco, 'xCpl').text = emitente.endereco_complemento
        etree.SubElement(endereco, 'xBairro').text = emitente.endereco_bairro
        etree.SubElement(endereco, 'cMun').text = obter_codigo_por_municipio(
            emitente.endereco_municipio, emitente.endereco_uf)
        etree.SubElement(endereco, 'xMun').text = emitente.endereco_municipio
        etree.SubElement(endereco, 'UF').text = emitente.endereco_uf
        etree.SubElement(endereco, 'CEP').text = so_numeros(emitente.endereco_cep)
        etree.SubElement(endereco, 'cPais').text = emitente.endereco_pais
        etree.SubElement(endereco, 'xPais').text = obter_pais_por_codigo(emitente.endereco_pais)
        etree.SubElement(endereco, 'fone').text = emitente.endereco_telefone

        if retorna_string:
            return etree.tostring(raiz, pretty_print=True)
        else:
            return raiz
Exemple #13
0
    def _cabecalho_soap(self):
        u"""Monta o XML do cabeçalho da requisição SOAP"""

        raiz = etree.Element('cabecMsg', xmlns=NAMESPACE_NFE, versao="1.02")
        etree.SubElement(raiz, 'versaoDados').text = self._versao

        return etree.tostring(raiz, encoding='utf-8', xml_declaration=True)
    def exportar(self, destino=None, retorna_string=False, limpar=True, **kwargs):
        """Gera o(s) arquivo(s) de Cancelamento Nota Fiscal eletronica
            no padrao oficial da migrate, invocity
        @param destino -
        @param retorna_string - Retorna uma string para debug.
        @param limpar - Limpa a fonte de dados para não gerar xml com dados duplicados.
        """
        try:
            # Carrega lista de Notas Fiscais
            eventos = self._fonte_dados.obter_lista(_classe=EventoCancelarNotaMigrate,
                                                    **kwargs)

            for evento in eventos:
                raiz = self._serializar_evento(evento, retorna_string=False)

            if retorna_string:
                return etree.tostring(raiz, encoding="unicode", pretty_print=False)
            else:
                return raiz
        except Exception as e:
            raise e

        finally:
            if limpar:
                self._fonte_dados.limpar_dados()
Exemple #15
0
    def _antes_de_assinar_ou_verificar(self, raiz):
        # Converte etree para string
        xml = etree.tostring(raiz, xml_declaration=True, encoding='utf-8')

        # Ativa funções criptográficas
        self._ativar_funcoes_criptograficas()

        # Colocamos o texto no avaliador XML FIXME: descobrir forma de evitar o uso do libxml2 neste processo
        doc_xml = libxml2.parseMemory(xml, len(xml))
    
        # Cria o contexto para manipulação do XML via sintaxe XPATH
        ctxt = doc_xml.xpathNewContext()
        ctxt.xpathRegisterNs(u'sig', NAMESPACE_SIG)
    
        # Separa o nó da assinatura
        noh_assinatura = ctxt.xpathEval(u'//*/sig:Signature')[0]
    
        # Buscamos a chave no arquivo do certificado
        chave = xmlsec.cryptoAppKeyLoad(
                filename=str(self.certificado.caminho_arquivo),
                format=xmlsec.KeyDataFormatPkcs12,
                pwd=str(self.senha),
                pwdCallback=None,
                pwdCallbackCtx=None,
                )
    
        # Cria a variável de chamada (callable) da função de assinatura
        assinador = xmlsec.DSigCtx()
    
        # Atribui a chave ao assinador
        assinador.signKey = chave

        return doc_xml, ctxt, noh_assinatura, assinador
    def exportar(self, destino=None, retorna_string=False, limpar=True, **kwargs):
        """Gera o(s) arquivo(s) de Nota Fiscal eletronica no padrao oficial da SEFAZ
        e Receita Federal, para ser(em) enviado(s) para o webservice ou para ser(em)
        armazenado(s) em cache local.
        @param destino -
        @param retorna_string - Retorna uma string para debug.
        @param limpar - Limpa a fonte de dados para não gerar xml com dados duplicados.
        """
        try:
            # Carrega lista de Notas Fiscais
            notas_fiscais = self._fonte_dados.obter_lista(_classe=NotaFiscal, **kwargs)

            for nf in notas_fiscais:
                raiz = self._serializar_nota_fiscal(nf, retorna_string=False)

            if retorna_string:
                return etree.tostring(raiz, encoding="unicode", pretty_print=False)
            else:
                return raiz
        except Exception:
            raise

        finally:
            if limpar:
                self._fonte_dados.limpar_dados()
    def exportar(self, destino=None, retorna_string=False, limpar=True, **kwargs):
        """Gera o(s) arquivo(s) de Consulta Nota Fiscal eletronica
            no padrao oficial da migrate, invocity
        @param destino -
        @param retorna_string - Retorna uma string para debug.
        @param limpar - Limpa a fonte de dados para não gerar xml com dados duplicados.
        """
        try:
            # Carrega lista de Notas Fiscais
            consultas = self._fonte_dados.obter_lista(_classe=ConsultaPuloNumeracao,
                                                      **kwargs)

            for consulta in consultas:
                raiz = self._serializar_pulo(consulta, retorna_string=False)

            if retorna_string:
                return etree.tostring(raiz, encoding="unicode", pretty_print=False)
            else:
                return raiz
        except:
            raise

        finally:
            if limpar:
                self._fonte_dados.limpar_dados()
    def _serializar_parametros(self, empresa, tag_raiz='Parametros', retorna_string=True):

        def _serializar_parametros_nfce(tag_raiz='NFCe', retorna_string=True):

            def _serializar_contingencia(tag_raiz='OrdemContingencia',
                                         retorna_string=True):
                raiz = etree.Element(tag_raiz)

                orderm = etree.SubElement(raiz, 'OrdemContingenciaItem')
                etree.SubElement(orderm, 'OrdemContingenciaNFCe').text = '0'

                if retorna_string:
                    return etree.tostring(raiz, encoding="unicode", pretty_print=True)
                else:
                    return raiz

            # Parâmetros referente ao módulo NFC-e
            raiz = etree.Element(tag_raiz)
            etree.SubElement(
                raiz, 'InutilizarAutomaticamenteDocumentosRejeitados').text = 'N'
            etree.SubElement(raiz, 'InutilizarPulosNumeracao').text = 'N'
            etree.SubElement(raiz, 'FormaRetornoPDFIntegracao').text = '3'
            etree.SubElement(raiz, 'FormaRetornoXMLIntegracao').text = '3'
            etree.SubElement(raiz, 'UltimoNSU').text = '000000000000000'
            etree.SubElement(raiz, 'IDTokenCscSEFAZ').text = empresa.token
            etree.SubElement(raiz, 'CscSEFAZ').text = empresa.csc
            etree.SubElement(raiz, 'PossuiLeituraX').text = 'S'
            etree.SubElement(raiz, 'PossuiGeracaoRelatorios').text = 'S'

            raiz.append(_serializar_contingencia(retorna_string=False))

            if retorna_string:
                return etree.tostring(raiz, encoding="unicode", pretty_print=True)
            else:
                return raiz

        raiz = etree.Element(tag_raiz)
        etree.SubElement(raiz, 'OrientDANFE').text = '1'
        etree.SubElement(raiz, 'InfCplVerso').text = 'N'
        etree.SubElement(raiz, 'DhImpressao').text = 'S'
        etree.SubElement(raiz, 'ImpTributos').text = '3'
        etree.SubElement(raiz, 'DescICMS').text = 'N'
        etree.SubElement(raiz, 'EnviarPDFEmail').text = 'N'
        etree.SubElement(raiz, 'EnviarXMLEmail').text = 'N'
        etree.SubElement(raiz, 'ReaprovDocsRejeitados').text = 'N'
        etree.SubElement(raiz, 'InutPulosNumeracao').text = 'N'
        etree.SubElement(raiz, 'IdTokenNFCe').text = empresa.token
        etree.SubElement(raiz, 'CSCNFCe').text = empresa.csc

        # NFC-e
        raiz.append(_serializar_parametros_nfce(retorna_string=False))

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
    def nfeInutilizacaoNF(self, raiz):
        data_hora = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')

        ret = etree.Element('retInutNFe')
        etree.SubElement(ret, 'versao').text = '1.00' # FIXME

        xml_dados = raiz.getroot().getchildren()[0].getchildren()[0].getchildren()[1].text

        xml = etree.tostring(ret, encoding='utf-8', xml_declaration=True)
        self.write(xml)
Exemple #20
0
 def autorizacao(self, nota):
     # url do serviço
     url = self._get_url()
     if self.autorizador == 'BETHA':
         # xml
         xml = etree.tostring(nota, encoding='unicode', pretty_print=False)
         # comunica via wsdl
         return self._post(url, xml, 'gerar')
     else:
         raise Exception('Este método só esta implementado no autorizador betha.')
Exemple #21
0
    def _serializar_url_qrcode(self, nota_fiscal, tag_raiz='infNFeSupl', retorna_string=True):
        raiz = etree.Element(tag_raiz)

        data = base64.b16encode(nota_fiscal.data_emissao.isoformat()).decode()
        digest = base64.b16encode(digest).decode()

        try:
            cpf = nota_fiscal.emitente.numero_documento
        except:
            cpf = None

        if cpf is None:
            url = 'chNFe={}&nVersao={}&tpAmb={}&dhEmi={}&vNF={}&vICMS={}&digVal={}&cIdToken={}'.format(
                   nota_fiscal.nota_fiscal.identificador_unico.replace('NFe', ''),
                   VERSAO_QRCODE,
                   self._ambiente,
                   data.lower(),
                   nota_fiscal.valor_total_nota,
                   nota_fiscal.valor_icms,
                   digest.lower(),
                   nota_fiscal.emitente.token)
        else:
            url = 'chNFe={}&nVersao={}&tpAmb={}&cDest={}&dhEmi={}&vNF={}&vICMS={}&digVal={}&cIdToken={}'.format(
                   nota_fiscal.nota_fiscal.identificador_unico.replace('NFe', ''),
                   VERSAO_QRCODE,
                   self._ambiente,
                   cpf,
                   data.lower(),
                   nota_fiscal.totais_icms_total_nota,
                   nota_fiscal.totais_icms_total,
                   digest.lower(),
                   nota_fiscal.emitente.token)

        url_hash = hashlib.sha1(url.encode()+nota_fiscal.emitente.csc.encode()).digest()
        url_hash = base64.b16encode(url_hash).decode()

        url = url + '&cHashQRCode=' + url_hash.upper()

        if nota_fiscal.uf.upper() == 'PR':
            url_qrcode = NFCE[nota_fiscal.uf.upper()]['QR'] + url
        else:
            if self._homologacao:
                url_qrcode = NFCE[nota_fiscal.uf.upper()]['HOMOLOGACAO'] +\
                    NFCE[nota_fiscal.uf.upper()]['QR'] + url
            else:
                url_qrcode = NFCE[nota_fiscal.uf.upper()]['HTTPS'] +\
                    NFCE[nota_fiscal.uf.upper()]['QR'] + url

        print url_qrcode
        etree.SubElement(raiz, 'qrCode').text = "<![CDATA[%s]]>" % (url_qrcode)

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemple #22
0
    def assinarNfse(self, xml, retorna_string=True):
        "Assina NFS-e"
        try:
            # define variaveis de acordo com autorizador
            if self.autorizador == 'ginfes':
                xpath = './/ns2:InfRps'
                tag = 'InfRps'
            elif self.autorizador == 'betha':
                xpath = './/ns1:InfDeclaracaoPrestacaoServico'
                tag = 'InfDeclaracaoPrestacaoServico'
            else:
                raise Exception('Autorizador não encontrado!')

            xml = etree.fromstring(xml)
            # define namespaces, pega do proprio xml
            namespaces = xml.nsmap
            # No raiz do XML de saida
            raiz = etree.Element('Signature', xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(siginfo, 'CanonicalizationMethod', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(siginfo, 'SignatureMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Tenta achar a tag
            ref = etree.SubElement(siginfo, 'Reference', URI='#' +
                                   xml.xpath(xpath, namespaces=namespaces)[0].attrib['Id'])
            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(ref, 'DigestMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            rps = xml.xpath(xpath+'/..', namespaces=namespaces)[0]
            rps.append(raiz)

            # Escreve no arquivo depois de remover caracteres especiais e parse string
            with open('nfse.xml', 'w') as arquivo:
                texto = remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False))
                # se for tag do Betha
                if tag == 'InfDeclaracaoPrestacaoServico':
                    texto = texto.replace('ns1:', '').replace(':ns1', '')
                arquivo.write(texto)

            subprocess.call(['xmlsec1', '--sign', '--pkcs12', self.certificado,
                             '--pwd', self.senha, '--crypto', 'openssl', '--output',
                             'nfse.xml', '--id-attr:Id', tag, 'nfse.xml'])

            if retorna_string:
                return open('nfse.xml', 'r').read()
            else:
                return etree.parse('nfse.xml').getroot()
        except Exception as e:
            raise e
            def _serializar_contingencia(tag_raiz='OrdemContingencia',
                                         retorna_string=True):
                raiz = etree.Element(tag_raiz)

                orderm = etree.SubElement(raiz, 'OrdemContingenciaItem')
                etree.SubElement(orderm, 'OrdemContingenciaNFCe').text = '0'

                if retorna_string:
                    return etree.tostring(raiz, encoding="unicode", pretty_print=True)
                else:
                    return raiz
    def _serializar_certificado(self, empresa, tag_raiz='Certificado',
                                retorna_string=True):
        raiz = etree.Element(tag_raiz)

        etree.SubElement(raiz, 'ArquivoPFX').text = empresa.certificado_pfx
        etree.SubElement(raiz, 'Senha').text = empresa.senha_certificado

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
    def _serializar_licenciamento(self, empresa, tag_raiz='Licenciamento',
                                  retorna_string=True):
        raiz = etree.Element(tag_raiz)

        item = etree.SubElement(raiz, 'LicenciamentoItem')
        etree.SubElement(item, 'Modulo').text = 'NFCe'
        etree.SubElement(item, 'Modelo').text = '2'

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemple #26
0
    def assinarCancelar(self, xml, retorna_string=True):
        """ Método que assina o xml para cancelamento de NFS-e """
        try:
            if self.autorizador == 'ginfes':
                xpath = 'CancelarNfseEnvio'
                tag = 'CancelarNfseEnvio'
                namespaces = {'ns1': 'http://www.ginfes.com.br/servico_cancelar_nfse_envio', 'ns2':'http://www.ginfes.com.br/tipos'}
            elif self.autorizador == 'betha':
                xpath = '/CancelarNfseEnvio/ns1:Pedido'
                tag = 'InfPedidoCancelamento'
                namespaces = {'ns1': 'http://www.betha.com.br/e-nota-contribuinte-ws'}
            else:
                raise Exception('Autorizador não encontrado!')

            xml = etree.fromstring(xml)
            # No raiz do XML de saida
            raiz = etree.Element('Signature', xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(siginfo, 'CanonicalizationMethod', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(siginfo, 'SignatureMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Tenta achar a tag informada no xpath
            if tag == 'InfPedidoCancelamento':
                ref = etree.SubElement(siginfo, 'Reference', URI='#'+xml.xpath('.//ns1:'+tag, namespaces=namespaces)[0].attrib['Id'])
            # ginfes não tem id no cancelamento v2
            else:
                ref = etree.SubElement(siginfo, 'Reference', URI='')
            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(ref, 'DigestMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            if tag == 'InfPedidoCancelamento':
                xml = xml.xpath(xpath, namespaces=namespaces)[0]
            # ginfes só possui a tag root
            else:
               xml.append(raiz)

            # Escreve no arquivo depois de remover caracteres especiais e parse string
            with open('nfse.xml', 'w') as arquivo:
                arquivo.write(remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False).replace('\n','')))

            subprocess.call(['xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd', self.senha, '--crypto', 'openssl', '--output', 'funfa.xml', '--id-attr:Id', tag, 'nfse.xml'])

            if retorna_string:
                return open('funfa.xml', 'r').read()
            else:
                return etree.parse('funfa.xml').getroot()
        except Exception as e:
            raise e
    def _serializar_usuario(self, usuario, tag_raiz='Usuarios', retorna_string=True):

        def _serializar_permissoes(tag_raiz='Permissoes', retorna_string=True):
            raiz = etree.Element(tag_raiz)

            # Permissões referente ao módulo NFC-e
            p_nfce = etree.SubElement(raiz, 'PermissaoNFCe')
            etree.SubElement(p_nfce, 'Visualizar').text = "S"
            etree.SubElement(p_nfce, 'Baixar').text = "S"

            # Permissões gerais da aplicação
            p_geral = etree.SubElement(raiz, 'PermissoesGerais')
            etree.SubElement(p_geral, 'ImportarDocumentos').text = "N"
            etree.SubElement(p_geral, 'AlterarDadosDoUsuario').text = "S"
            etree.SubElement(p_geral, 'AlterarDadosDaEmpresa').text = "N"
            etree.SubElement(p_geral, 'AlterarMarcasDaEmpresa').text = "N"
            etree.SubElement(p_geral, 'AlterarCertificadosDaEmpresa').text = "S"
            etree.SubElement(p_geral, 'AlterarConfiguracoesParametros').text = "N"
            etree.SubElement(p_geral, 'CadastrarEmpresas').text = "N"
            etree.SubElement(p_geral, 'AlterarCaixasDeEmail').text = "S"
            etree.SubElement(p_geral, 'AlterarPermissoesDeUsuario').text = "S"
            etree.SubElement(p_geral, 'AdicionarNovosUsuarios').text = "S"
            etree.SubElement(p_geral, 'VisualizarChaveAcesso').text = "N"
            etree.SubElement(p_geral, 'VisualizarAcoesDeUsuarios').text = "S"
            etree.SubElement(p_geral, 'VisualizarQuantidadesEmitidas').text = "S"
            etree.SubElement(p_geral, 'VisualizarLicencas').text = "S"
            etree.SubElement(p_geral, 'ConfiguracaoSenha').text = "N"
            etree.SubElement(p_geral, 'GerarRelatorios').text = "S"
            etree.SubElement(p_geral, 'InutilizarDocumentos').text = "S"
            etree.SubElement(p_geral, 'FerramentasIntegracao').text = "N"

            if retorna_string:
                return etree.tostring(raiz, encoding="unicode", pretty_print=True)
            else:
                return raiz

        raiz = etree.Element(tag_raiz)

        # Dados do usuario
        item = etree.SubElement(raiz, 'UsuariosItem')
        etree.SubElement(item, 'UsrNome').text = usuario.user_root_nome
        etree.SubElement(item, 'UsrEmail').text = usuario.user_root_email
        etree.SubElement(item, 'UsrSenha').text = usuario.user_root_senha
        # 1 - Gerente; 2 - Digitador; 3 - Nenhum
        etree.SubElement(item, 'GrupoUsuario').text = '3'

        # Permissoes
        item.append(_serializar_permissoes(retorna_string=False))

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
    def _serializar_empresa(self, empresa, tag_raiz='CadastroEmpresa',
                            retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Dados do empresa
        etree.SubElement(raiz, 'EmpCNPJ').text = so_numeros(empresa.cnpj)
        etree.SubElement(raiz, 'EmpRazSocial').text = empresa.razao_social
        etree.SubElement(raiz, 'EmpNomFantasia').text = empresa.nome_fantasia
        etree.SubElement(raiz, 'EmpApelido').text = empresa.apelido
        etree.SubElement(raiz, 'EmpIE').text = empresa.inscricao_estadual

        # Inscricao Municipal
        if empresa.inscricao_municipal:
            etree.SubElement(raiz, 'EmpIM').text = so_numeros(empresa.inscricao_municipal)

        # Endereço
        etree.SubElement(raiz, 'EmpEndereco').text = empresa.endereco_logradouro
        etree.SubElement(raiz, 'EmpNumero').text = empresa.endereco_numero
        if empresa.endereco_complemento:
            etree.SubElement(raiz, 'EmpComplemento').text = empresa.endereco_complemento
        etree.SubElement(raiz, 'EmpBairro').text = empresa.endereco_bairro
        etree.SubElement(raiz, 'MunCodigo').text = obter_codigo_por_municipio(
            empresa.endereco_municipio, empresa.endereco_uf)
        etree.SubElement(raiz, 'EmpCEP').text = so_numeros(empresa.endereco_cep)

        if empresa.endereco_telefone:
            etree.SubElement(raiz, 'EmpTelefone').text = empresa.endereco_telefone

        etree.SubElement(raiz, 'EmpCNAE').text = empresa.cnae_fiscal
        etree.SubElement(raiz, 'EmpCRT').text = empresa.codigo_de_regime_tributario
        etree.SubElement(raiz, 'EmpIEST').text = ''
        etree.SubElement(raiz, 'EmpMarca').text = ''
        etree.SubElement(raiz, 'EmpMarcaExtensao').text = ''
        etree.SubElement(raiz, 'EmpEmail').text = empresa.email
        etree.SubElement(raiz, 'EmpTpoEndereco').text = empresa.tipo_endereco

        # Certificado
        raiz.append(self._serializar_certificado(empresa, retorna_string=False))

        # Usuarios
        raiz.append(self._serializar_usuario(empresa, retorna_string=False))

        # Parametros
        raiz.append(self._serializar_parametros(empresa, retorna_string=False))

        # Licenciamento
        raiz.append(self._serializar_licenciamento(empresa, retorna_string=False))

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemple #29
0
    def assinar(self, xml, retorna_string=False):
        try:
            # No raiz do XML de saida
            tag = 'infNFe'  # tag que será assinada
            raiz = etree.Element('Signature', xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(siginfo, 'CanonicalizationMethod', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(siginfo, 'SignatureMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Tenta achar a tag infNFe
            try:
                ref = etree.SubElement(siginfo, 'Reference', URI='#'+xml.findall('infNFe')[0].attrib['Id'])
            # Caso nao tenha a tag infNFe, procura a tag infEvento
            except IndexError:
                tag = 'infEvento'
                ref = etree.SubElement(siginfo, 'Reference', URI='#'+xml.findall('infEvento')[0].attrib['Id'])
            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(ref, 'DigestMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            xml.append(raiz)

            # Escreve no arquivo depois de remover caracteres especiais e parse string
            with open('testes.xml', 'w') as arquivo:
                arquivo.write(remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False)))

            subprocess.call(['xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd', self.senha, '--crypto', 'openssl', '--output', 'funfa.xml', '--id-attr:Id', tag, 'testes.xml'])
            xml = etree.parse('funfa.xml').getroot()

            if retorna_string:
                return etree.tostring(xml, encoding="unicode", pretty_print=False)
            else:
                return xml
        except Exception as e:
            raise e
Exemple #30
0
    def _assinar(self, xml, tag, retorna_string=True):
        """ Método para assinar xml de NFS-e com tags sem ID
            Consulta de Lote e Consulta por RPS
            @param tag - raiz do xml que será assinado
        """
        try:
            xml = etree.fromstring(xml)
            # No raiz do XML de saida
            raiz = etree.Element('Signature', xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(siginfo, 'CanonicalizationMethod', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(siginfo, 'SignatureMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Consulta nao tem id
            ref = etree.SubElement(siginfo, 'Reference', URI='')

            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(ref, 'DigestMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            xml.append(raiz)

            # Escreve no arquivo depois de remover caracteres especiais e parse string
            with open('nfse.xml', 'w') as arquivo:
                arquivo.write(remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False).replace('\n','')))

            subprocess.call(['xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd', self.senha, '--crypto', 'openssl', '--output', 'funfa.xml', '--id-attr:Id', tag, 'nfse.xml'])
            xml = etree.parse('funfa.xml').getroot()

            if retorna_string:
                return etree.tostring(xml, encoding="unicode", pretty_print=False).replace('\n','')
            else:
                return xml
        except Exception as e:
            raise e
Exemple #31
0
    def _post(self, url, xml):
        certificado_a1 = CertificadoA1(self.certificado)
        chave, cert = certificado_a1.separar_arquivo(self.certificado_senha,
                                                     caminho=True)
        chave_cert = (cert, chave)
        # Abre a conexão HTTPS
        try:
            xml_declaration = '<?xml version="1.0" encoding="UTF-8"?>'

            # limpa xml com caracteres bugados para infMDFeSupl em NFC-e
            xml = re.sub(
                '<qrCodMDFe>(.*?)</qrCodMDFe>', lambda x: x.group(0).replace(
                    '&lt;', '<').replace('&gt;', '>').replace('amp;', ''),
                etree.tostring(xml, encoding='unicode').replace('\n', ''))
            xml = xml_declaration + xml
            xml = xml.encode(
                'utf8')  # necessário para o evento "CONSULTAR NÃO ENCERRADOS"

            print(xml)
            print('-' * 20)

            # Faz o request com o servidor
            result = requests.post(url,
                                   xml,
                                   headers=self._post_header(),
                                   cert=chave_cert,
                                   verify=False,
                                   timeout=50)
            result.encoding = 'utf-8'
            return result
        except requests.exceptions.Timeout as e:
            raise e
        except requests.exceptions.RequestException as e:
            raise e
        finally:
            certificado_a1.excluir()
Exemple #32
0
    def _cabecalho(self, retorna_string=True):
        """ Monta o XML do cabeçalho da requisição wsdl
            Namespaces padrão homologação (Ginfes) """

        xml_declaration = '<?xml version="1.0" encoding="UTF-8"?>'
        # cabecalho = '<ns2:cabecalho versao="3" xmlns:ns2="http://www.ginfes.com.br/cabecalho_v03.xsd"
        # xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><versaoDados>3</versaoDados></ns2:cabecalho>'
        # cabecalho
        raiz = etree.Element('{%s}cabecalho' % self._namespace,
                             nsmap={
                                 'ns2': self._namespace,
                                 'xsi': NAMESPACE_XSI
                             },
                             versao=self._versao)
        etree.SubElement(raiz, 'versaoDados').text = self._versao

        if retorna_string:
            cabecalho = etree.tostring(raiz,
                                       encoding='unicode',
                                       pretty_print=False).replace('\n', '')
            cabecalho = xml_declaration + cabecalho
            return cabecalho
        else:
            return raiz
Exemple #33
0
    def _serializar_produto_servico(self,
                                    produto_servico,
                                    tag_raiz='det',
                                    retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Produto
        prod = etree.SubElement(raiz, 'prod')
        etree.SubElement(prod, 'cProd').text = str(produto_servico.codigo)
        etree.SubElement(prod, 'cEAN').text = produto_servico.ean
        etree.SubElement(prod, 'xProd').text = produto_servico.descricao
        etree.SubElement(prod, 'CFOP').text = produto_servico.cfop
        etree.SubElement(prod, 'uCom').text = produto_servico.unidade_comercial
        etree.SubElement(prod, 'qCom').text = str(
            produto_servico.quantidade_comercial or 0)
        etree.SubElement(prod, 'vUnCom').text = str(
            produto_servico.valor_unitario_comercial or 0)
        etree.SubElement(prod,
                         'vProd').text = str(produto_servico.valor_total_bruto
                                             or 0)
        etree.SubElement(prod,
                         'cEANTrib').text = produto_servico.ean_tributavel
        etree.SubElement(prod,
                         'uTrib').text = produto_servico.unidade_tributavel
        etree.SubElement(prod, 'qTrib').text = str(
            produto_servico.quantidade_tributavel)
        etree.SubElement(prod, 'vUnTrib').text = str(
            produto_servico.valor_unitario_tributavel)

        # Imposto
        imposto = etree.SubElement(raiz, 'imposto')

        icms = etree.SubElement(imposto, 'ICMS')
        icms_item = etree.SubElement(
            icms, 'ICMS' + produto_servico.icms_situacao_tributaria)
        etree.SubElement(icms_item,
                         'orig').text = str(produto_servico.icms_origem)
        etree.SubElement(icms_item,
                         'CST').text = produto_servico.icms_situacao_tributaria
        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)

        pis = etree.SubElement(imposto, 'PIS')
        pis_item = etree.SubElement(pis, 'PISAliq')
        etree.SubElement(pis_item, 'CST').text = str(
            produto_servico.pis_situacao_tributaria)
        etree.SubElement(pis_item, 'vBC').text = str(
            produto_servico.pis_valor_base_calculo)
        etree.SubElement(pis_item, 'pPIS').text = str(
            produto_servico.pis_aliquota_percentual)
        etree.SubElement(pis_item,
                         'vPIS').text = str(produto_servico.pis_valor)

        cofins = etree.SubElement(imposto, 'COFINS')
        cofins_item = etree.SubElement(cofins, 'COFINSAliq')
        etree.SubElement(cofins_item, 'CST').text = str(
            produto_servico.cofins_situacao_tributaria)
        etree.SubElement(cofins_item, 'vBC').text = str(
            produto_servico.cofins_valor_base_calculo)
        etree.SubElement(cofins_item, 'pCOFINS').text = str(
            produto_servico.cofins_aliquota_percentual)
        etree.SubElement(cofins_item,
                         'vCOFINS').text = str(produto_servico.cofins_valor)

        if retorna_string:
            return etree.tostring(raiz, pretty_print=True)
        else:
            return raiz
Exemple #34
0
    def _assinar(self, xml, tag, retorna_string=True):
        """ Método para assinar xml de NFS-e com tags sem ID
            Consulta de Lote e Consulta por RPS
            @param tag - raiz do xml que será assinado
        """
        try:
            xml = etree.fromstring(xml)
            # No raiz do XML de saida
            raiz = etree.Element('Signature',
                                 xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(
                siginfo,
                'CanonicalizationMethod',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                siginfo,
                'SignatureMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Consulta nao tem id
            ref = etree.SubElement(siginfo, 'Reference', URI='')

            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm=
                'http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                ref,
                'DigestMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            xml.append(raiz)

            # Escreve no arquivo depois de remover caracteres especiais e parse string
            with open('nfse.xml', 'w') as arquivo:
                arquivo.write(
                    remover_acentos(
                        etree.tostring(xml,
                                       encoding="unicode",
                                       pretty_print=False).replace('\n', '')))

            subprocess.check_call([
                'xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd',
                self.senha, '--crypto', 'openssl', '--output', 'funfa.xml',
                '--id-attr:Id', tag, 'nfse.xml'
            ])
            xml = etree.parse('funfa.xml').getroot()

            if retorna_string:
                return etree.tostring(xml,
                                      encoding="unicode",
                                      pretty_print=False).replace('\n', '')
            else:
                return xml
        except Exception as e:
            raise e
Exemple #35
0
    def assinarNfse(self, xml, retorna_string=True):
        "Assina NFS-e"
        try:
            # define variaveis de acordo com autorizador
            if self.autorizador == 'ginfes':
                xpath = './/ns2:InfRps'
                tag = 'InfRps'
            elif self.autorizador == 'betha':
                xpath = './/ns1:InfDeclaracaoPrestacaoServico'
                tag = 'InfDeclaracaoPrestacaoServico'
            else:
                raise Exception('Autorizador não encontrado!')

            xml = etree.fromstring(xml)
            # define namespaces, pega do proprio xml
            namespaces = xml.nsmap
            # No raiz do XML de saida
            raiz = etree.Element('Signature',
                                 xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(
                siginfo,
                'CanonicalizationMethod',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                siginfo,
                'SignatureMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Tenta achar a tag
            ref = etree.SubElement(
                siginfo,
                'Reference',
                URI='#' +
                xml.xpath(xpath, namespaces=namespaces)[0].attrib['Id'])
            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm=
                'http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                ref,
                'DigestMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            rps = xml.xpath(xpath + '/..', namespaces=namespaces)[0]
            rps.append(raiz)

            # Escreve no arquivo depois de remover caracteres especiais e parse string
            with open('nfse.xml', 'w') as arquivo:
                texto = remover_acentos(
                    etree.tostring(xml, encoding="unicode",
                                   pretty_print=False))
                # se for tag do Betha
                if tag == 'InfDeclaracaoPrestacaoServico':
                    texto = texto.replace('ns1:', '').replace(':ns1', '')
                arquivo.write(texto)

            subprocess.check_call([
                'xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd',
                self.senha, '--crypto', 'openssl', '--output', 'nfse.xml',
                '--id-attr:Id', tag, 'nfse.xml'
            ])

            if retorna_string:
                return open('nfse.xml', 'r').read()
            else:
                return etree.parse('nfse.xml').getroot()
        except Exception as e:
            raise e
Exemple #36
0
    def assinar_etree(self, raiz, retorna_xml=False):
        # Extrai a tag do elemento raiz
        tipo = extrair_tag(raiz.getroot())

        # doctype compatível com o tipo da tag raiz
        if tipo == u'NFe':
            doctype = u'<!DOCTYPE NFe [<!ATTLIST infNFe Id ID #IMPLIED>]>'
        elif tipo == u'inutNFe':
            doctype = u'<!DOCTYPE inutNFe [<!ATTLIST infInut Id ID #IMPLIED>]>'
        elif tipo == u'cancNFe':
            doctype = u'<!DOCTYPE cancNFe [<!ATTLIST infCanc Id ID #IMPLIED>]>'
        elif tipo == u'DPEC':
            doctype = u'<!DOCTYPE DPEC [<!ATTLIST infDPEC Id ID #IMPLIED>]>'

        # Tag de assinatura
        if raiz.getroot().find('Signature') is None:
            signature = etree.Element(
                '{%s}Signature' % NAMESPACE_SIG,
                URI=raiz.getroot().getchildren()[0].attrib['Id'],
                nsmap={'sig': NAMESPACE_SIG},
            )

            signed_info = etree.SubElement(signature,
                                           '{%s}SignedInfo' % NAMESPACE_SIG)
            etree.SubElement(
                signed_info,
                'CanonicalizationMethod',
                Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315")
            etree.SubElement(
                signed_info,
                'SignatureMethod',
                Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1")

            reference = etree.SubElement(
                signed_info,
                '{%s}Reference' % NAMESPACE_SIG,
                URI=raiz.getroot().getchildren()[0].attrib['Id'])
            transforms = etree.SubElement(
                reference,
                'Transforms',
                URI=raiz.getroot().getchildren()[0].attrib['Id'])
            etree.SubElement(
                transforms,
                'Transform',
                Algorithm=
                "http://www.w3.org/2000/09/xmldsig#enveloped-signature")
            etree.SubElement(
                transforms,
                'Transform',
                Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315")
            etree.SubElement(
                reference,
                '{%s}DigestMethod' % NAMESPACE_SIG,
                Algorithm="http://www.w3.org/2000/09/xmldsig#sha1")
            digest_value = etree.SubElement(reference,
                                            '{%s}DigestValue' % NAMESPACE_SIG)

            signature_value = etree.SubElement(
                signature, '{%s}SignatureValue' % NAMESPACE_SIG)

            key_info = etree.SubElement(signature,
                                        '{%s}KeyInfo' % NAMESPACE_SIG)
            x509_data = etree.SubElement(key_info,
                                         '{%s}X509Data' % NAMESPACE_SIG)
            x509_certificate = etree.SubElement(
                x509_data, '{%s}X509Certificate' % NAMESPACE_SIG)

            raiz.getroot().insert(0, signature)

        # Acrescenta a tag de doctype (como o lxml nao suporta alteracao do doctype,
        # converte para string para faze-lo)
        xml = etree.tostring(raiz, xml_declaration=True, encoding='utf-8')

        if xml.find('<!DOCTYPE ') == -1:
            pos = xml.find('>') + 1
            xml = xml[:pos] + doctype + xml[pos:]
            #raiz = etree.parse(StringIO(xml))

        doc_xml, ctxt, noh_assinatura, assinador = self._antes_de_assinar_ou_verificar(
            raiz)

        # Realiza a assinatura
        assinador.sign(noh_assinatura)

        # Coloca na instância Signature os valores calculados
        digest_value.text = ctxt.xpathEval(
            u'//sig:DigestValue')[0].content.replace(u'\n', u'')
        signature_value.text = ctxt.xpathEval(
            u'//sig:SignatureValue')[0].content.replace(u'\n', u'')

        # Provavelmente retornarão vários certificados, já que o xmlsec inclui a cadeia inteira
        certificados = ctxt.xpathEval(u'//sig:X509Data/sig:X509Certificate')
        x509_certificate.text = certificados[len(certificados) -
                                             1].content.replace(u'\n', u'')

        resultado = assinador.status == xmlsec.DSigStatusSucceeded

        # Gera o XML para retornar
        xml = doc_xml.serialize()

        # Limpa objetos da memoria e desativa funções criptográficas
        self._depois_de_assinar_ou_verificar(doc_xml, ctxt, assinador)

        if retorna_xml:
            return xml
        else:
            return etree.parse(StringIO(xml))
Exemple #37
0
    def _serializar_produto_servico(self,
                                    produto_servico,
                                    modelo,
                                    tag_raiz='det',
                                    retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Produto
        prod = etree.SubElement(raiz, 'prod')
        etree.SubElement(prod, 'cProd').text = str(produto_servico.codigo)
        etree.SubElement(prod, 'cEAN').text = produto_servico.ean
        etree.SubElement(prod, 'xProd').text = produto_servico.descricao
        etree.SubElement(prod, 'NCM').text = produto_servico.ncm
        # Codificação opcional que detalha alguns NCM. Formato: duas letras maiúsculas e 4 algarismos. Se a mercadoria se enquadrar em mais de uma codificação, informar até 8 codificações principais.
        #etree.SubElement(prod, 'NVE').text = ''
        etree.SubElement(prod, 'CFOP').text = produto_servico.cfop
        etree.SubElement(prod, 'uCom').text = produto_servico.unidade_comercial
        etree.SubElement(prod, 'qCom').text = str(
            produto_servico.quantidade_comercial or 0)
        etree.SubElement(prod, 'vUnCom').text = str('{:.2f}').format(
            produto_servico.valor_unitario_comercial or 0)
        etree.SubElement(prod, 'vProd').text = str('{:.2f}').format(
            produto_servico.valor_total_bruto or 0)
        etree.SubElement(prod,
                         'cEANTrib').text = produto_servico.ean_tributavel
        etree.SubElement(prod,
                         'uTrib').text = produto_servico.unidade_tributavel
        etree.SubElement(prod, 'qTrib').text = str(
            produto_servico.quantidade_tributavel)
        etree.SubElement(prod, 'vUnTrib').text = str('{:.2f}').format(
            produto_servico.valor_unitario_tributavel)
        """ Indica se valor do Item (vProd) entra no valor total da NF-e (vProd)
            0=Valor do item (vProd) não compõe o valor total da NF-e
            1=Valor do item (vProd) compõe o valor total da NF-e (vProd) (v2.0)
        """
        etree.SubElement(prod, 'indTot').text = str(produto_servico.ind_total)

        # Imposto
        imposto = etree.SubElement(raiz, 'imposto')

        # Lei da transparencia
        # Tributos aprox por item
        if produto_servico.valor_tributos_aprox:
            etree.SubElement(
                imposto,
                'vTotTrib').text = produto_servico.valor_tributos_aprox

        ### ICMS
        icms = etree.SubElement(imposto, 'ICMS')
        icms_csosn = ('102', '103', '300', '400')
        if produto_servico.icms_modalidade in icms_csosn:
            icms_item = etree.SubElement(
                icms, 'ICMSSN' + produto_servico.icms_modalidade)
            etree.SubElement(icms_item,
                             'orig').text = str(produto_servico.icms_origem)
            etree.SubElement(icms_item,
                             'CSOSN').text = produto_servico.icms_csosn
        elif produto_servico.icms_modalidade == '101':
            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,
                             'CSOSN').text = produto_servico.icms_csosn
            etree.SubElement(
                icms_item, 'pCredSN'
            ).text = ''  # Alíquota aplicável de cálculo do crédito (Simples Nacional).
            etree.SubElement(
                icms_item, 'vCredICMSSN'
            ).text = ''  # Valor crédito do ICMS que pode ser aproveitado nos termos do art. 23 da LC 123 (Simples Nacional)
        elif produto_servico.icms_modalidade == 'ST':
            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 = '41'  # Nao tributado
            etree.SubElement(
                icms_item, 'vBCSTRet'
            ).text = ''  # Informar o valor da BC do ICMS ST retido na UF remetente
            etree.SubElement(
                icms_item, 'vICMSSTRet'
            ).text = ''  # Informar o valor do ICMS ST retido na UF remetente
            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
            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)

        # apenas nfe
        pisnt = ('04', '05', '06', '07', '08', '09')
        if modelo == 55:
            ## PIS
            pis = etree.SubElement(imposto, 'PIS')
            if produto_servico.pis_modalidade in pisnt:
                pis_item = etree.SubElement(pis, 'PISNT')
                etree.SubElement(pis_item,
                                 'CST').text = produto_servico.pis_modalidade
            elif produto_servico.pis_modalidade == '01' or produto_servico.pis_modalidade == '02':
                pis_item = etree.SubElement(pis, 'PISAliq')
                etree.SubElement(pis_item,
                                 'CST').text = produto_servico.pis_modalidade
                etree.SubElement(
                    pis_item,
                    'vBC').text = produto_servico.pis_valor_base_calculo
                etree.SubElement(
                    pis_item,
                    'pPIS').text = produto_servico.pis_aliquota_percentual
                etree.SubElement(pis_item,
                                 'vPIS').text = produto_servico.pis_valor
            elif produto_servico.pis_modalidade == '03':
                pis_item = etree.SubElement(pis, 'PISQtde')
                etree.SubElement(pis_item,
                                 'CST').text = produto_servico.pis_modalidade
                etree.SubElement(
                    pis_item,
                    'qBCProd').text = produto_servico.quantidade_comercial
                etree.SubElement(
                    pis_item,
                    'vAliqProd').text = produto_servico.pis_aliquota_percentual
                etree.SubElement(
                    pis_item,
                    'vPIS').text = produto_servico.pis_valor_base_calculo
            else:
                pis_item = etree.SubElement(pis, 'PISOutr')
                etree.SubElement(pis_item,
                                 'CST').text = produto_servico.pis_modalidade
                etree.SubElement(
                    pis_item,
                    'vBC').text = produto_servico.pis_valor_base_calculo
                etree.SubElement(
                    pis_item,
                    'pPIS').text = produto_servico.pis_aliquota_percentual
                etree.SubElement(
                    pis_item,
                    'qBCProd').text = produto_servico.quantidade_comercial
                etree.SubElement(
                    pis_item,
                    'vAliqProd').text = produto_servico.pis_aliquota_percentual
                etree.SubElement(
                    pis_item,
                    'vPIS').text = produto_servico.pis_valor_base_calculo

                ## PISST
                # pis_item = etree.SubElement(pis, 'PISST')
                # etree.SubElement(pis_item, 'vBC').text = produto_servico.pis_valor_base_calculo
                # etree.SubElement(pis_item, 'pPIS').text = produto_servico.pis_aliquota_percentual
                # etree.SubElement(pis_item, 'qBCProd').text = produto_servico.quantidade_comercial
                # etree.SubElement(pis_item, 'vAliqProd').text = produto_servico.pis_aliquota_percentual
                # etree.SubElement(pis_item, 'vPIS').text = produto_servico.pis_valor_base_calculo

            cofinsnt = ('04', '05', '06', '07', '08', '09')
            ## COFINS
            cofins = etree.SubElement(imposto, 'COFINS')
            if produto_servico.cofins_modalidade in cofinsnt:
                cofins_item = etree.SubElement(cofins, 'COFINSNT')
                etree.SubElement(
                    cofins_item,
                    'CST').text = produto_servico.cofins_modalidade
            elif produto_servico.cofins_modalidade == '01' or produto_servico.cofins_modalidade == '02':
                cofins_item = etree.SubElement(cofins, 'COFINSAliq')
                etree.SubElement(
                    cofins_item,
                    'CST').text = produto_servico.cofins_modalidade
                etree.SubElement(
                    cofins_item,
                    'vBC').text = produto_servico.cofins_valor_base_calculo
                etree.SubElement(
                    cofins_item, 'pCOFINS'
                ).text = produto_servico.cofins_aliquota_percentual
                etree.SubElement(cofins_item,
                                 'vCOFINS').text = produto_servico.cofins_valor
            elif produto_servico.cofins_modalidade == '03':
                cofins_item = etree.SubElement(cofins, 'COFINSQtde')
                etree.SubElement(
                    cofins_item,
                    'CST').text = produto_servico.cofins_modalidade
                etree.SubElement(
                    cofins_item,
                    'qBCProd').text = produto_servico.quantidade_comercial
                etree.SubElement(
                    cofins_item, 'vAliqProd'
                ).text = produto_servico.cofins_aliquota_percentual
                etree.SubElement(cofins_item,
                                 'vCOFINS').text = produto_servico.cofins_valor
            else:
                cofins_item = etree.SubElement(cofins, 'COFINSOutr')
                etree.SubElement(
                    cofins_item,
                    'CST').text = produto_servico.cofins_modalidade
                etree.SubElement(
                    cofins_item,
                    'vBC').text = produto_servico.cofins_valor_base_calculo
                etree.SubElement(
                    cofins_item, 'pCOFINS'
                ).text = produto_servico.cofins_aliquota_percentual
                etree.SubElement(
                    cofins_item, 'vAliqProd'
                ).text = produto_servico.cofins_aliquota_percentual
                etree.SubElement(cofins_item,
                                 'vCOFINS').text = produto_servico.cofins_valor

                ## COFINSST
                # cofins_item = etree.SubElement(cofins, 'COFINSOutr')
                # etree.SubElement(cofins_item, 'vBC').text = produto_servico.cofins_valor_base_calculo
                # etree.SubElement(cofins_item, 'pCOFINS').text = produto_servico.cofins_aliquota_percentual
                # etree.SubElement(cofins_item, 'qBCProd').text = produto_servico.quantidade_comercial
                # etree.SubElement(cofins_item, 'vAliqProd').text = produto_servico.cofins_aliquota_percentual
                # etree.SubElement(cofins_item, 'vCOFINS').text = produto_servico.cofins_valor

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemple #38
0
    def _serializar_nota_fiscal(self,
                                nota_fiscal,
                                tag_raiz='infNFe',
                                retorna_string=True):
        #raiz = etree.Element('NFe', xmlns='http://www.portalfiscal.inf.br/nfe')
        raiz = etree.Element(tag_raiz, versao=self._versao)

        # 'Id' da tag raiz
        # Ex.: NFe35080599999090910270550010000000011518005123
        raiz.attrib['Id'] = nota_fiscal.identificador_unico

        # timezone Brasília -03:00
        tz = time.strftime("%z")
        tz = "{}:{}".format(tz[:-2], tz[-2:])

        # Dados da Nota Fiscal
        ide = etree.SubElement(raiz, 'ide')
        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)
        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)
        etree.SubElement(
            ide, 'dhEmi'
        ).text = nota_fiscal.data_emissao.strftime('%Y-%m-%dT%H:%M:%S') + tz
        #etree.SubElement(ide, 'dhSaiEnt').text = nota_fiscal.data_saida_entrada.strftime('%Y-%m-%dT%H:%M:%S') + tz
        """dhCont Data e Hora da entrada em contingência E B01 D 0-1 Formato AAAA-MM-DDThh:mm:ssTZD (UTC - Universal
            Coordinated Time)
            Exemplo: no formato UTC para os campos de Data-Hora, "TZD" pode ser -02:00 (Fernando de Noronha), -03:00 (Brasília) ou -04:00 (Manaus), no
            horário de verão serão -01:00, -02:00 e -03:00. Exemplo: "2010-08-19T13:00:15-03:00".
        """
        etree.SubElement(ide, 'tpNF').text = str(
            nota_fiscal.tipo_documento)  # 0=entrada 1=saida
        """ nfce suporta apenas operação interna
            Identificador de local de destino da operação 1=Operação interna;2=Operação interestadual;3=Operação com exterior.
        """
        if nota_fiscal.modelo == 65:
            etree.SubElement(ide, 'idDest').text = str(1)
        else:
            etree.SubElement(ide, 'idDest').text = str(
                nota_fiscal.indicador_destino)
        etree.SubElement(ide, 'cMunFG').text = nota_fiscal.municipio
        etree.SubElement(ide,
                         'tpImp').text = str(nota_fiscal.tipo_impressao_danfe)
        """ ### CONTINGENCIA ###
            1=Emissão normal (não em contingência);
            2=Contingência FS-IA, com impressão do DANFE em formulário de segurança;
            3=Contingência SCAN (Sistema de Contingência do Ambiente Nacional);
            4=Contingência DPEC (Declaração Prévia da Emissão em Contingência);
            5=Contingência FS-DA, com impressão do DANFE em formulário de segurança;
            6=Contingência SVC-AN (SEFAZ Virtual de Contingência do AN);
            7=Contingência SVC-RS (SEFAZ Virtual de Contingência do RS);
            9=Contingência off-line da NFC-e (as demais opções de contingência são válidas também para a NFC-e).
            Para a NFC-e somente estão disponíveis e são válidas as opções de contingência 5 e 9.
        """
        if self._contingencia != None:
            if nota_fiscal.forma_emissao == '1':
                nota_fiscal.forma_emissao = '9'
        etree.SubElement(ide, 'tpEmis').text = str(nota_fiscal.forma_emissao)
        etree.SubElement(ide,
                         'cDV').text = nota_fiscal.dv_codigo_numerico_aleatorio
        etree.SubElement(ide, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(ide,
                         'finNFe').text = str(nota_fiscal.finalidade_emissao)
        if nota_fiscal.modelo == 65:
            etree.SubElement(ide, 'indFinal').text = str(1)
            etree.SubElement(ide, 'indPres').text = str(1)
        else:
            etree.SubElement(ide,
                             'indFinal').text = str(nota_fiscal.cliente_final)
            etree.SubElement(ide, 'indPres').text = str(
                nota_fiscal.indicador_presencial)
        etree.SubElement(ide,
                         'procEmi').text = str(nota_fiscal.processo_emissao)
        etree.SubElement(
            ide,
            'verProc').text = '%s %s' % (self._nome_aplicacao,
                                         nota_fiscal.versao_processo_emissao)
        ### CONTINGENCIA ###
        if self._contingencia != None:
            etree.SubElement(
                ide, 'dhCont'
            ).text = nota_fiscal.data_emissao.strftime(
                '%Y-%m-%dT%H:%M:%S'
            ) + tz  # Data e Hora da entrada em contingência AAAA-MM-DDThh:mm:ssTZD
            etree.SubElement(
                ide, 'xJust'
            ).text = nota_fiscal.self._contingencia  # Justificativa da entrada em contingência (min 20, max 256 caracteres)

        # Emitente
        raiz.append(
            self._serializar_emitente(nota_fiscal.emitente,
                                      retorna_string=False))

        # Destinatário
        try:
            raiz.append(
                self._serializar_cliente(nota_fiscal.cliente,
                                         modelo=nota_fiscal.modelo,
                                         retorna_string=False))
        except AttributeError as e:
            # NFC-e pode ser gerada sem destinatário
            if nota_fiscal.modelo == 65:
                pass
            else:
                raise e
        # Retirada
        if nota_fiscal.retirada:
            raiz.append(
                self._serializar_entrega_retirada(
                    nota_fiscal.retirada,
                    retorna_string=False,
                    tag_raiz='retirada',
                ))

        # Entrega
        if nota_fiscal.entrega:
            raiz.append(
                self._serializar_entrega_retirada(
                    nota_fiscal.entrega,
                    retorna_string=False,
                    tag_raiz='entrega',
                ))

        # Itens
        for num, item in enumerate(nota_fiscal.produtos_e_servicos):
            det = self._serializar_produto_servico(item,
                                                   modelo=nota_fiscal.modelo,
                                                   retorna_string=False)
            det.attrib['nItem'] = str(num + 1)

            raiz.append(det)

        # Totais
        total = etree.SubElement(raiz, 'total')
        icms_total = etree.SubElement(total, 'ICMSTot')
        #etree.SubElement(icms_total, 'vBC').text = str(nota_fiscal.totais_icms_base_calculo)
        etree.SubElement(icms_total, 'vBC').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_base_calculo)
        etree.SubElement(icms_total, 'vICMS').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_total)
        etree.SubElement(icms_total, 'vICMSDeson').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_desonerado
        )  # Valor Total do ICMS desonerado
        etree.SubElement(icms_total, 'vBCST').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_st_base_calculo)
        etree.SubElement(icms_total, 'vST').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_st_total)
        etree.SubElement(icms_total, 'vProd').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_total_produtos_e_servicos)
        etree.SubElement(icms_total, 'vFrete').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_total_frete)
        etree.SubElement(icms_total, 'vSeg').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_total_seguro)
        etree.SubElement(icms_total, 'vDesc').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_total_desconto)

        # Tributos
        etree.SubElement(icms_total, 'vII').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_total_ii)
        etree.SubElement(icms_total, 'vIPI').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_total_ipi)
        etree.SubElement(icms_total, 'vPIS').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_pis)
        etree.SubElement(icms_total, 'vCOFINS').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_cofins)

        etree.SubElement(icms_total, 'vOutro').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_outras_despesas_acessorias)
        etree.SubElement(icms_total, 'vNF').text = str('{:.2f}').format(
            nota_fiscal.totais_icms_total_nota)
        if nota_fiscal.totais_tributos_aproximado:
            etree.SubElement(icms_total,
                             'vTotTrib').text = str('{:.2f}').format(
                                 nota_fiscal.totais_tributos_aproximado)

        # 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(
                        nota_fiscal.transporte_transportadora,
                        retorna_string=False,
                    ))
                # Veículo
                veiculo = etree.SubElement(transp, 'veicTransp')
                etree.SubElement(
                    veiculo, 'placa'
                ).text = nota_fiscal.transporte_veiculo_placa  # Obrigatório EX: XXX9999
                etree.SubElement(veiculo,
                                 'UF').text = nota_fiscal.transporte_veiculo_uf
                etree.SubElement(
                    veiculo, 'RNTC').text = nota_fiscal.transporte_veiculo_rntc

                # Reboque
                reboque = etree.SubElement(transp, 'reboque')
                etree.SubElement(
                    reboque,
                    'placa').text = nota_fiscal.transporte_reboque_placa
                etree.SubElement(reboque,
                                 'UF').text = nota_fiscal.transporte_reboque_uf
                etree.SubElement(
                    reboque, 'RNTC').text = nota_fiscal.transporte_reboque_rntc

                # Volumes
                for volume in nota_fiscal.transporte_volumes:
                    vol = etree.SubElement(transp, 'vol')
                    etree.SubElement(vol, 'qVol').text = str(volume.quantidade)
                    etree.SubElement(vol, 'esp').text = volume.especie
                    etree.SubElement(vol, 'marca').text = volume.marca
                    etree.SubElement(vol, 'nVol').text = volume.numeracao
                    etree.SubElement(vol,
                                     'pesoL').text = str(volume.peso_liquido)
                    etree.SubElement(vol,
                                     'pesoB').text = str(volume.peso_bruto)

                    # Lacres
                    lacres = etree.SubElement(vol, 'lacres')
                    for lacre in volume.lacres:
                        etree.SubElement(lacres,
                                         'nLacre').text = lacre.numero_lacre

        # Somente NFC-e
        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 = str('{:.2f}').format(
                nota_fiscal.totais_icms_total_nota)
            #etree.SubElement(pag, 'card').text = ''
            #etree.SubElement(pag, 'CNPJ').text = '' # Informar o CNPJ da Credenciadora de cartão de crédito / débito
            #etree.SubElement(pag, 'tBand').text = '' # 01=Visa 02=Mastercard 03=American Express 04=Sorocred 99=Outros
            #etree.SubElement(pag, '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

        # Informações adicionais
        if nota_fiscal.informacoes_adicionais_interesse_fisco or nota_fiscal.informacoes_complementares_interesse_contribuinte:
            info_ad = etree.SubElement(raiz, 'infAdic')
            if nota_fiscal.informacoes_adicionais_interesse_fisco:
                etree.SubElement(
                    info_ad, 'infAdFisco'
                ).text = nota_fiscal.informacoes_adicionais_interesse_fisco
            if nota_fiscal.informacoes_complementares_interesse_contribuinte:
                etree.SubElement(
                    info_ad, 'infCpl'
                ).text = nota_fiscal.informacoes_complementares_interesse_contribuinte

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemple #39
0
f.close()
#a1 = AssinaturaA1(certificado, "1234")
#xml = a1.assinar(xml)
res = post(xml, url)
f = open("file.txt", "w")
a = str(res.content)
f.write(a)
f.close()
print(a)
'''

#'''
certificado_a1 = CertificadoA1(certificado)
chave, cert = certificado_a1.separar_arquivo(senha, caminho=True)
chave_cert = (cert, chave)
f = open("xmlfuncional.xml", "r")
a1 = AssinaturaA1(certificado, senha)
xml = etree.XML(f.read())
xml = a1.assinar(xml)
print(etree.tostring(xml))
#a1 = AssinaturaA1(certificado, "1234")
#xml = a1.assinar(xml)
#print(etree.tostring(xml))
res = mdfe.post(xml, url, chave_cert)
f = open("file.txt", "w")
a = str(res.content)
f.write(a)
f.close()
print(a)

#'''
Exemple #40
0
    def _serializar_cliente(self,
                            cliente,
                            modelo,
                            tag_raiz='dest',
                            retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Dados do cliente (distinatario)
        etree.SubElement(raiz, cliente.tipo_documento).text = so_numeros(
            cliente.numero_documento)
        if cliente.razao_social:
            etree.SubElement(raiz, 'xNome').text = cliente.razao_social
        if not self._so_cpf:
            endereco = etree.SubElement(raiz, 'enderDest')
            etree.SubElement(endereco,
                             'xLgr').text = cliente.endereco_logradouro
            etree.SubElement(endereco, 'nro').text = cliente.endereco_numero
            if cliente.endereco_complemento:
                etree.SubElement(endereco,
                                 'xCpl').text = cliente.endereco_complemento
            etree.SubElement(endereco,
                             'xBairro').text = cliente.endereco_bairro
            etree.SubElement(endereco,
                             'cMun').text = obter_codigo_por_municipio(
                                 cliente.endereco_municipio,
                                 cliente.endereco_uf)
            etree.SubElement(endereco,
                             'xMun').text = cliente.endereco_municipio
            etree.SubElement(endereco, 'UF').text = cliente.endereco_uf
            etree.SubElement(endereco,
                             'CEP').text = so_numeros(cliente.endereco_cep)
            etree.SubElement(endereco, 'cPais').text = cliente.endereco_pais
            etree.SubElement(endereco, 'xPais').text = obter_pais_por_codigo(
                cliente.endereco_pais)
            if cliente.endereco_telefone:
                etree.SubElement(endereco,
                                 'fone').text = cliente.endereco_telefone
        #Indicador da IE do destinatário: 1 – Contribuinte ICMSpagamento à vista; 2 – Contribuinte isento de inscrição; 9 – Não Contribuinte
        if cliente.isento_icms or cliente.inscricao_estadual.upper(
        ) == 'ISENTO':
            etree.SubElement(raiz, 'indIEDest').text = str(2)
            etree.SubElement(raiz, 'IE').text = 'ISENTO'
        elif cliente.indicador_ie == 9:
            # 9 – Não Contribuinte
            etree.SubElement(raiz, 'indIEDest').text = str(9)
        else:
            # Indicador da IE do destinatário: 1 – Contribuinte ICMSpagamento à vista;
            etree.SubElement(raiz, 'indIEDest').text = cliente.indicador_ie
            etree.SubElement(raiz, 'IE').text = cliente.inscricao_estadual
        # Suframa
        if cliente.inscricao_suframa:
            etree.SubElement(raiz, 'ISUF').text = cliente.inscricao_suframa
        # Inscrição Municipal do tomador do serviço
        if cliente.inscricao_municipal:
            etree.SubElement(raiz, 'IM').text = cliente.inscricao_municipal
        # E-mail
        if cliente.email:
            etree.SubElement(raiz, 'email').text = cliente.email
        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemple #41
0
    def assinarConsulta(self, xml, retorna_string=True):
        try:
            xml = etree.fromstring(xml)
            # No raiz do XML de saida
            tag = 'ns1:ConsultarNfseEnvio'  # tag que será assinada
            raiz = etree.Element('Signature',
                                 xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(
                siginfo,
                'CanonicalizationMethod',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                siginfo,
                'SignatureMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Consulta nao tem id
            ref = etree.SubElement(siginfo, 'Reference', URI='')

            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm=
                'http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                ref,
                'DigestMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            consulta = xml.xpath(
                '/ns1:ConsultarNfseEnvio',
                namespaces={
                    'ns1':
                    'http://www.ginfes.com.br/servico_consultar_nfse_envio_v03.xsd',
                    'ns2': 'http://www.ginfes.com.br/tipos_v03.xsd'
                })[0]
            consulta.append(raiz)

            # Escreve no arquivo depois de remover caracteres especiais e parse string
            with open('nfse.xml', 'w') as arquivo:
                arquivo.write(
                    remover_acentos(
                        etree.tostring(xml,
                                       encoding="unicode",
                                       pretty_print=False).replace('\n', '')))

            subprocess.check_call([
                'xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd',
                self.senha, '--crypto', 'openssl', '--output', 'funfa.xml',
                '--id-attr:Id', tag, 'nfse.xml'
            ])
            xml = etree.parse('funfa.xml').getroot()

            if retorna_string:
                return etree.tostring(xml,
                                      encoding="unicode",
                                      pretty_print=False)
            else:
                return xml
        except Exception as e:
            raise e
Exemple #42
0
    def gerar_qrcode(self, token, csc, xml, return_qr=False):
        """ Classe para gerar url do qrcode da NFC-e """
        # Procura atributos no xml
        ns = {'ns':'http://www.portalfiscal.inf.br/nfe'}
        sig = {'sig':'http://www.w3.org/2000/09/xmldsig#'}
        # Tag Raiz NFe Ex: <NFe>
        nfe = xml
        chave = nfe[0].attrib['Id'].replace('NFe','')
        data = nfe.xpath('ns:infNFe/ns:ide/ns:dhEmi/text()', namespaces=ns)[0].encode()
        tpamb = nfe.xpath('ns:infNFe/ns:ide/ns:tpAmb/text()', namespaces=ns)[0]
        cuf = nfe.xpath('ns:infNFe/ns:ide/ns:cUF/text()', namespaces=ns)[0]
        uf = [key for key, value in CODIGOS_ESTADOS.items() if value == cuf][0]

        # tenta encontrar a tag cpf
        try:
            cpf = nfe.xpath('ns:infNFe/ns:dest/ns:CPF/text()', namespaces=ns)[0]
        except IndexError:
            # em caso de erro tenta procurar a tag cnpj
            try:
                cpf = nfe.xpath('ns:infNFe/ns:dest/ns:CNPJ/text()', namespaces=ns)[0]
            except IndexError:
                cpf = None
        total = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vNF/text()', namespaces=ns)[0]
        icms = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vICMS/text()', namespaces=ns)[0]
        digest = nfe.xpath('sig:Signature/sig:SignedInfo/sig:Reference/sig:DigestValue/text()', namespaces=sig)[0].encode()

        data = base64.b16encode(data).decode()
        digest = base64.b16encode(digest).decode()

        if cpf is None:
            url = 'chNFe={}&nVersao={}&tpAmb={}&dhEmi={}&vNF={}&vICMS={}&digVal={}&cIdToken={}'.format(
                   chave, VERSAO_QRCODE, tpamb, data.lower(), total, icms, digest.lower(), token)
        else:
            url = 'chNFe={}&nVersao={}&tpAmb={}&cDest={}&dhEmi={}&vNF={}&vICMS={}&digVal={}&cIdToken={}'.format(
                   chave, VERSAO_QRCODE, tpamb, cpf, data.lower(), total, icms, digest.lower(), token)

        url_hash = hashlib.sha1(url.encode()+csc.encode()).digest()
        url_hash = base64.b16encode(url_hash).decode()

        url = url + '&cHashQRCode=' + url_hash.upper()

        # 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 = '<![CDATA['+ qrcode.strip() + ']]>'
        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')
        etree.tostring(nfe.find(".//qrCode"), encoding='unicode') \
            .replace('\n','').replace('&lt;','<').replace('&gt;','>').replace('amp;','')
        nfe = etree.fromstring(tnfe)
        # retorna nfe com o qrcode incluido NT2015/002 e qrcode
        if return_qr:
            return nfe, qrcode.strip()
        # retorna apenas nfe com o qrcode incluido NT2015/002
        else:
            return nfe
Exemple #43
0
    def _serializar_produto_servico(self, produto_servico, modelo, tag_raiz='det', retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Produto
        prod = etree.SubElement(raiz, 'prod')
        etree.SubElement(prod, 'cProd').text = str(produto_servico.codigo)
        etree.SubElement(prod, 'cEAN').text = produto_servico.ean
        etree.SubElement(prod, 'xProd').text = produto_servico.descricao
        etree.SubElement(prod, 'NCM').text = produto_servico.ncm
        # Codificação opcional que detalha alguns NCM. Formato: duas letras maiúsculas e 4 algarismos.
        # Se a mercadoria se enquadrar em mais de uma codificação, informar até 8 codificações principais.
        #etree.SubElement(prod, 'NVE').text = ''
        etree.SubElement(prod, 'CFOP').text = produto_servico.cfop
        etree.SubElement(prod, 'uCom').text = produto_servico.unidade_comercial
        etree.SubElement(prod, 'qCom').text = str(produto_servico.quantidade_comercial or 0)
        etree.SubElement(prod, 'vUnCom').text = str('{:.4f}').format(produto_servico.valor_unitario_comercial or 0)
        """ Código Especificador da Substituição Tributária – CEST, que estabelece a sistemática de uniformização e identificação das mercadorias e bens passíveis de
        sujeição aos regimes de substituição tributária e de antecipação de recolhimento do ICMS. """
        #if produto_servico.cest:
        #    etree.SubElement(prod, 'CEST').text = produto_servico.cest
        etree.SubElement(prod, 'vProd').text = str('{:.2f}').format(produto_servico.valor_total_bruto or 0)
        etree.SubElement(prod, 'cEANTrib').text = produto_servico.ean_tributavel
        etree.SubElement(prod, 'uTrib').text = produto_servico.unidade_tributavel
        etree.SubElement(prod, 'qTrib').text = str(produto_servico.quantidade_tributavel)
        etree.SubElement(prod, 'vUnTrib').text = '{:.4f}'.format(produto_servico.valor_unitario_tributavel or 0)
        """ Indica se valor do Item (vProd) entra no valor total da NF-e (vProd)
            0=Valor do item (vProd) não compõe o valor total da NF-e
            1=Valor do item (vProd) compõe o valor total da NF-e (vProd) (v2.0)
        """
        etree.SubElement(prod, 'indTot').text = str(produto_servico.ind_total)

        """ Informação de interesse do emissor para controle do B2B.(v2.0) """
        # Número do Pedido de Compra. Tam 1-15
        if produto_servico.numero_pedido:
            etree.SubElement(prod, 'xPed').text = str(produto_servico.numero_pedido)
        # Item do Pedido de Compra. Tam 6
        if produto_servico.numero_item:
            etree.SubElement(prod, 'nItemPed').text = str(produto_servico.numero_item)

        # Imposto
        imposto = etree.SubElement(raiz, 'imposto')

        # Lei da transparencia
        # Tributos aprox por item
        if produto_servico.valor_tributos_aprox:
            etree.SubElement(imposto, 'vTotTrib').text = produto_servico.valor_tributos_aprox

        ### ICMS
        icms = etree.SubElement(imposto, 'ICMS')
        icms_csosn = ('102', '103', '300', '400')
        if produto_servico.icms_modalidade in icms_csosn:
            icms_item = etree.SubElement(icms, 'ICMSSN'+produto_servico.icms_modalidade)
            etree.SubElement(icms_item, 'orig').text = str(produto_servico.icms_origem)
            etree.SubElement(icms_item, 'CSOSN').text = produto_servico.icms_csosn
        elif produto_servico.icms_modalidade == '101':
            icms_item = etree.SubElement(icms, 'ICMSSN'+produto_servico.icms_modalidade)
            etree.SubElement(icms_item, 'orig').text = str(produto_servico.icms_origem)
            etree.SubElement(icms_item, 'CSOSN').text = produto_servico.icms_csosn
            etree.SubElement(icms_item, 'pCredSN').text = str(produto_servico.icms_aliquota)       # Alíquota aplicável de cálculo do crédito (Simples Nacional).
            etree.SubElement(icms_item, 'vCredICMSSN').text = str(produto_servico.icms_credito)    # Valor crédito do ICMS que pode ser aproveitado nos termos do art. 23 da LC 123 (Simples Nacional)
        elif produto_servico.icms_modalidade == 'ST':
            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 = '41'          # Nao tributado
            etree.SubElement(icms_item, 'vBCSTRet').text = ''       # Informar o valor da BC do ICMS ST retido na UF remetente
            etree.SubElement(icms_item, 'vICMSSTRet').text = ''     # Informar o valor do ICMS ST retido na UF remetente
            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:
            ### 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)
            # 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
        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')
                etree.SubElement(pis_item, 'CST').text = produto_servico.pis_modalidade
            elif produto_servico.pis_modalidade == '01' or produto_servico.pis_modalidade == '02':
                pis_item = etree.SubElement(pis, 'PISAliq')
                etree.SubElement(pis_item, 'CST').text = produto_servico.pis_modalidade
                etree.SubElement(pis_item, 'vBC').text = produto_servico.pis_valor_base_calculo
                etree.SubElement(pis_item, 'pPIS').text = produto_servico.pis_aliquota_percentual
                etree.SubElement(pis_item, 'vPIS').text = produto_servico.pis_valor
            elif produto_servico.pis_modalidade == '03':
                pis_item = etree.SubElement(pis, 'PISQtde')
                etree.SubElement(pis_item, 'CST').text = produto_servico.pis_modalidade
                etree.SubElement(pis_item, 'qBCProd').text = produto_servico.quantidade_comercial
                etree.SubElement(pis_item, 'vAliqProd').text = produto_servico.pis_aliquota_percentual
                etree.SubElement(pis_item, 'vPIS').text = produto_servico.pis_valor_base_calculo
            else:
                pis_item = etree.SubElement(pis, 'PISOutr')
                etree.SubElement(pis_item, 'CST').text = produto_servico.pis_modalidade
                etree.SubElement(pis_item, 'vBC').text = produto_servico.pis_valor_base_calculo
                etree.SubElement(pis_item, 'pPIS').text = produto_servico.pis_aliquota_percentual
                if produto_servico.pis_modalidade is not '99':
                    etree.SubElement(pis_item, 'qBCProd').text = produto_servico.quantidade_comercial
                    etree.SubElement(pis_item, 'vAliqProd').text = produto_servico.pis_aliquota_percentual
                etree.SubElement(pis_item, 'vPIS').text = produto_servico.pis_valor_base_calculo

                ## PISST
                # pis_item = etree.SubElement(pis, 'PISST')
                # etree.SubElement(pis_item, 'vBC').text = produto_servico.pis_valor_base_calculo
                # etree.SubElement(pis_item, 'pPIS').text = produto_servico.pis_aliquota_percentual
                # etree.SubElement(pis_item, 'qBCProd').text = produto_servico.quantidade_comercial
                # etree.SubElement(pis_item, 'vAliqProd').text = produto_servico.pis_aliquota_percentual
                # etree.SubElement(pis_item, 'vPIS').text = produto_servico.pis_valor_base_calculo

            cofinsnt = ('04','05','06','07','08','09')
            ## COFINS
            cofins = etree.SubElement(imposto, 'COFINS')
            if produto_servico.cofins_modalidade in cofinsnt:
                cofins_item = etree.SubElement(cofins, 'COFINSNT')
                etree.SubElement(cofins_item, 'CST').text = produto_servico.cofins_modalidade
            elif produto_servico.cofins_modalidade == '01' or produto_servico.cofins_modalidade == '02':
                cofins_item = etree.SubElement(cofins, 'COFINSAliq')
                etree.SubElement(cofins_item, 'CST').text = produto_servico.cofins_modalidade
                etree.SubElement(cofins_item, 'vBC').text = produto_servico.cofins_valor_base_calculo
                etree.SubElement(cofins_item, 'pCOFINS').text = produto_servico.cofins_aliquota_percentual
                etree.SubElement(cofins_item, 'vCOFINS').text = produto_servico.cofins_valor
            elif produto_servico.cofins_modalidade == '03':
                cofins_item = etree.SubElement(cofins, 'COFINSQtde')
                etree.SubElement(cofins_item, 'CST').text = produto_servico.cofins_modalidade
                etree.SubElement(cofins_item, 'qBCProd').text = produto_servico.quantidade_comercial
                etree.SubElement(cofins_item, 'vAliqProd').text = produto_servico.cofins_aliquota_percentual
                etree.SubElement(cofins_item, 'vCOFINS').text = produto_servico.cofins_valor
            else:
                cofins_item = etree.SubElement(cofins, 'COFINSOutr')
                etree.SubElement(cofins_item, 'CST').text = produto_servico.cofins_modalidade
                etree.SubElement(cofins_item, 'vBC').text = produto_servico.cofins_valor_base_calculo
                etree.SubElement(cofins_item, 'pCOFINS').text = produto_servico.cofins_aliquota_percentual
                if produto_servico.cofins_modalidade is not '99':
                    etree.SubElement(cofins_item, 'vAliqProd').text = produto_servico.cofins_aliquota_percentual
                etree.SubElement(cofins_item, 'vCOFINS').text = produto_servico.cofins_valor

                ## COFINSST
                # cofins_item = etree.SubElement(cofins, 'COFINSOutr')
                # etree.SubElement(cofins_item, 'vBC').text = produto_servico.cofins_valor_base_calculo
                # etree.SubElement(cofins_item, 'pCOFINS').text = produto_servico.cofins_aliquota_percentual
                # etree.SubElement(cofins_item, 'qBCProd').text = produto_servico.quantidade_comercial
                # etree.SubElement(cofins_item, 'vAliqProd').text = produto_servico.cofins_aliquota_percentual
                # etree.SubElement(cofins_item, 'vCOFINS').text = produto_servico.cofins_valor

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemple #44
0
    def _serializar_nota_fiscal(self, nota_fiscal, tag_raiz='infNFe', retorna_string=True):
        raiz = etree.Element(tag_raiz, versao=self._versao)

        # 'Id' da tag raiz
        # Ex.: NFe35080599999090910270550010000000011518005123
        raiz.attrib['Id'] = nota_fiscal.identificador_unico

        tz = datetime.now().astimezone().strftime('%z')
        tz = "{}:{}".format(tz[:-2], tz[-2:])

        # Dados da Nota Fiscal
        ide = etree.SubElement(raiz, 'ide')
        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, 'mod').text = str(nota_fiscal.modelo)
        etree.SubElement(ide, 'serie').text = nota_fiscal.serie
        etree.SubElement(ide, 'nNF').text = str(nota_fiscal.numero_nf)
        etree.SubElement(ide, 'dhEmi').text = nota_fiscal.data_emissao.strftime('%Y-%m-%dT%H:%M:%S') + tz
        """dhCont Data e Hora da entrada em contingência E B01 D 0-1 Formato AAAA-MM-DDThh:mm:ssTZD (UTC - Universal
            Coordinated Time)
            Exemplo: no formato UTC para os campos de Data-Hora, "TZD" pode ser -02:00 (Fernando de Noronha), -03:00 (Brasília) ou -04:00 (Manaus), no
            horário de verão serão -01:00, -02:00 e -03:00. Exemplo: "2010-08-19T13:00:15-03:00".
        """
        etree.SubElement(ide, 'tpNF').text = str(nota_fiscal.tipo_documento)  # 0=entrada 1=saida
        """ nfce suporta apenas operação interna
            Identificador de local de destino da operação 1=Operação interna;2=Operação interestadual;3=Operação com exterior.
        """
        if nota_fiscal.modelo == 65:
            etree.SubElement(ide, 'idDest').text = str(1)
        else:
            etree.SubElement(ide, 'idDest').text = str(nota_fiscal.indicador_destino)
        etree.SubElement(ide, 'cMunFG').text = nota_fiscal.municipio
        etree.SubElement(ide, 'tpImp').text = str(nota_fiscal.tipo_impressao_danfe)
        """ ### CONTINGENCIA ###
            1=Emissão normal (não em contingência);
            2=Contingência FS-IA, com impressão do DANFE em formulário de segurança;
            3=Contingência SCAN (Sistema de Contingência do Ambiente Nacional);
            4=Contingência DPEC (Declaração Prévia da Emissão em Contingência);
            5=Contingência FS-DA, com impressão do DANFE em formulário de segurança;
            6=Contingência SVC-AN (SEFAZ Virtual de Contingência do AN);
            7=Contingência SVC-RS (SEFAZ Virtual de Contingência do RS);
            9=Contingência off-line da NFC-e (as demais opções de contingência são válidas também para a NFC-e).
            Para a NFC-e somente estão disponíveis e são válidas as opções de contingência 5 e 9.
        """
        if self._contingencia != None:
            if nota_fiscal.forma_emissao == '1':
                nota_fiscal.forma_emissao = '9'
        etree.SubElement(ide, 'tpEmis').text = str(nota_fiscal.forma_emissao)
        etree.SubElement(ide, 'cDV').text = nota_fiscal.dv_codigo_numerico_aleatorio
        etree.SubElement(ide, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(ide, 'finNFe').text = str(nota_fiscal.finalidade_emissao)
        if nota_fiscal.modelo == 65:
            etree.SubElement(ide, 'indFinal').text = str(1)
            etree.SubElement(ide, 'indPres').text = str(1)
        else:
            etree.SubElement(ide, 'indFinal').text = str(nota_fiscal.cliente_final)
            etree.SubElement(ide, 'indPres').text = str(nota_fiscal.indicador_presencial)
        etree.SubElement(ide, 'procEmi').text = str(nota_fiscal.processo_emissao)
        etree.SubElement(ide, 'verProc').text = '%s %s'%(self._nome_aplicacao, nota_fiscal.versao_processo_emissao)

        ### NF-e referenciada (utilizado em casos de devolução/garantia) ###
        # Apenas NF-e
        if nota_fiscal.modelo == 55:
            if nota_fiscal.notas_fiscais_referenciadas:
                nfref = etree.SubElement(ide, 'NFref')
                for refNFe in nota_fiscal.notas_fiscais_referenciadas:
                    etree.SubElement(nfref, 'refNFe').text = refNFe.chave_acesso

        ### CONTINGENCIA ###
        if self._contingencia != None:
            etree.SubElement(ide, 'dhCont').text = nota_fiscal.data_emissao.strftime('%Y-%m-%dT%H:%M:%S') + tz # Data e Hora da entrada em contingência AAAA-MM-DDThh:mm:ssTZD
            etree.SubElement(ide, 'xJust').text = nota_fiscal.self._contingencia  # Justificativa da entrada em contingência (min 20, max 256 caracteres)

        # Emitente
        raiz.append(self._serializar_emitente(nota_fiscal.emitente, retorna_string=False))

        # Destinatário
        try:
            raiz.append(self._serializar_cliente(nota_fiscal.cliente, modelo=nota_fiscal.modelo, retorna_string=False))
        except AttributeError as e:
            # NFC-e pode ser gerada sem destinatário
            if nota_fiscal.modelo == 65:
                pass
            else:
                raise e
        # Retirada
        if nota_fiscal.retirada:
            raiz.append(self._serializar_entrega_retirada(
                nota_fiscal.retirada,
                retorna_string=False,
                tag_raiz='retirada',
                ))

        # Entrega
        if nota_fiscal.entrega:
            raiz.append(self._serializar_entrega_retirada(
                nota_fiscal.entrega,
                retorna_string=False,
                tag_raiz='entrega',
                ))

        # Itens
        for num, item in enumerate(nota_fiscal.produtos_e_servicos):
            det = self._serializar_produto_servico(item, modelo=nota_fiscal.modelo, retorna_string=False)
            det.attrib['nItem'] = str(num+1)

            raiz.append(det)

        # Totais
        total = etree.SubElement(raiz, 'total')
        icms_total = etree.SubElement(total, 'ICMSTot')
        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_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, 'vFCP').text = '{:.2f}'.format(nota_fiscal.totais_fcp)
        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)
        etree.SubElement(icms_total, 'vDesc').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_desconto)

        # 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)

        etree.SubElement(icms_total, 'vOutro').text = '{:.2f}'.format(nota_fiscal.totais_icms_outras_despesas_acessorias)
        etree.SubElement(icms_total, 'vNF').text = str(nota_fiscal.totais_icms_total_nota)
        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:
            # Transportadora
            if nota_fiscal.transporte_transportadora:
                transp.append(self._serializar_transportadora(
                    nota_fiscal.transporte_transportadora,
                    retorna_string=False,
                    ))

            # Veículo
            if nota_fiscal.transporte_veiculo_placa and nota_fiscal.transporte_veiculo_uf:
                veiculo = etree.SubElement(transp, 'veicTransp')
                etree.SubElement(veiculo, 'placa').text = nota_fiscal.transporte_veiculo_placa # Obrigatório EX: XXX9999
                etree.SubElement(veiculo, 'UF').text = nota_fiscal.transporte_veiculo_uf
                # Registro Nacional de Transportador de Carga (ANTT)
                if nota_fiscal.transporte_veiculo_rntc:
                    etree.SubElement(veiculo, 'RNTC').text = nota_fiscal.transporte_veiculo_rntc

            # Reboque
            if nota_fiscal.transporte_reboque_placa and nota_fiscal.transporte_reboque_uf:
                reboque = etree.SubElement(transp, 'reboque')
                etree.SubElement(reboque, 'placa').text = nota_fiscal.transporte_reboque_placa
                etree.SubElement(reboque, 'UF').text = nota_fiscal.transporte_reboque_uf
                # Registro Nacional de Transportador de Carga (ANTT)
                if nota_fiscal.transporte_reboque_rntc:
                    etree.SubElement(reboque, 'RNTC').text = nota_fiscal.transporte_reboque_rntc

            # Volumes
            if nota_fiscal.transporte_volumes:
                for volume in nota_fiscal.transporte_volumes:
                    vol = etree.SubElement(transp, 'vol')
                    if volume.quantidade:
                        etree.SubElement(vol, 'qVol').text = str(volume.quantidade)
                        etree.SubElement(vol, 'esp').text = volume.especie
                        if volume.marca:
                            etree.SubElement(vol, 'marca').text = volume.marca
                        if volume.numeracao:
                            etree.SubElement(vol, 'nVol').text = volume.numeracao
                        etree.SubElement(vol, 'pesoL').text = str(volume.peso_liquido)
                        etree.SubElement(vol, 'pesoB').text = str(volume.peso_bruto)

                        # Lacres
                        if volume.lacres:
                            lacres = etree.SubElement(vol, 'lacres')
                            for lacre in volume.lacres:
                                etree.SubElement(lacres, 'nLacre').text = lacre.numero_lacre

        # 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')
        if nota_fiscal.finalidade_emissao == '3' or nota_fiscal.finalidade_emissao == '4':
            etree.SubElement(detpag, 'tPag').text = '90'
            etree.SubElement(detpag, 'vPag').text = '{:.2f}'.format(0)
        else:
            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 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:
            info_ad = etree.SubElement(raiz, 'infAdic')
            if nota_fiscal.informacoes_adicionais_interesse_fisco:
                etree.SubElement(info_ad, 'infAdFisco').text = nota_fiscal.informacoes_adicionais_interesse_fisco
            if nota_fiscal.informacoes_complementares_interesse_contribuinte:
                etree.SubElement(info_ad, 'infCpl').text = nota_fiscal.informacoes_complementares_interesse_contribuinte

        # Responsavel Tecnico NT2018/003
        if nota_fiscal.responsavel_tecnico:
            raiz.append(self._serializar_responsavel_tecnico(
                nota_fiscal.responsavel_tecnico[0], retorna_string=False))


        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemple #45
0
    def gerar_qrcode(self, token, csc, xml, return_qr=False, online=True):
        """ Classe para gerar url do qrcode da NFC-e """
        # Procura atributos no xml
        ns = {'ns':NAMESPACE_NFE}
        sig = {'sig':NAMESPACE_SIG}
        # Tag Raiz NFe Ex: <NFe>
        nfe = xml
        chave = nfe[0].attrib['Id'].replace('NFe','')
        data = nfe.xpath('ns:infNFe/ns:ide/ns:dhEmi/text()', namespaces=ns)[0].encode()
        tpamb = nfe.xpath('ns:infNFe/ns:ide/ns:tpAmb/text()', namespaces=ns)[0]
        cuf = nfe.xpath('ns:infNFe/ns:ide/ns:cUF/text()', namespaces=ns)[0]
        uf = [key for key, value in CODIGOS_ESTADOS.items() if value == cuf][0]

        # tenta encontrar a tag cpf
        try:
            cpf = nfe.xpath('ns:infNFe/ns:dest/ns:CPF/text()', namespaces=ns)[0]
        except IndexError:
            # em caso de erro tenta procurar a tag cnpj
            try:
                cpf = nfe.xpath('ns:infNFe/ns:dest/ns:CNPJ/text()', namespaces=ns)[0]
            except IndexError:
                cpf = None
        total = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vNF/text()', namespaces=ns)[0]
        # icms = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vICMS/text()', namespaces=ns)[0]
        digest = nfe.xpath('sig:Signature/sig:SignedInfo/sig:Reference/sig:DigestValue/text()', namespaces=sig)[0].encode()

        lista_dia = re.findall("-\d{2}", str(data))
        dia = str(lista_dia[1])
        dia = dia[1:]
        replacements = {'0': ''}
        token = re.sub('([0])', lambda m: replacements[m.group()], token)

        #VERSAO_QRCODE =2
        if online:
            #versão online
            url = '{}|{}|{}|{}'.format(chave,VERSAO_QRCODE, tpamb, token)
        else:
            #versão offline
            digest = digest.lower()
            digest = digest.hex()

            url = '{}|{}|{}|{}|{}|{}|{}'.format(
                chave,VERSAO_QRCODE,tpamb,dia,total,digest,token
                )

        url_complementar = url + csc
        url_hash = hashlib.sha1(url_complementar.encode()).digest()
        url_hash = base64.b16encode(url_hash).decode()

        url = 'p={}|{}'.format(url, url_hash)

        # 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', 'DF']
        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']
            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']
        # BA tem comportamento distindo para qrcode e url
        elif uf.upper() == 'BA':
            if tpamb == '1':
                qrcode = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['QR'] + url
            else:
                qrcode = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['QR'] + url
            url_chave = url_chave = NFCE[uf.upper()]['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']
            else:
                qrcode = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['QR'] + url
                url_chave = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['URL']
        # adicionta tag infNFeSupl com qrcode
        info = etree.Element('infNFeSupl')
        etree.SubElement(info, 'qrCode').text = '<![CDATA['+ qrcode.strip() + ']]>'
        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')
        etree.tostring(nfe.find(".//qrCode"), encoding='unicode') \
            .replace('\n','').replace('&lt;','<').replace('&gt;','>').replace('amp;','')
        nfe = etree.fromstring(tnfe)
        # retorna nfe com o qrcode incluido NT2015/002 e qrcode
        if return_qr:
            return nfe, qrcode.strip()
        # retorna apenas nfe com o qrcode incluido NT2015/002
        else:
            return nfe
Exemple #46
0
    def assinarLote(self, xml, retorna_string=True):
        "Assina nfse e lote"
        try:
            xml = self.assinarNfse(xml, retorna_string=False)
            xpath = './/ns1:LoteRps'
            tag = 'LoteRps'
            # define namespaces, pega do proprio xml
            namespaces = xml.nsmap
            # No raiz do XML de saida
            raiz = etree.Element('Signature',
                                 xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(
                siginfo,
                'CanonicalizationMethod',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                siginfo,
                'SignatureMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Tenta achar a tag
            ref = etree.SubElement(
                siginfo,
                'Reference',
                URI='#' +
                xml.xpath(xpath, namespaces=namespaces)[0].attrib['Id'])
            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm=
                'http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                ref,
                'DigestMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            # posiciona tag Signature antes do LoteRps para assinar
            base = xml.xpath(xpath + '/..', namespaces=namespaces)[0]
            base.insert(0, raiz)

            # Escreve no arquivo depois de remover caracteres especiais
            with open('nfse.xml', 'w') as arquivo:
                texto = remover_acentos(
                    etree.tostring(xml, encoding="unicode",
                                   pretty_print=False))
                arquivo.write(texto)
            # assina lote
            subprocess.check_call([
                'xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd',
                self.senha, '--crypto', 'openssl', '--output', 'nfse.xml',
                '--id-attr:Id', tag, 'nfse.xml'
            ])

            # Reposiciona tag Signature apos LoteRps
            xml = etree.fromstring(open('nfse.xml', 'r').read())
            namespaces = xml.nsmap
            sig = xml.find('{http://www.w3.org/2000/09/xmldsig#}Signature')
            sig.getparent().remove(sig)
            xml.append(sig)

            if retorna_string:
                return etree.tostring(xml,
                                      encoding="unicode",
                                      pretty_print=False)
            else:
                return xml
        except Exception as e:
            raise e
Exemple #47
0
    def assinar(self, xml, retorna_string=False):
        try:
            # No raiz do XML de saida
            tag = 'infNFe'  # tag que será assinada
            raiz = etree.Element('Signature',
                                 xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(
                siginfo,
                'CanonicalizationMethod',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                siginfo,
                'SignatureMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Tenta achar a tag infNFe
            try:
                if len(xml.nsmap.items()) == 0:  # não tem namespace
                    ref = etree.SubElement(
                        siginfo,
                        'Reference',
                        URI='#' + xml.findall('infNFe')[0].attrib['Id'])
                else:
                    ns = {'ns': 'http://www.portalfiscal.inf.br/nfe'}
                    ref = etree.SubElement(
                        siginfo,
                        'Reference',
                        URI='#' + xml.findall('ns:infNFe',
                                              namespaces=ns)[0].attrib['Id'])
            # Caso nao tenha a tag infNFe, procura a tag infEvento
            except IndexError:
                try:
                    tag = 'infEvento'
                    ref = etree.SubElement(
                        siginfo,
                        'Reference',
                        URI='#' + xml.findall('infEvento')[0].attrib['Id'])
                # Caso nao tenha a tag infNFe, procura a tag inutNFe
                except IndexError:
                    tag = 'infInut'
                    ref = etree.SubElement(
                        siginfo,
                        'Reference',
                        URI='#' + xml.findall('infInut')[0].attrib['Id'])
            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm=
                'http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                ref,
                'DigestMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            xml.append(raiz)

            # Escreve no arquivo depois de remover caracteres especiais e parse string
            with open('testes.xml', 'w') as arquivo:
                arquivo.write(
                    remover_acentos(
                        etree.tostring(xml,
                                       encoding="unicode",
                                       pretty_print=False)))

            subprocess.check_call([
                'xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd',
                self.senha, '--crypto', 'openssl', '--output', 'funfa.xml',
                '--id-attr:Id', tag, 'testes.xml'
            ])
            xml = etree.parse('funfa.xml').getroot()

            if retorna_string:
                return etree.tostring(xml,
                                      encoding="unicode",
                                      pretty_print=False)
            else:
                return xml
        except Exception as e:
            raise e
Exemple #48
0
    def _serializar_notas_fiscal(self,
                                 nota_fiscal,
                                 tag_raiz='infNFe',
                                 retorna_string=True):
        raiz = etree.Element(tag_raiz, versao=self._versao)

        # Dados da Nota Fiscal
        ide = etree.SubElement(raiz, 'ide')
        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)
        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)
        etree.SubElement(
            ide, 'dEmi').text = nota_fiscal.data_emissao.strftime('%Y-%m-%d')
        etree.SubElement(
            ide, 'dSaiEnt').text = nota_fiscal.data_saida_entrada.strftime(
                '%Y-%m-%d')
        etree.SubElement(ide, 'tpNF').text = str(nota_fiscal.tipo_documento)
        etree.SubElement(ide, 'cMunFG').text = nota_fiscal.municipio
        etree.SubElement(ide,
                         'tpImp').text = str(nota_fiscal.tipo_impressao_danfe)
        etree.SubElement(ide, 'tpEmis').text = str(nota_fiscal.forma_emissao)
        etree.SubElement(ide,
                         'cDV').text = nota_fiscal.dv_codigo_numerico_aleatorio
        etree.SubElement(ide, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(ide,
                         'finNFe').text = str(nota_fiscal.finalidade_emissao)
        etree.SubElement(ide,
                         'procEmi').text = str(nota_fiscal.processo_emissao)
        etree.SubElement(
            ide,
            'verProc').text = '%s %s' % (self._nome_aplicacao,
                                         nota_fiscal.versao_processo_emissao)

        # Emitente
        raiz.append(
            self._serializar_emitente(nota_fiscal.emitente,
                                      retorna_string=False))

        # Destinatário
        raiz.append(
            self._serializar_cliente(nota_fiscal.cliente,
                                     retorna_string=False))

        # Retirada
        if nota_fiscal.retirada:
            raiz.append(
                self._serializar_entrega_retirada(
                    nota_fiscal.retirada,
                    retorna_string=False,
                    tag_raiz='retirada',
                ))

        # Entrega
        if nota_fiscal.entrega:
            raiz.append(
                self._serializar_entrega_retirada(
                    nota_fiscal.entrega,
                    retorna_string=False,
                    tag_raiz='entrega',
                ))

        # Itens
        for num, item in enumerate(nota_fiscal.produtos_e_servicos):
            det = self._serializar_produto_servico(item, retorna_string=False)
            det.attrib['nItem'] = str(num + 1)

            raiz.append(det)

        # Totais
        total = etree.SubElement(raiz, 'total')
        icms_total = etree.SubElement(total, 'ICMSTot')
        etree.SubElement(icms_total, 'vBC').text = str(
            nota_fiscal.totais_icms_base_calculo)
        etree.SubElement(icms_total,
                         'vICMS').text = str(nota_fiscal.totais_icms_total)
        etree.SubElement(icms_total, 'vBCST').text = str(
            nota_fiscal.totais_icms_st_base_calculo)
        etree.SubElement(icms_total,
                         'vST').text = str(nota_fiscal.totais_icms_st_total)
        etree.SubElement(icms_total, 'vProd').text = str(
            nota_fiscal.totais_icms_total_produtos_e_servicos)
        etree.SubElement(icms_total, 'vFrete').text = str(
            nota_fiscal.totais_icms_total_frete)
        etree.SubElement(icms_total, 'vSeg').text = str(
            nota_fiscal.totais_icms_total_seguro)
        etree.SubElement(icms_total, 'vDesc').text = str(
            nota_fiscal.totais_icms_total_desconto)
        etree.SubElement(icms_total,
                         'vII').text = str(nota_fiscal.totais_icms_total_ii)
        etree.SubElement(icms_total,
                         'vIPI').text = str(nota_fiscal.totais_icms_total_ipi)
        etree.SubElement(icms_total,
                         'vPIS').text = str(nota_fiscal.totais_icms_pis)
        etree.SubElement(icms_total,
                         'vCOFINS').text = str(nota_fiscal.totais_icms_cofins)
        etree.SubElement(icms_total, 'vOutro').text = str(
            nota_fiscal.totais_icms_outras_despesas_acessorias)
        etree.SubElement(icms_total,
                         'vNF').text = str(nota_fiscal.totais_icms_total_nota)

        # Transporte
        transp = etree.SubElement(raiz, 'transp')
        etree.SubElement(transp, 'modFrete').text = str(
            nota_fiscal.transporte_modalidade_frete)

        # Transportadora
        transp.append(
            self._serializar_transportadora(
                nota_fiscal.transporte_transportadora,
                retorna_string=False,
            ))

        # Veículo
        veiculo = etree.SubElement(transp, 'veicTransp')
        etree.SubElement(veiculo,
                         'placa').text = nota_fiscal.transporte_veiculo_placa
        etree.SubElement(veiculo,
                         'UF').text = nota_fiscal.transporte_veiculo_uf
        etree.SubElement(veiculo,
                         'RNTC').text = nota_fiscal.transporte_veiculo_rntc

        # Reboque
        reboque = etree.SubElement(transp, 'reboque')
        etree.SubElement(reboque,
                         'placa').text = nota_fiscal.transporte_reboque_placa
        etree.SubElement(reboque,
                         'UF').text = nota_fiscal.transporte_reboque_uf
        etree.SubElement(reboque,
                         'RNTC').text = nota_fiscal.transporte_reboque_rntc

        # Volumes
        for volume in nota_fiscal.transporte_volumes:
            vol = etree.SubElement(transp, 'vol')
            etree.SubElement(vol, 'qVol').text = str(volume.quantidade)
            etree.SubElement(vol, 'esp').text = volume.especie
            etree.SubElement(vol, 'marca').text = volume.marca
            etree.SubElement(vol, 'nVol').text = volume.numeracao
            etree.SubElement(vol, 'pesoL').text = str(volume.peso_liquido)
            etree.SubElement(vol, 'pesoB').text = str(volume.peso_bruto)

            # Lacres
            lacres = etree.SubElement(vol, 'lacres')
            for lacre in volume.lacres:
                etree.SubElement(lacres, 'nLacre').text = lacre.numero_lacre

        # Informações adicionais
        info_ad = etree.SubElement(raiz, 'infAdic')
        etree.SubElement(
            info_ad, 'infAdFisco'
        ).text = nota_fiscal.informacoes_adicionais_interesse_fisco
        etree.SubElement(
            info_ad, 'infCpl'
        ).text = nota_fiscal.informacoes_complementares_interesse_contribuinte

        # 'Id' da tag raiz
        # Ex.: NFe35080599999090910270550010000000011518005123
        raiz.attrib['Id'] = nota_fiscal.identificador_unico

        if retorna_string:
            return etree.tostring(raiz, pretty_print=True)
        else:
            return raiz
Exemple #49
0
    def assinarCancelar(self, xml, retorna_string=True):
        """ Método que assina o xml para cancelamento de NFS-e """
        try:
            if self.autorizador == 'ginfes':
                xpath = 'CancelarNfseEnvio'
                tag = 'CancelarNfseEnvio'
                namespaces = {
                    'ns1':
                    'http://www.ginfes.com.br/servico_cancelar_nfse_envio',
                    'ns2': 'http://www.ginfes.com.br/tipos'
                }
            elif self.autorizador == 'betha':
                xpath = '/CancelarNfseEnvio/ns1:Pedido'
                tag = 'InfPedidoCancelamento'
                namespaces = {
                    'ns1': 'http://www.betha.com.br/e-nota-contribuinte-ws'
                }
            else:
                raise Exception('Autorizador não encontrado!')

            xml = etree.fromstring(xml)
            # No raiz do XML de saida
            raiz = etree.Element('Signature',
                                 xmlns='http://www.w3.org/2000/09/xmldsig#')
            siginfo = etree.SubElement(raiz, 'SignedInfo')
            etree.SubElement(
                siginfo,
                'CanonicalizationMethod',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                siginfo,
                'SignatureMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
            # Tenta achar a tag informada no xpath
            if tag == 'InfPedidoCancelamento':
                ref = etree.SubElement(
                    siginfo,
                    'Reference',
                    URI='#' + xml.xpath('.//ns1:' + tag,
                                        namespaces=namespaces)[0].attrib['Id'])
            # ginfes não tem id no cancelamento v2
            else:
                ref = etree.SubElement(siginfo, 'Reference', URI='')
            trans = etree.SubElement(ref, 'Transforms')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm=
                'http://www.w3.org/2000/09/xmldsig#enveloped-signature')
            etree.SubElement(
                trans,
                'Transform',
                Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
            etree.SubElement(
                ref,
                'DigestMethod',
                Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
            etree.SubElement(ref, 'DigestValue')
            etree.SubElement(raiz, 'SignatureValue')
            keyinfo = etree.SubElement(raiz, 'KeyInfo')
            etree.SubElement(keyinfo, 'X509Data')

            if tag == 'InfPedidoCancelamento':
                xml = xml.xpath(xpath, namespaces=namespaces)[0]
            # ginfes só possui a tag root
            else:
                xml.append(raiz)

            # Escreve no arquivo depois de remover caracteres especiais e parse string
            with open('nfse.xml', 'w') as arquivo:
                arquivo.write(
                    remover_acentos(
                        etree.tostring(xml,
                                       encoding="unicode",
                                       pretty_print=False).replace('\n', '')))

            subprocess.check_call([
                'xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd',
                self.senha, '--crypto', 'openssl', '--output', 'funfa.xml',
                '--id-attr:Id', tag, 'nfse.xml'
            ])

            if retorna_string:
                return open('funfa.xml', 'r').read()
            else:
                return etree.parse('funfa.xml').getroot()
        except Exception as e:
            raise e