nfse_prefeitura_sp 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +233 -0
- data/lib/nfse_prefeitura_sp/client.rb +68 -0
- data/lib/nfse_prefeitura_sp/response.rb +37 -0
- data/lib/nfse_prefeitura_sp/services/async/.keep +0 -0
- data/lib/nfse_prefeitura_sp/services/sync/cancelamento_nfe.rb +39 -0
- data/lib/nfse_prefeitura_sp/services/sync/envio_rps.rb +28 -0
- data/lib/nfse_prefeitura_sp/services/sync/teste_envio_lote_rps.rb +32 -0
- data/lib/nfse_prefeitura_sp/services.rb +9 -0
- data/lib/nfse_prefeitura_sp/signer.rb +104 -0
- data/lib/nfse_prefeitura_sp/types/complex.rb +32 -0
- data/lib/nfse_prefeitura_sp/types/simple.rb +16 -0
- data/lib/nfse_prefeitura_sp/types/tp_chave_nfe.rb +16 -0
- data/lib/nfse_prefeitura_sp/types/tp_chave_rps.rb +14 -0
- data/lib/nfse_prefeitura_sp/types/tp_cpf_cnpj.rb +15 -0
- data/lib/nfse_prefeitura_sp/types/tp_cpf_cnpj_nif.rb +21 -0
- data/lib/nfse_prefeitura_sp/types/tp_endereco.rb +24 -0
- data/lib/nfse_prefeitura_sp/types/tp_g_ibs_cbs.rb +10 -0
- data/lib/nfse_prefeitura_sp/types/tp_ibs_cbs.rb +18 -0
- data/lib/nfse_prefeitura_sp/types/tp_rps.rb +215 -0
- data/lib/nfse_prefeitura_sp/types/tp_trib.rb +10 -0
- data/lib/nfse_prefeitura_sp/types/tp_valores.rb +10 -0
- data/lib/nfse_prefeitura_sp/types.rb +2 -0
- data/lib/nfse_prefeitura_sp/version.rb +5 -0
- data/lib/nfse_prefeitura_sp.rb +20 -0
- metadata +111 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6282b1849a38ea73bf0b6135bf8352d18aceae83fe24eef2b18b3a1a2bd6e3e1
|
|
4
|
+
data.tar.gz: 1b1973bd9b62c2cb94fe2f72743ac19044bfa7af17e647b5d8991935acf9daae
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a3c9ed5c4abb1d7ce5895f6a7ce294879f71ad1466bd8142df6d21b0dd0f0b05a55a0f55c02bff614ef76b254d8eb8280cb57364f6224131b6c607cdc38445a1
|
|
7
|
+
data.tar.gz: 5267fdbc2a84282053ae64fa441a4cd1844b890dd023df0758a8f9ded98a05262684f4c7140cc0920a29177522f770a407dcbcb1aeb6f0db5aa1b38e5fca98bb
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Infosimples - https://www.infosimples.com.br
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# NfsePrefeituraSp
|
|
2
|
+
|
|
3
|
+
>WORK IN PROGRESS
|
|
4
|
+
|
|
5
|
+
Gem para integração com a Nota Fiscal de Serviços Eletrônica (NFS-e) da Prefeitura de São Paulo.
|
|
6
|
+
|
|
7
|
+
**Esta gem se integra exclusivamente com a "Versão 2" dos serviços da Prefeitura, contemplando as mudanças introduzidas
|
|
8
|
+
pela Reforma Triburtária de 2026 (IBS/CBS).**
|
|
9
|
+
|
|
10
|
+
## Manuais da Prefeitura de São Paulo
|
|
11
|
+
|
|
12
|
+
Os manuais técnicos disponibilizados pela Prefeitura de São Paulo estão disponíveis [aqui](https://notadomilhao.sf.prefeitura.sp.gov.br/manuais/).
|
|
13
|
+
|
|
14
|
+
## Módulos disponíveis
|
|
15
|
+
|
|
16
|
+
Abaixo estão indicados os serviços já disponíveis (`[X]`) e os pendentes de implementação (`[ ]`).
|
|
17
|
+
|
|
18
|
+
### Serviços síncronos
|
|
19
|
+
|
|
20
|
+
- `[X] ENVIO DE RPS`
|
|
21
|
+
- `[ ] ENVIO DE LOTE DE RPS`
|
|
22
|
+
- `[X] TESTE DE ENVIO DE LOTE DE RPS`
|
|
23
|
+
- `[ ] CONSULTA DE NF-E`
|
|
24
|
+
- `[ ] CONSULTA DE NF-E RECEBIDAS`
|
|
25
|
+
- `[ ] CONSULTA DE NF-E EMITIDAS`
|
|
26
|
+
- `[ ] CONSULTA DE LOTE`
|
|
27
|
+
- `[ ] CONSULTA INFORMAÇÕES DO LOTE`
|
|
28
|
+
- `[X] CANCELAMENTO DE NF-E`
|
|
29
|
+
- `[ ] CONSULTA DE CNPJ`
|
|
30
|
+
|
|
31
|
+
### Serviços assíncronos
|
|
32
|
+
|
|
33
|
+
- `[ ] ENVIO DE LOTE DE RPS - ASSÍNCRONO`
|
|
34
|
+
- `[ ] CONSULTA SITUAÇÃO LOTE ASSÍNCRONO`
|
|
35
|
+
- `[ ] TESTE ENVIO DE LOTE RPS - ASSÍNCRONO`
|
|
36
|
+
- `[ ] EMISSÃO DE GUIA - ASSÍNCRONO`
|
|
37
|
+
- `[ ] CONSULTA SITUAÇÃO GUIA`
|
|
38
|
+
- `[ ] CONSULTA GUIA`
|
|
39
|
+
|
|
40
|
+
## Instalação
|
|
41
|
+
|
|
42
|
+
Criando um cliente:
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
require 'nfse_prefeitura_sp'
|
|
46
|
+
client = NfsePrefeituraSp::Client.new(
|
|
47
|
+
cert_path: '/path/to/cert.p12',
|
|
48
|
+
cert_password: 'passwd'
|
|
49
|
+
)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Exemplos de serviços síncronos
|
|
53
|
+
|
|
54
|
+
ENVIO DE RPS:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
data = {
|
|
58
|
+
cnpj_remetente: '00000000000000',
|
|
59
|
+
rps: [
|
|
60
|
+
{
|
|
61
|
+
chave_rps: {
|
|
62
|
+
inscricao_prestador: '00000000',
|
|
63
|
+
numero_rps: '000000',
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
tipo_rps: 'RPS',
|
|
67
|
+
codigo_servico: '00000',
|
|
68
|
+
aliquota_servicos: '0.029'
|
|
69
|
+
tributacao_rps: 'T',
|
|
70
|
+
status_rps: 'N',
|
|
71
|
+
data_emissao: 'YYYY-MM-DD',
|
|
72
|
+
discriminacao: 'Serviço prestado...',
|
|
73
|
+
percentual_carga_tributaria: '0.XXXX',
|
|
74
|
+
valor_carga_tributaria: 'XX.XX',
|
|
75
|
+
valor_final_cobrado: 'XXX.XX',
|
|
76
|
+
valor_ipi: 'XX.XX',
|
|
77
|
+
valor_pis: 'XX.XX',
|
|
78
|
+
valor_cofins: 'XX.XX',
|
|
79
|
+
valor_inss: 'XX.XX',
|
|
80
|
+
valor_ir: 'XX.XX',
|
|
81
|
+
valor_csll: 'XX.XX',
|
|
82
|
+
exigibilidade_suspensa: '0',
|
|
83
|
+
pagamento_parcelado_antecipado: '0',
|
|
84
|
+
nbs: '000000000',
|
|
85
|
+
c_loc_prestacao: '0000000', # Código IBGE
|
|
86
|
+
iss_retido: false,
|
|
87
|
+
valor_deducoes: '0.00',
|
|
88
|
+
endereco_tomador: {
|
|
89
|
+
tipo_logradouro: 'Rua',
|
|
90
|
+
logradouro: 'Logradouro',
|
|
91
|
+
numero_endereco: '000',
|
|
92
|
+
complemento_endereco: 'Complemento',
|
|
93
|
+
bairro: 'Bairro',
|
|
94
|
+
cidade: '0000000', # Código IBGE
|
|
95
|
+
uf: 'SP',
|
|
96
|
+
cep: '00000000',
|
|
97
|
+
},
|
|
98
|
+
cpf_cnpj_tomador: {
|
|
99
|
+
cnpj: '00000000000000',
|
|
100
|
+
},
|
|
101
|
+
razao_social_tomador: 'Razão Social',
|
|
102
|
+
ibs_cbs: {
|
|
103
|
+
fin_nfse: '0',
|
|
104
|
+
ind_final: '0',
|
|
105
|
+
c_ind_op: '000000',
|
|
106
|
+
ind_dest: '0',
|
|
107
|
+
valores: {
|
|
108
|
+
trib: {
|
|
109
|
+
g_ibs_cbs: {
|
|
110
|
+
c_class_trib: '000000',
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
response = client.sync_envio_rps(data)
|
|
120
|
+
|
|
121
|
+
response.success? # true / false
|
|
122
|
+
response.retorno[:chave_n_fe_rps][:chave_n_fe][:inscricao_prestador] # Inscrição do prestador de serviços
|
|
123
|
+
response.retorno[:chave_n_fe_rps][:chave_n_fe][:numero_n_fe] # Número da nota fiscal
|
|
124
|
+
response.retorno[:chave_n_fe_rps][:chave_n_fe][:codigo_verificacao] # Código de verificação
|
|
125
|
+
response.retorno[:alerta] # Alertas
|
|
126
|
+
response.retorno[:erro] # Erros
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
TESTE DE ENVIO DE LOTE DE RPS:
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
data = {
|
|
133
|
+
cnpj_remetente: '00000000000000',
|
|
134
|
+
dt_inicio:'YYYY-MM-DD',
|
|
135
|
+
dt_fim: 'YYYY-MM-DD',
|
|
136
|
+
rps: [
|
|
137
|
+
{
|
|
138
|
+
chave_rps: {
|
|
139
|
+
inscricao_prestador: '00000000',
|
|
140
|
+
numero_rps: '000000',
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
tipo_rps: 'RPS',
|
|
144
|
+
codigo_servico: '00000',
|
|
145
|
+
aliquota_servicos: '0.029'
|
|
146
|
+
tributacao_rps: 'T',
|
|
147
|
+
status_rps: 'N',
|
|
148
|
+
data_emissao: 'YYYY-MM-DD',
|
|
149
|
+
discriminacao: 'Serviço prestado...',
|
|
150
|
+
percentual_carga_tributaria: '0.XXXX',
|
|
151
|
+
valor_carga_tributaria: 'XX.XX',
|
|
152
|
+
valor_final_cobrado: 'XXX.XX',
|
|
153
|
+
valor_ipi: 'XX.XX',
|
|
154
|
+
valor_pis: 'XX.XX',
|
|
155
|
+
valor_cofins: 'XX.XX',
|
|
156
|
+
valor_inss: 'XX.XX',
|
|
157
|
+
valor_ir: 'XX.XX',
|
|
158
|
+
valor_csll: 'XX.XX',
|
|
159
|
+
exigibilidade_suspensa: '0',
|
|
160
|
+
pagamento_parcelado_antecipado: '0',
|
|
161
|
+
nbs: '000000000',
|
|
162
|
+
c_loc_prestacao: '0000000', # Código IBGE
|
|
163
|
+
iss_retido: false,
|
|
164
|
+
valor_deducoes: '0.00',
|
|
165
|
+
endereco_tomador: {
|
|
166
|
+
tipo_logradouro: 'Rua',
|
|
167
|
+
logradouro: 'Logradouro',
|
|
168
|
+
numero_endereco: '000',
|
|
169
|
+
complemento_endereco: 'Complemento',
|
|
170
|
+
bairro: 'Bairro',
|
|
171
|
+
cidade: '0000000', # Código IBGE
|
|
172
|
+
uf: 'SP',
|
|
173
|
+
cep: '00000000',
|
|
174
|
+
},
|
|
175
|
+
cpf_cnpj_tomador: {
|
|
176
|
+
cnpj: '00000000000000',
|
|
177
|
+
},
|
|
178
|
+
inscricao_municipal_tomador: '000000000000',
|
|
179
|
+
razao_social_tomador: 'Razão Social',
|
|
180
|
+
ibs_cbs: {
|
|
181
|
+
fin_nfse: '0',
|
|
182
|
+
ind_final: '0',
|
|
183
|
+
c_ind_op: '000000',
|
|
184
|
+
ind_dest: '0',
|
|
185
|
+
valores: {
|
|
186
|
+
trib: {
|
|
187
|
+
g_ibs_cbs: {
|
|
188
|
+
c_class_trib: '000000',
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
response = client.sync_teste_envio_lote_rps(data)
|
|
198
|
+
# TODO: exemplo de resposta
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
CANCELAMENTO DE NF-E:
|
|
202
|
+
|
|
203
|
+
```ruby
|
|
204
|
+
data = {
|
|
205
|
+
cnpj_remetente: '00000000000000',
|
|
206
|
+
transacao: false,
|
|
207
|
+
detalhes: [
|
|
208
|
+
{
|
|
209
|
+
chave_nfe: {
|
|
210
|
+
inscricao_prestador: '00000000',
|
|
211
|
+
numero_nfe: '000000000000',
|
|
212
|
+
# codigo_verificacao: '000000',
|
|
213
|
+
# chave_nota_nacional: '000000',
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
],
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
response = client.sync_cancelamento_nfe(data)
|
|
220
|
+
|
|
221
|
+
response.success? # true / false
|
|
222
|
+
response.retorno # Hash
|
|
223
|
+
response.retorno[:alerta] # Alertas
|
|
224
|
+
response.retorno[:erro] # Erros
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Exemplos de serviços assíncronos
|
|
228
|
+
|
|
229
|
+
TODO
|
|
230
|
+
|
|
231
|
+
## Licença
|
|
232
|
+
|
|
233
|
+
Esta gem está disponível como código aberto sob os termos da [Licença MIT](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Handles communication with Prefeitura de São Paulo web services.
|
|
4
|
+
class NfsePrefeituraSp::Client
|
|
5
|
+
def initialize(cert_path:, cert_password:)
|
|
6
|
+
raise "[NfsePrefeituraSp] Certificate path missing" if !File.exist?(cert_path)
|
|
7
|
+
OpenSSL::Provider.load("legacy") if defined?(OpenSSL::Provider)
|
|
8
|
+
@cert = OpenSSL::PKCS12.new(File.read(cert_path), cert_password)
|
|
9
|
+
@signer = NfsePrefeituraSp::Signer.new(@cert)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# TESTE DE ENVIO DE LOTE DE RPS
|
|
13
|
+
def sync_teste_envio_lote_rps(data)
|
|
14
|
+
call_service(NfsePrefeituraSp::Services::Sync::TesteEnvioLoteRPS.new(data, @signer))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# ENVIO DE RPS
|
|
18
|
+
def sync_envio_rps(data)
|
|
19
|
+
call_service(NfsePrefeituraSp::Services::Sync::EnvioRps.new(data, @signer))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# CANCELAMENTO DE NF-E
|
|
23
|
+
def sync_cancelamento_nfe(data)
|
|
24
|
+
call_service(NfsePrefeituraSp::Services::Sync::CancelamentoNfe.new(data, @signer))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def call_service(service)
|
|
30
|
+
soap_client = new_soap_client(:sync)
|
|
31
|
+
message = service.request_xml
|
|
32
|
+
|
|
33
|
+
# request = soap_client.build_request(service.class::OPERATION_REQUEST, message: message, attributes:{ xmlns: 'http://www.prefeitura.sp.gov.br/nfe' })
|
|
34
|
+
# puts "\n\n\n\n\n=============== REQUEST ==============="
|
|
35
|
+
# puts request.body
|
|
36
|
+
# puts "=============== REQUEST ===============\n\n\n\n\n"
|
|
37
|
+
|
|
38
|
+
response = soap_client.call(service.class::OPERATION_REQUEST, message: message, attributes: { xmlns: 'http://www.prefeitura.sp.gov.br/nfe' })
|
|
39
|
+
# puts "=============== RESPONSE ==============="
|
|
40
|
+
# puts response.full_hash[:envelope][:body][service.class::OPERATION_RESPONSE][:retorno_xml]
|
|
41
|
+
# puts "=============== RESPONSE ===============\n\n\n\n\n"
|
|
42
|
+
|
|
43
|
+
NfsePrefeituraSp::Response.new(xml: response.full_hash[:envelope][:body][service.class::OPERATION_RESPONSE][:retorno_xml], method: service.class::OPERATION_REQUEST)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def new_soap_client(interface)
|
|
47
|
+
wsdl = case interface
|
|
48
|
+
when :sync
|
|
49
|
+
NfsePrefeituraSp::Services::Sync::WSDL_URL
|
|
50
|
+
when :async
|
|
51
|
+
NfsePrefeituraSp::Services::Async::WSDL_URL
|
|
52
|
+
else
|
|
53
|
+
raise "[NfsePrefeituraSp] Unknown interface `#{interface}`."
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
Savon.client(
|
|
57
|
+
env_namespace: :soap,
|
|
58
|
+
soap_version: 2,
|
|
59
|
+
ssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
|
|
60
|
+
ssl_cert: @cert.certificate,
|
|
61
|
+
ssl_cert_key: @cert.key,
|
|
62
|
+
wsdl: wsdl,
|
|
63
|
+
namespace_identifier: nil,
|
|
64
|
+
open_timeout: 300,
|
|
65
|
+
read_timeout: 300,
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Based on https://github.com/iugu/nfe-paulistana in order to keep as consistent as possible.
|
|
3
|
+
class NfsePrefeituraSp::Response
|
|
4
|
+
RETURN_ROOT = {
|
|
5
|
+
teste_envio_lote_rps: :envio_lote_rps,
|
|
6
|
+
consulta_n_fe: :consulta,
|
|
7
|
+
consulta_n_fe_emitidas: :consulta,
|
|
8
|
+
consulta_n_fe_recebidas: :consulta,
|
|
9
|
+
consulta_lote: :consulta,
|
|
10
|
+
consulta_informacoes_lote: :informacoes_lote,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
def initialize(options = {})
|
|
14
|
+
@options = options
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def xml
|
|
18
|
+
@options[:xml]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def nfe_method
|
|
22
|
+
@options[:method]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def retorno
|
|
26
|
+
Hash.from_xml(Nokogiri::XML(xml).to_s).deep_transform_keys { |key| key.to_s.underscore.to_sym }[("retorno_" + (RETURN_ROOT[@options[:method]] || @options[:method]).to_s).to_sym]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def success?
|
|
30
|
+
retorno[:cabecalho][:sucesso] == 'true'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def errors
|
|
34
|
+
return if success?
|
|
35
|
+
retorno[:alerta] || retorno[:erro]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# PedidoCancelamentoNFe
|
|
2
|
+
class NfsePrefeituraSp::Services::Sync::CancelamentoNfe
|
|
3
|
+
OPERATION_REQUEST = :cancelamento_n_fe
|
|
4
|
+
OPERATION_RESPONSE = :cancelamento_n_fe_response
|
|
5
|
+
|
|
6
|
+
def initialize(data, signer)
|
|
7
|
+
@data = data
|
|
8
|
+
@signer = signer
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def request_xml
|
|
12
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
|
13
|
+
xml.PedidoCancelamentoNFe("xmlns" => "http://www.prefeitura.sp.gov.br/nfe") do
|
|
14
|
+
xml.Cabecalho('Versao' => '2', 'xmlns' => '') do
|
|
15
|
+
xml.CPFCNPJRemetente do
|
|
16
|
+
xml.CNPJ @data[:cnpj_remetente]
|
|
17
|
+
end
|
|
18
|
+
xml.transacao (@data[:transacao] == false ? false : true)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Array(@data[:detalhes]).each do |detalhe|
|
|
22
|
+
xml.Detalhe('xmlns' => '') do
|
|
23
|
+
NfsePrefeituraSp::Types::TpChaveNfe.new('ChaveNFe', detalhe[:chave_nfe]).add_tag_to_xml(xml)
|
|
24
|
+
|
|
25
|
+
# Cadeia de caracteres (com informações do RPS emitido) assinada conforme descrito no item 4.3.10.
|
|
26
|
+
inscricao_prestador = detalhe[:chave_nfe][:inscricao_prestador].to_s.rjust(8, '0')
|
|
27
|
+
numero = detalhe[:chave_nfe][:numero_nfe].to_s.rjust(12, '0')
|
|
28
|
+
str_to_sign = "#{inscricao_prestador}#{numero}"
|
|
29
|
+
|
|
30
|
+
xml.AssinaturaCancelamento @signer.sign(str_to_sign)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
signed_xml = @signer.sign_xml(builder.to_xml)
|
|
37
|
+
("<VersaoSchema>#{NfsePrefeituraSp::XSD_VERSION.to_s}</VersaoSchema><MensagemXML>" + "<![CDATA[#{signed_xml}]]>" + "</MensagemXML>").gsub(/\n/,'')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# PedidoEnvioRPS
|
|
2
|
+
class NfsePrefeituraSp::Services::Sync::EnvioRps
|
|
3
|
+
OPERATION_REQUEST = :envio_rps
|
|
4
|
+
OPERATION_RESPONSE = :envio_rps_response
|
|
5
|
+
|
|
6
|
+
def initialize(data, signer)
|
|
7
|
+
@data = data
|
|
8
|
+
@signer = signer
|
|
9
|
+
@rps = NfsePrefeituraSp::Types::TpRps.new('RPS', @data, @signer)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def request_xml
|
|
13
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
|
14
|
+
xml.PedidoEnvioRPS("xmlns" => "http://www.prefeitura.sp.gov.br/nfe") do
|
|
15
|
+
xml.Cabecalho('Versao' => '2', 'xmlns' => '') do
|
|
16
|
+
xml.CPFCNPJRemetente do
|
|
17
|
+
xml.CNPJ @data[:cnpj_remetente]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
@rps.add_tag_to_xml(xml, 'xmlns' => '')
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
signed_xml = @signer.sign_xml(builder.to_xml)
|
|
26
|
+
("<VersaoSchema>#{NfsePrefeituraSp::XSD_VERSION.to_s}</VersaoSchema><MensagemXML>" + "<![CDATA[#{signed_xml}]]>" + "</MensagemXML>").gsub(/\n/,'')
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# TestePedidoEnvioLoteRPS
|
|
2
|
+
class NfsePrefeituraSp::Services::Sync::TesteEnvioLoteRPS
|
|
3
|
+
OPERATION_REQUEST = :teste_envio_lote_rps
|
|
4
|
+
OPERATION_RESPONSE = :teste_envio_lote_rps_response
|
|
5
|
+
|
|
6
|
+
def initialize(data, signer)
|
|
7
|
+
@data = data
|
|
8
|
+
@signer = signer
|
|
9
|
+
@rps = NfsePrefeituraSp::Types::TpRps.new('RPS', @data, @signer)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def request_xml
|
|
13
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
|
14
|
+
xml.PedidoEnvioLoteRPS("xmlns" => "http://www.prefeitura.sp.gov.br/nfe") do
|
|
15
|
+
xml.Cabecalho('Versao' => '2', 'xmlns' => '') do
|
|
16
|
+
xml.CPFCNPJRemetente do
|
|
17
|
+
xml.CNPJ @data[:cnpj_remetente]
|
|
18
|
+
end
|
|
19
|
+
xml.transacao false
|
|
20
|
+
xml.dtInicio @data[:dt_inicio]
|
|
21
|
+
xml.dtFim @data[:dt_fim]
|
|
22
|
+
xml.QtdRPS 1
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
@rps.add_tag_to_xml(xml, 'xmlns' => '')
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
signed_xml = @signer.sign_xml(builder.to_xml)
|
|
30
|
+
("<VersaoSchema>#{NfsePrefeituraSp::XSD_VERSION.to_s}</VersaoSchema><MensagemXML>" + "<![CDATA[#{signed_xml}]]>" + "</MensagemXML>").gsub(/\n/,'')
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Based on https://github.com/iugu/nfe-paulistana
|
|
3
|
+
class NfsePrefeituraSp::Signer
|
|
4
|
+
def initialize(cert)
|
|
5
|
+
@cert = cert
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def sign(input_str)
|
|
9
|
+
sign_hash = @cert.key.sign(OpenSSL::Digest::SHA1.new, input_str)
|
|
10
|
+
Base64.strict_encode64(sign_hash)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def sign_xml(xml)
|
|
14
|
+
xml = Nokogiri::XML(xml.to_s, &:noblanks)
|
|
15
|
+
|
|
16
|
+
# 1. Digest Hash for all XML
|
|
17
|
+
xml_canon = xml.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
|
|
18
|
+
xml_digest = Base64.encode64(OpenSSL::Digest::SHA1.digest(xml_canon)).strip
|
|
19
|
+
|
|
20
|
+
# 2. Add Signature Node
|
|
21
|
+
signature = xml.xpath("//ds:Signature", "ds" => "http://www.w3.org/2000/09/xmldsig#").first
|
|
22
|
+
unless signature
|
|
23
|
+
signature = Nokogiri::XML::Node.new('Signature', xml)
|
|
24
|
+
signature.default_namespace = 'http://www.w3.org/2000/09/xmldsig#'
|
|
25
|
+
xml.root().add_child(signature)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# 3. Add Elements to Signature Node
|
|
29
|
+
|
|
30
|
+
# 3.1 Create Signature Info
|
|
31
|
+
signature_info = Nokogiri::XML::Node.new('SignedInfo', xml)
|
|
32
|
+
|
|
33
|
+
# 3.2 Add CanonicalizationMethod
|
|
34
|
+
child_node = Nokogiri::XML::Node.new('CanonicalizationMethod', xml)
|
|
35
|
+
child_node['Algorithm'] = 'http://www.w3.org/2001/10/xml-exc-c14n#'
|
|
36
|
+
signature_info.add_child child_node
|
|
37
|
+
|
|
38
|
+
# 3.3 Add SignatureMethod
|
|
39
|
+
child_node = Nokogiri::XML::Node.new('SignatureMethod', xml)
|
|
40
|
+
child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
|
|
41
|
+
signature_info.add_child child_node
|
|
42
|
+
|
|
43
|
+
# 3.4 Create Reference
|
|
44
|
+
reference = Nokogiri::XML::Node.new('Reference', xml)
|
|
45
|
+
reference['URI'] = ''
|
|
46
|
+
|
|
47
|
+
# 3.5 Add Transforms
|
|
48
|
+
transforms = Nokogiri::XML::Node.new('Transforms', xml)
|
|
49
|
+
|
|
50
|
+
child_node = Nokogiri::XML::Node.new('Transform', xml)
|
|
51
|
+
child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'
|
|
52
|
+
transforms.add_child child_node
|
|
53
|
+
|
|
54
|
+
child_node = Nokogiri::XML::Node.new('Transform', xml)
|
|
55
|
+
child_node['Algorithm'] = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
|
|
56
|
+
transforms.add_child child_node
|
|
57
|
+
|
|
58
|
+
reference.add_child transforms
|
|
59
|
+
|
|
60
|
+
# 3.6 Add Digest
|
|
61
|
+
child_node = Nokogiri::XML::Node.new('DigestMethod', xml)
|
|
62
|
+
child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#sha1'
|
|
63
|
+
reference.add_child child_node
|
|
64
|
+
|
|
65
|
+
# 3.6 Add DigestValue
|
|
66
|
+
child_node = Nokogiri::XML::Node.new('DigestValue', xml)
|
|
67
|
+
child_node.content = xml_digest
|
|
68
|
+
reference.add_child child_node
|
|
69
|
+
|
|
70
|
+
# 3.7 Add Reference and Signature Info
|
|
71
|
+
signature_info.add_child reference
|
|
72
|
+
signature.add_child signature_info
|
|
73
|
+
|
|
74
|
+
# 4 Sign Signature
|
|
75
|
+
sign_canon = signature_info.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
|
|
76
|
+
signature_hash = @cert.key.sign(OpenSSL::Digest::SHA1.new, sign_canon)
|
|
77
|
+
signature_value = Base64.encode64(signature_hash).gsub("\n", '')
|
|
78
|
+
|
|
79
|
+
# 4.1 Add SignatureValue
|
|
80
|
+
child_node = Nokogiri::XML::Node.new('SignatureValue', xml)
|
|
81
|
+
child_node.content = signature_value
|
|
82
|
+
signature.add_child child_node
|
|
83
|
+
|
|
84
|
+
# 5 Create KeyInfo
|
|
85
|
+
key_info = Nokogiri::XML::Node.new('KeyInfo', xml)
|
|
86
|
+
|
|
87
|
+
# 5.1 Add X509 Data and Certificate
|
|
88
|
+
x509_data = Nokogiri::XML::Node.new('X509Data', xml)
|
|
89
|
+
x509_certificate = Nokogiri::XML::Node.new('X509Certificate', xml)
|
|
90
|
+
x509_certificate.content = @cert.certificate.to_s.gsub(/\-\-\-\-\-[A-Z]+ CERTIFICATE\-\-\-\-\-/, "").gsub(/\n/,"")
|
|
91
|
+
|
|
92
|
+
x509_data.add_child x509_certificate
|
|
93
|
+
key_info.add_child x509_data
|
|
94
|
+
|
|
95
|
+
# 5.2 Add KeyInfo
|
|
96
|
+
signature.add_child key_info
|
|
97
|
+
|
|
98
|
+
# 6 Add Signature
|
|
99
|
+
xml.root().add_child signature
|
|
100
|
+
|
|
101
|
+
# Return XML
|
|
102
|
+
xml.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module NfsePrefeituraSp::Types
|
|
2
|
+
class Complex
|
|
3
|
+
def initialize(key, data, signer = nil)
|
|
4
|
+
@key = key
|
|
5
|
+
@data = data || {}
|
|
6
|
+
@data = (@data.respond_to?('with_indifferent_access') ? @data.with_indifferent_access : @data)
|
|
7
|
+
@signer = signer
|
|
8
|
+
@children = {}
|
|
9
|
+
|
|
10
|
+
initialize_children
|
|
11
|
+
@children.each { |key, child| define_singleton_method(key) { child } }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize_children; end
|
|
15
|
+
|
|
16
|
+
def has_any_child_value?
|
|
17
|
+
@children.find { |_, child| child.has_any_child_value? }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def add_tag_to_xml(xml, attrs = {})
|
|
21
|
+
if has_any_child_value?
|
|
22
|
+
xml.send(@key, attrs) do
|
|
23
|
+
add_children_tags_to_xml(xml)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def add_children_tags_to_xml
|
|
29
|
+
raise "[NfsePrefeituraSp] Method not implemented error."
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module NfsePrefeituraSp::Types
|
|
2
|
+
class Simple
|
|
3
|
+
attr_accessor :key, :value
|
|
4
|
+
|
|
5
|
+
def initialize(key, value)
|
|
6
|
+
@key = key
|
|
7
|
+
@value = value
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def has_any_child_value?; !@value.nil?; end
|
|
11
|
+
|
|
12
|
+
def add_tag_to_xml(xml)
|
|
13
|
+
xml.send(@key, @value) if !@value.nil?
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# tpChaveNFe
|
|
2
|
+
class NfsePrefeituraSp::Types::TpChaveNfe < NfsePrefeituraSp::Types::Complex
|
|
3
|
+
def initialize_children
|
|
4
|
+
@children[:inscricao_prestador] = NfsePrefeituraSp::Types::Simple.new('InscricaoPrestador', @data[:inscricao_prestador])
|
|
5
|
+
@children[:numero_nfe] = NfsePrefeituraSp::Types::Simple.new('NumeroNFe', @data[:numero_nfe])
|
|
6
|
+
@children[:codigo_verificacao] = NfsePrefeituraSp::Types::Simple.new('CodigoVerificacao', @data[:codigo_verificacao]) if @data[:codigo_verificacao]
|
|
7
|
+
@children[:chave_nota_nacional] = NfsePrefeituraSp::Types::Simple.new('ChaveNotaNacional', @data[:chave_nota_nacional]) if @data[:chave_nota_nacional]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def add_children_tags_to_xml(xml)
|
|
11
|
+
inscricao_prestador.add_tag_to_xml(xml)
|
|
12
|
+
numero_nfe.add_tag_to_xml(xml)
|
|
13
|
+
codigo_verificacao.add_tag_to_xml(xml) if @data[:codigo_verificacao]
|
|
14
|
+
chave_nota_nacional.add_tag_to_xml(xml) if @data[:chave_nota_nacional]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# tpChaveRPS
|
|
2
|
+
class NfsePrefeituraSp::Types::TpChaveRps < NfsePrefeituraSp::Types::Complex
|
|
3
|
+
def initialize_children
|
|
4
|
+
@children[:inscricao_prestador] = NfsePrefeituraSp::Types::Simple.new('InscricaoPrestador', @data[:inscricao_prestador])
|
|
5
|
+
@children[:serie_rps] = NfsePrefeituraSp::Types::Simple.new('SerieRPS', @data[:serie_rps])
|
|
6
|
+
@children[:numero_rps] = NfsePrefeituraSp::Types::Simple.new('NumeroRPS', @data[:numero_rps])
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def add_children_tags_to_xml(xml)
|
|
10
|
+
inscricao_prestador.add_tag_to_xml(xml)
|
|
11
|
+
serie_rps.add_tag_to_xml(xml)
|
|
12
|
+
numero_rps.add_tag_to_xml(xml)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# tpCPFCNPJ
|
|
2
|
+
class NfsePrefeituraSp::Types::TpCpfCnpj < NfsePrefeituraSp::Types::Complex
|
|
3
|
+
def initialize_children
|
|
4
|
+
@children[:cpf] = NfsePrefeituraSp::Types::Simple.new('CPF', @data[:cpf])
|
|
5
|
+
@children[:cnpj] = NfsePrefeituraSp::Types::Simple.new('CNPJ', @data[:cnp])
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def add_children_tags_to_xml(xml)
|
|
9
|
+
if !cpf.nil?
|
|
10
|
+
cpf.add_tag_to_xml(xml)
|
|
11
|
+
elsif !cnpj.nil?
|
|
12
|
+
cnpj.add_tag_to_xml(xml)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# tpCPFCNPJNIF
|
|
2
|
+
class NfsePrefeituraSp::Types::TpCpfCnpjNif < NfsePrefeituraSp::Types::Complex
|
|
3
|
+
def initialize_children
|
|
4
|
+
@children[:cpf] = NfsePrefeituraSp::Types::Simple.new('CPF', @data[:cpf])
|
|
5
|
+
@children[:cnpj] = NfsePrefeituraSp::Types::Simple.new('CNPJ', @data[:cnpj])
|
|
6
|
+
@children[:nif] = NfsePrefeituraSp::Types::Simple.new('NIF', @data[:nif])
|
|
7
|
+
@children[:nao_nif] = NfsePrefeituraSp::Types::Simple.new('NaoNIF', @data[:nao_nif])
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def add_children_tags_to_xml(xml)
|
|
11
|
+
if !cpf.value.nil?
|
|
12
|
+
cpf.add_tag_to_xml(xml)
|
|
13
|
+
elsif !cnpj.value.nil?
|
|
14
|
+
cnpj.add_tag_to_xml(xml)
|
|
15
|
+
elsif !nif.value.nil?
|
|
16
|
+
nif.add_tag_to_xml(xml)
|
|
17
|
+
elsif !nao_nif.value.nil?
|
|
18
|
+
nao_nif.add_tag_to_xml(xml)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# tpEndereco
|
|
2
|
+
class NfsePrefeituraSp::Types::TpEndereco < NfsePrefeituraSp::Types::Complex
|
|
3
|
+
def initialize_children
|
|
4
|
+
@children[:tipo_logradouro] = NfsePrefeituraSp::Types::Simple.new('TipoLogradouro', @data[:tipo_logradouro])
|
|
5
|
+
@children[:logradouro] = NfsePrefeituraSp::Types::Simple.new('Logradouro', @data[:logradouro])
|
|
6
|
+
@children[:numero_endereco] = NfsePrefeituraSp::Types::Simple.new('NumeroEndereco', @data[:numero_endereco])
|
|
7
|
+
@children[:complemento_endereco] = NfsePrefeituraSp::Types::Simple.new('ComplementoEndereco', @data[:complemento_endereco])
|
|
8
|
+
@children[:bairro] = NfsePrefeituraSp::Types::Simple.new('Bairro', @data[:bairro])
|
|
9
|
+
@children[:cidade] = NfsePrefeituraSp::Types::Simple.new('Cidade', @data[:cidade])
|
|
10
|
+
@children[:uf] = NfsePrefeituraSp::Types::Simple.new('UF', @data[:uf])
|
|
11
|
+
@children[:cep] = NfsePrefeituraSp::Types::Simple.new('CEP', @data[:cep])
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def add_children_tags_to_xml(xml)
|
|
15
|
+
tipo_logradouro.add_tag_to_xml(xml)
|
|
16
|
+
logradouro.add_tag_to_xml(xml)
|
|
17
|
+
numero_endereco.add_tag_to_xml(xml)
|
|
18
|
+
complemento_endereco.add_tag_to_xml(xml)
|
|
19
|
+
bairro.add_tag_to_xml(xml)
|
|
20
|
+
cidade.add_tag_to_xml(xml)
|
|
21
|
+
uf.add_tag_to_xml(xml)
|
|
22
|
+
cep.add_tag_to_xml(xml)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# tpGIBSCBS
|
|
2
|
+
class NfsePrefeituraSp::Types::TpGIbsCbs < NfsePrefeituraSp::Types::Complex
|
|
3
|
+
def initialize_children
|
|
4
|
+
@children[:c_class_trib] = NfsePrefeituraSp::Types::Simple.new('cClassTrib', @data[:c_class_trib])
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def add_children_tags_to_xml(xml)
|
|
8
|
+
c_class_trib.add_tag_to_xml(xml)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# tpIBSCBS
|
|
2
|
+
class NfsePrefeituraSp::Types::TpIbsCbs < NfsePrefeituraSp::Types::Complex
|
|
3
|
+
def initialize_children
|
|
4
|
+
@children[:fin_nfse] = NfsePrefeituraSp::Types::Simple.new('finNFSe', @data[:fin_nfse])
|
|
5
|
+
@children[:ind_final] = NfsePrefeituraSp::Types::Simple.new('indFinal', @data[:ind_final])
|
|
6
|
+
@children[:c_ind_op] = NfsePrefeituraSp::Types::Simple.new('cIndOp', @data[:c_ind_op])
|
|
7
|
+
@children[:ind_dest] = NfsePrefeituraSp::Types::Simple.new('indDest', @data[:ind_dest])
|
|
8
|
+
@children[:valores] = NfsePrefeituraSp::Types::TpValores.new('valores', @data[:valores])
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def add_children_tags_to_xml(xml)
|
|
12
|
+
fin_nfse.add_tag_to_xml(xml)
|
|
13
|
+
ind_final.add_tag_to_xml(xml)
|
|
14
|
+
c_ind_op.add_tag_to_xml(xml)
|
|
15
|
+
ind_dest.add_tag_to_xml(xml)
|
|
16
|
+
valores.add_tag_to_xml(xml)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# tpRPS
|
|
2
|
+
class NfsePrefeituraSp::Types::TpRps < NfsePrefeituraSp::Types::Complex
|
|
3
|
+
def initialize_children
|
|
4
|
+
@children[:chave_rps] = NfsePrefeituraSp::Types::TpChaveRps.new('ChaveRPS', @data[:chave_rps])
|
|
5
|
+
@children[:tipo_rps] = NfsePrefeituraSp::Types::Simple.new('TipoRPS', @data[:tipo_rps])
|
|
6
|
+
@children[:data_emissao] = NfsePrefeituraSp::Types::Simple.new('DataEmissao', @data[:data_emissao])
|
|
7
|
+
@children[:status_rps] = NfsePrefeituraSp::Types::Simple.new('StatusRPS', @data[:status_rps])
|
|
8
|
+
@children[:tributacao_rps] = NfsePrefeituraSp::Types::Simple.new('TributacaoRPS', @data[:tributacao_rps])
|
|
9
|
+
@children[:valor_deducoes] = NfsePrefeituraSp::Types::Simple.new('ValorDeducoes', @data[:valor_deducoes])
|
|
10
|
+
@children[:valor_pis] = NfsePrefeituraSp::Types::Simple.new('ValorPIS', @data[:valor_pis])
|
|
11
|
+
@children[:valor_cofins] = NfsePrefeituraSp::Types::Simple.new('ValorCOFINS', @data[:valor_cofins])
|
|
12
|
+
@children[:valor_inss] = NfsePrefeituraSp::Types::Simple.new('ValorINSS', @data[:valor_inss])
|
|
13
|
+
@children[:valor_ir] = NfsePrefeituraSp::Types::Simple.new('ValorIR', @data[:valor_ir])
|
|
14
|
+
@children[:valor_csll] = NfsePrefeituraSp::Types::Simple.new('ValorCSLL', @data[:valor_csll])
|
|
15
|
+
@children[:codigo_servico] = NfsePrefeituraSp::Types::Simple.new('CodigoServico', @data[:codigo_servico])
|
|
16
|
+
@children[:aliquota_servicos] = NfsePrefeituraSp::Types::Simple.new('AliquotaServicos', @data[:aliquota_servicos])
|
|
17
|
+
@children[:iss_retido] = NfsePrefeituraSp::Types::Simple.new('ISSRetido', @data[:iss_retido])
|
|
18
|
+
@children[:cpf_cnpj_tomador] = NfsePrefeituraSp::Types::TpCpfCnpjNif.new('CPFCNPJTomador', @data[:cpf_cnpj_tomador])
|
|
19
|
+
@children[:inscricao_municipal_tomador] = NfsePrefeituraSp::Types::Simple.new('InscricaoMunicipalTomador', @data[:inscricao_municipal_tomador])
|
|
20
|
+
@children[:inscricao_estadual_tomador] = NfsePrefeituraSp::Types::Simple.new('InscricaoEstadualTomador', @data[:inscricao_estadual_tomador])
|
|
21
|
+
@children[:razao_social_tomador] = NfsePrefeituraSp::Types::Simple.new('RazaoSocialTomador', @data[:razao_social_tomador])
|
|
22
|
+
@children[:endereco_tomador] = NfsePrefeituraSp::Types::TpEndereco.new('EnderecoTomador', @data[:endereco_tomador])
|
|
23
|
+
@children[:email_tomador] = NfsePrefeituraSp::Types::Simple.new('EmailTomador', @data[:email_tomador])
|
|
24
|
+
@children[:cpf_cnpj_intermediario] = NfsePrefeituraSp::Types::TpCpfCnpj.new('CPFCNPJIntermediario', @data[:cpf_cnpj_intermediario])
|
|
25
|
+
@children[:inscricao_municipal_intermediario] = NfsePrefeituraSp::Types::Simple.new('InscricaoMunicipalIntermediario', @data[:inscricao_municipal_intermediario])
|
|
26
|
+
@children[:iss_retido_intermediario] = NfsePrefeituraSp::Types::Simple.new('ISSRetidoIntermediario', @data[:iss_retido_intermediario])
|
|
27
|
+
@children[:email_intermediario] = NfsePrefeituraSp::Types::Simple.new('EmailIntermediario', @data[:email_intermediario])
|
|
28
|
+
@children[:discriminacao] = NfsePrefeituraSp::Types::Simple.new('Discriminacao', @data[:discriminacao])
|
|
29
|
+
@children[:valor_carga_tributaria] = NfsePrefeituraSp::Types::Simple.new('ValorCargaTributaria', @data[:valor_carga_tributaria])
|
|
30
|
+
@children[:percentual_carga_tributaria] = NfsePrefeituraSp::Types::Simple.new('PercentualCargaTributaria', @data[:percentual_carga_tributaria])
|
|
31
|
+
@children[:fonte_carga_tributaria] = NfsePrefeituraSp::Types::Simple.new('FonteCargaTributaria', @data[:fonte_carga_tributaria])
|
|
32
|
+
@children[:codigo_cei] = NfsePrefeituraSp::Types::Simple.new('CodigoCEI', @data[:codigo_cei])
|
|
33
|
+
@children[:matricula_obra] = NfsePrefeituraSp::Types::Simple.new('MatriculaObra', @data[:matricula_obra])
|
|
34
|
+
@children[:municipio_prestacao] = NfsePrefeituraSp::Types::Simple.new('MunicipioPrestacao', @data[:municipio_prestacao])
|
|
35
|
+
@children[:valor_total_recebido] = NfsePrefeituraSp::Types::Simple.new('ValorTotalRecebido', @data[:valor_total_recebido])
|
|
36
|
+
@children[:numero_encapsulamento] = NfsePrefeituraSp::Types::Simple.new('NumeroEncapsulamento', @data[:numero_encapsulamento])
|
|
37
|
+
@children[:valor_inicial_cobrado] = NfsePrefeituraSp::Types::Simple.new('ValorInicialCobrado', @data[:valor_inicial_cobrado])
|
|
38
|
+
@children[:valor_final_cobrado] = NfsePrefeituraSp::Types::Simple.new('ValorFinalCobrado', @data[:valor_final_cobrado])
|
|
39
|
+
@children[:valor_multa] = NfsePrefeituraSp::Types::Simple.new('ValorMulta', @data[:valor_multa])
|
|
40
|
+
@children[:valor_juros] = NfsePrefeituraSp::Types::Simple.new('ValorJuros', @data[:valor_juros])
|
|
41
|
+
@children[:valor_ipi] = NfsePrefeituraSp::Types::Simple.new('ValorIPI', @data[:valor_ipi])
|
|
42
|
+
@children[:exigibilidade_suspensa] = NfsePrefeituraSp::Types::Simple.new('ExigibilidadeSuspensa', @data[:exigibilidade_suspensa])
|
|
43
|
+
@children[:pagamento_parcelado_antecipado] = NfsePrefeituraSp::Types::Simple.new('PagamentoParceladoAntecipado', @data[:pagamento_parcelado_antecipado])
|
|
44
|
+
@children[:ncm] = NfsePrefeituraSp::Types::Simple.new('NCM', @data[:ncm])
|
|
45
|
+
@children[:nbs] = NfsePrefeituraSp::Types::Simple.new('NBS', @data[:nbs])
|
|
46
|
+
@children[:c_loc_prestacao] = NfsePrefeituraSp::Types::Simple.new('cLocPrestacao', @data[:c_loc_prestacao])
|
|
47
|
+
@children[:c_pais_prestacao] = NfsePrefeituraSp::Types::Simple.new('cPaisPrestacao', @data[:c_pais_prestacao])
|
|
48
|
+
@children[:ibs_cbs] = NfsePrefeituraSp::Types::TpIbsCbs.new('IBSCBS', @data[:ibs_cbs])
|
|
49
|
+
@children[:assinatura] = NfsePrefeituraSp::Types::Simple.new('Assinatura', generate_signature)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def add_children_tags_to_xml(xml)
|
|
53
|
+
assinatura.add_tag_to_xml(xml)
|
|
54
|
+
chave_rps.add_tag_to_xml(xml)
|
|
55
|
+
tipo_rps.add_tag_to_xml(xml)
|
|
56
|
+
data_emissao.add_tag_to_xml(xml)
|
|
57
|
+
status_rps.add_tag_to_xml(xml)
|
|
58
|
+
tributacao_rps.add_tag_to_xml(xml)
|
|
59
|
+
valor_deducoes.add_tag_to_xml(xml)
|
|
60
|
+
valor_pis.add_tag_to_xml(xml)
|
|
61
|
+
valor_cofins.add_tag_to_xml(xml)
|
|
62
|
+
valor_inss.add_tag_to_xml(xml)
|
|
63
|
+
valor_ir.add_tag_to_xml(xml)
|
|
64
|
+
valor_csll.add_tag_to_xml(xml)
|
|
65
|
+
codigo_servico.add_tag_to_xml(xml)
|
|
66
|
+
aliquota_servicos.add_tag_to_xml(xml)
|
|
67
|
+
iss_retido.add_tag_to_xml(xml)
|
|
68
|
+
cpf_cnpj_tomador.add_tag_to_xml(xml)
|
|
69
|
+
inscricao_municipal_tomador.add_tag_to_xml(xml)
|
|
70
|
+
inscricao_estadual_tomador.add_tag_to_xml(xml)
|
|
71
|
+
razao_social_tomador.add_tag_to_xml(xml)
|
|
72
|
+
endereco_tomador.add_tag_to_xml(xml)
|
|
73
|
+
email_tomador.add_tag_to_xml(xml)
|
|
74
|
+
cpf_cnpj_intermediario.add_tag_to_xml(xml)
|
|
75
|
+
inscricao_municipal_intermediario.add_tag_to_xml(xml)
|
|
76
|
+
iss_retido_intermediario.add_tag_to_xml(xml)
|
|
77
|
+
email_intermediario.add_tag_to_xml(xml)
|
|
78
|
+
discriminacao.add_tag_to_xml(xml)
|
|
79
|
+
valor_carga_tributaria.add_tag_to_xml(xml)
|
|
80
|
+
percentual_carga_tributaria.add_tag_to_xml(xml)
|
|
81
|
+
fonte_carga_tributaria.add_tag_to_xml(xml)
|
|
82
|
+
codigo_cei.add_tag_to_xml(xml)
|
|
83
|
+
matricula_obra.add_tag_to_xml(xml)
|
|
84
|
+
municipio_prestacao.add_tag_to_xml(xml)
|
|
85
|
+
valor_total_recebido.add_tag_to_xml(xml)
|
|
86
|
+
numero_encapsulamento.add_tag_to_xml(xml)
|
|
87
|
+
|
|
88
|
+
if !valor_inicial_cobrado.value.nil?
|
|
89
|
+
valor_inicial_cobrado.add_tag_to_xml(xml)
|
|
90
|
+
else
|
|
91
|
+
valor_final_cobrado.add_tag_to_xml(xml)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
valor_multa.add_tag_to_xml(xml)
|
|
95
|
+
valor_juros.add_tag_to_xml(xml)
|
|
96
|
+
valor_ipi.add_tag_to_xml(xml)
|
|
97
|
+
exigibilidade_suspensa.add_tag_to_xml(xml)
|
|
98
|
+
pagamento_parcelado_antecipado.add_tag_to_xml(xml)
|
|
99
|
+
ncm.add_tag_to_xml(xml)
|
|
100
|
+
nbs.add_tag_to_xml(xml)
|
|
101
|
+
|
|
102
|
+
if !c_loc_prestacao.value.nil?
|
|
103
|
+
c_loc_prestacao.add_tag_to_xml(xml)
|
|
104
|
+
else
|
|
105
|
+
c_pais_prestacao.add_tag_to_xml(xml)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
ibs_cbs.add_tag_to_xml(xml)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def generate_signature
|
|
112
|
+
# Build the base string.
|
|
113
|
+
str = ''
|
|
114
|
+
|
|
115
|
+
# 1. Inscrição Municipal do Prestador com 12 posições (dígitos). Completar com zeros à esquerda caso seja necessário.
|
|
116
|
+
str << @children[:chave_rps].inscricao_prestador.value.to_s.rjust(12, '0')
|
|
117
|
+
|
|
118
|
+
# 2. Série do RPS com 5 posições (caracteres). Completar com espaços em branco à direita caso seja necessário.
|
|
119
|
+
# Atenção: Não utilize espaços à esquerda. O conteúdo deverá estar alinhado à esquerda.
|
|
120
|
+
str << @children[:chave_rps].serie_rps.value.to_s.ljust(5, ' ')
|
|
121
|
+
|
|
122
|
+
# 3. Número do RPS com 12 posições (dígitos). Completar com zeros à esquerda caso seja necessário.
|
|
123
|
+
str << @children[:chave_rps].numero_rps.value.to_s.rjust(12, '0')
|
|
124
|
+
|
|
125
|
+
# 4. Data de emissão do RPS no formato AAAAMMDD (caracteres).
|
|
126
|
+
str << @children[:data_emissao].value.to_s.gsub(/\D/, '')
|
|
127
|
+
|
|
128
|
+
# 5. Tipo de Tributação do RPS com 1 posição (caractere).
|
|
129
|
+
str << @children[:tributacao_rps].value.to_s
|
|
130
|
+
|
|
131
|
+
# 6. Status do RPS com 1 posição (caractere).
|
|
132
|
+
str << @children[:status_rps].value.to_s
|
|
133
|
+
|
|
134
|
+
# 7. Valor 'S' (SIM) para ISS Retido.
|
|
135
|
+
# Valor 'N' (NÃO) para Nota Fiscal sem ISS Retido.
|
|
136
|
+
str << (@children[:iss_retido].value.to_s === true ? 'S' : 'N')
|
|
137
|
+
|
|
138
|
+
# 8. Valor Inicial ou Final Cobrado dos Serviços do RPS, incluindo os centavos (sem ponto decimal e sem R$),
|
|
139
|
+
# com 15 posições (dígitos).
|
|
140
|
+
position_8 = (!@children[:valor_inicial_cobrado].value.nil? ? @children[:valor_inicial_cobrado].value : @children[:valor_final_cobrado].value).to_s
|
|
141
|
+
str << position_8.delete(',').delete('.').rjust(15, '0')
|
|
142
|
+
|
|
143
|
+
# 9. Valor das Deduções do RPS, incluindo os centavos (sem ponto decimal e sem R$), com 15 posições (dígitos).
|
|
144
|
+
str << @children[:valor_deducoes].value.to_s.delete(',').delete('.').rjust(15, '0')
|
|
145
|
+
|
|
146
|
+
# 10. Código do Serviço do RPS com 5 posições (dígitos). Completar com zeros à esquerda caso seja necessário.
|
|
147
|
+
str << @children[:codigo_servico].value.to_s.rjust(5, '0')
|
|
148
|
+
|
|
149
|
+
# Positions 11 and 12.
|
|
150
|
+
if !@children[:cpf_cnpj_tomador].cpf.value.nil?
|
|
151
|
+
position_11 = '1'
|
|
152
|
+
position_12 = @children[:cpf_cnpj_tomador].cpf.value.to_s
|
|
153
|
+
elsif !@children[:cpf_cnpj_tomador].cnpj.value.nil?
|
|
154
|
+
position_11 = '2'
|
|
155
|
+
position_12 = @children[:cpf_cnpj_tomador].cnpj.value.to_s
|
|
156
|
+
elsif !@children[:cpf_cnpj_tomador].nif.value.nil?
|
|
157
|
+
position_11 = '4'
|
|
158
|
+
position_12 = @children[:cpf_cnpj_tomador].nif.value.to_s
|
|
159
|
+
else
|
|
160
|
+
position_11 = '3'
|
|
161
|
+
position_12 = ''
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# 11. Indicador de CPF/CNPJ do Tomador com 1 posição (dígito).
|
|
165
|
+
# Valor 1 para CPF.
|
|
166
|
+
# Valor 2 para CNPJ.
|
|
167
|
+
# Valor 3 para Não informado.
|
|
168
|
+
# Valor 4 para NIF (obrigatório preencher campo 16).
|
|
169
|
+
str << position_11
|
|
170
|
+
|
|
171
|
+
# 12. CPF/CNPJ do tomador com 14 posições (dígitos). Sem formatação (ponto, traço, barra, ....).
|
|
172
|
+
# Completar com zeros à esquerda caso seja necessário. Se o Indicador do CPF/CNPJ for 3 (não informado) ou 4 (NIF),
|
|
173
|
+
# preencher com 14 zeros.
|
|
174
|
+
str << position_12.rjust(14, '0')
|
|
175
|
+
|
|
176
|
+
# Observação: não é necessário informar os dados de intermediário na assinatura se não houver intermediário.
|
|
177
|
+
if !@children[:cpf_cnpj_intermediario].cpf.value.nil? || !@children[:cpf_cnpj_intermediario].cnpj.value.nil?
|
|
178
|
+
# Positions 13 and 14.
|
|
179
|
+
if !@children[:cpf_cnpj_intermediario].cpf.nil?
|
|
180
|
+
position_13 = '1'
|
|
181
|
+
position_14 = @children[:cpf_cnpj_intermediario].cpf.to_s
|
|
182
|
+
elsif !@children[:cpf_cnpj_intermediario].cnpj.nil?
|
|
183
|
+
position_13 = '2'
|
|
184
|
+
position_14 = @children[:cpf_cnpj_intermediario].cnpj.to_s
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# 13. Indicador de CPF/CNPJ do Intermediário com 1 posição (dígito).
|
|
188
|
+
# Valor 1 para CPF.
|
|
189
|
+
# Valor 2 para CNPJ.
|
|
190
|
+
# Valor 3 para Não informado o CPF/CNPJ do Intermediário.
|
|
191
|
+
str << position_13
|
|
192
|
+
|
|
193
|
+
# 14. CPF/CNPJ do intermediário com 14 posições (dígitos). Sem formatação (ponto, traço, barra,....).
|
|
194
|
+
# Completar com zeros à esquerda caso seja necessário. Se o Indicador do CPF/CNPJ for 3 (não informado),
|
|
195
|
+
# preencher com 14 zeros.
|
|
196
|
+
str << position_14.rjust(14, '0')
|
|
197
|
+
|
|
198
|
+
# 15. ISS Retido Intermediário
|
|
199
|
+
# Valor 'S' (SIM) para ISS Retido pelo Intermediário
|
|
200
|
+
# Valor 'N' (NÃO) para ISS não retido pelo Intermediário
|
|
201
|
+
str << @children[:iss_retido_intermediario].value.to_s
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# 16. NIF ou NãoNIF
|
|
205
|
+
# Caso for preenchido NaoNif, informar apenas 1 posição com o valor:
|
|
206
|
+
# 0 - Não informado na nota de origem
|
|
207
|
+
# 1 - Dispensado do NIF
|
|
208
|
+
# 2 - Não exigência do NIF
|
|
209
|
+
# Caso tenha o NIF, preencher com o NIF, sem espaços no começo ou final do NIF.
|
|
210
|
+
# O tamanho total do NIF não pode ultrapassar 40 caracteres.
|
|
211
|
+
# str << ... TODO
|
|
212
|
+
|
|
213
|
+
@signer.sign(str)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# tpTrib
|
|
2
|
+
class NfsePrefeituraSp::Types::TpTrib < NfsePrefeituraSp::Types::Complex
|
|
3
|
+
def initialize_children
|
|
4
|
+
@children[:g_ibs_cbs] = NfsePrefeituraSp::Types::TpGIbsCbs.new('gIBSCBS', @data[:g_ibs_cbs])
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def add_children_tags_to_xml(xml)
|
|
8
|
+
g_ibs_cbs.add_tag_to_xml(xml)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# tpValores
|
|
2
|
+
class NfsePrefeituraSp::Types::TpValores < NfsePrefeituraSp::Types::Complex
|
|
3
|
+
def initialize_children
|
|
4
|
+
@children[:trib] = NfsePrefeituraSp::Types::TpTrib.new('trib', @data[:trib])
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def add_children_tags_to_xml(xml)
|
|
8
|
+
trib.add_tag_to_xml(xml)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'base64'
|
|
4
|
+
require 'openssl'
|
|
5
|
+
require 'nokogiri'
|
|
6
|
+
require 'savon'
|
|
7
|
+
|
|
8
|
+
module NfsePrefeituraSp
|
|
9
|
+
# Supports only XSD version 2.x introduced by the "Reforma triburtária 2026".
|
|
10
|
+
XSD_VERSION = 2
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
require_relative 'nfse_prefeitura_sp/client'
|
|
14
|
+
require_relative 'nfse_prefeitura_sp/response'
|
|
15
|
+
require_relative 'nfse_prefeitura_sp/services'
|
|
16
|
+
require_relative 'nfse_prefeitura_sp/signer'
|
|
17
|
+
require_relative 'nfse_prefeitura_sp/types'
|
|
18
|
+
require_relative 'nfse_prefeitura_sp/version'
|
|
19
|
+
Dir.glob(File.join(File.expand_path('../', __FILE__), 'nfse_prefeitura_sp/types/**', '*.rb')).each { |file| require_relative(file) }
|
|
20
|
+
Dir.glob(File.join(File.expand_path('../', __FILE__), 'nfse_prefeitura_sp/services/**', '*.rb')).each { |file| require_relative(file) }
|
metadata
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: nfse_prefeitura_sp
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- https://www.infosimples.com.br
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-03-05 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: openssl
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 3.3.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 3.3.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: nokogiri
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 1.18.0
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 1.18.0
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: savon
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 3.0.0.rc2
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 3.0.0.rc2
|
|
55
|
+
description:
|
|
56
|
+
email:
|
|
57
|
+
- contato@infosimples.com.br
|
|
58
|
+
executables: []
|
|
59
|
+
extensions: []
|
|
60
|
+
extra_rdoc_files: []
|
|
61
|
+
files:
|
|
62
|
+
- LICENSE.txt
|
|
63
|
+
- README.md
|
|
64
|
+
- lib/nfse_prefeitura_sp.rb
|
|
65
|
+
- lib/nfse_prefeitura_sp/client.rb
|
|
66
|
+
- lib/nfse_prefeitura_sp/response.rb
|
|
67
|
+
- lib/nfse_prefeitura_sp/services.rb
|
|
68
|
+
- lib/nfse_prefeitura_sp/services/async/.keep
|
|
69
|
+
- lib/nfse_prefeitura_sp/services/sync/cancelamento_nfe.rb
|
|
70
|
+
- lib/nfse_prefeitura_sp/services/sync/envio_rps.rb
|
|
71
|
+
- lib/nfse_prefeitura_sp/services/sync/teste_envio_lote_rps.rb
|
|
72
|
+
- lib/nfse_prefeitura_sp/signer.rb
|
|
73
|
+
- lib/nfse_prefeitura_sp/types.rb
|
|
74
|
+
- lib/nfse_prefeitura_sp/types/complex.rb
|
|
75
|
+
- lib/nfse_prefeitura_sp/types/simple.rb
|
|
76
|
+
- lib/nfse_prefeitura_sp/types/tp_chave_nfe.rb
|
|
77
|
+
- lib/nfse_prefeitura_sp/types/tp_chave_rps.rb
|
|
78
|
+
- lib/nfse_prefeitura_sp/types/tp_cpf_cnpj.rb
|
|
79
|
+
- lib/nfse_prefeitura_sp/types/tp_cpf_cnpj_nif.rb
|
|
80
|
+
- lib/nfse_prefeitura_sp/types/tp_endereco.rb
|
|
81
|
+
- lib/nfse_prefeitura_sp/types/tp_g_ibs_cbs.rb
|
|
82
|
+
- lib/nfse_prefeitura_sp/types/tp_ibs_cbs.rb
|
|
83
|
+
- lib/nfse_prefeitura_sp/types/tp_rps.rb
|
|
84
|
+
- lib/nfse_prefeitura_sp/types/tp_trib.rb
|
|
85
|
+
- lib/nfse_prefeitura_sp/types/tp_valores.rb
|
|
86
|
+
- lib/nfse_prefeitura_sp/version.rb
|
|
87
|
+
homepage: https://github.com/infosimples/nfse_prefeitura_sp
|
|
88
|
+
licenses:
|
|
89
|
+
- MIT
|
|
90
|
+
metadata: {}
|
|
91
|
+
post_install_message:
|
|
92
|
+
rdoc_options: []
|
|
93
|
+
require_paths:
|
|
94
|
+
- lib
|
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: 3.1.0
|
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: '0'
|
|
105
|
+
requirements: []
|
|
106
|
+
rubygems_version: 3.5.22
|
|
107
|
+
signing_key:
|
|
108
|
+
specification_version: 4
|
|
109
|
+
summary: Gem para integração com a Nota Fiscal de Serviços Eletrônica (NFS-e) da Prefeitura
|
|
110
|
+
de São Paulo.
|
|
111
|
+
test_files: []
|