nfe-paulistana 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -14,6 +14,7 @@ coverage/
14
14
  tmp/
15
15
  tmp/*/*
16
16
  tmp/**
17
+ pkg/*
17
18
  */*.swp
18
19
  db/schema.rb
19
20
  public/system/*
@@ -1,25 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nfe-paulistana (0.0.1)
4
+ nfe-paulistana (0.5.0)
5
5
  nokogiri
6
- savon
6
+ savon (= 0.9.9)
7
7
  signer
8
8
 
9
9
  GEM
10
10
  remote: http://rubygems.org/
11
11
  specs:
12
- akami (1.0.0)
12
+ akami (1.2.0)
13
13
  gyoku (>= 0.4.0)
14
- builder (3.0.0)
14
+ nokogiri (>= 1.4.0)
15
+ builder (3.0.4)
15
16
  diff-lcs (1.1.3)
16
- gyoku (0.4.4)
17
+ gyoku (1.0.0)
17
18
  builder (>= 2.1.2)
18
19
  httpi (0.9.7)
19
20
  rack
20
- nokogiri (1.5.2)
21
- nori (1.1.0)
22
- rack (1.4.1)
21
+ nokogiri (1.5.9)
22
+ nori (1.1.5)
23
+ rack (1.4.5)
23
24
  rspec (2.10.0)
24
25
  rspec-core (~> 2.10.0)
25
26
  rspec-expectations (~> 2.10.0)
@@ -36,9 +37,9 @@ GEM
36
37
  nokogiri (>= 1.4.0)
37
38
  nori (~> 1.1)
38
39
  wasabi (~> 2.1)
39
- signer (1.0.0)
40
+ signer (1.1.1)
40
41
  nokogiri (>= 1.5.1)
41
- wasabi (2.1.1)
42
+ wasabi (2.3.0)
42
43
  nokogiri (>= 1.4.0)
43
44
 
44
45
  PLATFORMS
@@ -0,0 +1,176 @@
1
+ Nota Fiscal Paulistana
2
+ =============
3
+
4
+ Instanciando o Gateway
5
+ --------------------
6
+
7
+ gateway = NfePaulistana::Gateway.new(cert_path: "path/to/certificate.p12", cert_pass: "password")
8
+
9
+ Metodos
10
+ ------------
11
+
12
+ **EnvioRPS**
13
+
14
+ response = gateway.envio_rps({
15
+ :cnpj_remetente => "99999999999999",
16
+ :inscricao_prestador => "99999999",
17
+ :data_emissao => "AAAA-MM-DD",
18
+ :email_tomador => "email@email.email",
19
+ :tipo_rps => "RPS",
20
+ :serie_rps => "AAAAA",
21
+ :status_rps => "N",
22
+ :valor_servicos => "10.00",
23
+ :aliquota_servicos => "0.05",
24
+ :tributacao_rps => "T",
25
+ :numero_rps => "1",
26
+ :cpf_tomador => "99999999999",
27
+ :codigo_servico => "99999",
28
+ :discriminacao => ""
29
+ })
30
+
31
+ **EnvioLoteRPS**
32
+
33
+ response = gateway.envio_lote_rps({
34
+ :cnpj_remetente => "99999999999999",
35
+ :inscricao_prestador => "99999999",
36
+ :data_inicio => "AAAA-MM-DD",
37
+ :data_fim => "AAAA-MM-DD",
38
+ :qtd_rps => "2",
39
+ :valor_total_servicos => "20.00",
40
+ :valor_total_deducoes => "0",
41
+ :lote_rps => => [{
42
+ :inscricao_prestador => "99999999",
43
+ :data_emissao => "AAAA-MM-DD",
44
+ :email_tomador => "email@email.email",
45
+ :tipo_rps => "RPS",
46
+ :serie_rps => "AAAAA",
47
+ :status_rps => "N",
48
+ :valor_servicos => "10.00",
49
+ :aliquota_servicos => "0.05",
50
+ :tributacao_rps => "T",
51
+ :numero_rps => "1",
52
+ :cpf_tomador => "99999999999",
53
+ :codigo_servico => "99999",
54
+ :discriminacao => ""
55
+ },{
56
+ :inscricao_prestador => "99999999",
57
+ :data_emissao => "AAAA-MM-DD",
58
+ :email_tomador => "email@email.email",
59
+ :tipo_rps => "RPS",
60
+ :serie_rps => "AAAAA",
61
+ :status_rps => "N",
62
+ :valor_servicos => "10.00",
63
+ :aliquota_servicos => "0.05",
64
+ :tributacao_rps => "T",
65
+ :numero_rps => "2",
66
+ :cpf_tomador => "99999999999",
67
+ :codigo_servico => "99999",
68
+ :discriminacao => ""
69
+ }]
70
+ })
71
+
72
+ **TesteEnvioLoteRPS**
73
+
74
+ response = gateway.teste_envio_lote_rps({
75
+ :cnpj_remetente => "99999999999999",
76
+ :inscricao_prestador => "99999999",
77
+ :data_inicio => "AAAA-MM-DD",
78
+ :data_fim => "AAAA-MM-DD",
79
+ :qtd_rps => "2",
80
+ :valor_total_servicos => "20.00",
81
+ :valor_total_deducoes => "0",
82
+ :lote_rps => => [{
83
+ :inscricao_prestador => "99999999",
84
+ :data_emissao => "AAAA-MM-DD",
85
+ :email_tomador => "email@email.email",
86
+ :tipo_rps => "RPS",
87
+ :serie_rps => "AAAAA",
88
+ :status_rps => "N",
89
+ :valor_servicos => "10.00",
90
+ :aliquota_servicos => "0.05",
91
+ :tributacao_rps => "T",
92
+ :numero_rps => "1",
93
+ :cpf_tomador => "99999999999",
94
+ :codigo_servico => "99999",
95
+ :discriminacao => ""
96
+ },{
97
+ :inscricao_prestador => "99999999",
98
+ :data_emissao => "AAAA-MM-DD",
99
+ :email_tomador => "email@email.email",
100
+ :tipo_rps => "RPS",
101
+ :serie_rps => "AAAAA",
102
+ :status_rps => "N",
103
+ :valor_servicos => "10.00",
104
+ :aliquota_servicos => "0.05",
105
+ :tributacao_rps => "T",
106
+ :numero_rps => "2",
107
+ :cpf_tomador => "99999999999",
108
+ :codigo_servico => "99999",
109
+ :discriminacao => ""
110
+ }]
111
+ })
112
+
113
+ **ConsultaNFe**
114
+
115
+ response = gateway.consulta_nfe({
116
+ cnpj_remetente: "99999999999999",
117
+ inscricao_prestador: "99999999",
118
+ numero_nfe: "9"
119
+ })
120
+
121
+ response = gateway.consulta_nfe({
122
+ cnpj_remetente: "99999999999999",
123
+ numero_rps: "9",
124
+ serie_rps: "AAAAA"
125
+ })
126
+
127
+ **ConsultaNFeRecebidas**
128
+
129
+ response = gateway.consulta_nfe_recebidas({
130
+ cnpj_remetente: "99999999999999",
131
+ cnpj: "99999999999999",
132
+ data_inicio: "AAAA-MM-DD",
133
+ data_fim: "AAAA-MM-DD",
134
+ inscricao: "99999999"
135
+ })
136
+
137
+
138
+ **ConsultaNFeEmitidas**
139
+
140
+ response = gateway.consulta_nfe_emitidas({
141
+ cnpj_remetente: "99999999999999",
142
+ cnpj: "99999999999999",
143
+ data_inicio: "AAAA-MM-DD",
144
+ data_fim: "AAAA-MM-DD",
145
+ inscricao: "99999999"
146
+ })
147
+
148
+ **ConsultaLote**
149
+
150
+ response = gateway.consulta_lote({
151
+ :cnpj_remetente => "99999999999999",
152
+ :numero_lote => "9"
153
+ })
154
+
155
+ **ConsultaInformacoesLote**
156
+
157
+ response = gateway.consulta_informacoes_lote({
158
+ :cnpj_remetente => "99999999999999",
159
+ :inscricao_prestador => "99999999",
160
+ :numero_lote => "9"
161
+ })
162
+
163
+ **CancelamentoNFe**
164
+
165
+ response = gateway.cancelamento_nfe({
166
+ cnpj_remetente: "99999999999999",
167
+ inscricao_prestador: "99999999",
168
+ numero_nfe: "9"
169
+ })
170
+
171
+ **ConsultaCNPJ**
172
+
173
+ response = gateway.consulta_cnpj({
174
+ cnpj_remetente: "99999999999999",
175
+ cnpj_contribuinte: "99999999999999"
176
+ })
@@ -1,316 +1,55 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  require "nfe-paulistana/version"
4
+ require "nfe-paulistana/xml_builder"
5
+ require "nfe-paulistana/response"
6
+ require "nfe-paulistana/gateway"
4
7
  require "signer"
5
8
  require "savon"
6
9
 
7
- class NfePaulistana
8
- def initialize(options)
9
- default_options = {
10
- :cpf_remetente => '',
11
- :cnpj_remetente => '',
12
- :inscricao_prestador => '',
13
- :serie_rps => '',
14
- :numero_rps => '',
15
- :tipo_rps => '',
16
- :data_emissao => '',
17
- :status_rps => '',
18
- :tributacao_rps => '',
19
- :valor_servicos => '0',
20
- :valor_deducoes => '0',
21
- :valor_pis => '0',
22
- :valor_cofins => '0',
23
- :valor_inss => '0',
24
- :valor_ir => '0',
25
- :valor_csll => '0',
26
- :codigo_servico => '0',
27
- :aliquota_servicos => '0',
28
- :iss_retido => false,
29
- :cpf_tomador => '',
30
- :cnpj_tomador => '',
31
- :im_tomador => '',
32
- :ie_tomador => '',
33
- :razao_tomador => '',
34
- :tp_logradouro => '',
35
- :logradouro => '',
36
- :nr_endereco => '',
37
- :compl_endereco => '',
38
- :bairro => '',
39
- :cidade => '',
40
- :uf => '',
41
- :cep => '',
42
- :email_tomador => '',
43
- :discriminacao => '',
44
- :cert_path => '',
45
- :cert_pass => '',
46
- :wsdl => 'https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx?wsdl'
47
- }
48
-
49
- @options = default_options.merge(options)
50
-
51
- @certificado = OpenSSL::PKCS12.new(File.read(@options[:cert_path]), @options[:cert_pass])
10
+ module NfePaulistana
11
+ WSDL = 'https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx?wsdl'
12
+ Savon.configure do |config|
13
+ config.soap_version = 2
52
14
  end
15
+ Savon.env_namespace = :soap
53
16
 
54
- def enviar
55
- client = Savon::Client.new do |wsdl, http|
56
- wsdl.document = @options[:wsdl]
57
- # http.auth.ssl.cert_key_file = "/Users/patricknegri/Desenvolvimento/Certificado-Iugu-Chave.pem"
58
- # http.auth.ssl.cert_file = "/Users/patricknegri/Desenvolvimento/Certificado-Iugu.pem"
59
- http.auth.ssl.cert_key = @certificado.key
60
- http.auth.ssl.cert = @certificado.certificate
61
- http.auth.ssl.verify_mode = :peer
17
+ def self.enviar(data = {})
18
+ certificado = OpenSSL::PKCS12.new(File.read(data[:cert_path]), data[:cert_pass])
19
+ client = get_client(certificado)
62
20
 
63
- # http.ssl_client_auth( :cert => @certificado, :key => @certificado.key, :verify_mode => OpenSSL::SSL::VERIFY_NONE )
64
- # http.auth.ssl.cert = @certificado
65
- # http.auth.ssl.key = @certificado.key
66
- # http.auth.ssl.verify_mode = :none
67
- end
68
-
69
- Savon.configure do |config|
70
- config.soap_version = 2
71
- end
72
- Savon.env_namespace = :soap
73
-
74
- #http.ssl_client_auth( :cert => @certificado, :key => @certificado.key, :verify_mode => OpenSSL::SSL::VERIFY_NONE )
75
-
76
21
  begin
77
22
  response = client.request(:envio_rps) do |soap|
78
23
  soap.input = [
79
24
  "EnvioRPSRequest",
80
25
  {"xmlns" => "http://www.prefeitura.sp.gov.br/nfe"}
81
26
  ]
82
- doc_txt = "<VersaoSchema>1</VersaoSchema><MensagemXML>" + assinar(to_xml).gsub("&","&amp;").gsub(">","&gt;").gsub("<","&lt;").gsub("\"","&quot;").gsub("'","&apos;") + "</MensagemXML>"
83
- doc_txt = doc_txt.gsub(/\n/,'')
84
- doc_xml = Nokogiri::XML( doc_txt )
85
-
86
27
 
87
- soap.body = doc_txt
28
+ soap.body = XmlBuilder.new.xml_for(:envio_rps, data, certificado)
88
29
 
89
- # soap.body = assinar( to_xml )
90
30
  soap.version = 2
91
31
  end
92
- @retorno_xml = response.to_hash[:envio_rps_response][:retorno_xml]
93
- @retorno = Nori.parse( retorno_xml )[:retorno_envio_rps]
94
- @success = @retorno[:cabecalho][:sucesso]
32
+ Response.new(xml: response.to_hash[:envio_rps_response][:retorno_xml], method: :envio_rps_response)
95
33
  rescue Savon::Error => error
96
34
  end
97
35
  end
98
36
 
99
- def retorno_xml
100
- @retorno_xml
101
- end
102
-
103
- def retorno
104
- @retorno
105
- end
106
-
107
- def success?
108
- !!@success
109
- end
110
-
111
- def error
112
- if !success?
113
- errors = retorno[:alerta] || retorno[:erro]
114
- errors.try('[]', :descricao)
115
- end
116
- end
117
-
118
37
  private
119
-
120
- def assinar(xml)
121
-
122
- xml = Nokogiri::XML(xml.to_s, &:noblanks)
123
-
124
- # 1. Digest Hash for all XML
125
- xml_canon = xml.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
126
- xml_digest = Base64.encode64(OpenSSL::Digest::SHA1.digest(xml_canon)).strip
127
-
128
- # 2. Add Signature Node
129
- signature = xml.xpath("//ds:Signature", "ds" => "http://www.w3.org/2000/09/xmldsig#").first
130
- unless signature
131
- signature = Nokogiri::XML::Node.new('Signature', xml)
132
- signature.default_namespace = 'http://www.w3.org/2000/09/xmldsig#'
133
- xml.root().add_child(signature)
134
- end
135
-
136
- # 3. Add Elements to Signature Node
137
-
138
- # 3.1 Create Signature Info
139
- signature_info = Nokogiri::XML::Node.new('SignedInfo', xml)
140
-
141
- # 3.2 Add CanonicalizationMethod
142
- child_node = Nokogiri::XML::Node.new('CanonicalizationMethod', xml)
143
- child_node['Algorithm'] = 'http://www.w3.org/2001/10/xml-exc-c14n#'
144
- signature_info.add_child child_node
145
38
 
146
- # 3.3 Add SignatureMethod
147
- child_node = Nokogiri::XML::Node.new('SignatureMethod', xml)
148
- child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
149
- signature_info.add_child child_node
150
-
151
- # 3.4 Create Reference
152
- reference = Nokogiri::XML::Node.new('Reference', xml)
153
- reference['URI'] = ''
154
-
155
- # 3.5 Add Transforms
156
- transforms = Nokogiri::XML::Node.new('Transforms', xml)
157
-
158
- child_node = Nokogiri::XML::Node.new('Transform', xml)
159
- child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'
160
- transforms.add_child child_node
161
-
162
- child_node = Nokogiri::XML::Node.new('Transform', xml)
163
- child_node['Algorithm'] = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
164
- transforms.add_child child_node
165
-
166
- reference.add_child transforms
167
-
168
- # 3.6 Add Digest
169
- child_node = Nokogiri::XML::Node.new('DigestMethod', xml)
170
- child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#sha1'
171
- reference.add_child child_node
172
-
173
- # 3.6 Add DigestValue
174
- child_node = Nokogiri::XML::Node.new('DigestValue', xml)
175
- child_node.content = xml_digest
176
- reference.add_child child_node
177
-
178
- # 3.7 Add Reference and Signature Info
179
- signature_info.add_child reference
180
- signature.add_child signature_info
181
-
182
- # 4 Sign Signature
183
- sign_canon = signature_info.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
184
- signature_hash = @certificado.key.sign(OpenSSL::Digest::SHA1.new, sign_canon)
185
- signature_value = Base64.encode64( signature_hash ).gsub("\n", '')
186
-
187
- # 4.1 Add SignatureValue
188
- child_node = Nokogiri::XML::Node.new('SignatureValue', xml)
189
- child_node.content = signature_value
190
- signature.add_child child_node
191
-
192
- # 5 Create KeyInfo
193
- key_info = Nokogiri::XML::Node.new('KeyInfo', xml)
194
-
195
- # 5.1 Add X509 Data and Certificate
196
- x509_data = Nokogiri::XML::Node.new('X509Data', xml)
197
- x509_certificate = Nokogiri::XML::Node.new('X509Certificate', xml)
198
- x509_certificate.content = @certificado.certificate.to_s.gsub(/\-\-\-\-\-[A-Z]+ CERTIFICATE\-\-\-\-\-/, "").gsub(/\n/,"")
199
-
200
- x509_data.add_child x509_certificate
201
- key_info.add_child x509_data
202
-
203
- # 5.2 Add KeyInfo
204
- signature.add_child key_info
205
-
206
- # 6 Add Signature
207
- xml.root().add_child signature
208
-
209
- # Return XML
210
- xml.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
211
- # xml.to_xml( :save_with => 0 )
212
- end
213
-
214
- def assinatura_simples
215
- value = @options[:inscricao_prestador].rjust(8,'0') + @options[:serie_rps].ljust(5) + @options[:numero_rps].rjust(12,'0') + @options[:data_emissao].delete('-') \
216
- + @options[:tributacao_rps] + @options[:status_rps] + (@options[:iss_retido] ? 'S' : 'N') + @options[:valor_servicos].delete(',').delete('.').rjust(15,'0') \
217
- + @options[:valor_deducoes].delete(',').delete('.').rjust(15,'0') + @options[:codigo_servico].rjust(5,'0') \
218
- + (@options[:cpf_tomador].blank? ? (@options[:cnpj_tomador].blank? ? '3' : '2') : '1') \
219
- + (@options[:cpf_tomador].blank? ? (@options[:cnpj_tomador].blank? ? "".rjust(14,'0') : @options[:cnpj_tomador]) : @options[:cpf_tomador])
220
-
221
- part_1 = @options[:inscricao_prestador].rjust(8,'0')
222
- part_2 = @options[:serie_rps].ljust(5)
223
- part_3 = @options[:numero_rps].rjust(12,'0')
224
- part_4 = @options[:data_emissao].delete('-')
225
- part_5 = @options[:tributacao_rps]
226
- part_6 = @options[:status_rps]
227
- part_7 = @options[:iss_retido] ? 'S' : 'N'
228
- part_8 = @options[:valor_servicos].delete(',').delete('.').rjust(15,'0')
229
- part_9 = @options[:valor_deducoes].delete(',').delete('.').rjust(15,'0')
230
- part_10 = @options[:codigo_servico].rjust(5,'0')
231
- part_11 = (@options[:cpf_tomador].blank? ? (@options[:cnpj_tomador].blank? ? '3' : '2') : '1')
232
- part_12 = (@options[:cpf_tomador].blank? ? (@options[:cnpj_tomador].blank? ? "".rjust(14,'0') : @options[:cnpj_tomador].rjust(14,'0') ) : @options[:cpf_tomador].rjust(14,'0'))
233
-
234
- 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
235
-
236
- # PHP Sign
237
- # $digestValue = base64_encode( hash( 'sha1', $content, true ) );
238
- # $pkeyId = openssl_get_privatekey( file_get_contents( $this->privateKey ) );
239
- # openssl_sign( $digestValue, $signatureValue, $pkeyId );
240
-
241
- # a_hash = OpenSSL::Digest::SHA1.digest( value )
242
- # Base64.encode64( @certificado.key.private_encrypt( value ) ).gsub("\n",'').strip()
243
-
244
- sign_hash = @certificado.key.sign( OpenSSL::Digest::SHA1.new, value )
245
- Base64.encode64( sign_hash ).gsub("\n",'').gsub("\r",'').strip()
246
- end
39
+ def get_client(certificado)
40
+ client = Savon::Client.new do |wsdl, http|
41
+ wsdl.document = WSDL
42
+ # http.auth.ssl.cert_key_file = "/Users/patricknegri/Desenvolvimento/Certificado-Iugu-Chave.pem"
43
+ # http.auth.ssl.cert_file = "/Users/patricknegri/Desenvolvimento/Certificado-Iugu.pem"
44
+ http.auth.ssl.cert_key = certificado.key
45
+ http.auth.ssl.cert = certificado.certificate
46
+ http.auth.ssl.verify_mode = :peer
247
47
 
248
- def to_xml
249
- builder = Nokogiri::XML::Builder.new do |xml|
250
- xml.PedidoEnvioRPS( "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" ) {
251
- xml.Cabecalho( "Versao" => "1", :xmlns => "" ) {
252
- xml.CPFCNPJRemetente {
253
- xml.CPF @options[:cpf_remetente] unless @options[:cpf_remetente].blank?
254
- xml.CNPJ @options[:cnpj_remetente] unless @options[:cnpj_remetente].blank?
255
- }
256
- }
257
- xml.RPS( :xmlns => "" ) {
258
- xml.Assinatura assinatura_simples()
259
- xml.ChaveRPS {
260
- xml.InscricaoPrestador @options[:inscricao_prestador]
261
- xml.SerieRPS @options[:serie_rps] unless @options[:serie_rps].blank?
262
- xml.NumeroRPS @options[:numero_rps] unless @options[:numero_rps].blank?
263
- }
264
- xml.TipoRPS @options[:tipo_rps]
265
- xml.DataEmissao @options[:data_emissao]
266
- xml.StatusRPS @options[:status_rps]
267
- xml.TributacaoRPS @options[:tributacao_rps]
268
- xml.ValorServicos @options[:valor_servicos]
269
- xml.ValorDeducoes @options[:valor_deducoes]
270
- xml.ValorPIS @options[:valor_pis] if @options[:valor_pis] != '0'
271
- xml.ValorCOFINS @options[:valor_cofins] if @options[:valor_cofins] != '0'
272
- xml.ValorINSS @options[:valor_inss] if @options[:valor_inss] != '0'
273
- xml.ValorIR @options[:valor_ir] if @options[:valor_ir] != '0'
274
- xml.ValorCSLL @options[:valor_csll] if @options[:valor_csll] != '0'
275
- xml.CodigoServico @options[:codigo_servico]
276
- xml.AliquotaServicos @options[:aliquota_servicos]
277
- xml.ISSRetido @options[:iss_retido]
278
- unless (@options[:cpf_tomador].blank? and @options[:cnpj_tomador].blank?)
279
- xml.CPFCNPJTomador {
280
- xml.CPF @options[:cpf_tomador] unless @options[:cpf_tomador].blank?
281
- xml.CNPJ @options[:cnpj_tomador] unless @options[:cnpj_tomador].blank?
282
- }
283
- end
284
- xml.InscricaoMunicipalTomador @options[:im_tomador] unless @options[:im_tomador]
285
- xml.InscricaoEstadualTomador @options[:ie_tomador] unless @options[:ie_tomador]
286
- xml.RazaoSocialTomador @options[:razao_tomador] unless @options[:razao_tomador]
287
- unless (@options[:tp_logradouro].blank? and @options[:logradouro].blank? and @options[:nr_endereco] and @options[:compl_endereco])
288
- xml.EnderecoTomador {
289
- xml.TipoLogradouro @options[:tp_logradouro]
290
- xml.Logradouro @options[:logradouro]
291
- xml.NumeroEndereco @options[:nr_endereco]
292
- xml.ComplementoEndereco @options[:compl_endereco]
293
- xml.Bairro @options[:bairro] unless @options[:bairro].blank?
294
- xml.Cidade @options[:cidade] unless @options[:cidade].blank?
295
- xml.UF @options[:uf] unless @options[:uf]
296
- xml.CEP @options[:cep] unless @options[:cep]
297
- }
298
- end
299
- xml.EmailTomador @options[:email_tomador]
300
- xml.Discriminacao @options[:discriminacao]
301
- }
302
- # xml.Signature( "xmlns" => "http://www.w3.org/2000/09/xmldsig#" ) {
303
- # TODO: These elements must be added later, after the sign
304
- # xml.KeyInfo {
305
- # xml.X509Data {
306
- # xml.X509Certificate @certificado.certificate.to_s.gsub(/\-\-\-\-\-[A-Z]+ CERTIFICATE\-\-\-\-\-/, "").gsub(/\n/,"")
307
- # }
308
- # }
309
- # }
310
- }
48
+ # http.ssl_client_auth( :cert => @certificado, :key => @certificado.key, :verify_mode => OpenSSL::SSL::VERIFY_NONE )
49
+ # http.auth.ssl.cert = @certificado
50
+ # http.auth.ssl.key = @certificado.key
51
+ # http.auth.ssl.verify_mode = :none
311
52
  end
312
- # builder.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION).gsub("<root>","").gsub("</root>","").gsub("\n","")
313
- Nokogiri::XML( builder.to_xml( :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION ) )
314
53
  end
315
54
 
316
55
  end
@@ -0,0 +1,102 @@
1
+ require 'savon'
2
+
3
+ module NfePaulistana
4
+ class Gateway
5
+ Savon.configure do |config|
6
+ config.soap_version = 2
7
+ end
8
+ Savon.env_namespace = :soap
9
+
10
+ METHODS = {
11
+ envio_rps: "EnvioRPSRequest",
12
+ envio_lote_rps: "EnvioLoteRPSRequest",
13
+ teste_envio_lote_rps: "TesteEnvioLoteRPSRequest",
14
+ cancelamento_n_fe: "CancelamentoNFeRequest",
15
+ consulta_cnpj: "ConsultaCNPJRequest",
16
+ consulta_n_fe: "ConsultaNFeRequest",
17
+ consulta_n_fe_recebidas: "ConsultaNFeRecebidasRequest",
18
+ consulta_n_fe_emitidas: "ConsultaNFeEmitidasRequest",
19
+ consulta_lote: "ConsultaLoteRequest",
20
+ consulta_informacoes_lote: "ConsultaInformacoesLoteRequest"
21
+ }
22
+
23
+ def initialize(options = {})
24
+ @options = {
25
+ cert_path: "",
26
+ cert_pass: "",
27
+ wdsl: 'https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx?wsdl'
28
+ }.merge(options)
29
+ end
30
+
31
+ def envio_rps(data = {})
32
+ request(:envio_rps, data)
33
+ end
34
+
35
+ def envio_lote_rps(data = {})
36
+ request(:envio_lote_rps, data)
37
+ end
38
+
39
+ def teste_envio_lote_rps(data = {})
40
+ request(:teste_envio_lote_rps, data)
41
+ end
42
+
43
+ def cancelamento_nfe(data = {})
44
+ request(:cancelamento_n_fe, data)
45
+ end
46
+
47
+ def consulta_nfe(data = {})
48
+ request(:consulta_n_fe, data)
49
+ end
50
+
51
+ def consulta_nfe_recebidas(data = {})
52
+ request(:consulta_n_fe_recebidas, data)
53
+ end
54
+
55
+ def consulta_nfe_emitidas(data = {})
56
+ request(:consulta_n_fe_emitidas, data)
57
+ end
58
+
59
+ def consulta_lote(data = {})
60
+ request(:consulta_lote, data)
61
+ end
62
+
63
+ def consulta_informacoes_lote(data = {})
64
+ request(:consulta_informacoes_lote, data)
65
+ end
66
+
67
+ def consulta_cnpj(data = {})
68
+ request(:consulta_cnpj, data)
69
+ end
70
+
71
+ private
72
+
73
+ def certificate
74
+ OpenSSL::PKCS12.new(File.read(@options[:cert_path]), @options[:cert_pass])
75
+ end
76
+
77
+ def request(method, data = {})
78
+ certificado = certificate
79
+ client = get_client(certificado)
80
+ response = client.request(method) do |soap|
81
+ soap.input = [
82
+ METHODS[method],
83
+ {"xmlns" => "http://www.prefeitura.sp.gov.br/nfe"}
84
+ ]
85
+ soap.body = XmlBuilder.new.xml_for(method, data, certificado)
86
+ soap.version = 2
87
+ end
88
+ method_response = (method.to_s + "_response").to_sym
89
+ Response.new(xml: response.to_hash[method_response][:retorno_xml], method: method)
90
+ rescue Savon::Error => error
91
+ end
92
+
93
+ def get_client(certificado)
94
+ Savon::Client.new do |wsdl, http|
95
+ wsdl.document = @options[:wdsl]
96
+ http.auth.ssl.cert_key = certificado.key
97
+ http.auth.ssl.cert = certificado.certificate
98
+ http.auth.ssl.verify_mode = :peer
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,32 @@
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 retorno
20
+ Nori.parse(xml)[("retorno_" + (RETURN_ROOT[@options[:method]] || @options[:method]).to_s).to_sym]
21
+ end
22
+
23
+ def success?
24
+ !!retorno[:cabecalho][:sucesso]
25
+ end
26
+
27
+ def errors
28
+ return unless !success?
29
+ retorno[:alerta] || retorno[:erro]
30
+ end
31
+ end
32
+ end
@@ -1,3 +1,3 @@
1
- class NfePaulistana
2
- VERSION = "0.5.0"
1
+ module NfePaulistana
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,374 @@
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
+ :im_tomador => '',
40
+ :ie_tomador => '',
41
+ :razao_tomador => '',
42
+ :tp_logradouro => '',
43
+ :logradouro => '',
44
+ :nr_endereco => '',
45
+ :compl_endereco => '',
46
+ :bairro => '',
47
+ :cidade => '',
48
+ :uf => '',
49
+ :cep => '',
50
+ :email_tomador => '',
51
+ :discriminacao => '',
52
+ :wsdl => 'https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx?wsdl'
53
+ }
54
+
55
+ def xml_for(method,data, certificado)
56
+ data = DEFAULT_DATA.merge(data)
57
+ ("<VersaoSchema>1</VersaoSchema><MensagemXML>" + assinar(xml(method, data, certificado), certificado).gsub("&","&amp;").gsub(">","&gt;").gsub("<","&lt;").gsub("\"","&quot;").gsub("'","&apos;") + "</MensagemXML>").gsub(/\n/,'')
58
+ end
59
+
60
+ private
61
+
62
+ def xml(method, data, certificado)
63
+ builder = Nokogiri::XML::Builder.new do |xml|
64
+ 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" ) {
65
+ xml.Cabecalho( "Versao" => "1", :xmlns => "" ) {
66
+ xml.CPFCNPJRemetente {
67
+ xml.CPF data[:cpf_remetente] unless data[:cpf_remetente].blank?
68
+ xml.CNPJ data[:cnpj_remetente] unless data[:cnpj_remetente].blank?
69
+ }
70
+ send("add_#{method}_cabecalho_data_to_xml", xml, data, certificado)
71
+ }
72
+ send("add_#{method}_data_to_xml", xml, data, certificado)
73
+ }
74
+ end
75
+ puts builder.to_xml
76
+ Nokogiri::XML( builder.to_xml( :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION ) )
77
+ end
78
+
79
+ def add_cancelamento_n_fe_cabecalho_data_to_xml(xml, data, certificado)
80
+ xml.transacao data[:transacao] || true
81
+ end
82
+
83
+ def add_envio_rps_cabecalho_data_to_xml(xml, data, certificado)
84
+ end
85
+
86
+ def add_envio_lote_rps_cabecalho_data_to_xml(xml, data, certificado)
87
+ add_lote_cabecalho_data_to_xml(xml, data, certificado)
88
+ end
89
+
90
+ def add_teste_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_lote_cabecalho_data_to_xml(xml, data, certificado)
95
+ xml.transacao data[:transacao] || true
96
+ xml.dtInicio data[:data_inicio]
97
+ xml.dtFim data[:data_fim]
98
+ xml.QtdRPS data[:qtd_rps]
99
+ xml.ValorTotalServicos data[:valor_total_servicos]
100
+ xml.ValorTotalDeducoes data[:valor_total_deducoes]
101
+ end
102
+
103
+ def add_consulta_cnpj_cabecalho_data_to_xml(xml, data, certificado)
104
+ end
105
+
106
+ def add_consulta_n_fe_cabecalho_data_to_xml(xml, data, certificado)
107
+ end
108
+
109
+ def add_consulta_n_fe_recebidas_cabecalho_data_to_xml(xml,data,certificado)
110
+ add_consulta_n_fe_periodo_cabecalho_data_to_xml(xml, data, certificado)
111
+ end
112
+
113
+ def add_consulta_n_fe_emitidas_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_periodo_cabecalho_data_to_xml(xml, data, certificado)
118
+ unless (data[:cpf].blank? and data[:cnpj].blank?)
119
+ xml.CPFCNPJ {
120
+ xml.CPF data[:cpf] unless data[:cpf].blank?
121
+ xml.CNPJ data[:cnpj] unless data[:cnpj].blank?
122
+ }
123
+ end
124
+ xml.Inscricao data[:inscricao] if !data[:inscricao].blank?
125
+ xml.dtInicio data[:data_inicio]
126
+ xml.dtFim data[:data_fim]
127
+ xml.NumeroPagina data[:pagina] || 1
128
+ end
129
+
130
+ def add_consulta_lote_cabecalho_data_to_xml(xml, data, certificado)
131
+ xml.NumeroLote data[:numero_lote]
132
+ end
133
+
134
+ def add_consulta_informacoes_lote_cabecalho_data_to_xml(xml, data, certificado)
135
+ xml.NumeroLote data[:numero_lote]
136
+ xml.InscricaoPrestador data[:inscricao_prestador]
137
+ end
138
+
139
+ def add_consulta_n_fe_recebidas_data_to_xml(xml, data, certificado)
140
+ end
141
+
142
+ def add_consulta_n_fe_emitidas_data_to_xml(xml, data, certificado)
143
+ end
144
+
145
+ def add_consulta_n_fe_data_to_xml(xml, data, certificado)
146
+ xml.Detalhe(:xmlns => "") {
147
+ add_chave_rps_to_xml(xml, data) if !data[:numero_rps].blank? and !data[:serie_rps].blank?
148
+ add_chave_nfe_to_xml(xml, data) if data[:numero_nfe]
149
+ }
150
+ end
151
+
152
+ def add_consulta_cnpj_data_to_xml(xml, data, certificado)
153
+ xml.CNPJContribuinte(:xmlns => "") {
154
+ xml.CNPJ data[:cnpj_contribuinte]
155
+ }
156
+ end
157
+
158
+ def add_cancelamento_n_fe_data_to_xml(xml, data, certificado)
159
+ xml.Detalhe(:xmlns => "") {
160
+ add_chave_nfe_to_xml(xml, data)
161
+ xml.AssinaturaCancelamento assinatura_cancelamento_n_fe(data, certificado)
162
+ }
163
+ end
164
+
165
+ def add_envio_rps_data_to_xml(xml, data, certificado)
166
+ add_rps_to_xml(xml, data, certificado)
167
+ end
168
+
169
+ def add_envio_lote_rps_data_to_xml(xml, data, certificado)
170
+ add_lote_rps_data_to_xml(xml, data, certificado)
171
+ end
172
+
173
+ def add_teste_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_lote_rps_data_to_xml(xml, data, certificado)
178
+ data[:lote_rps].each do |rps|
179
+ add_rps_to_xml(xml, rps, certificado)
180
+ end
181
+ end
182
+
183
+ def add_consulta_lote_data_to_xml(xml, data, certificado)
184
+ end
185
+
186
+ def add_consulta_informacoes_lote_data_to_xml(xml, data, certificado)
187
+ end
188
+
189
+ def add_chave_nfe_to_xml(xml, data)
190
+ xml.ChaveNFe {
191
+ xml.InscricaoPrestador data[:inscricao_prestador]
192
+ xml.NumeroNFe data[:numero_nfe]
193
+ }
194
+ end
195
+
196
+ def add_chave_rps_to_xml(xml, data)
197
+ xml.ChaveRPS {
198
+ xml.InscricaoPrestador data[:inscricao_prestador]
199
+ xml.SerieRPS data[:serie_rps] unless data[:serie_rps].blank?
200
+ xml.NumeroRPS data[:numero_rps] unless data[:numero_rps].blank?
201
+ }
202
+ end
203
+
204
+ def add_rps_to_xml(xml, data, certificado)
205
+ data = DEFAULT_DATA.merge(data)
206
+ xml.RPS( :xmlns => "" ) {
207
+ xml.Assinatura assinatura_envio_rps(data, certificado)
208
+ add_chave_rps_to_xml(xml, data)
209
+ xml.TipoRPS data[:tipo_rps]
210
+ xml.DataEmissao data[:data_emissao]
211
+ xml.StatusRPS data[:status_rps]
212
+ xml.TributacaoRPS data[:tributacao_rps]
213
+ xml.ValorServicos data[:valor_servicos]
214
+ xml.ValorDeducoes data[:valor_deducoes]
215
+ xml.ValorPIS data[:valor_pis] if data[:valor_pis] != '0'
216
+ xml.ValorCOFINS data[:valor_cofins] if data[:valor_cofins] != '0'
217
+ xml.ValorINSS data[:valor_inss] if data[:valor_inss] != '0'
218
+ xml.ValorIR data[:valor_ir] if data[:valor_ir] != '0'
219
+ xml.ValorCSLL data[:valor_csll] if data[:valor_csll] != '0'
220
+ xml.CodigoServico data[:codigo_servico]
221
+ xml.AliquotaServicos data[:aliquota_servicos]
222
+ xml.ISSRetido data[:iss_retido]
223
+ unless (data[:cpf_tomador].blank? and data[:cnpj_tomador].blank?)
224
+ xml.CPFCNPJTomador {
225
+ xml.CPF data[:cpf_tomador] unless data[:cpf_tomador].blank?
226
+ xml.CNPJ data[:cnpj_tomador] unless data[:cnpj_tomador].blank?
227
+ }
228
+ end
229
+ xml.InscricaoMunicipalTomador data[:im_tomador] unless data[:im_tomador].blank?
230
+ xml.InscricaoEstadualTomador data[:ie_tomador] unless data[:ie_tomador].blank?
231
+ xml.RazaoSocialTomador data[:razao_tomador] unless data[:razao_tomador].blank?
232
+ unless (data[:tp_logradouro].blank? and data[:logradouro].blank? and data[:nr_endereco] and data[:compl_endereco])
233
+ xml.EnderecoTomador {
234
+ xml.TipoLogradouro data[:tp_logradouro]
235
+ xml.Logradouro data[:logradouro]
236
+ xml.NumeroEndereco data[:nr_endereco]
237
+ xml.ComplementoEndereco data[:compl_endereco]
238
+ xml.Bairro data[:bairro] unless data[:bairro].blank?
239
+ xml.Cidade data[:cidade] unless data[:cidade].blank?
240
+ xml.UF data[:uf] unless data[:uf]
241
+ xml.CEP data[:cep] unless data[:cep]
242
+ }
243
+ end
244
+ xml.EmailTomador data[:email_tomador]
245
+ xml.Discriminacao data[:discriminacao]
246
+ }
247
+ end
248
+
249
+ def assinar(xml, certificado)
250
+
251
+ xml = Nokogiri::XML(xml.to_s, &:noblanks)
252
+
253
+ # 1. Digest Hash for all XML
254
+ xml_canon = xml.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
255
+ xml_digest = Base64.encode64(OpenSSL::Digest::SHA1.digest(xml_canon)).strip
256
+
257
+ # 2. Add Signature Node
258
+ signature = xml.xpath("//ds:Signature", "ds" => "http://www.w3.org/2000/09/xmldsig#").first
259
+ unless signature
260
+ signature = Nokogiri::XML::Node.new('Signature', xml)
261
+ signature.default_namespace = 'http://www.w3.org/2000/09/xmldsig#'
262
+ xml.root().add_child(signature)
263
+ end
264
+
265
+ # 3. Add Elements to Signature Node
266
+
267
+ # 3.1 Create Signature Info
268
+ signature_info = Nokogiri::XML::Node.new('SignedInfo', xml)
269
+
270
+ # 3.2 Add CanonicalizationMethod
271
+ child_node = Nokogiri::XML::Node.new('CanonicalizationMethod', xml)
272
+ child_node['Algorithm'] = 'http://www.w3.org/2001/10/xml-exc-c14n#'
273
+ signature_info.add_child child_node
274
+
275
+ # 3.3 Add SignatureMethod
276
+ child_node = Nokogiri::XML::Node.new('SignatureMethod', xml)
277
+ child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
278
+ signature_info.add_child child_node
279
+
280
+ # 3.4 Create Reference
281
+ reference = Nokogiri::XML::Node.new('Reference', xml)
282
+ reference['URI'] = ''
283
+
284
+ # 3.5 Add Transforms
285
+ transforms = Nokogiri::XML::Node.new('Transforms', xml)
286
+
287
+ child_node = Nokogiri::XML::Node.new('Transform', xml)
288
+ child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'
289
+ transforms.add_child child_node
290
+
291
+ child_node = Nokogiri::XML::Node.new('Transform', xml)
292
+ child_node['Algorithm'] = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
293
+ transforms.add_child child_node
294
+
295
+ reference.add_child transforms
296
+
297
+ # 3.6 Add Digest
298
+ child_node = Nokogiri::XML::Node.new('DigestMethod', xml)
299
+ child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#sha1'
300
+ reference.add_child child_node
301
+
302
+ # 3.6 Add DigestValue
303
+ child_node = Nokogiri::XML::Node.new('DigestValue', xml)
304
+ child_node.content = xml_digest
305
+ reference.add_child child_node
306
+
307
+ # 3.7 Add Reference and Signature Info
308
+ signature_info.add_child reference
309
+ signature.add_child signature_info
310
+
311
+ # 4 Sign Signature
312
+ sign_canon = signature_info.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
313
+ signature_hash = certificado.key.sign(OpenSSL::Digest::SHA1.new, sign_canon)
314
+ signature_value = Base64.encode64( signature_hash ).gsub("\n", '')
315
+
316
+ # 4.1 Add SignatureValue
317
+ child_node = Nokogiri::XML::Node.new('SignatureValue', xml)
318
+ child_node.content = signature_value
319
+ signature.add_child child_node
320
+
321
+ # 5 Create KeyInfo
322
+ key_info = Nokogiri::XML::Node.new('KeyInfo', xml)
323
+
324
+ # 5.1 Add X509 Data and Certificate
325
+ x509_data = Nokogiri::XML::Node.new('X509Data', xml)
326
+ x509_certificate = Nokogiri::XML::Node.new('X509Certificate', xml)
327
+ x509_certificate.content = certificado.certificate.to_s.gsub(/\-\-\-\-\-[A-Z]+ CERTIFICATE\-\-\-\-\-/, "").gsub(/\n/,"")
328
+
329
+ x509_data.add_child x509_certificate
330
+ key_info.add_child x509_data
331
+
332
+ # 5.2 Add KeyInfo
333
+ signature.add_child key_info
334
+
335
+ # 6 Add Signature
336
+ xml.root().add_child signature
337
+
338
+ # Return XML
339
+ xml.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
340
+ end
341
+
342
+ def assinatura_cancelamento_n_fe(data, certificado)
343
+ part_1 = data[:inscricao_prestador].rjust(8,'0')
344
+ part_2 = data[:numero_nfe].rjust(12,'0')
345
+ value = part_1 + part_2
346
+ assinatura_simples(value, certificado)
347
+ end
348
+
349
+ def assinatura_envio_rps(data, certificado)
350
+ part_1 = data[:inscricao_prestador].rjust(8,'0')
351
+ part_2 = data[:serie_rps].ljust(5)
352
+ part_3 = data[:numero_rps].rjust(12,'0')
353
+ part_4 = data[:data_emissao].delete('-')
354
+ part_5 = data[:tributacao_rps]
355
+ part_6 = data[:status_rps]
356
+ part_7 = data[:iss_retido] ? 'S' : 'N'
357
+ part_8 = data[:valor_servicos].delete(',').delete('.').rjust(15,'0')
358
+ part_9 = data[:valor_deducoes].delete(',').delete('.').rjust(15,'0')
359
+ part_10 = data[:codigo_servico].rjust(5,'0')
360
+ part_11 = (data[:cpf_tomador].blank? ? (data[:cnpj_tomador].blank? ? '3' : '2') : '1')
361
+ 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'))
362
+
363
+ 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
364
+
365
+ assinatura_simples(value, certificado)
366
+ end
367
+
368
+ def assinatura_simples(value, certificado)
369
+ sign_hash = certificado.key.sign( OpenSSL::Digest::SHA1.new, value )
370
+ Base64.encode64( sign_hash ).gsub("\n",'').gsub("\r",'').strip()
371
+ end
372
+
373
+ end
374
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nfe-paulistana
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-07 00:00:00.000000000 Z
12
+ date: 2013-06-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -85,11 +85,14 @@ files:
85
85
  - .gitignore
86
86
  - Gemfile
87
87
  - Gemfile.lock
88
+ - README.md
88
89
  - Rakefile
89
90
  - lib/nfe-paulistana.rb
91
+ - lib/nfe-paulistana/gateway.rb
92
+ - lib/nfe-paulistana/response.rb
90
93
  - lib/nfe-paulistana/version.rb
94
+ - lib/nfe-paulistana/xml_builder.rb
91
95
  - nfe-paulistana.gemspec
92
- - test.rb
93
96
  homepage: https://iugu.com.br
94
97
  licenses: []
95
98
  post_install_message:
data/test.rb DELETED
@@ -1,21 +0,0 @@
1
- require 'nfe-paulistana.rb'
2
- nfe = NfePaulistana.new({
3
- :cert_path => "",
4
- :cert_pass => "",
5
- :cnpj_remetente => "",
6
- :inscricao_prestador => "",
7
- :aliquota_servicos => "0.03",
8
- :data_emissao => "2013-03-04",
9
- :email_tomador => "",
10
- :discriminacao => "",
11
- :codigo_servico => "",
12
- :valor_servicos => "10.00",
13
- :tributacao_rps => "T",
14
- :status_rps => "N",
15
- :tipo_rps => "RPS",
16
- :serie_rps => "TESTE",
17
- :numero_rps => "1"
18
- #:cpf_tomador => ""
19
- })
20
- ret = nfe.enviar()
21
- puts ret