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:merge-master3
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
51 Commits
master
...
merge-mast
107 changed files with 2182 additions and 1450 deletions
-
2.gitignore
-
10.travis.yml
-
26README.md
-
7cidades/dsf.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
-
38pytrustnfe/nfe/danfe.py
-
BINpytrustnfe/nfe/fonts/NimbusSanL Bold.ttf
-
BINpytrustnfe/nfe/fonts/NimbusSanL Regular.ttf
-
90pytrustnfe/nfse/assinatura.py
-
2pytrustnfe/nfse/betha/__init__.py
-
74pytrustnfe/nfse/carioca/__init__.py
-
13pytrustnfe/nfse/carioca/templates/CancelarNfse.xml
-
3pytrustnfe/nfse/carioca/templates/GerarNfse.xml
-
91pytrustnfe/nfse/carioca/templates/Rps.xml
-
131pytrustnfe/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
-
11pytrustnfe/nfse/imperial/__init__.py
-
13pytrustnfe/nfse/paulistana/__init__.py
-
2pytrustnfe/nfse/susesu/__init__.py
-
1pytrustnfe/test/XMLs/paulistana_resultado.xml
-
16pytrustnfe/utils.py
-
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
-
25setup.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,7 @@ |
|||
* Belém - PA |
|||
* Sorocaba - SP |
|||
* Teresina - PI |
|||
* Campinas - SP |
|||
* Uberlandia - MG |
|||
* São Luis - MA |
|||
* Campo Grande - MS |
|||
@ -0,0 +1,74 @@ |
|||
# © 2018 Danimar Ribeiro, Trustcode |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import os |
|||
import suds |
|||
from pytrustnfe.client import get_authenticated_client |
|||
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key |
|||
from pytrustnfe.xml import render_xml, sanitize_response |
|||
from pytrustnfe.nfe.assinatura import Assinatura |
|||
|
|||
|
|||
def _render(certificado, method, **kwargs): |
|||
path = os.path.join(os.path.dirname(__file__), 'templates') |
|||
xml_send = render_xml(path, '%s.xml' % method, True, **kwargs) |
|||
|
|||
reference = '' |
|||
if method == 'GerarNfse': |
|||
reference = 'r%s' % kwargs['rps']['numero'] |
|||
elif method == 'CancelarNfse': |
|||
reference = 'Cancelamento_NF%s' % kwargs['cancelamento']['numero_nfse'] |
|||
|
|||
signer = Assinatura(certificado.pfx, certificado.password) |
|||
xml_send = signer.assina_xml(xml_send, reference) |
|||
return xml_send.encode('utf-8') |
|||
|
|||
|
|||
def _send(certificado, method, **kwargs): |
|||
base_url = '' |
|||
if kwargs['ambiente'] == 'producao': |
|||
base_url = 'https://notacarioca.rio.gov.br/WSNacional/nfse.asmx?wsdl' |
|||
else: |
|||
base_url = 'https://homologacao.notacarioca.rio.gov.br/WSNacional/nfse.asmx?wsdl' # noqa |
|||
|
|||
xml_send = kwargs["xml"].decode('utf-8') |
|||
cert, key = extract_cert_and_key_from_pfx( |
|||
certificado.pfx, certificado.password) |
|||
cert, key = save_cert_key(cert, key) |
|||
client = get_authenticated_client(base_url, cert, key) |
|||
|
|||
try: |
|||
response = getattr(client.service, method)(xml_send) |
|||
except suds.WebFault as e: |
|||
return { |
|||
'sent_xml': str(xml_send), |
|||
'received_xml': str(e.fault.faultstring), |
|||
'object': None |
|||
} |
|||
|
|||
response, obj = sanitize_response(response) |
|||
return { |
|||
'sent_xml': str(xml_send), |
|||
'received_xml': str(response), |
|||
'object': obj |
|||
} |
|||
|
|||
|
|||
def xml_gerar_nfse(certificado, **kwargs): |
|||
return _render(certificado, 'GerarNfse', **kwargs) |
|||
|
|||
|
|||
def gerar_nfse(certificado, **kwargs): |
|||
if "xml" not in kwargs: |
|||
kwargs['xml'] = xml_gerar_nfse(certificado, **kwargs) |
|||
return _send(certificado, 'GerarNfse', **kwargs) |
|||
|
|||
|
|||
def xml_cancelar_nfse(certificado, **kwargs): |
|||
return _render(certificado, 'CancelarNfse', **kwargs) |
|||
|
|||
|
|||
def cancelar_nfse(certificado, **kwargs): |
|||
if "xml" not in kwargs: |
|||
kwargs['xml'] = xml_cancelar_nfse(certificado, **kwargs) |
|||
return _send(certificado, 'CancelarNfse', **kwargs) |
|||
@ -0,0 +1,13 @@ |
|||
<CancelarNfseEnvio xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd"> |
|||
<Pedido> |
|||
<InfPedidoCancelamento Id="Cancelamento_NF{{ cancelamento.numero_nfse }}"> |
|||
<IdentificacaoNfse> |
|||
<Numero>{{ cancelamento.numero_nfse }}</Numero> |
|||
<Cnpj>{{ cancelamento.cnpj_prestador }}</Cnpj> |
|||
<InscricaoMunicipal>{{ cancelamento.inscricao_municipal }}</InscricaoMunicipal> |
|||
<CodigoMunicipio>{{ cancelamento.cidade }}</CodigoMunicipio> |
|||
</IdentificacaoNfse> |
|||
<CodigoCancelamento>1</CodigoCancelamento> |
|||
</InfPedidoCancelamento> |
|||
</Pedido> |
|||
</CancelarNfseEnvio> |
|||
@ -0,0 +1,3 @@ |
|||
<GerarNfseEnvio xmlns="http://notacarioca.rio.gov.br/WSNacional/XSD/1/nfse_pcrj_v01.xsd"> |
|||
{% include 'Rps.xml' %} |
|||
</GerarNfseEnvio> |
|||
@ -0,0 +1,91 @@ |
|||
<Rps> |
|||
<InfRps xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd" Id="r{{ rps.numero }}"> |
|||
<IdentificacaoRps> |
|||
<Numero>{{ rps.numero }}</Numero> |
|||
<Serie>{{ rps.serie }}</Serie> |
|||
<Tipo>{{ rps.tipo_rps }}</Tipo> |
|||
</IdentificacaoRps> |
|||
<DataEmissao>{{ rps.data_emissao }}</DataEmissao> |
|||
<NaturezaOperacao>{{ rps.natureza_operacao }}</NaturezaOperacao> |
|||
<RegimeEspecialTributacao>{{ rps.regime_tributacao }}</RegimeEspecialTributacao> |
|||
<OptanteSimplesNacional>{{ rps.optante_simples }}</OptanteSimplesNacional> |
|||
<IncentivadorCultural>{{ rps.incentivador_cultural }}</IncentivadorCultural> |
|||
<Status>{{ rps.status }}</Status> |
|||
<RpsSubstituido> |
|||
<Numero>{{ rps.numero_substituido }}</Numero> |
|||
<Serie>{{ rps.serie_substituido }}</Serie> |
|||
<Tipo>{{ rps.tipo_substituido }}</Tipo> |
|||
</RpsSubstituido> |
|||
<Servico> |
|||
<Valores> |
|||
<ValorServicos>{{ rps.valor_servico }}</ValorServicos> |
|||
<ValorDeducoes>{{ rps.valor_deducao }}</ValorDeducoes> |
|||
<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> |
|||
<IssRetido>{{ rps.iss_retido }}</IssRetido> |
|||
<ValorIss>{{ rps.valor_iss }}</ValorIss> |
|||
<ValorIssRetido>{{ rps.valor_iss_retido }}</ValorIssRetido> |
|||
<OutrasRetencoes>{{ rps.outras_retencoes }}</OutrasRetencoes> |
|||
<BaseCalculo>{{ rps.base_calculo }}</BaseCalculo> |
|||
<Aliquota>{{ rps.aliquota_issqn }}</Aliquota> |
|||
<ValorLiquidoNfse>{{ rps.valor_liquido_nfse }}</ValorLiquidoNfse> |
|||
<DescontoIncondicionado>{{ rps.desconto_incondicionado }}</DescontoIncondicionado> |
|||
<DescontoCondicionado>{{ rps.desconto_condicionado }}</DescontoCondicionado> |
|||
</Valores> |
|||
<ItemListaServico>{{ rps.codigo_servico }}</ItemListaServico> |
|||
<CodigoCnae>{{ rps.cnae_servico }}</CodigoCnae> |
|||
<CodigoTributacaoMunicipio>{{ rps.codigo_tributacao_municipio }}</CodigoTributacaoMunicipio> |
|||
<Discriminacao>{{ rps.descricao }}</Discriminacao> |
|||
<CodigoMunicipio>{{ rps.codigo_municipio }}</CodigoMunicipio> |
|||
</Servico> |
|||
<Prestador> |
|||
<Cnpj>{{ rps.prestador.cnpj }}</Cnpj> |
|||
<InscricaoMunicipal>{{ rps.prestador.inscricao_municipal }}</InscricaoMunicipal> |
|||
</Prestador> |
|||
<Tomador> |
|||
<IdentificacaoTomador> |
|||
<CpfCnpj> |
|||
{% if rps.tomador.cnpj_cpf|length == 14 %} |
|||
<Cnpj>{{ rps.tomador.cnpj_cpf }}</Cnpj> |
|||
{% endif %} |
|||
{% if rps.tomador.cnpj_cpf|length == 11 %} |
|||
<Cpf>{{ rps.tomador.cnpj_cpf }}</Cpf> |
|||
{% endif %} |
|||
</CpfCnpj> |
|||
<InscricaoMunicipal>{{ rps.tomador.inscricao_municipal }}</InscricaoMunicipal> |
|||
</IdentificacaoTomador> |
|||
<RazaoSocial>{{ rps.tomador.razao_social }}</RazaoSocial> |
|||
<Endereco> |
|||
<Endereco>{{ rps.tomador.logradouro }}</Endereco> |
|||
<Numero>{{ rps.tomador.numero }}</Numero> |
|||
<Complemento>{{ rps.tomador.complemento }}</Complemento> |
|||
<Bairro>{{ rps.tomador.bairro }}</Bairro> |
|||
<CodigoMunicipio>{{ rps.tomador.cidade }}</CodigoMunicipio> |
|||
<Uf>{{ rps.tomador.uf }}</Uf> |
|||
<Cep>{{ rps.tomador.cep }}</Cep> |
|||
</Endereco> |
|||
<Contato> |
|||
<Telefone>{{ rps.tomador.telefone }}</Telefone> |
|||
<Email>{{ rps.tomador.email }}</Email> |
|||
</Contato> |
|||
</Tomador> |
|||
{% if rps.intermediario is defined -%} |
|||
<IntermediarioServico> |
|||
<RazaoSocial>{{ rps.intermediario.razao_social }}</RazaoSocial> |
|||
<CpfCnpj> |
|||
<Cnpj>{{ rps.intermediario.cnpj }}</Cnpj> |
|||
</CpfCnpj> |
|||
<InscricaoMunicipal>{{ rps.intermediario.inscricao_municipal }}</InscricaoMunicipal> |
|||
</IntermediarioServico> |
|||
{% endif %} |
|||
{% if rps.construcao_civil is defined -%} |
|||
<ContrucaoCivil> |
|||
<CodigoObra>{{ rps.construcao_civil.codigo_obra }}</CodigoObra> |
|||
<Art>{{ rps.construcao_civil.art }}</Art> |
|||
</ContrucaoCivil> |
|||
{% endif %} |
|||
</InfRps> |
|||
</Rps> |
|||
@ -0,0 +1,131 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
# © 2017 Fábio Luna, Trustcode |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import os |
|||
import suds |
|||
from lxml import etree |
|||
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 |
|||
from pytrustnfe.client import get_client |
|||
|
|||
|
|||
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) |
|||
|
|||
if type(xml_send) != str: |
|||
xml_send = etree.tostring(xml_send) |
|||
|
|||
return xml_send |
|||
|
|||
|
|||
def _get_url(**kwargs): |
|||
|
|||
try: |
|||
cod_cidade = kwargs['nfse']['cidade'] |
|||
except (KeyError, TypeError): |
|||
raise KeyError("Código de cidade inválido!") |
|||
|
|||
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 |
|||
'2729': 'http://issdigital.pmcg.ms.gov.br/WsNFe2/LoteRps.jws?wsdl', |
|||
} |
|||
|
|||
try: |
|||
return urls[str(cod_cidade)] |
|||
except KeyError: |
|||
raise KeyError("DSF não emite notas da cidade {}!".format( |
|||
cod_cidade)) |
|||
|
|||
|
|||
def _send(certificado, method, **kwargs): |
|||
url = _get_url(**kwargs) |
|||
|
|||
path = os.path.join(os.path.dirname(__file__), 'templates') |
|||
|
|||
xml_send = _render(path, method, **kwargs) |
|||
client = get_client(url) |
|||
response = False |
|||
|
|||
if certificado: |
|||
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, '') |
|||
|
|||
try: |
|||
response = getattr(client.service, method)(xml_send) |
|||
response, obj = sanitize_response(response.encode()) |
|||
except suds.WebFault as e: |
|||
return { |
|||
'sent_xml': xml_send, |
|||
'received_xml': e.fault.faultstring, |
|||
'object': None |
|||
} |
|||
except Exception as e: |
|||
if response: |
|||
raise Exception(response) |
|||
else: |
|||
raise e |
|||
|
|||
return { |
|||
'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.name|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