Compare commits
merge into: felipe:master
felipe:feature/betha
felipe:feature/cte
felipe:feature/nfe-4.0
felipe:feature/nfe-mde
felipe:feature/nota-dsf
felipe:fix-endereco
felipe:fix-invalid-token-bug
felipe:fix-url-df
felipe:fix/warning
felipe:iss-net
felipe:master
felipe:master3
felipe:merge-master3
pull from: felipe:feature/nota-dsf
felipe:feature/betha
felipe:feature/cte
felipe:feature/nfe-4.0
felipe:feature/nfe-mde
felipe:feature/nota-dsf
felipe:fix-endereco
felipe:fix-invalid-token-bug
felipe:fix-url-df
felipe:fix/warning
felipe:iss-net
felipe:master
felipe:master3
felipe:merge-master3
42 Commits
master
...
feature/no
101 changed files with 1969 additions and 1434 deletions
-
32.appveyor.yml
-
2.gitignore
-
10.travis.yml
-
15README.md
-
4pytrustnfe/Servidores.py
-
8pytrustnfe/__init__.py
-
13pytrustnfe/certificado.py
-
16pytrustnfe/client.py
-
126pytrustnfe/nfe/__init__.py
-
4pytrustnfe/nfe/assinatura.py
-
4pytrustnfe/nfe/comunicacao.py
-
26pytrustnfe/nfe/danfe.py
-
BINpytrustnfe/nfe/fonts/NimbusSanL Bold.ttf
-
BINpytrustnfe/nfe/fonts/NimbusSanL Regular.ttf
-
90pytrustnfe/nfse/assinatura.py
-
2pytrustnfe/nfse/betha/__init__.py
-
113pytrustnfe/nfse/dsf/__init__.py
-
18pytrustnfe/nfse/dsf/templates/cancelar.xml
-
11pytrustnfe/nfse/dsf/templates/consulta_notas.xml
-
10pytrustnfe/nfse/dsf/templates/consultarLote.xml
-
22pytrustnfe/nfse/dsf/templates/consultarNFSeRps.xml
-
108pytrustnfe/nfse/dsf/templates/enviar.xml
-
12pytrustnfe/nfse/dsf/templates/soap_header.xml
-
119pytrustnfe/nfse/floripa/__init__.py
-
7pytrustnfe/nfse/floripa/templates/cancelar_nota.xml
-
40pytrustnfe/nfse/floripa/templates/processar_nota.xml
-
2pytrustnfe/nfse/ginfes/__init__.py
-
9pytrustnfe/nfse/paulistana/__init__.py
-
2pytrustnfe/nfse/susesu/__init__.py
-
1pytrustnfe/test/XMLs/paulistana_resultado.xml
-
26pytrustnfe/xml/__init__.py
-
18pytrustnfe/xml/filters.py
-
0pytrustnfe/xml/schemas/enviNFe_v3.10.xsd
-
0pytrustnfe/xml/schemas/leiauteNFe_v3.10.xsd
-
0pytrustnfe/xml/schemas/nfe_v3.10.xsd
-
2pytrustnfe/xml/schemas/tiposBasico_v3.10.xsd
-
0pytrustnfe/xml/schemas/xmldsig-core-schema_v1.01.xsd
-
31pytrustnfe/xml/validate.py
-
22requirements.txt
-
24setup.py
-
0tests/XMLs/NFe00000857.xml
-
0tests/XMLs/jinja_remove_empty.xml
-
0tests/XMLs/jinja_result.xml
-
0tests/XMLs/jinja_template.xml
-
0tests/XMLs/paulistana_canc.xml
-
1tests/XMLs/paulistana_canc_errado.xml
-
1tests/XMLs/paulistana_canc_ok.xml
-
1tests/XMLs/paulistana_resultado.xml
-
16tests/XMLs/paulistana_signature.xml
-
0tests/XMLs/recibo_envio_1.xml
-
0tests/XMLs/recibo_envio_2.xml
-
0tests/XMLs/recibo_protocolo_sucesso_1.xml
-
0tests/XMLs/recibo_protocolo_sucesso_2.xml
-
0tests/__init__.py
-
6tests/test_add_qr_code.py
-
12tests/test_assinatura.py
-
8tests/test_certificado.py
-
0tests/test_comunicacao.py
-
2tests/test_consulta_cadastro.py
-
2tests/test_danfe.py
-
2tests/test_ginfes.py
-
8tests/test_nfse_paulistana.py
-
0tests/test_servidores.py
-
16tests/test_utils.py
-
4tests/test_xml.py
-
5tests/test_xml_serializacao.py
-
0tests/teste.pfx
-
0tests/xml_assinado.xml
-
6tests/xml_com_qrcode.xml
-
6tests/xml_sem_qrcode.xml
-
0tests/xml_valido_assinado.xml
@ -0,0 +1,32 @@ |
|||
version: 1.3.{build} |
|||
|
|||
environment: |
|||
matrix: |
|||
- python: 35 |
|||
- python: 35-x64 |
|||
- python: 36 |
|||
- python: 36-x64 |
|||
|
|||
install: |
|||
- SET PATH=C:\\Python%PYTHON%;c:\\Python%PYTHON%\\scripts;%PATH% |
|||
- python -m pip.__main__ install -U pip wheel setuptools |
|||
- pip install -r requirements.txt |
|||
|
|||
build: off |
|||
build_script: |
|||
# configure version |
|||
- ps: >- |
|||
If ($env:APPVEYOR_REPO_TAG -Eq "true" ) { |
|||
$version = "$env:APPVEYOR_REPO_TAG_NAME" |
|||
} Else { |
|||
$version = "$env:APPVEYOR_BUILD_VERSION.dev0" |
|||
} |
|||
$version | Set-Content version.txt |
|||
- python setup.py build bdist_wheel |
|||
- ps: Get-ChildItem dist\*.whl | % { pip install $_.FullName } |
|||
|
|||
test: off |
|||
test_script: |
|||
- pip list |
|||
- py.test -v tests |
|||
- ps: Get-ChildItem dist\*.whl | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } |
|||
@ -0,0 +1,113 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
# © 2017 Fábio Luna, Trustcode |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import os |
|||
import requests |
|||
from pytrustnfe.xml import render_xml, sanitize_response |
|||
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key |
|||
from pytrustnfe.nfse.assinatura import Assinatura |
|||
|
|||
|
|||
def _render(certificado, method, **kwargs): |
|||
path = os.path.join(os.path.dirname(__file__), 'templates') |
|||
if method == "testeEnviar": |
|||
xml_send = render_xml(path, 'enviar.xml', True, **kwargs) |
|||
else: |
|||
xml_send = render_xml(path, '%s.xml' % method, False, **kwargs) |
|||
|
|||
cert, key = extract_cert_and_key_from_pfx( |
|||
certificado.pfx, certificado.password) |
|||
cert, key = save_cert_key(cert, key) |
|||
signer = Assinatura(cert, key, certificado.password) |
|||
xml_send = signer.assina_xml(xml_send, '') |
|||
|
|||
return xml_send |
|||
|
|||
|
|||
def _get_url(**kwargs): |
|||
urls = { |
|||
# Belém - PA |
|||
'2715': 'http://www.issdigitalbel.com.br/WsNFe2/LoteRps.jws', |
|||
# Sorocaba - SP |
|||
'7145': 'http://issdigital.sorocaba.sp.gov.br/WsNFe2/LoteRps.jws', |
|||
# Teresina - PI |
|||
'1219': 'http://www.issdigitalthe.com.br/WsNFe2/LoteRps.jws', |
|||
# Campinas - SP |
|||
'6291': 'http://issdigital.campinas.sp.gov.br/WsNFe2/LoteRps.jws?wsdl', |
|||
# Uberlandia - MG |
|||
'5403': 'http://udigital.uberlandia.mg.gov.br/WsNFe2/LoteRps.jws', |
|||
# São Luis - MA |
|||
'0921': 'https://stm.semfaz.saoluis.ma.gov.br/WsNFe2/LoteRps?wsdl', |
|||
# Campo Grande - MS |
|||
'9051': 'http://issdigital.pmcg.ms.gov.br/WsNFe2/LoteRps.jws?wsdl', |
|||
} |
|||
return urls[kwargs['siafi_code']] |
|||
|
|||
|
|||
def _send(certificado, method, **kwargs): |
|||
url = _get_url(**kwargs) |
|||
|
|||
xml_send = '<?xml version="1.0" encoding="utf-8"?>' +\ |
|||
kwargs['xml'].decode('utf-8') |
|||
|
|||
response = False |
|||
soap = '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">'\ |
|||
'<Body>'\ |
|||
'<enviarSincrono xmlns="http://issdigital.pmcg.ms.gov.br/WsNFe2/LoteRps.jws">'\ |
|||
'<mensagemXml><![CDATA[' + xml_send + ']]></mensagemXml>'\ |
|||
'</enviarSincrono>'\ |
|||
'</Body>'\ |
|||
'</Envelope>' |
|||
|
|||
headers = { |
|||
"Content-Type": 'text/xml; charset="utf-8"', |
|||
"SOAPAction": "", |
|||
} |
|||
http_response = requests.post(url, data=soap, headers=headers) |
|||
response, obj = sanitize_response(http_response.text.encode('utf-8')) |
|||
|
|||
return { |
|||
'status_code': http_response.status_code, |
|||
'sent_xml': xml_send, |
|||
'received_xml': response, |
|||
'object': obj |
|||
} |
|||
|
|||
|
|||
def xml_enviar(certificado, **kwargs): |
|||
return _render(certificado, 'enviar', **kwargs) |
|||
|
|||
|
|||
def enviar(certificado, **kwargs): |
|||
if "xml" not in kwargs: |
|||
kwargs['xml'] = xml_enviar(certificado, **kwargs) |
|||
return _send(certificado, 'enviar', **kwargs) |
|||
|
|||
|
|||
def xml_teste_enviar(certificado, **kwargs): |
|||
return _render(certificado, 'testeEnviar', **kwargs) |
|||
|
|||
|
|||
def teste_enviar(certificado, **kwargs): |
|||
if "xml" not in kwargs: |
|||
kwargs['xml'] = xml_teste_enviar(certificado, **kwargs) |
|||
return _send(certificado, 'testeEnviar', **kwargs) |
|||
|
|||
|
|||
def cancelar(certificado, ** kwargs): |
|||
return _send(certificado, 'cancelar', **kwargs) |
|||
|
|||
|
|||
def consulta_lote(**kwargs): |
|||
return _send(False, 'consultarLote', **kwargs) |
|||
|
|||
|
|||
def xml_consultar_nfse_rps(certificado, **kwargs): |
|||
return _render(certificado, 'consultarNFSeRps', **kwargs) |
|||
|
|||
|
|||
def consultar_nfse_rps(certificado, **kwargs): |
|||
if "xml" not in kwargs: |
|||
kwargs['xml'] = xml_consultar_nfse_rps(certificado, **kwargs) |
|||
return _send(certificado, 'consultarNFSeRps', **kwargs) |
|||
@ -0,0 +1,18 @@ |
|||
<ns1:ReqCancelamentoNFSe xmlns:ns1="http://localhost:8080/WsNFe2/lote" |
|||
xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqCancelamentoNFSe.xsd"> |
|||
<Cabecalho> |
|||
<CodCidade>{{ cancelamento.cidade }}</CodCidade> |
|||
<CPFCNPJRemetente>{{ cancelamento.cpf_cnpj }}</CPFCNPJRemetente> |
|||
<transacao>true</transacao> |
|||
<Versao>1</Versao> |
|||
</Cabecalho> |
|||
<Lote Id="lote:1ABCDZ"> |
|||
<Nota Id="nota:{{ cancelamento.nota_id }}"> |
|||
<InscricaoMunicipalPrestador>{{ cancelamento.inscricao_municipal }}</InscricaoMunicipalPrestador> |
|||
<NumeroNota>{{ cancelamento.nota_id }}</NumeroNota> |
|||
<CodigoVerificacao>{{ cancelamento.assinatura }}</CodigoVerificacao> |
|||
<MotivoCancelamento>{{ cancelamento.motivo }}</MotivoCancelamento> |
|||
</Nota> |
|||
</Lote> |
|||
</ns1:ReqCancelamentoNFSe> |
|||
@ -0,0 +1,11 @@ |
|||
<ns1:ReqConsultaNotas xmlns:ns1="http://localhost:8080/WsNFe2/lote" xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqConsultaNotas.xsd"> |
|||
<Cabecalho Id="Consulta:notas"> |
|||
<CodCidade>{{ consulta.cidade }}</CodCidade> |
|||
<CPFCNPJRemetente>{{ consulta.cpf_cnpj }}</CPFCNPJRemetente> |
|||
<InscricaoMunicipalPrestador>{{ consulta.inscricao_municipal }}</InscricaoMunicipalPrestador> |
|||
<dtInicio>{{ consulta.data_inicio }}</dtInicio> |
|||
<dtFim>{{ consulta.data_final }}</dtFim> |
|||
<NotaInicial>{{ consulta.nota_inicial }}</NotaInicial> |
|||
<Versao>1</Versao> |
|||
</Cabecalho> |
|||
</ns1:ReqConsultaNotas> |
|||
@ -0,0 +1,10 @@ |
|||
<ns1:ReqConsultaLote xmlns:ns1="http://localhost:8080/WsNFe2/lote" |
|||
xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqConsultaLote.xsd"> |
|||
<Cabecalho> |
|||
<CodCidade>{{ consulta.cidade }}</CodCidade> |
|||
<CPFCNPJRemetente>{{ consulta.cpf_cnpj }}</CPFCNPJRemetente> |
|||
<Versao>1</Versao> |
|||
<NumeroLote>{{ consulta.lote }}</NumeroLote> |
|||
</Cabecalho> |
|||
</ns1:ReqConsultaLote> |
|||
@ -0,0 +1,22 @@ |
|||
<ns1:ReqConsultaNFSeRPS |
|||
xmlns:ns1="http://localhost:8080/WsNFe2/lote" |
|||
xmlns:tipos="http://localhost:8080/WsNFe2/tp" |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqConsultaNFSeRPS.xsd"> |
|||
<Cabecalho> |
|||
<CodCidade>{{ nfse.cidade }}</CodCidade> |
|||
<CPFCNPJRemetente>{{ nfse.cpf_cnpj }}</CPFCNPJRemetente> |
|||
<transacao>true</transacao> |
|||
<Versao>1</Versao> |
|||
</Cabecalho> |
|||
<Lote Id="lote:{{ nfse.lote }}"> |
|||
{% for rps in nfse.lista_rps -%} |
|||
<RPSConsulta> |
|||
<RPS Id="rps:{{ rps.numero }}"> |
|||
<InscricaoMunicipalPrestador>{{ rps.prestador.inscricao_municipal }}</InscricaoMunicipalPrestador> |
|||
<NumeroRPS>{{ rps.numero }}</NumeroRPS> |
|||
<SeriePrestacao>{{ rps.serie_prestacao }}</SeriePrestacao> |
|||
</RPS> |
|||
</RPSConsulta> |
|||
{% endfor %} |
|||
</Lote> |
|||
</ns1:ReqConsultaNFSeRPS> |
|||
@ -0,0 +1,108 @@ |
|||
<ns1:ReqEnvioLoteRPS xmlns:ns1="http://localhost:8080/WsNFe2/lote" |
|||
xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqEnvioLoteRPS.xsd"> |
|||
<Cabecalho> |
|||
<CodCidade>{{ nfse.cidade }}</CodCidade> |
|||
<CPFCNPJRemetente>{{ nfse.cpf_cnpj }}</CPFCNPJRemetente> |
|||
<RazaoSocialRemetente>{{ nfse.remetente }}</RazaoSocialRemetente> |
|||
<transacao>{{ nfse.transacao }}</transacao> |
|||
<dtInicio>{{ nfse.data_inicio|format_date }}</dtInicio> |
|||
<dtFim>{{ nfse.data_fim|format_date }}</dtFim> |
|||
<QtdRPS>{{ nfse.total_rps }}</QtdRPS> |
|||
<ValorTotalServicos>{{ nfse.total_servicos }}</ValorTotalServicos> |
|||
<ValorTotalDeducoes>{{ nfse.total_deducoes }}</ValorTotalDeducoes> |
|||
<Versao>1</Versao> |
|||
<MetodoEnvio>WS</MetodoEnvio> |
|||
</Cabecalho> |
|||
<Lote Id="{{ nfse.lote_id }}"> |
|||
{% for rps in nfse.lista_rps -%} |
|||
<RPS Id="{{ rps.numero }}"> |
|||
<Assinatura>{{ rps.assinatura }}</Assinatura> |
|||
<InscricaoMunicipalPrestador>{{ rps.prestador.inscricao_municipal }} |
|||
</InscricaoMunicipalPrestador> |
|||
<RazaoSocialPrestador>{{ rps.prestador.razao_social }}</RazaoSocialPrestador> |
|||
<TipoRPS>RPS</TipoRPS> |
|||
<SerieRPS>{{ rps.serie }}</SerieRPS> |
|||
<NumeroRPS>{{ rps.numero }}</NumeroRPS> |
|||
<DataEmissaoRPS>{{ rps.data_emissao|format_datetime }} |
|||
</DataEmissaoRPS> |
|||
<SituacaoRPS>{{ rps.situacao }}</SituacaoRPS> |
|||
<SerieRPSSubstituido></SerieRPSSubstituido> |
|||
<NumeroRPSSubstituido>0</NumeroRPSSubstituido> |
|||
<NumeroNFSeSubstituida>0</NumeroNFSeSubstituida> |
|||
<DataEmissaoNFSeSubstituida>1900-01-01</DataEmissaoNFSeSubstituida> |
|||
<SeriePrestacao>{{ rps.serie_prestacao }}</SeriePrestacao> |
|||
<InscricaoMunicipalTomador>{{ rps.tomador.inscricao_municipal }}</InscricaoMunicipalTomador> |
|||
<CPFCNPJTomador>{{ rps.tomador.cpf_cnpj }}</CPFCNPJTomador> |
|||
<RazaoSocialTomador>{{ rps.tomador.razao_social }} |
|||
</RazaoSocialTomador> |
|||
<TipoLogradouroTomador>{{ rps.tomador.tipo_logradouro }} |
|||
</TipoLogradouroTomador> |
|||
<LogradouroTomador>{{ rps.tomador.logradouro }}</LogradouroTomador> |
|||
<NumeroEnderecoTomador>{{ rps.tomador.numero }} |
|||
</NumeroEnderecoTomador> |
|||
<TipoBairroTomador>{{ rps.tomador.tipo_bairro }}</TipoBairroTomador> |
|||
<BairroTomador>{{ rps.tomador.bairro }}</BairroTomador> |
|||
<CidadeTomador>{{ rps.tomador.cidade }}</CidadeTomador> |
|||
<CidadeTomadorDescricao>{{ rps.tomador.cidade_descricao }} |
|||
</CidadeTomadorDescricao> |
|||
<CEPTomador>{{ rps.tomador.cep }}</CEPTomador> |
|||
<EmailTomador>{{ rps.tomador.email }}</EmailTomador> |
|||
<CodigoAtividade>{{ rps.codigo_atividade }}</CodigoAtividade> |
|||
<AliquotaAtividade>{{ rps.aliquota_atividade }}</AliquotaAtividade> |
|||
<TipoRecolhimento>{{ rps.tipo_recolhimento }}</TipoRecolhimento> |
|||
<MunicipioPrestacao>{{ rps.municipio_prestacao }} |
|||
</MunicipioPrestacao> |
|||
<MunicipioPrestacaoDescricao>{{ rps.municipio_descricao_prestacao }} |
|||
</MunicipioPrestacaoDescricao> |
|||
<Operacao>{{ rps.operacao }}</Operacao> |
|||
<Tributacao>{{ rps.tributacao }}</Tributacao> |
|||
<ValorPIS>{{ rps.valor_pis }}</ValorPIS> |
|||
<ValorCOFINS>{{ rps.valor_cofins }}</ValorCOFINS> |
|||
<ValorINSS>{{ rps.valor_inss }}</ValorINSS> |
|||
<ValorIR>{{ rps.valor_ir }}</ValorIR> |
|||
<ValorCSLL>{{ rps.valor_csll }}</ValorCSLL> |
|||
<AliquotaPIS>{{ rps.aliquota_pis }}</AliquotaPIS> |
|||
<AliquotaCOFINS>{{ rps.aliquota_cofins }}</AliquotaCOFINS> |
|||
<AliquotaINSS>{{ rps.aliquota_inss }}</AliquotaINSS> |
|||
<AliquotaIR>{{ rps.aliquota_ir }}</AliquotaIR> |
|||
<AliquotaCSLL>{{ rps.aliquota_csll }}</AliquotaCSLL> |
|||
<DescricaoRPS>{{ rps.descricao }}</DescricaoRPS> |
|||
<DDDPrestador>{{ rps.prestador.ddd }}</DDDPrestador> |
|||
<TelefonePrestador>{{ rps.prestador.telefone }}</TelefonePrestador> |
|||
<DDDTomador>{{ rps.tomador.ddd }}</DDDTomador> |
|||
<TelefoneTomador>{{ rps.tomador.telefone }}</TelefoneTomador> |
|||
<MotCancelamento>{{ rps.motivo_cancelamento }}</MotCancelamento> |
|||
{% if rps.deducoes|count > 0 %} |
|||
<Deducoes> |
|||
{% for deducao in rps.deducoes -%} |
|||
<Deducao> |
|||
<DeducaoPor>{{ deducao.por }}</DeducaoPor> |
|||
<TipoDeducao>{{ deducao.tipo }}</TipoDeducao> |
|||
<CPFCNPJReferencia>{{ deducao.cnpj_referencia }}</CPFCNPJReferencia> |
|||
<NumeroNFReferencia>{{ deducao.nf_referencia }}</NumeroNFReferencia> |
|||
<ValorTotalReferencia>{{ deducao.valor_referencia }}</ValorTotalReferencia> |
|||
<PercentualDeduzir>{{ deducao.percentual_deduzir }}</PercentualDeduzir> |
|||
<ValorDeduzir>{{ deducao.valor_deduzir }}</ValorDeduzir> |
|||
</Deducao> |
|||
{% endfor %} |
|||
</Deducoes> |
|||
{% endif %} |
|||
{% if rps.deducoes|count == 0 %} |
|||
<Deducoes /> |
|||
{% endif %} |
|||
<Itens> |
|||
{% for item in rps.itens -%} |
|||
<Item> |
|||
<DiscriminacaoServico>{{ item.descricao }}</DiscriminacaoServico> |
|||
<Quantidade>{{ item.quantidade }}</Quantidade> |
|||
<ValorUnitario>{{ item.valor_unitario }}</ValorUnitario> |
|||
<ValorTotal>{{ item.valor_total }}</ValorTotal> |
|||
<Tributavel>S</Tributavel> |
|||
</Item> |
|||
{% endfor %} |
|||
</Itens> |
|||
</RPS> |
|||
{% endfor %} |
|||
</Lote> |
|||
</ns1:ReqEnvioLoteRPS> |
|||
@ -0,0 +1,12 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" |
|||
xmlns:dsf="http://dsfnet.com.br"> |
|||
<soapenv:Body> |
|||
<dsf:enviar soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> |
|||
<mensagemXml xsi:type="xsd:string"><![CDATA[ |
|||
{% block content %}{% endblock %} |
|||
]]></mensagemXml> |
|||
</dsf:enviar> |
|||
</soapenv:Body> |
|||
</soapenv:Envelope> |
|||
@ -0,0 +1,119 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2017 Danimar Ribeiro, Trustcode |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import os |
|||
import hashlib |
|||
import base64 |
|||
import requests |
|||
from pytrustnfe.xml import render_xml, sanitize_response |
|||
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key |
|||
from pytrustnfe.nfse.assinatura import Assinatura |
|||
|
|||
URLS = { |
|||
'producao': { |
|||
'processar_nota': 'https://nfps-e.pmf.sc.gov.br/api/v1/processamento/notas/processa', |
|||
'cancelar_nota': 'https://nfps-e.pmf.sc.gov.br/api/v1/cancelamento/notas/cancela' |
|||
}, |
|||
'homologacao': { |
|||
'processar_nota': 'https://nfps-e-hml.pmf.sc.gov.br/api/v1/processamento/notas/processa', |
|||
'cancelar_nota': 'https://nfps-e-hml.pmf.sc.gov.br/api/v1/cancelamento/notas/cancela' |
|||
} |
|||
} |
|||
|
|||
|
|||
def _render(certificado, method, **kwargs): |
|||
path = os.path.join(os.path.dirname(__file__), 'templates') |
|||
xml_send = render_xml(path, '%s.xml' % method, False, **kwargs) |
|||
|
|||
cert, key = extract_cert_and_key_from_pfx( |
|||
certificado.pfx, certificado.password) |
|||
cert, key = save_cert_key(cert, key) |
|||
signer = Assinatura(cert, key, certificado.password) |
|||
xml_send = signer.assina_xml(xml_send, '') |
|||
return xml_send |
|||
|
|||
|
|||
def _get_oauth_token(**kwargs): |
|||
if kwargs['ambiente'] == 'producao': |
|||
url = 'https://nfps-e.pmf.sc.gov.br/api/v1/autenticacao/oauth/token' |
|||
else: |
|||
url = 'https://nfps-e-hml.pmf.sc.gov.br/api/v1/autenticacao/oauth/token' |
|||
|
|||
m = hashlib.md5() |
|||
secret = "%s:%s" % (kwargs["client_id"], kwargs["secret_id"]) |
|||
auth = base64.b64encode(secret.encode('utf-8')) |
|||
headers = { |
|||
"Content-Type": "application/x-www-form-urlencoded", |
|||
"Authorization": "Basic %s" % auth.decode('utf-8').replace('\n', '') |
|||
} |
|||
m.update(kwargs["password"].encode('utf-8')) |
|||
password = m.hexdigest().upper() |
|||
|
|||
dados = "grant_type=password&username=%s&password=%s&client_id=%s&client_secret=%s" % ( |
|||
kwargs["username"], password, kwargs["client_id"], kwargs["secret_id"]) |
|||
r = requests.post(url, data=dados, headers=headers) |
|||
if r.status_code == 200: |
|||
return r.json() |
|||
else: |
|||
return r.json() |
|||
|
|||
|
|||
def _send(certificado, method, **kwargs): |
|||
url = URLS[kwargs['ambiente']][method] |
|||
xml_send = kwargs['xml'] |
|||
|
|||
token = _get_oauth_token(**kwargs) |
|||
if "access_token" not in token: |
|||
raise Exception("%s - %s: %s" % (token["status"], token["error"], |
|||
token["message"])) |
|||
kwargs.update({"numero": 1, 'access_token': token["access_token"]}) |
|||
|
|||
headers = {"Accept": "application/xml;charset=UTF-8", |
|||
"Content-Type": "application/xml", |
|||
"Authorization": "Bearer %s" % kwargs['access_token']} |
|||
r = requests.post(url, headers=headers, data=xml_send) |
|||
|
|||
response, obj = sanitize_response(r.text.strip().encode('utf-8')) |
|||
return { |
|||
'sent_xml': xml_send, |
|||
'received_xml': response, |
|||
'object': obj, |
|||
'status_code': r.status_code, |
|||
} |
|||
|
|||
|
|||
def xml_processar_nota(certificado, **kwargs): |
|||
return _render(certificado, 'processar_nota', **kwargs) |
|||
|
|||
|
|||
def processar_nota(certificado, **kwargs): |
|||
if "xml" not in kwargs: |
|||
kwargs['xml'] = xml_processar_nota(certificado, **kwargs) |
|||
return _send(certificado, 'processar_nota', **kwargs) |
|||
|
|||
|
|||
def xml_cancelar_nota(certificado, **kwargs): |
|||
return _render(certificado, 'cancelar_nota', **kwargs) |
|||
|
|||
|
|||
def cancelar_nota(certificado, **kwargs): |
|||
if "xml" not in kwargs: |
|||
kwargs['xml'] = xml_cancelar_nota(certificado, **kwargs) |
|||
return _send(certificado, 'cancelar_nota', **kwargs) |
|||
|
|||
|
|||
def consultar_nota(certificado, **kwargs): |
|||
if kwargs['ambiente'] == 'producao': |
|||
url = "https://nfps-e.pmf.sc.gov.br/api/v1/consultas/notas/numero/%s" % (kwargs["numero"]) |
|||
else: |
|||
url = "https://nfps-e-hml.pmf.sc.gov.br/api/v1/consultas/notas/numero/%s" % (kwargs["numero"]) |
|||
|
|||
headers = {"Accept": "application/json", |
|||
"Authorization": "Bearer %s" % kwargs['access_token']} |
|||
r = requests.get(url, headers=headers) |
|||
print(r.status_code) |
|||
if r.status_code == 200: |
|||
return r.text |
|||
else: |
|||
return r.text |
|||
@ -0,0 +1,7 @@ |
|||
<?xml version="1.0"?> |
|||
<xmlCancelamentoNfpse> |
|||
<motivoCancelamento>{{ cancelamento.motivo }}</motivoCancelamento> |
|||
<nuAedf>{{ cancelamento.aedf }}</nuAedf> |
|||
<nuNotaFiscal>{{ cancelamento.numero }}</nuNotaFiscal> |
|||
<codigoVerificacao>{{ cancelamento.codigo_verificacao }}</codigoVerificacao> |
|||
</xmlCancelamentoNfpse> |
|||
@ -0,0 +1,40 @@ |
|||
<?xml version="1.0"?> |
|||
<xmlProcessamentoNfpse> |
|||
<bairroTomador>{{ rps.tomador.bairro|normalize|escape }}</bairroTomador> |
|||
<baseCalculo>{{ rps.base_calculo }}</baseCalculo> |
|||
<baseCalculoSubstituicao>0.0</baseCalculoSubstituicao> |
|||
<cfps>{{ rps.cfps }}</cfps> |
|||
<codigoMunicipioTomador>{{ rps.tomador.cidade }}</codigoMunicipioTomador> |
|||
<codigoPostalTomador>{{ rps.tomador.cep }}</codigoPostalTomador> |
|||
<complementoEnderecoTomador>{{ rps.tomador.complemento|normalize|escape }}</complementoEnderecoTomador> |
|||
<dadosAdicionais>{{ rps.observacoes|normalize|escape }}</dadosAdicionais> |
|||
<dataEmissao>{{ rps.data_emissao }}</dataEmissao> |
|||
<emailTomador>{{ rps.tomador.email }}</emailTomador> |
|||
<identificacao>{{ rps.numero }}</identificacao> |
|||
<identificacaoTomador>{{ rps.tomador.cnpj_cpf }}</identificacaoTomador> |
|||
<inscricaoMunicipalTomador>{{ rps.tomador.inscricao_municipal }}</inscricaoMunicipalTomador> |
|||
<itensServico> |
|||
{% for item in rps.itens_servico -%} |
|||
<itemServico> |
|||
<aliquota>{{ item.aliquota }}</aliquota> |
|||
<cst>{{ item.cst_servico }}</cst> |
|||
<descricaoServico>{{ item.descricao|normalize|escape }}</descricaoServico> |
|||
<idCNAE>{{ item.cnae }}</idCNAE> |
|||
<quantidade>{{ item.quantidade }}</quantidade> |
|||
<valorTotal>{{ item.valor_total }}</valorTotal> |
|||
<valorUnitario>{{ item.valor_unitario }}</valorUnitario> |
|||
</itemServico> |
|||
{% endfor %} |
|||
</itensServico> |
|||
<logradouroTomador>{{ rps.tomador.logradouro|normalize|escape }}</logradouroTomador> |
|||
<nomeMunicipioTomador></nomeMunicipioTomador> |
|||
<numeroAEDF>{{ rps.aedf }}</numeroAEDF> |
|||
<numeroEnderecoTomador>{{ rps.tomador.numero }}</numeroEnderecoTomador> |
|||
<paisTomador>1058</paisTomador> |
|||
<razaoSocialTomador>{{ rps.tomador.razao_social|normalize|escape }}</razaoSocialTomador> |
|||
<telefoneTomador>{{ rps.tomador.telefone }}</telefoneTomador> |
|||
<ufTomador>{{ rps.tomador.uf }}</ufTomador> |
|||
<valorISSQN>{{rps.valor_issqn }}</valorISSQN> |
|||
<valorISSQNSubstituicao>0.0</valorISSQNSubstituicao> |
|||
<valorTotalServicos>{{ rps.valor_total }}</valorTotalServicos> |
|||
</xmlProcessamentoNfpse> |
|||
@ -1 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?><RetornoEnvioLoteRPS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.prefeitura.sp.gov.br/nfe"><Cabecalho Versao="1" xmlns=""><Sucesso>true</Sucesso><InformacoesLote><NumeroLote>2654364</NumeroLote><InscricaoPrestador>51212</InscricaoPrestador><CPFCNPJRemetente><CNPJ>21332900163</CNPJ></CPFCNPJRemetente><DataEnvioLote>2016-08-29T10:52:15</DataEnvioLote><QtdNotasProcessadas>1</QtdNotasProcessadas><TempoProcessamento>0</TempoProcessamento><ValorTotalServicos>1.35</ValorTotalServicos></InformacoesLote></Cabecalho><ChaveNFeRPS xmlns=""><ChaveNFe><InscricaoPrestador>52382</InscricaoPrestador><NumeroNFe>446</NumeroNFe><CodigoVerificacao>APR9MJR</CodigoVerificacao></ChaveNFe><ChaveRPS><InscricaoPrestador>51282</InscricaoPrestador><SerieRPS>1</SerieRPS><NumeroRPS>6</NumeroRPS></ChaveRPS></ChaveNFeRPS></RetornoEnvioLoteRPS> |
|||
@ -1,16 +1,16 @@ |
|||
lxml >= 3.5.0, < 4 |
|||
nose |
|||
mock |
|||
lxml >= 3.5.0, < 5 |
|||
coveralls |
|||
http://xmlsoft.org/sources/python/libxml2-python-2.6.21.tar.gz |
|||
https://github.com/odoo-brazil/pyxmlsec/archive/master.zip |
|||
Jinja2 |
|||
signxml |
|||
suds >= 0.4 |
|||
suds_requests >= 0.3 |
|||
defusedxml >= 0.4.1, < 0.6 |
|||
eight >= 0.3.0, < 0.5 |
|||
cryptography >= 1.8, < 1.10 |
|||
pyOpenSSL >= 16.0.0, < 17 |
|||
urllib3 >= 1.22 |
|||
suds-jurko >= 0.6 |
|||
suds-jurko-requests >= 1.1 |
|||
defusedxml >= 0.4.1, < 1 |
|||
eight >= 0.3.0, < 1 |
|||
cryptography >= 1.8, < 3 |
|||
pyOpenSSL >= 16.0.0, < 18 |
|||
certifi >= 2015.11.20.1 |
|||
xmlsec >= 1.3.3 |
|||
reportlab |
|||
pytest |
|||
pytest-cov |
|||
@ -1,4 +1,3 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<RetornoCancelamentoNFe |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
|||
@ -1,4 +1,3 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<RetornoCancelamentoNFe |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
|||
@ -0,0 +1 @@ |
|||
<RetornoEnvioLoteRPS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.prefeitura.sp.gov.br/nfe"><Cabecalho Versao="1" xmlns=""><Sucesso>true</Sucesso><InformacoesLote><NumeroLote>2654364</NumeroLote><InscricaoPrestador>51212</InscricaoPrestador><CPFCNPJRemetente><CNPJ>21332900163</CNPJ></CPFCNPJRemetente><DataEnvioLote>2016-08-29T10:52:15</DataEnvioLote><QtdNotasProcessadas>1</QtdNotasProcessadas><TempoProcessamento>0</TempoProcessamento><ValorTotalServicos>1.35</ValorTotalServicos></InformacoesLote></Cabecalho><ChaveNFeRPS xmlns=""><ChaveNFe><InscricaoPrestador>52382</InscricaoPrestador><NumeroNFe>446</NumeroNFe><CodigoVerificacao>APR9MJR</CodigoVerificacao></ChaveNFe><ChaveRPS><InscricaoPrestador>51282</InscricaoPrestador><SerieRPS>1</SerieRPS><NumeroRPS>6</NumeroRPS></ChaveRPS></ChaveNFeRPS></RetornoEnvioLoteRPS> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue