nfe-paulistana 0.5.0 → 1.0.5
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/.gitignore +1 -0
- data/.ruby-version +1 -0
- data/Gemfile.lock +43 -30
- data/LICENSE +21 -0
- data/README.md +186 -0
- data/Rakefile +10 -0
- data/lib/nfe-paulistana.rb +18 -296
- data/lib/nfe-paulistana/gateway.rb +96 -0
- data/lib/nfe-paulistana/response.rb +36 -0
- data/lib/nfe-paulistana/version.rb +2 -2
- data/lib/nfe-paulistana/xml_builder.rb +395 -0
- data/nfe-paulistana.gemspec +9 -8
- data/test/lib/nfe-paulistana/envio_rps_test.rb +32 -0
- data/test/lib/nfe-paulistana/version_test.rb +7 -0
- data/test/test_helper.rb +4 -0
- metadata +67 -36
- data/test.rb +0 -21
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'savon'
|
2
|
+
|
3
|
+
module NfePaulistana
|
4
|
+
class Gateway
|
5
|
+
|
6
|
+
METHODS = {
|
7
|
+
envio_rps: "EnvioRPSRequest",
|
8
|
+
envio_lote_rps: "EnvioLoteRPSRequest",
|
9
|
+
teste_envio_lote_rps: "TesteEnvioLoteRPSRequest",
|
10
|
+
cancelamento_n_fe: "CancelamentoNFeRequest",
|
11
|
+
consulta_cnpj: "ConsultaCNPJRequest",
|
12
|
+
consulta_n_fe: "ConsultaNFeRequest",
|
13
|
+
consulta_n_fe_recebidas: "ConsultaNFeRecebidasRequest",
|
14
|
+
consulta_n_fe_emitidas: "ConsultaNFeEmitidasRequest",
|
15
|
+
consulta_lote: "ConsultaLoteRequest",
|
16
|
+
consulta_informacoes_lote: "ConsultaInformacoesLoteRequest"
|
17
|
+
}
|
18
|
+
|
19
|
+
def initialize(options = {})
|
20
|
+
@options = {
|
21
|
+
ssl_cert_p12_path: "",
|
22
|
+
ssl_cert_path: "",
|
23
|
+
ssl_key_path: "",
|
24
|
+
ssl_cert_pass: "",
|
25
|
+
wsdl: 'https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx?wsdl'
|
26
|
+
}.merge(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def envio_rps(data = {})
|
30
|
+
request(:envio_rps, data)
|
31
|
+
end
|
32
|
+
|
33
|
+
def envio_lote_rps(data = {})
|
34
|
+
request(:envio_lote_rps, data)
|
35
|
+
end
|
36
|
+
|
37
|
+
def teste_envio_lote_rps(data = {})
|
38
|
+
request(:teste_envio_lote_rps, data)
|
39
|
+
end
|
40
|
+
|
41
|
+
def cancelamento_nfe(data = {})
|
42
|
+
request(:cancelamento_n_fe, data)
|
43
|
+
end
|
44
|
+
|
45
|
+
def consulta_nfe(data = {})
|
46
|
+
request(:consulta_n_fe, data)
|
47
|
+
end
|
48
|
+
|
49
|
+
def consulta_nfe_recebidas(data = {})
|
50
|
+
request(:consulta_n_fe_recebidas, data)
|
51
|
+
end
|
52
|
+
|
53
|
+
def consulta_nfe_emitidas(data = {})
|
54
|
+
request(:consulta_n_fe_emitidas, data)
|
55
|
+
end
|
56
|
+
|
57
|
+
def consulta_lote(data = {})
|
58
|
+
request(:consulta_lote, data)
|
59
|
+
end
|
60
|
+
|
61
|
+
def consulta_informacoes_lote(data = {})
|
62
|
+
request(:consulta_informacoes_lote, data)
|
63
|
+
end
|
64
|
+
|
65
|
+
def consulta_cnpj(data = {})
|
66
|
+
request(:consulta_cnpj, data)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def certificate
|
72
|
+
OpenSSL::PKCS12.new(File.read(@options[:ssl_cert_p12_path]), @options[:ssl_cert_pass])
|
73
|
+
end
|
74
|
+
|
75
|
+
def request(method, data = {})
|
76
|
+
certificado = certificate
|
77
|
+
client = get_client
|
78
|
+
message = XmlBuilder.new.xml_for(method, data, certificado)
|
79
|
+
response = client.call(method, message: message)
|
80
|
+
method_response = (method.to_s + "_response").to_sym
|
81
|
+
Response.new(xml: response.hash[:envelope][:body][method_response][:retorno_xml], method: method)
|
82
|
+
rescue Savon::Error => error
|
83
|
+
error
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_client
|
87
|
+
Savon.client(env_namespace: :soap,
|
88
|
+
ssl_verify_mode: :peer,
|
89
|
+
ssl_cert_file: @options[:ssl_cert_path],
|
90
|
+
ssl_cert_key_file: @options[:ssl_key_path],
|
91
|
+
ssl_cert_key_password: @options[:ssl_cert_pass],
|
92
|
+
wsdl: @options[:wsdl],
|
93
|
+
namespace_identifier: nil)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module NfePaulistana
|
2
|
+
class Response
|
3
|
+
RETURN_ROOT = {
|
4
|
+
teste_envio_lote_rps: :envio_lote_rps,
|
5
|
+
consulta_n_fe: :consulta,
|
6
|
+
consulta_n_fe_emitidas: :consulta,
|
7
|
+
consulta_n_fe_recebidas: :consulta,
|
8
|
+
consulta_lote: :consulta,
|
9
|
+
consulta_informacoes_lote: :informacoes_lote,
|
10
|
+
}
|
11
|
+
def initialize(options = {})
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def xml
|
16
|
+
@options[:xml]
|
17
|
+
end
|
18
|
+
|
19
|
+
def nfe_method
|
20
|
+
@options[:method]
|
21
|
+
end
|
22
|
+
|
23
|
+
def retorno
|
24
|
+
Nori.new(:convert_tags_to => lambda { |tag| tag.snakecase.to_sym }).parse(xml)[("retorno_" + (RETURN_ROOT[@options[:method]] || @options[:method]).to_s).to_sym]
|
25
|
+
end
|
26
|
+
|
27
|
+
def success?
|
28
|
+
!!retorno[:cabecalho][:sucesso]
|
29
|
+
end
|
30
|
+
|
31
|
+
def errors
|
32
|
+
return unless !success?
|
33
|
+
retorno[:alerta] || retorno[:erro]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = "0.5
|
1
|
+
module NfePaulistana
|
2
|
+
VERSION = "1.0.5"
|
3
3
|
end
|
@@ -0,0 +1,395 @@
|
|
1
|
+
module NfePaulistana
|
2
|
+
class XmlBuilder
|
3
|
+
|
4
|
+
METHODS = {
|
5
|
+
envio_rps: "PedidoEnvioRPS",
|
6
|
+
envio_lote_rps: "PedidoEnvioLoteRPS",
|
7
|
+
teste_envio_lote_rps: "PedidoEnvioLoteRPS",
|
8
|
+
cancelamento_n_fe: "PedidoCancelamentoNFe",
|
9
|
+
consulta_n_fe: "PedidoConsultaNFe",
|
10
|
+
consulta_n_fe_recebidas: "PedidoConsultaNFePeriodo",
|
11
|
+
consulta_n_fe_emitidas: "PedidoConsultaNFePeriodo",
|
12
|
+
consulta_lote: "PedidoConsultaLote",
|
13
|
+
consulta_informacoes_lote: "PedidoInformacoesLote",
|
14
|
+
consulta_cnpj: "PedidoConsultaCNPJ"
|
15
|
+
}
|
16
|
+
|
17
|
+
DEFAULT_DATA = {
|
18
|
+
:cpf_remetente => '',
|
19
|
+
:cnpj_remetente => '',
|
20
|
+
:inscricao_prestador => '',
|
21
|
+
:serie_rps => '',
|
22
|
+
:numero_rps => '',
|
23
|
+
:tipo_rps => '',
|
24
|
+
:data_emissao => '',
|
25
|
+
:status_rps => '',
|
26
|
+
:tributacao_rps => '',
|
27
|
+
:valor_servicos => '0',
|
28
|
+
:valor_deducoes => '0',
|
29
|
+
:valor_pis => '0',
|
30
|
+
:valor_cofins => '0',
|
31
|
+
:valor_inss => '0',
|
32
|
+
:valor_ir => '0',
|
33
|
+
:valor_csll => '0',
|
34
|
+
:codigo_servico => '0',
|
35
|
+
:aliquota_servicos => '0',
|
36
|
+
:iss_retido => false,
|
37
|
+
:cpf_tomador => '',
|
38
|
+
:cnpj_tomador => '',
|
39
|
+
:iss_retido_intermediario => false,
|
40
|
+
:cpf_intermediario => '',
|
41
|
+
:cnpj_intermediario => '',
|
42
|
+
:im_tomador => '',
|
43
|
+
:ie_tomador => '',
|
44
|
+
:im_intermediario => '',
|
45
|
+
:razao_tomador => '',
|
46
|
+
:tp_logradouro => '',
|
47
|
+
:logradouro => '',
|
48
|
+
:nr_endereco => '',
|
49
|
+
:compl_endereco => '',
|
50
|
+
:bairro => '',
|
51
|
+
:cidade => '',
|
52
|
+
:uf => '',
|
53
|
+
:cep => '',
|
54
|
+
:email_tomador => '',
|
55
|
+
:email_intermediario => '',
|
56
|
+
:discriminacao => '',
|
57
|
+
:wsdl => 'https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx?wsdl'
|
58
|
+
}
|
59
|
+
|
60
|
+
def xml_for(method,data, certificado)
|
61
|
+
data = DEFAULT_DATA.merge(data)
|
62
|
+
("<VersaoSchema>1</VersaoSchema><MensagemXML>" + assinar(xml(method, data, certificado), certificado).gsub("&","&").gsub(">",">").gsub("<","<").gsub("\"",""").gsub("'","'") + "</MensagemXML>").gsub(/\n/,'')
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def xml(method, data, certificado)
|
68
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
69
|
+
xml.send(METHODS[method], "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" ) {
|
70
|
+
xml.Cabecalho( "Versao" => "1", :xmlns => "" ) {
|
71
|
+
xml.CPFCNPJRemetente {
|
72
|
+
xml.CPF data[:cpf_remetente] unless data[:cpf_remetente].blank?
|
73
|
+
xml.CNPJ data[:cnpj_remetente] unless data[:cnpj_remetente].blank?
|
74
|
+
}
|
75
|
+
send("add_#{method}_cabecalho_data_to_xml", xml, data, certificado)
|
76
|
+
}
|
77
|
+
send("add_#{method}_data_to_xml", xml, data, certificado)
|
78
|
+
}
|
79
|
+
end
|
80
|
+
Nokogiri::XML( builder.to_xml( :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION ) )
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_cancelamento_n_fe_cabecalho_data_to_xml(xml, data, certificado)
|
84
|
+
xml.transacao data[:transacao] || true
|
85
|
+
end
|
86
|
+
|
87
|
+
def add_envio_rps_cabecalho_data_to_xml(xml, data, certificado)
|
88
|
+
end
|
89
|
+
|
90
|
+
def add_envio_lote_rps_cabecalho_data_to_xml(xml, data, certificado)
|
91
|
+
add_lote_cabecalho_data_to_xml(xml, data, certificado)
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_teste_envio_lote_rps_cabecalho_data_to_xml(xml, data, certificado)
|
95
|
+
add_lote_cabecalho_data_to_xml(xml, data, certificado)
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_lote_cabecalho_data_to_xml(xml, data, certificado)
|
99
|
+
xml.transacao data[:transacao] || true
|
100
|
+
xml.dtInicio data[:data_inicio]
|
101
|
+
xml.dtFim data[:data_fim]
|
102
|
+
xml.QtdRPS data[:qtd_rps]
|
103
|
+
xml.ValorTotalServicos data[:valor_total_servicos]
|
104
|
+
xml.ValorTotalDeducoes data[:valor_total_deducoes]
|
105
|
+
end
|
106
|
+
|
107
|
+
def add_consulta_cnpj_cabecalho_data_to_xml(xml, data, certificado)
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_consulta_n_fe_cabecalho_data_to_xml(xml, data, certificado)
|
111
|
+
end
|
112
|
+
|
113
|
+
def add_consulta_n_fe_recebidas_cabecalho_data_to_xml(xml,data,certificado)
|
114
|
+
add_consulta_n_fe_periodo_cabecalho_data_to_xml(xml, data, certificado)
|
115
|
+
end
|
116
|
+
|
117
|
+
def add_consulta_n_fe_emitidas_cabecalho_data_to_xml(xml,data,certificado)
|
118
|
+
add_consulta_n_fe_periodo_cabecalho_data_to_xml(xml, data, certificado)
|
119
|
+
end
|
120
|
+
|
121
|
+
def add_consulta_n_fe_periodo_cabecalho_data_to_xml(xml, data, certificado)
|
122
|
+
unless (data[:cpf].blank? and data[:cnpj].blank?)
|
123
|
+
xml.CPFCNPJ {
|
124
|
+
xml.CPF data[:cpf] unless data[:cpf].blank?
|
125
|
+
xml.CNPJ data[:cnpj] unless data[:cnpj].blank?
|
126
|
+
}
|
127
|
+
end
|
128
|
+
xml.Inscricao data[:inscricao] if !data[:inscricao].blank?
|
129
|
+
xml.dtInicio data[:data_inicio]
|
130
|
+
xml.dtFim data[:data_fim]
|
131
|
+
xml.NumeroPagina data[:pagina] || 1
|
132
|
+
end
|
133
|
+
|
134
|
+
def add_consulta_lote_cabecalho_data_to_xml(xml, data, certificado)
|
135
|
+
xml.NumeroLote data[:numero_lote]
|
136
|
+
end
|
137
|
+
|
138
|
+
def add_consulta_informacoes_lote_cabecalho_data_to_xml(xml, data, certificado)
|
139
|
+
xml.NumeroLote data[:numero_lote]
|
140
|
+
xml.InscricaoPrestador data[:inscricao_prestador]
|
141
|
+
end
|
142
|
+
|
143
|
+
def add_consulta_n_fe_recebidas_data_to_xml(xml, data, certificado)
|
144
|
+
end
|
145
|
+
|
146
|
+
def add_consulta_n_fe_emitidas_data_to_xml(xml, data, certificado)
|
147
|
+
end
|
148
|
+
|
149
|
+
def add_consulta_n_fe_data_to_xml(xml, data, certificado)
|
150
|
+
xml.Detalhe(:xmlns => "") {
|
151
|
+
add_chave_rps_to_xml(xml, data) if !data[:numero_rps].blank? and !data[:serie_rps].blank?
|
152
|
+
add_chave_nfe_to_xml(xml, data) if data[:numero_nfe]
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
156
|
+
def add_consulta_cnpj_data_to_xml(xml, data, certificado)
|
157
|
+
xml.CNPJContribuinte(:xmlns => "") {
|
158
|
+
xml.CNPJ data[:cnpj_contribuinte]
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
def add_cancelamento_n_fe_data_to_xml(xml, data, certificado)
|
163
|
+
xml.Detalhe(:xmlns => "") {
|
164
|
+
add_chave_nfe_to_xml(xml, data)
|
165
|
+
xml.AssinaturaCancelamento assinatura_cancelamento_n_fe(data, certificado)
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
def add_envio_rps_data_to_xml(xml, data, certificado)
|
170
|
+
add_rps_to_xml(xml, data, certificado)
|
171
|
+
end
|
172
|
+
|
173
|
+
def add_envio_lote_rps_data_to_xml(xml, data, certificado)
|
174
|
+
add_lote_rps_data_to_xml(xml, data, certificado)
|
175
|
+
end
|
176
|
+
|
177
|
+
def add_teste_envio_lote_rps_data_to_xml(xml, data, certificado)
|
178
|
+
add_lote_rps_data_to_xml(xml, data, certificado)
|
179
|
+
end
|
180
|
+
|
181
|
+
def add_lote_rps_data_to_xml(xml, data, certificado)
|
182
|
+
data[:lote_rps].each do |rps|
|
183
|
+
add_rps_to_xml(xml, rps, certificado)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def add_consulta_lote_data_to_xml(xml, data, certificado)
|
188
|
+
end
|
189
|
+
|
190
|
+
def add_consulta_informacoes_lote_data_to_xml(xml, data, certificado)
|
191
|
+
end
|
192
|
+
|
193
|
+
def add_chave_nfe_to_xml(xml, data)
|
194
|
+
xml.ChaveNFe {
|
195
|
+
xml.InscricaoPrestador data[:inscricao_prestador]
|
196
|
+
xml.NumeroNFe data[:numero_nfe]
|
197
|
+
}
|
198
|
+
end
|
199
|
+
|
200
|
+
def add_chave_rps_to_xml(xml, data)
|
201
|
+
xml.ChaveRPS {
|
202
|
+
xml.InscricaoPrestador data[:inscricao_prestador]
|
203
|
+
xml.SerieRPS data[:serie_rps] unless data[:serie_rps].blank?
|
204
|
+
xml.NumeroRPS data[:numero_rps] unless data[:numero_rps].blank?
|
205
|
+
}
|
206
|
+
end
|
207
|
+
|
208
|
+
def add_rps_to_xml(xml, data, certificado)
|
209
|
+
data = DEFAULT_DATA.merge(data)
|
210
|
+
xml.RPS( :xmlns => "" ) {
|
211
|
+
xml.Assinatura assinatura_envio_rps(data, certificado)
|
212
|
+
add_chave_rps_to_xml(xml, data)
|
213
|
+
xml.TipoRPS data[:tipo_rps]
|
214
|
+
xml.DataEmissao data[:data_emissao]
|
215
|
+
xml.StatusRPS data[:status_rps]
|
216
|
+
xml.TributacaoRPS data[:tributacao_rps]
|
217
|
+
xml.ValorServicos data[:valor_servicos]
|
218
|
+
xml.ValorDeducoes data[:valor_deducoes]
|
219
|
+
xml.ValorPIS data[:valor_pis] if data[:valor_pis] != '0'
|
220
|
+
xml.ValorCOFINS data[:valor_cofins] if data[:valor_cofins] != '0'
|
221
|
+
xml.ValorINSS data[:valor_inss] if data[:valor_inss] != '0'
|
222
|
+
xml.ValorIR data[:valor_ir] if data[:valor_ir] != '0'
|
223
|
+
xml.ValorCSLL data[:valor_csll] if data[:valor_csll] != '0'
|
224
|
+
xml.CodigoServico data[:codigo_servico]
|
225
|
+
xml.AliquotaServicos data[:aliquota_servicos]
|
226
|
+
xml.ISSRetido data[:iss_retido]
|
227
|
+
unless (data[:cpf_tomador].blank? and data[:cnpj_tomador].blank?)
|
228
|
+
xml.CPFCNPJTomador {
|
229
|
+
xml.CPF data[:cpf_tomador] unless data[:cpf_tomador].blank?
|
230
|
+
xml.CNPJ data[:cnpj_tomador] unless data[:cnpj_tomador].blank?
|
231
|
+
}
|
232
|
+
end
|
233
|
+
xml.InscricaoMunicipalTomador data[:im_tomador] unless data[:im_tomador].blank?
|
234
|
+
xml.InscricaoEstadualTomador data[:ie_tomador] unless data[:ie_tomador].blank?
|
235
|
+
xml.RazaoSocialTomador data[:razao_tomador] unless data[:razao_tomador].blank?
|
236
|
+
unless (data[:tp_logradouro].blank? and data[:logradouro].blank? and data[:nr_endereco] and data[:compl_endereco])
|
237
|
+
xml.EnderecoTomador {
|
238
|
+
xml.TipoLogradouro data[:tp_logradouro]
|
239
|
+
xml.Logradouro data[:logradouro]
|
240
|
+
xml.NumeroEndereco data[:nr_endereco]
|
241
|
+
xml.ComplementoEndereco data[:compl_endereco]
|
242
|
+
xml.Bairro data[:bairro] unless data[:bairro].blank?
|
243
|
+
xml.Cidade data[:cidade] unless data[:cidade].blank?
|
244
|
+
xml.UF data[:uf] unless data[:uf]
|
245
|
+
xml.CEP data[:cep] unless data[:cep]
|
246
|
+
}
|
247
|
+
end
|
248
|
+
xml.EmailTomador data[:email_tomador]
|
249
|
+
=begin
|
250
|
+
unless (data[:cpf_intermediario].blank? and data[:cnpj_intermediario].blank?)
|
251
|
+
xml.CPFCNPJIntermediario {
|
252
|
+
xml.CPF data[:cpf_intermediario] unless data[:cpf_intermediario].blank?
|
253
|
+
xml.CNPJ data[:cnpj_intermediario] unless data[:cnpj_intermediario].blank?
|
254
|
+
}
|
255
|
+
xml.InscricaoMunicipalIntermediario data[:im_intermediario] unless data[:im_intermediario].blank?
|
256
|
+
xml.ISSRetidoIntermediario data[:iss_retido_intermediario]
|
257
|
+
xml.EmailIntermediario data[:email_intermediario]
|
258
|
+
end
|
259
|
+
=end
|
260
|
+
xml.Discriminacao data[:discriminacao]
|
261
|
+
}
|
262
|
+
end
|
263
|
+
|
264
|
+
def assinar(xml, certificado)
|
265
|
+
|
266
|
+
xml = Nokogiri::XML(xml.to_s, &:noblanks)
|
267
|
+
|
268
|
+
# 1. Digest Hash for all XML
|
269
|
+
xml_canon = xml.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
|
270
|
+
xml_digest = Base64.encode64(OpenSSL::Digest::SHA1.digest(xml_canon)).strip
|
271
|
+
|
272
|
+
# 2. Add Signature Node
|
273
|
+
signature = xml.xpath("//ds:Signature", "ds" => "http://www.w3.org/2000/09/xmldsig#").first
|
274
|
+
unless signature
|
275
|
+
signature = Nokogiri::XML::Node.new('Signature', xml)
|
276
|
+
signature.default_namespace = 'http://www.w3.org/2000/09/xmldsig#'
|
277
|
+
xml.root().add_child(signature)
|
278
|
+
end
|
279
|
+
|
280
|
+
# 3. Add Elements to Signature Node
|
281
|
+
|
282
|
+
# 3.1 Create Signature Info
|
283
|
+
signature_info = Nokogiri::XML::Node.new('SignedInfo', xml)
|
284
|
+
|
285
|
+
# 3.2 Add CanonicalizationMethod
|
286
|
+
child_node = Nokogiri::XML::Node.new('CanonicalizationMethod', xml)
|
287
|
+
child_node['Algorithm'] = 'http://www.w3.org/2001/10/xml-exc-c14n#'
|
288
|
+
signature_info.add_child child_node
|
289
|
+
|
290
|
+
# 3.3 Add SignatureMethod
|
291
|
+
child_node = Nokogiri::XML::Node.new('SignatureMethod', xml)
|
292
|
+
child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
|
293
|
+
signature_info.add_child child_node
|
294
|
+
|
295
|
+
# 3.4 Create Reference
|
296
|
+
reference = Nokogiri::XML::Node.new('Reference', xml)
|
297
|
+
reference['URI'] = ''
|
298
|
+
|
299
|
+
# 3.5 Add Transforms
|
300
|
+
transforms = Nokogiri::XML::Node.new('Transforms', xml)
|
301
|
+
|
302
|
+
child_node = Nokogiri::XML::Node.new('Transform', xml)
|
303
|
+
child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'
|
304
|
+
transforms.add_child child_node
|
305
|
+
|
306
|
+
child_node = Nokogiri::XML::Node.new('Transform', xml)
|
307
|
+
child_node['Algorithm'] = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
|
308
|
+
transforms.add_child child_node
|
309
|
+
|
310
|
+
reference.add_child transforms
|
311
|
+
|
312
|
+
# 3.6 Add Digest
|
313
|
+
child_node = Nokogiri::XML::Node.new('DigestMethod', xml)
|
314
|
+
child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#sha1'
|
315
|
+
reference.add_child child_node
|
316
|
+
|
317
|
+
# 3.6 Add DigestValue
|
318
|
+
child_node = Nokogiri::XML::Node.new('DigestValue', xml)
|
319
|
+
child_node.content = xml_digest
|
320
|
+
reference.add_child child_node
|
321
|
+
|
322
|
+
# 3.7 Add Reference and Signature Info
|
323
|
+
signature_info.add_child reference
|
324
|
+
signature.add_child signature_info
|
325
|
+
|
326
|
+
# 4 Sign Signature
|
327
|
+
sign_canon = signature_info.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
|
328
|
+
signature_hash = certificado.key.sign(OpenSSL::Digest::SHA1.new, sign_canon)
|
329
|
+
signature_value = Base64.encode64( signature_hash ).gsub("\n", '')
|
330
|
+
|
331
|
+
# 4.1 Add SignatureValue
|
332
|
+
child_node = Nokogiri::XML::Node.new('SignatureValue', xml)
|
333
|
+
child_node.content = signature_value
|
334
|
+
signature.add_child child_node
|
335
|
+
|
336
|
+
# 5 Create KeyInfo
|
337
|
+
key_info = Nokogiri::XML::Node.new('KeyInfo', xml)
|
338
|
+
|
339
|
+
# 5.1 Add X509 Data and Certificate
|
340
|
+
x509_data = Nokogiri::XML::Node.new('X509Data', xml)
|
341
|
+
x509_certificate = Nokogiri::XML::Node.new('X509Certificate', xml)
|
342
|
+
x509_certificate.content = certificado.certificate.to_s.gsub(/\-\-\-\-\-[A-Z]+ CERTIFICATE\-\-\-\-\-/, "").gsub(/\n/,"")
|
343
|
+
|
344
|
+
x509_data.add_child x509_certificate
|
345
|
+
key_info.add_child x509_data
|
346
|
+
|
347
|
+
# 5.2 Add KeyInfo
|
348
|
+
signature.add_child key_info
|
349
|
+
|
350
|
+
# 6 Add Signature
|
351
|
+
xml.root().add_child signature
|
352
|
+
|
353
|
+
# Return XML
|
354
|
+
xml.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
|
355
|
+
end
|
356
|
+
|
357
|
+
def assinatura_cancelamento_n_fe(data, certificado)
|
358
|
+
part_1 = data[:inscricao_prestador].rjust(8,'0')
|
359
|
+
part_2 = data[:numero_nfe].rjust(12,'0')
|
360
|
+
value = part_1 + part_2
|
361
|
+
assinatura_simples(value, certificado)
|
362
|
+
end
|
363
|
+
|
364
|
+
def assinatura_envio_rps(data, certificado)
|
365
|
+
part_1 = data[:inscricao_prestador].rjust(8,'0')
|
366
|
+
part_2 = data[:serie_rps].ljust(5)
|
367
|
+
part_3 = data[:numero_rps].rjust(12,'0')
|
368
|
+
part_4 = data[:data_emissao].delete('-')
|
369
|
+
part_5 = data[:tributacao_rps]
|
370
|
+
part_6 = data[:status_rps]
|
371
|
+
part_7 = data[:iss_retido] ? 'S' : 'N'
|
372
|
+
part_8 = data[:valor_servicos].delete(',').delete('.').rjust(15,'0')
|
373
|
+
part_9 = data[:valor_deducoes].delete(',').delete('.').rjust(15,'0')
|
374
|
+
part_10 = data[:codigo_servico].rjust(5,'0')
|
375
|
+
part_11 = (data[:cpf_tomador].blank? ? (data[:cnpj_tomador].blank? ? '3' : '2') : '1')
|
376
|
+
part_12 = (data[:cpf_tomador].blank? ? (data[:cnpj_tomador].blank? ? "".rjust(14,'0') : data[:cnpj_tomador].rjust(14,'0') ) : data[:cpf_tomador].rjust(14,'0'))
|
377
|
+
=begin
|
378
|
+
part_13 = (data[:cpf_intermediario].blank? ? (data[:cnpj_intermediario].blank? ? '3' : '2') : '1')
|
379
|
+
part_14 = (data[:cpf_intermediario].blank? ? (data[:cnpj_intermediario].blank? ? "".rjust(14,'0') : data[:cnpj_intermediario].rjust(14,'0') ) : data[:cpf_intermediario].rjust(14,'0'))
|
380
|
+
part_15 = data[:iss_retido_intermediario] ? 'S' : 'N'
|
381
|
+
=end
|
382
|
+
|
383
|
+
#value = part_1 + part_2 + part_3 + part_4 + part_5 + part_6 + part_7 + part_8 + part_9 + part_10 + part_11 + part_12 + part_13 + part_14 + part_15
|
384
|
+
value = part_1 + part_2 + part_3 + part_4 + part_5 + part_6 + part_7 + part_8 + part_9 + part_10 + part_11 + part_12
|
385
|
+
|
386
|
+
assinatura_simples(value, certificado)
|
387
|
+
end
|
388
|
+
|
389
|
+
def assinatura_simples(value, certificado)
|
390
|
+
sign_hash = certificado.key.sign( OpenSSL::Digest::SHA1.new, value )
|
391
|
+
Base64.encode64( sign_hash ).gsub("\n",'').gsub("\r",'').strip()
|
392
|
+
end
|
393
|
+
|
394
|
+
end
|
395
|
+
end
|