sefaz 0.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +115 -0
  3. data/Gemfile.lock +31 -17
  4. data/README.md +449 -17
  5. data/Rakefile +1 -0
  6. data/docs/CFe-SAT/Especificacao_SAT_v_ER_2_30_03.pdf +0 -0
  7. data/docs/CFe-SAT/Manual_Orientacao_SAT_v_MO_2_19_04.pdf +0 -0
  8. data/docs/CFe-SAT/Manual_do_Emulador_SAT-CF-e_Offline_2015_09_10.pdf +0 -0
  9. data/docs/CFe-SAT/_CANCEL_dataset.md +14 -0
  10. data/docs/CFe-SAT/_SALE_dataset.md +171 -0
  11. data/docs/CFe-SAT/emulador_off_line_v2_9_4.zip +0 -0
  12. data/docs/NFe-NFCe/ANEXO I - Leiaute e Regra de Valida/303/247/303/243o - NF-e e NFC-e.pdf +0 -0
  13. data/docs/NFe-NFCe/ANEXO II -Manual Especifica/303/247/303/265esT/303/251cnicas - Danfe-C/303/263digo-Barras.pdf +0 -0
  14. data/docs/NFe-NFCe/Anexo III - Manual de Conting/303/252ncia - NF-e.pdf +0 -0
  15. data/docs/NFe-NFCe/Anexo IV - Manual de Conting/303/252ncia - NFC-e.pdf +0 -0
  16. data/docs/NFe-NFCe/Manual de Orienta/303/247/303/243o ao Contribuinte - MOC - vers/303/243o 7.0 - NF-e e NFC-e.pdf +0 -0
  17. data/docs/NFe-NFCe/_dataset.md +819 -0
  18. data/lib/sefaz/base.rb +11 -0
  19. data/lib/sefaz/configuration.rb +58 -0
  20. data/lib/sefaz/exception.rb +14 -0
  21. data/lib/sefaz/refinement.rb +91 -0
  22. data/lib/sefaz/utils/connection.rb +35 -0
  23. data/lib/sefaz/utils/prawn_helper.rb +47 -0
  24. data/lib/sefaz/utils/signer.rb +122 -0
  25. data/lib/sefaz/version.rb +1 -1
  26. data/lib/sefaz/webservice/base.rb +13 -0
  27. data/lib/sefaz/webservice/nfe/auditor.rb +35 -0
  28. data/lib/sefaz/webservice/nfe/client.rb +426 -0
  29. data/lib/sefaz/webservice/nfe/connection.rb +17 -0
  30. data/lib/sefaz/webservice/nfe/dataset.rb +451 -0
  31. data/lib/sefaz/webservice/nfe/validator.rb +63 -0
  32. data/lib/sefaz/webservice/nfe/wsdl.rb +117 -0
  33. data/lib/sefaz/webservice/sat/client.rb +44 -0
  34. data/lib/sefaz/webservice/sat/dataset/cancel.rb +34 -0
  35. data/lib/sefaz/webservice/sat/dataset/sale.rb +176 -0
  36. data/lib/sefaz/webservice/sat/templates/base.rb +54 -0
  37. data/lib/sefaz/webservice/sat/templates/cupom_fiscal_55mm.rb +307 -0
  38. data/lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb +307 -0
  39. data/lib/sefaz.rb +45 -3
  40. data/sefaz.gemspec +5 -3
  41. metadata +80 -6
@@ -0,0 +1,426 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SEFAZ
4
+ module Webservice
5
+ module NFE
6
+ # Principal classe de integração com o módulo NF-e/NFC-e
7
+ class Client < SEFAZ::Webservice::Base
8
+
9
+ SERVICES = %i[ setaAmbiente setaRespTecnico setaPFXTss setaPFXAss statusDoServico consultarNF consultarCadastro consultarRecibo
10
+ assinarNF validarNF auditarNF inutilizarNF exportarInutilizarNF enviarInutilizarNF calculaChaveInutilizacao
11
+ enviarEvento enviarLoteDeEvento cancelarNF exportarCancelarNF enviarCCe exportarCCe enviarNF enviarLoteNF calculaChaveNF]
12
+
13
+ # Métodos de Configuração:
14
+ # - setaAmbiente
15
+ # - setaRespTecnico
16
+ # - setaPFXTss
17
+ # - setaPFXAss
18
+
19
+ # Métodos de Consulta, Validação e Documentos: (SEM ASSINATURA)
20
+ # - statusDoServico
21
+ # - consultarNF
22
+ # - consultarCadastro
23
+ # - consultarRecibo
24
+ # - consultarGTIN (PENDENTE)
25
+ # - consultarDistribuicaoDFe (PENDENTE)
26
+ # - consultarDistribuicaoDFeChave (PENDENTE)
27
+ # - validarNF
28
+ # - auditarNF
29
+
30
+ # Métodos de Manipulação: (MAIORIA EXIGE ASSINATURA)
31
+ # -- Os métodos 'enviarNF' e 'enviarLoteNF' não precisa 'exportar', pois os dados são montados externo à gema (XML ou Hash ou Dataset)
32
+ # - assinarNF
33
+ # - enviarNF
34
+ # - enviarLoteNF
35
+ # - calculaChaveNF
36
+ # - inutilizarNF
37
+ # - exportarInutilizarNF
38
+ # - enviarInutilizarNF
39
+ # - calculaChaveInutilizacao
40
+ # - cancelarNF (EVENTO)
41
+ # - exportarCancelarNF (EVENTO)
42
+ # - enviarCCe (EVENTO)
43
+ # - exportarCCe (EVENTO)
44
+ # - enviarManifestacao (PENDENTE) (EVENTO)
45
+ # - exportarManifestacao (PENDENTE) (EVENTO)
46
+ # - enviarEvento
47
+ # - enviarLoteDeEvento
48
+ # - gerarLeiauteEvento (PRIVADO)
49
+
50
+ def initialize
51
+ end
52
+
53
+ def setaAmbiente(params = {})
54
+ @uf = params[:uf]
55
+ @ambiente = params[:ambiente]
56
+ @cnpj = params[:cnpj].to_s.delete("^0-9")
57
+ end
58
+
59
+ def setaRespTecnico(params = {})
60
+ @cnpjTec = params[:cnpj]
61
+ @contatoTec = params[:contato]
62
+ @emailTec = params[:email]
63
+ @foneTec = params[:fone]
64
+ @idCSRT = params[:idCSRT]
65
+ @CSRT = params[:CSRT]
66
+ end
67
+
68
+ def setaPFXTss(params = {})
69
+ @pkcs12Tss = OpenSSL::PKCS12.new(params[:pfx], params[:senha])
70
+ end
71
+
72
+ def setaPFXAss(params = {})
73
+ @pkcs12Ass = OpenSSL::PKCS12.new(params[:pfx], params[:senha])
74
+ end
75
+
76
+ # Consulta Status SEFAZ
77
+ def statusDoServico
78
+ versao = "4.00"
79
+ hash = { consStatServ: { tpAmb: @ambiente, cUF: @uf, xServ: 'STATUS', :@xmlns => "http://www.portalfiscal.inf.br/nfe", :@versao => versao } }
80
+ wsdl = SEFAZ::Webservice::NFE::WSDL.get(:NfeStatusServico, @ambiente, @uf)
81
+ conn = SEFAZ::Webservice::NFE::Connection.new(@pkcs12Tss, wsdl, versao, @uf)
82
+ resp = conn.call(:nfe_status_servico_nf, hash)
83
+ return [resp.body.to_xml!, resp.body]
84
+ end
85
+
86
+ # Consulta Situação NF
87
+ # @chaveNF(String) = Chave de acesso de uma NF
88
+ def consultarNF(chaveNF)
89
+ versao = "4.00"
90
+ hash = { consSitNFe: { tpAmb: @ambiente, xServ: 'CONSULTAR', chNFe: chaveNF, :@xmlns => "http://www.portalfiscal.inf.br/nfe", :@versao => versao } }
91
+ wsdl = SEFAZ::Webservice::NFE::WSDL.get(:NfeConsultaProtocolo, @ambiente, @uf)
92
+ conn = SEFAZ::Webservice::NFE::Connection.new(@pkcs12Tss, wsdl, versao, @uf)
93
+ resp = conn.call(:nfe_consulta_nf, hash)
94
+ return [resp.body.to_xml!, resp.body]
95
+ end
96
+
97
+ # Consulta Cadastro
98
+ # @nroDocumento(String) = Número do documento
99
+ # @tpDocumento(String) = CNPJ/CPF/IE
100
+ # @uf(String) = Sigla do estado que será consultado (SP; MG; RJ; ...)
101
+ def consultarCadastro(nroDocumento, tpDocumento, uf)
102
+ versao = "2.00"
103
+ hash = { ConsCad: { infCons: { xServ: 'CONS-CAD', UF: uf }, :@xmlns => "http://www.portalfiscal.inf.br/nfe", :@versao => versao } }
104
+ case tpDocumento
105
+ when 'CNPJ'; hash[:ConsCad][:infCons][:CNPJ] = nroDocumento.to_s.delete("^0-9")
106
+ when 'CPF'; hash[:ConsCad][:infCons][:CPF] = nroDocumento.to_s.delete("^0-9")
107
+ when 'IE'; hash[:ConsCad][:infCons][:IE] = nroDocumento.to_s.delete("^0-9")
108
+ end
109
+ wsdl = SEFAZ::Webservice::NFE::WSDL.get(:NfeConsultaCadastro, @ambiente, @uf)
110
+ conn = SEFAZ::Webservice::NFE::Connection.new(@pkcs12Tss, wsdl, versao, @uf)
111
+ resp = conn.call(:consulta_cadastro, hash)
112
+ return [resp.body.to_xml!, resp.body]
113
+ end
114
+
115
+ # Consulta Recebido de Lote
116
+ # @numRecibo(String) = Número do recibo do lote de NF-e
117
+ def consultarRecibo(numRecibo)
118
+ versao = "4.00"
119
+ hash = { consReciNFe: { tpAmb: @ambiente, nRec: numRecibo, :@xmlns => "http://www.portalfiscal.inf.br/nfe", :@versao => versao } }
120
+ wsdl = SEFAZ::Webservice::NFE::WSDL.get(:NFeRetAutorizacao, @ambiente, @uf)
121
+ conn = SEFAZ::Webservice::NFE::Connection.new(@pkcs12Tss, wsdl, versao, @uf)
122
+ resp = conn.call(:nfe_ret_autorizacao_lote, hash)
123
+ return [resp.body.to_xml!, resp.body]
124
+ end
125
+
126
+ # Assinar NF - PFX de assinatura - Certificado A1
127
+ # @documento(Hash ou String) = XML ou HASH que será assinado
128
+ def assinarNF(documento)
129
+ xml = (documento.is_a?(Hash) ? documento.to_xml! : documento)
130
+ doc = SEFAZ::Utils::Signer.new(xml)
131
+ doc.sign!(@pkcs12Ass.certificate, @pkcs12Ass.key)
132
+ xml = doc.to_xml
133
+ return [xml, xml.to_hash!]
134
+ end
135
+
136
+ # Enviar NF - Necessário uma NF assinada
137
+ # @documento(Hash ou String) = XML ou HASH assinado que será enviado
138
+ # @indSinc(String) = "0"=Assíncrono / "1"=Síncrono
139
+ # @idLote(String) = Identificador de controle do Lote de envio do Lote
140
+ def enviarNF(documento, indSinc, idLote)
141
+ return enviarLoteNF([ documento ], indSinc, idLote)
142
+ end
143
+
144
+ # Envia Lote de NF - Necessário que cada NF esteja assinada
145
+ # OBS: Recomendado para envio em lote de NF, cada elemento do Array pode ser Hash ou XML assinados
146
+ # @lote(Array) = Array de NF assinadas
147
+ # @indSinc(String) = "0"=Assíncrono / "1"=Síncrono
148
+ # @idLote(String) = Identificador de controle do Lote de envio do Lote
149
+ # Exemplo de @lote:
150
+ # @nf1_xml, @nf1_hash = @webservice.assinarNF(...)
151
+ # @nf2_xml, @nf2_hash = @webservice.assinarNF(...)
152
+ # @lote = [ @nf1_xml, @nf2_hash ]
153
+ def enviarLoteNF(lote, indSinc, idLote)
154
+ versao = "4.00"
155
+ lote = (lote.map { |el| el.is_a?(Hash) ? el[:NFe] : el.to_hash![:NFe] })
156
+ hash = {
157
+ enviNFe: { :@xmlns => "http://www.portalfiscal.inf.br/nfe", :@versao => versao,
158
+ idLote: idLote,
159
+ indSinc: indSinc,
160
+ NFe: lote
161
+ }
162
+ }
163
+ wsdl = SEFAZ::Webservice::NFE::WSDL.get(:NFeAutorizacao, @ambiente, @uf)
164
+ conn = SEFAZ::Webservice::NFE::Connection.new(@pkcs12Tss, wsdl, versao, @uf)
165
+ resp = conn.call(:nfe_autorizacao_lote, hash)
166
+ return [resp.body.to_xml!, resp.body]
167
+ end
168
+
169
+ # Calcular Chave NF
170
+ # @uf = Código da UF do emitente do Documento Fiscal
171
+ # @aamm = Ano e Mês de emissão da NF-e
172
+ # @cnpj = CNPJ do emitente
173
+ # @modelo = Modelo do Documento Fiscal (55 ou 65)
174
+ # @serie = Série do Documento Fiscal
175
+ # @nNF = Número do Documento Fiscal
176
+ # @tpEmis = Forma de emissão da NF-e
177
+ # @cNF = Código Numérico que compõe a Chave de Acesso (ID do sistema)
178
+ def calculaChaveNF(uf, aamm, cnpj, modelo, serie, nNF, tpEmis, cNF)
179
+ uf = uf.to_s.rjust(2, "0")
180
+ aamm = aamm.to_s.rjust(4, "0")
181
+ cnpj = cnpj.to_s.delete("^0-9").rjust(14, "0")
182
+ modelo = modelo.to_s.rjust(2, "0")
183
+ serie = serie.to_s.rjust(3, "0")
184
+ nNF = nNF.to_s.rjust(9, "0")
185
+ cNF = cNF.to_s.rjust(8, "0")
186
+ nChave = "#{uf[0,2]}#{aamm[0,4]}#{cnpj[0,14]}#{modelo[0,2]}#{serie[0,3]}#{nNF[0,9]}#{tpEmis[0,1]}#{cNF[0,8]}"
187
+ nPesos = "4329876543298765432987654329876543298765432"
188
+ cDV = 11 - (nChave.split("").each_with_index.map { |n, index| n.to_i * nPesos[index].to_i }.sum % 11)
189
+ return ["#{nChave}#{cDV}", cDV]
190
+ end
191
+
192
+ # Valida NF no SEFAZ RS NF-e (https://www.sefaz.rs.gov.br/NFE/NFE-VAL.aspx)
193
+ # @documento(Hash ou String) = XML ou HASH que será validado
194
+ # @openTimeout(Integer) = Tempo de espera em segundos para abrir conexão (opcional: padrão 60)
195
+ # @readTimeout(Integer) = Tempo de espera em segundos para ler resposta (opcional: padrão 60)
196
+ def validarNF(documento, openTimeout = 60, readTimeout = 60)
197
+ xml = (documento.is_a?(Hash) ? documento.to_xml! : documento)
198
+ validator = SEFAZ::Webservice::NFE::Validator.new(xml)
199
+ stat, msg, err = validator.exec(openTimeout, readTimeout)
200
+ case stat
201
+ when :ok; return [true, msg, err]
202
+ else return [false, {}, {}]
203
+ end
204
+ end
205
+
206
+ # Auditar NF no validador TecnoSpeed (https://validador.nfe.tecnospeed.com.br/)
207
+ # @documento(Hash ou String) = XML ou HASH que será auditado
208
+ # @openTimeout(Integer) = Tempo de espera em segundos para abrir conexão (opcional: padrão 60)
209
+ # @readTimeout(Integer) = Tempo de espera em segundos para ler resposta (opcional: padrão 60)
210
+ def auditarNF(documento, openTimeout = 60, readTimeout = 60)
211
+ xml = (documento.is_a?(Hash) ? documento.to_xml! : documento)
212
+ auditor = SEFAZ::Webservice::NFE::Auditor.new(xml)
213
+ stat, msg = auditor.exec(openTimeout, readTimeout)
214
+ case stat
215
+ when :ok; return [true, msg]
216
+ else return [false, {}]
217
+ end
218
+ end
219
+
220
+ # Inutilizar NF - Gera, assina e envia o documento com certificado A1 (exportarInutilizarNF, assinarNF, enviarInutilizarNF)
221
+ # OBS: Caso parâmetro @chaveInut estiver em branco, a chave será calculada automaticamente (calculaChaveInutilizacao)
222
+ # @chaveInut = Identificador da TAG a ser assinada
223
+ # @ano = Ano de inutilização da numeração
224
+ # @modelo = Modelo do documento (55 ou 65)
225
+ # @serie = Série da NF-e
226
+ # @nroNFIni = Número da NF-e inicial a ser inutilizada
227
+ # @nroNFFin = Número da NF-e final a ser inutilizada
228
+ # @justificativa = Informar a justificativa do pedido de inutilização
229
+ def inutilizarNF(chaveInut, ano, modelo, serie, nroNFIni, nroNFFin, justificativa)
230
+ _, hash = exportarInutilizarNF(chaveInut, ano, modelo, serie, nroNFIni, nroNFFin, justificativa)
231
+ _, hash = assinarNF(hash)
232
+ return enviarInutilizarNF(hash)
233
+ end
234
+
235
+ # Calcular Chave de Inutilização
236
+ # @ano = Ano de inutilização da numeração
237
+ # @cnpj = CNPJ do emitente
238
+ # @modelo = Modelo do documento (55 ou 65)
239
+ # @serie = Série da NF-e
240
+ # @nroNFIni = Número da NF-e inicial a ser inutilizada
241
+ # @nroNFFin = Número da NF-e final a ser inutilizada
242
+ def calculaChaveInutilizacao(ano, cnpj, modelo, serie, nroNFIni, nroNFFin)
243
+ serie = serie.to_s.rjust(3, "0")
244
+ nroNFIni = nroNFIni.to_s.rjust(9, "0")
245
+ nroNFFin = nroNFFin.to_s.rjust(9, "0")
246
+ return "ID#{@uf}#{ano}#{cnpj}#{modelo}#{serie}#{nroNFIni}#{nroNFFin}"
247
+ end
248
+
249
+ # Exportar Inutilização NF - Exporta um documento bruto (sem assinatura)
250
+ # OBS: Recomendado quando utilizado o certificado A3
251
+ # Caso parâmetro @chaveInut estiver em branco, a chave será calculada automaticamente (calculaChaveInutilizacao)
252
+ # @chaveInut = Identificador da TAG a ser assinada
253
+ # @ano = Ano de inutilização da numeração
254
+ # @modelo = Modelo do documento (55 ou 65)
255
+ # @serie = Série da NF-e
256
+ # @nroNFIni = Número da NF-e inicial a ser inutilizada
257
+ # @nroNFFin = Número da NF-e final a ser inutilizada
258
+ # @justificativa = Informar a justificativa do pedido de inutilização
259
+ def exportarInutilizarNF(chaveInut, ano, modelo, serie, nroNFIni, nroNFFin, justificativa)
260
+ versao = "4.00"
261
+ chaveInut = calculaChaveInutilizacao(ano, @cnpj, modelo, serie, nroNFIni, nroNFFin) if chaveInut.blank?
262
+ hash = { inutNFe: { :@xmlns => "http://www.portalfiscal.inf.br/nfe", :@versao => versao, infInut: {
263
+ :@Id => chaveInut,
264
+ tpAmb: @ambiente,
265
+ xServ: 'INUTILIZAR',
266
+ cUF: @uf,
267
+ ano: ano,
268
+ CNPJ: @cnpj,
269
+ mod: modelo,
270
+ serie: serie,
271
+ nNFIni: nroNFIni,
272
+ nNFFin: nroNFFin,
273
+ xJust: justificativa
274
+ } } }
275
+ return [hash.to_xml!, hash]
276
+ end
277
+
278
+ # Enviar Inutilização NF - Necessário um documento assinado
279
+ # OBS: Recomendado quando utilizado o certificado A3
280
+ # @documento(Hash ou String) = XML ou HASH assinado que será enviado
281
+ def enviarInutilizarNF(documento)
282
+ versao = "4.00"
283
+ hash = (documento.is_a?(Hash) ? documento : documento.to_hash!)
284
+ wsdl = SEFAZ::Webservice::NFE::WSDL.get(:NfeInutilizacao, @ambiente, @uf)
285
+ conn = SEFAZ::Webservice::NFE::Connection.new(@pkcs12Tss, wsdl, versao, @uf)
286
+ resp = conn.call(:nfe_inutilizacao_nf, hash)
287
+ return [resp.body.to_xml!, resp.body]
288
+ end
289
+
290
+ # Cancelar NF - Gera, assina e envia o documento com certificado A1 (exportarCancelarNF, assinarNF, enviarEvento)
291
+ # @chaveNF = Chave de acesso de uma NF
292
+ # @sequenciaEvento = O número do evento
293
+ # @dataHoraEvento = Data e Hora da Emissão do Evento (ex: 2023-01-15T17:23:00+03:00)
294
+ # @numProtocolo = Número do Protocolo de registro da NF
295
+ # @justificativa = Motivo do cancelamento da NF
296
+ # @idLote = Número de controle interno
297
+ def cancelarNF(chaveNF, sequenciaEvento, dataHoraEvento, numProtocolo, justificativa, idLote)
298
+ _, hash = exportarCancelarNF(chaveNF, sequenciaEvento, dataHoraEvento, numProtocolo, justificativa)
299
+ _, hash = assinarNF(hash)
300
+ return enviarEvento(hash, idLote)
301
+ end
302
+
303
+ # Exportar Cancelar NF - Exporta um documento bruto (sem assinatura)
304
+ # OBS: Recomendado quando utilizado o certificado A3
305
+ # @chaveNF = Chave de acesso de uma NF
306
+ # @sequenciaEvento = O número do evento
307
+ # @dataHoraEvento = Data e Hora da Emissão do Evento (ex: 2023-01-15T17:23:00+03:00)
308
+ # @numProtocolo = Número do Protocolo de registro da NF
309
+ # @justificativa = Motivo do cancelamento da NF
310
+ # @idLote = Número de controle interno
311
+ def exportarCancelarNF(chaveNF, sequenciaEvento, dataHoraEvento, numProtocolo, justificativa)
312
+ versao = "1.00"
313
+ tpEvento = "110111"
314
+ _, hash = gerarLeiauteEvento(versao, tpEvento, chaveNF, sequenciaEvento, dataHoraEvento)
315
+ hash[:evento][:infEvento][:detEvento] = { :@versao => versao,
316
+ descEvento: "Cancelamento",
317
+ nProt: numProtocolo,
318
+ xJust: justificativa
319
+ }
320
+ return [hash.to_xml!, hash]
321
+ end
322
+
323
+ # Enviar CCe - Gera, assina e envia o documento com certificado A1 (exportarCCe, assinarNF, enviarEvento)
324
+ # @chaveNF = Chave de acesso de uma NF
325
+ # @sequenciaEvento = O número do evento
326
+ # @dataHoraEvento = Data e Hora da Emissão do Evento (ex: 2023-01-15T17:23:00+03:00)
327
+ # @textoCorrecao = Motivo do cancelamento da NF
328
+ # @idLote = Número de controle interno
329
+ def enviarCCe(chaveNF, sequenciaEvento, dataHoraEvento, textoCorrecao, idLote)
330
+ _, hash = exportarCCe(chaveNF, sequenciaEvento, dataHoraEvento, textoCorrecao)
331
+ _, hash = assinarNF(hash)
332
+ return enviarEvento(hash, idLote)
333
+ end
334
+
335
+ # Exportar CCe - Exporta um documento bruto (sem assinatura)
336
+ # OBS: Recomendado quando utilizado o certificado A3
337
+ # @chaveNF = Chave de acesso de uma NF
338
+ # @sequenciaEvento = O número do evento
339
+ # @dataHoraEvento = Data e Hora da Emissão do Evento (ex: 2023-01-15T17:23:00+03:00)
340
+ # @textoCorrecao = Motivo do cancelamento da NF
341
+ def exportarCCe(chaveNF, sequenciaEvento, dataHoraEvento, textoCorrecao)
342
+ versao = "1.00"
343
+ tpEvento = "110110"
344
+ _, hash = gerarLeiauteEvento(versao, tpEvento, chaveNF, sequenciaEvento, dataHoraEvento)
345
+ hash[:evento][:infEvento][:detEvento] = { :@versao => versao,
346
+ descEvento: "Carta de Correcao",
347
+ xCorrecao: textoCorrecao,
348
+ xCondUso: "A Carta de Correcao e disciplinada pelo paragrafo 1o-A do art. 7o do Convenio S/N, de 15 de dezembro de 1970 e pode ser utilizada para regularizacao de erro ocorrido na emissao de documento fiscal, desde que o erro nao esteja relacionado com: I - as variaveis que determinam o valor do imposto tais como: base de calculo, aliquota, diferenca de preco, quantidade, valor da operacao ou da prestacao; II - a correcao de dados cadastrais que implique mudanca do remetente ou do destinatario; III - a data de emissao ou de saida."
349
+ }
350
+ return [hash.to_xml!, hash]
351
+ end
352
+
353
+ # Enviar Evento - Necessário um documento assinado
354
+ # OBS: Recomendado quando utilizado o certificado A3
355
+ # @evento(Hash ou String) = XML ou HASH assinado que será enviado
356
+ # @idLote(String) = Identificador de controle do Lote de envio do Evento
357
+ def enviarEvento(evento, idLote)
358
+ return enviarLoteDeEvento([ evento ], idLote)
359
+ end
360
+
361
+ # Envia Lote de Eventos - Necessário que cada evento esteja assinado
362
+ # OBS: Recomendado quando utilizado o certificado A3 e/ou para envio em lote de eventos
363
+ # Cada elemento do Array pode ser Hash ou XML assinados
364
+ # @lote(Array) = Array de eventos assinados
365
+ # @idLote(String) = Identificador de controle do Lote de envio do Evento
366
+ # Exemplo de @lote:
367
+ # @eve1_xml, @eve1_hash = @webservice.exportarCancelarNF(...)
368
+ # @eve2_xml, @eve2_hash = @webservice.exportarCancelarNF(...)
369
+ # @lote = [ @eve1_xml, @eve2_hash ]
370
+ def enviarLoteDeEvento(lote, idLote)
371
+ versao = "1.00"
372
+ lote = (lote.map { |el| el.is_a?(Hash) ? el[:evento] : el.to_hash![:evento] })
373
+ hash = {
374
+ envEvento: { :@xmlns => "http://www.portalfiscal.inf.br/nfe", :@versao => versao,
375
+ idLote: idLote,
376
+ evento: lote
377
+ }
378
+ }
379
+ wsdl = SEFAZ::Webservice::NFE::WSDL.get(:RecepcaoEvento, @ambiente, @uf)
380
+ conn = SEFAZ::Webservice::NFE::Connection.new(@pkcs12Tss, wsdl, versao, @uf)
381
+ resp = conn.call(:nfe_recepcao_evento, hash)
382
+ return [resp.body.to_xml!, resp.body]
383
+ end
384
+
385
+ # Gera Informações do Responsável Técnico - Calcula o hashCSRT e cria o grupo do responsável técnico
386
+ # Necessário quando estiver emitindo uma NF-e/NFC-e
387
+ # @documento(Hash ou String) = XML ou HASH que será tratado
388
+ def gerarInfRespTec(documento)
389
+ hash = (documento.is_a?(Hash) ? documento : documento.to_hash!)
390
+ chaveNF = hash[:NFe][:infNFe][:@Id].to_s.delete("^0-9")
391
+ concat = @CSRT.to_s + chaveNF.to_s
392
+ hexdigest = Digest::SHA1.hexdigest(concat)
393
+ hashCSRT = Base64.strict_encode64(hexdigest)
394
+ infRespTec = { infRespTec: { CNPJ: @cnpjTec, xContato: @contatoTec, email: @emailTec, fone: @foneTec, idCSRT: @idCSRT, hashCSRT: hashCSRT } }.compress!
395
+ hash[:NFe][:infNFe][:infRespTec] = infRespTec[:infRespTec]
396
+ return [hash.to_xml!, hash]
397
+ end
398
+
399
+ private
400
+
401
+ # Gera o Leiaute Mensagem de Entrada (Parte Geral) dos Eventos
402
+ # Utilizado internamente nos métodos: exportarCancelarNF, exportarCCe, exportarManifestacao, ... (métodos de eventos)
403
+ def gerarLeiauteEvento(verEvento, tpEvento, chaveNF, sequenciaEvento, dataHoraEvento)
404
+ versao = "1.00"
405
+ id = "ID" + tpEvento.to_s + chaveNF.to_s + sequenciaEvento.to_s.rjust(2, "0")
406
+ hash = {
407
+ evento: { :@xmlns => "http://www.portalfiscal.inf.br/nfe", :@versao => versao,
408
+ infEvento: { :@Id => id,
409
+ cOrgao: @uf,
410
+ tpAmb: @ambiente,
411
+ CNPJ: @cnpj,
412
+ chNFe: chaveNF,
413
+ dhEvento: dataHoraEvento,
414
+ tpEvento: tpEvento,
415
+ nSeqEvento: sequenciaEvento,
416
+ verEvento: verEvento
417
+ }
418
+ }
419
+ }
420
+ return [hash.to_xml!, hash]
421
+ end
422
+
423
+ end
424
+ end
425
+ end
426
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SEFAZ
4
+ module Webservice
5
+ module NFE
6
+ # Principal classe de conexão SOAP com o módulo NF-e/NFC-e
7
+ class Connection < SEFAZ::Utils::Connection
8
+
9
+ def initialize(pkcs12, wsdl, versaoDados, cUF)
10
+ @soap_header = { nfeCabecMsg: { versaoDados: versaoDados, cUF: cUF, :@xmlns => 'http://www.portalfiscal.inf.br/nfe' } }
11
+ super(pkcs12, wsdl, @soap_header)
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end