Class: BrNfe::Base

Inherits:
ActiveModelBase show all
Includes:
Helper::HaveEmitente
Defined in:
lib/br_nfe/base.rb

Direct Known Subclasses

Service::Base

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helper::HaveEmitente

#emitente, #emitente=

Methods inherited from ActiveModelBase

#assign_attributes, #default_values, #initialize

Constructor Details

This class inherits a constructor from BrNfe::ActiveModelBase

Instance Attribute Details

#certificate_pkcs12_passwordObject

Returns the value of attribute certificate_pkcs12_password.



5
6
7
# File 'lib/br_nfe/base.rb', line 5

def certificate_pkcs12_password
  @certificate_pkcs12_password
end

#certificate_pkcs12_pathObject

Returns the value of attribute certificate_pkcs12_path.



6
7
8
# File 'lib/br_nfe/base.rb', line 6

def certificate_pkcs12_path
  @certificate_pkcs12_path
end

#certificate_pkcs12_valueObject

Caso não tenha o certificate_pkcs12 salvo em arquivo, pode setar a string do certificate_pkcs12 direto pelo atributo certificate_pkcs12_value Caso tenha o certificate_pkcs12 em arquivo, basta setar o atributo certificate_pkcs12_path e deixar o atributo certificate_pkcs12_value em branco



178
179
180
# File 'lib/br_nfe/base.rb', line 178

def certificate_pkcs12_value
  @certificate_pkcs12_value
end

#client_wsdl_ssl_cert_fileObject

Returns the value of attribute client_wsdl_ssl_cert_file.



11
12
13
# File 'lib/br_nfe/base.rb', line 11

def client_wsdl_ssl_cert_file
  @client_wsdl_ssl_cert_file
end

#client_wsdl_ssl_cert_key_fileObject

Returns the value of attribute client_wsdl_ssl_cert_key_file.



12
13
14
# File 'lib/br_nfe/base.rb', line 12

def client_wsdl_ssl_cert_key_file
  @client_wsdl_ssl_cert_key_file
end

#client_wsdl_ssl_cert_key_passwordObject

Returns the value of attribute client_wsdl_ssl_cert_key_password.



13
14
15
# File 'lib/br_nfe/base.rb', line 13

def client_wsdl_ssl_cert_key_password
  @client_wsdl_ssl_cert_key_password
end

#client_wsdl_ssl_verify_modeObject

Returns the value of attribute client_wsdl_ssl_verify_mode.



10
11
12
# File 'lib/br_nfe/base.rb', line 10

def client_wsdl_ssl_verify_mode
  @client_wsdl_ssl_verify_mode
end

#envObject

Returns the value of attribute env.



8
9
10
# File 'lib/br_nfe/base.rb', line 8

def env
  @env
end

Instance Method Details

#certificado_obrigatorio?Boolean

Método que deve ser sobrescrito para as ações que necessitam do certificate_pkcs12 para assinatura

Returns:

  • (Boolean)


19
20
21
# File 'lib/br_nfe/base.rb', line 19

def certificado_obrigatorio?
	false
end

#certificateObject



208
209
210
# File 'lib/br_nfe/base.rb', line 208

def certificate
	@certificate ||= certificate_pkcs12.try :certificate
end

#certificate=(value) ⇒ Object



204
205
206
# File 'lib/br_nfe/base.rb', line 204

def certificate=(value)
	@certificate = value
end

#certificate_keyObject



212
213
214
# File 'lib/br_nfe/base.rb', line 212

def certificate_key
	@certificate_key ||= certificate_pkcs12.try :key
end

#certificate_key=(value) ⇒ Object



216
217
218
# File 'lib/br_nfe/base.rb', line 216

def certificate_key=(value)
	@certificate_key = value
end

#certificate_pkcs12Object



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/br_nfe/base.rb', line 182

def certificate_pkcs12
	return @certificate_pkcs12 if @certificate_pkcs12
	@certificate_pkcs12 = nil
	
	# É utilizado uma Thread e limpado os errors do OpenSSL para evitar perda de 
	# conexão com o banco de dados PostgreSQL.
	# Veja: http://stackoverflow.com/questions/33112155/pgconnectionbad-pqconsumeinput-ssl-error-key-values-mismatch/36283315#36283315
	# Veja: https://github.com/tedconf/front_end_builds/pull/66
	Thread.new do 
		@certificate_pkcs12 = OpenSSL::PKCS12.new(certificate_pkcs12_value, certificate_pkcs12_password) 
		OpenSSL.errors.clear
	end.join
	OpenSSL.errors.clear

	@certificate_pkcs12 
rescue
end

#certificate_pkcs12=(value) ⇒ Object



200
201
202
# File 'lib/br_nfe/base.rb', line 200

def certificate_pkcs12=(value)
	@certificate_pkcs12 = value
end

#client_wsdlObject



150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/br_nfe/base.rb', line 150

def client_wsdl
	@client_wsdl ||= Savon.client({
		wsdl:                  wsdl,
		log:                   BrNfe.client_wsdl_log,
		pretty_print_xml:      BrNfe.client_wsdl_pretty_print_xml,

		ssl_verify_mode:       client_wsdl_ssl_verify_mode,
		ssl_cert_file:         client_wsdl_ssl_cert_file,
		ssl_cert_key_file:     client_wsdl_ssl_cert_key_file,
		ssl_cert_key_password: client_wsdl_ssl_cert_key_password
	})
end

#content_xmlObject

Esse método serve para ser utilizado no Base de cada orgão emissor onde em alguns casos é necessário colocar o xml em um CDATA É esse método que é passado dentro do Body da equisição SOAP



66
67
68
# File 'lib/br_nfe/base.rb', line 66

def content_xml
	xml_builder
end

#env_namespaceObject

Namespace da requisição SOAP



37
38
39
# File 'lib/br_nfe/base.rb', line 37

def env_namespace
	:soapenv
end

#find_xml(file_name, dir, context = nil, options = {}) ⇒ Object



255
256
257
258
259
# File 'lib/br_nfe/base.rb', line 255

def find_xml(file_name, dir, context=nil, options={})
	if File.exists?("#{dir}/#{file_name}.xml.slim")
		Slim::Template.new("#{dir}/#{file_name}.xml.slim").render(context, options).html_safe 
	end
end

#get_xml_dirs(custom_dir_path = nil) ⇒ Object



261
262
263
# File 'lib/br_nfe/base.rb', line 261

def get_xml_dirs(custom_dir_path=nil)
	[custom_dir_path, xml_current_dir_path, xml_default_dir_path].flatten.select(&:present?)
end

#message_namespacesObject



104
105
106
# File 'lib/br_nfe/base.rb', line 104

def message_namespaces
	{}
end

#method_wsdlObject

Método que contem qual a operação que deverá ser chamada do WS SOAP.



50
51
52
# File 'lib/br_nfe/base.rb', line 50

def method_wsdl
	raise "Não implementado."
end

#namespace_for_signatureObject

Utilizado para colocar o namespace nas tags da assiantura Exemplo: <ns2:Signature Id=“?”>

<ns2:SignedInfo Id="?">
  <ns2:CanonicalizationMethod Algorithm="?">?</ns2:CanonicalizationMethod>
  .....


101
102
# File 'lib/br_nfe/base.rb', line 101

def namespace_for_signature
end

#namespace_for_tagsObject

Utilizado para colocar o namespace nas tags de valores Exemplo: <ns1:LoteRps id=“123”>

<ns1:NumeroLote>3311</ns1:NumeroLote>
<ns1:Cnpj>23020443000140</ns1:Cnpj>


91
92
# File 'lib/br_nfe/base.rb', line 91

def namespace_for_tags
end

#namespace_identifierObject

O Namespace Indentifier é utilizado para adicionar o namespace na tag principal da requisição. Normalmente deve seguir o namespace utilizado para identificar o namespace da mensagem.

Exemplo: se o método message_namespaces for BrNfe::Base.xmlns:ns1=“httpxmlns:ns1=“http.…” então o namespace_identifier deveria ser ‘ns1:’. E com isso irá adicionar o namespace na tag principal da requsição. Exemplo com a requisição EnviarLoteRps: COM namespace_identifier => ns1:EnviarLoteRpsEnvio SEM namespace_identifier => EnviarLoteRpsEnvio

Tipo de retorno: String OR Nil



83
84
# File 'lib/br_nfe/base.rb', line 83

def namespace_identifier
end

#original_responseObject



27
28
29
# File 'lib/br_nfe/base.rb', line 27

def original_response
	@original_response
end

#render_xml(file_name, opts = {}) ⇒ Object

Renderiza o xml a partir do nome de um arquivo Irá procurar o arquivo a partir dos seguintes diretórios> 1° - A partir do parâmetro :dir_path 2° - A partir do método xml_current_dir_path 3° - A partir do método xml_default_dir_path

Se não encontrar o arquivo em nenhum dos diretórios irá execurar uma excessão de RuntimeError

Utilização ‘render_xml(’file_name’, ‘/my/custom/dir’, context: Object‘

<b>Tipo de retorno: <b> String (XML)



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/br_nfe/base.rb', line 234

def render_xml file_name, opts={}
	opts ||= {}
	default_options = opts.extract!(:dir_path, :context)
	default_options[:context] ||= self
	
	# Inicializa a variavel xml com nil para comparar se oa rquivo foi de fato encontrado.
	xml = nil
	get_xml_dirs(default_options[:dir_path]).each do |dir|
		if xml = find_xml(file_name, dir, default_options[:context], opts)
			break # Stop loop
		end
	end

	# Lança uma excessão se não for encontrado o xml
	# Deve verificar se é nil pois o arquivo xml pode estar vazio
	if xml.nil?
		raise "Arquivo #{file_name}.xml.slim não encontrado nos diretórios #{get_xml_dirs(default_options[:dir_path])}" 
	end
	xml
end

#responseObject



31
32
33
# File 'lib/br_nfe/base.rb', line 31

def response
	@response
end

#response_encodingObject



121
122
123
# File 'lib/br_nfe/base.rb', line 121

def response_encoding
	"UTF-8"
end

#sign_xml(xml, sign_nodes = []) ⇒ Object

USE EXAMPLE

@xml = <?xml version="1.0" encoding="ISO-8859-1"?>
        <EnviarLoteRpsEnvio xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd">
          <LoteRps id="L2">
            ...
            <ListaRps>
              <Rps>
                <InfRps id="R2">
                  ...
                </>InfRps
              </Rps>
              <Rps>
                <InfRps id="R3">
                  ...
                </>InfRps
              </Rps>
            </ListaRps>
          </LoteRps>
        </EnviarLoteRpsEnvio>

sign_nodes = [

{

node_path: “//nf:EnviarLoteRpsEnvio/nf:LoteRps/nf:ListaRps/nf:Rps/nf:InfRps”, node_namespaces: ‘www.abrasf.org.br/ABRASF/arquivos/nfse.xsd’, node_ids: [‘R2’,‘R3’]

},
{
  node_path: "//nf:EnviarLoteRpsEnvio/nf:LoteRps", 
  node_namespaces: {nf: 'http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd'},
  node_ids: ['L2']
},

]

Call Method: sign_xml(@xml, sign_nodes)



333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/br_nfe/base.rb', line 333

def sign_xml(xml, sign_nodes=[])
	return xml unless certificate
	signer = Signer.new(xml)
	signer.cert        = certificate
	signer.private_key = certificate_key

	# Como o documento não é um envelope SOAP preciso setar o security_node e o security_token_id
	signer.security_node = signer.document.root
	signer.security_token_id = ""

	sign_nodes.each do |options|
		node_ids = [options[:node_ids]].flatten
		signer.document.xpath(options[:node_path], options[:node_namespaces]).each_with_index do |node, i|
			# digo quais tags devem ser assinadas
			signer.digest!(node, id: "#{node_ids[i]}", enveloped: true)
		end				
	end
	
	# Assina o XML
	signer.sign!(security_token: false, issuer_serial: true)

	signer.to_xml
end

#signature_typeObject

Existem 2 tipos de assinatura da NFS-e

  • :default

    Assina o XML no momento em que está sendo montado. Funciona normalmente para a maiora das prefeituras. Primeiro assina cada RPS individualmente e adiciona a tag da assinatura e depois Assina o LOTE RPS com todas os RPSs assinados

  • :method_sign

    Assina o XML após a montagem do mesmo. Utiliza a gem ‘signer’ para assinar os nós do XML. Adiciona toda a assinatura no final do XML, diferente do que é descrito nas documentações. Porém em algumas cidades só consegui validar a assinatura utilizando esse método Estava dando o erro: E515 - Erro ao validar assinatura. - Remessa adulterada após a assinatura.



291
292
293
# File 'lib/br_nfe/base.rb', line 291

def signature_type
	:default
end

#signature_type?(type) ⇒ Boolean

Returns:

  • (Boolean)


294
295
296
# File 'lib/br_nfe/base.rb', line 294

def signature_type?(type)
	signature_type == type
end

#soap_namespacesObject



108
109
110
111
112
113
114
115
# File 'lib/br_nfe/base.rb', line 108

def soap_namespaces
	{
		'xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/',
		'xmlns:ins0'    => 'http://www.w3.org/2000/09/xmldsig#',
		'xmlns:xsd'     => 'http://www.w3.org/2001/XMLSchema',
		'xmlns:xsi'     => 'http://www.w3.org/2001/XMLSchema-instance'
	}
end

#soap_xmlObject

XML que irá na requisição SOAP

Tipo de retorno: _String XML_



137
138
139
# File 'lib/br_nfe/base.rb', line 137

def soap_xml
	@soap_xml ||= "#{tag_xml}#{render_xml('soap_env')}".html_safe
end

#tag_xmlObject

Tag XML que vai na requisição SOAP

Tipo de retorno: String



129
130
131
# File 'lib/br_nfe/base.rb', line 129

def tag_xml
	"<?xml version=\"1.0\" encoding=\"#{wsdl_encoding}\"?>"
end

#wsdlObject

Deve conter o LINK do webservice a ser chamado



43
44
45
# File 'lib/br_nfe/base.rb', line 43

def wsdl
	raise "Não implementado."
end

#wsdl_encodingObject



117
118
119
# File 'lib/br_nfe/base.rb', line 117

def wsdl_encoding
	"UTF-8"
end

#xml_builderObject

O xml_builder é o que contém o conteúdo de cada tipo de requisição e deve ser sobrescrito em cada classe implementada. Por exemplo: recepcao_lote_rps, consulta_lote_rps, cancelamento_nfs, etc..



58
59
60
# File 'lib/br_nfe/base.rb', line 58

def xml_builder
	raise "Não implementado."
end

#xml_current_dir_pathObject

Diretório personalizado para cada classe Podendo ser sobrescrito em cada herança



268
269
270
# File 'lib/br_nfe/base.rb', line 268

def xml_current_dir_path
	[]
end

#xml_default_dir_pathObject

Diretório padrão dos arquivos XML



274
275
276
# File 'lib/br_nfe/base.rb', line 274

def xml_default_dir_path
	"#{BrNfe.root}/lib/br_nfe/xml"
end

#xml_versionObject

Versão do XML utilizado Cada Cidade pode utilizar uma versão diferente do XML

Tipo de retorno: Symbol



146
147
148
# File 'lib/br_nfe/base.rb', line 146

def xml_version
	:v1
end