br_nfe 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +15 -0
  3. data/Gemfile.lock +169 -0
  4. data/LICENSE +20 -0
  5. data/README.markdown +6 -0
  6. data/Rakefile +13 -0
  7. data/br_nfe.gemspec +28 -0
  8. data/lib/br_nfe/active_model_base.rb +62 -0
  9. data/lib/br_nfe/base.rb +168 -0
  10. data/lib/br_nfe/condicao_pagamento.rb +26 -0
  11. data/lib/br_nfe/destinatario.rb +26 -0
  12. data/lib/br_nfe/emitente.rb +40 -0
  13. data/lib/br_nfe/endereco.rb +44 -0
  14. data/lib/br_nfe/helper/cpf_cnpj.rb +60 -0
  15. data/lib/br_nfe/helper/have_address.rb +29 -0
  16. data/lib/br_nfe/helper/have_condicao_pagamento.rb +24 -0
  17. data/lib/br_nfe/helper/have_destinatario.rb +18 -0
  18. data/lib/br_nfe/helper/have_emitente.rb +20 -0
  19. data/lib/br_nfe/helper/have_intermediario.rb +24 -0
  20. data/lib/br_nfe/helper/have_rps.rb +27 -0
  21. data/lib/br_nfe/helper/string_methods.rb +21 -0
  22. data/lib/br_nfe/seed.rb +195 -0
  23. data/lib/br_nfe/servico/base.rb +35 -0
  24. data/lib/br_nfe/servico/betha/base.rb +74 -0
  25. data/lib/br_nfe/servico/betha/v1/build_response.rb +219 -0
  26. data/lib/br_nfe/servico/betha/v1/cancelamento_nfs.rb +52 -0
  27. data/lib/br_nfe/servico/betha/v1/consulta_lote_rps.rb +31 -0
  28. data/lib/br_nfe/servico/betha/v1/consulta_nfs_por_rps.rb +34 -0
  29. data/lib/br_nfe/servico/betha/v1/consulta_nfse.rb +50 -0
  30. data/lib/br_nfe/servico/betha/v1/consulta_situacao_lote_rps.rb +18 -0
  31. data/lib/br_nfe/servico/betha/v1/gateway.rb +115 -0
  32. data/lib/br_nfe/servico/betha/v1/recepcao_lote_rps.rb +89 -0
  33. data/lib/br_nfe/servico/betha/v2/cancelamento_nfs.rb +25 -0
  34. data/lib/br_nfe/servico/betha/v2/consulta_lote_rps.rb +27 -0
  35. data/lib/br_nfe/servico/betha/v2/consulta_nfse_por_rps.rb +27 -0
  36. data/lib/br_nfe/servico/betha/v2/envio_lote_rps_sincrono.rb +26 -0
  37. data/lib/br_nfe/servico/betha/v2/gateway.rb +198 -0
  38. data/lib/br_nfe/servico/betha/v2/gera_nfse.rb +25 -0
  39. data/lib/br_nfe/servico/betha/v2/recepcao_lote_rps.rb +47 -0
  40. data/lib/br_nfe/servico/betha/v2/response.rb +23 -0
  41. data/lib/br_nfe/servico/betha/v2/substituicao_nfse.rb +39 -0
  42. data/lib/br_nfe/servico/intermediario.rb +17 -0
  43. data/lib/br_nfe/servico/response/default.rb +34 -0
  44. data/lib/br_nfe/servico/response/nota_fiscal.rb +73 -0
  45. data/lib/br_nfe/servico/rps.rb +103 -0
  46. data/lib/br_nfe/version.rb +8 -0
  47. data/lib/br_nfe.rb +146 -0
  48. data/test/br_nfe/base_test.rb +274 -0
  49. data/test/br_nfe/condicao_pagamento_test.rb +23 -0
  50. data/test/br_nfe/destinatario_test.rb +26 -0
  51. data/test/br_nfe/emitente_test.rb +26 -0
  52. data/test/br_nfe/endereco_test.rb +50 -0
  53. data/test/br_nfe/helper/have_address_test.rb +62 -0
  54. data/test/br_nfe/helper/have_condicao_pagamento_test.rb +71 -0
  55. data/test/br_nfe/helper/have_destinatario_test.rb +64 -0
  56. data/test/br_nfe/helper/have_emitente_test.rb +63 -0
  57. data/test/br_nfe/helper/have_intermediario_test.rb +77 -0
  58. data/test/br_nfe/helper/have_rps_test.rb +59 -0
  59. data/test/br_nfe/servico/base_test.rb +23 -0
  60. data/test/br_nfe/servico/betha/base_test.rb +106 -0
  61. data/test/br_nfe/servico/betha/v1/build_response_test.rb +558 -0
  62. data/test/br_nfe/servico/betha/v1/cancelamento_nfs_test.rb +62 -0
  63. data/test/br_nfe/servico/betha/v1/consulta_lote_rps_test.rb +42 -0
  64. data/test/br_nfe/servico/betha/v1/consulta_nfs_por_rps_test.rb +68 -0
  65. data/test/br_nfe/servico/betha/v1/consulta_nfse_test.rb +57 -0
  66. data/test/br_nfe/servico/betha/v1/consulta_situacao_lote_rps_test.rb +27 -0
  67. data/test/br_nfe/servico/betha/v1/gateway_test.rb +174 -0
  68. data/test/br_nfe/servico/betha/v1/recepcao_lote_rps_test.rb +235 -0
  69. data/test/br_nfe/servico/response/default_test.rb +54 -0
  70. data/test/br_nfe/servico/response/nota_fiscal_test.rb +41 -0
  71. data/test/br_nfe/servico/rps_test.rb +214 -0
  72. data/test/certificado.rb +12 -0
  73. data/test/factories/base.rb +5 -0
  74. data/test/factories/condicao_pagamento.rb +10 -0
  75. data/test/factories/destinatario.rb +11 -0
  76. data/test/factories/emitente.rb +15 -0
  77. data/test/factories/endereco.rb +12 -0
  78. data/test/factories/servico/base.rb +5 -0
  79. data/test/factories/servico/betha/base.rb +5 -0
  80. data/test/factories/servico/betha/v1/build_response.rb +6 -0
  81. data/test/factories/servico/betha/v1/cancelamento_nfs.rb +7 -0
  82. data/test/factories/servico/betha/v1/consulta_lote_rps.rb +6 -0
  83. data/test/factories/servico/betha/v1/consulta_nfs_por_rps.rb +6 -0
  84. data/test/factories/servico/betha/v1/consulta_nfse.rb +8 -0
  85. data/test/factories/servico/betha/v1/consulta_situacao_lote_rps.rb +6 -0
  86. data/test/factories/servico/betha/v1/gateway.rb +5 -0
  87. data/test/factories/servico/betha/v1/recepcao_lote_rps.rb +6 -0
  88. data/test/factories/servico/intermediario.rb +7 -0
  89. data/test/factories/servico/response/default.rb +10 -0
  90. data/test/factories/servico/response/nota_fiscal.rb +47 -0
  91. data/test/factories/servico/rps.rb +44 -0
  92. data/test/test_helper.rb +39 -0
  93. metadata +263 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f5bff6e1698aa7f99b9173ab613f2b9de121b63e
4
+ data.tar.gz: 204e49ce93ce25e694a3b6a097ba6160bdf0f65e
5
+ SHA512:
6
+ metadata.gz: 06922cf1c5b2512e79f14b70a3c97410a84e683cb2ee88bc7184ffc246c84546e4ea4038396a417ff8e4dc2b45a64727905102f2273be85260cce467a3b999a7
7
+ data.tar.gz: c9d88601560d5130d7d8c4d04e4226d68a050f8a98f96d7a74605a8f06e1c04609f3993805cd244274bdc14e8c6c380f5266429ae811e2154da962464556087e
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ # gem "mocha", :require => false
7
+ gem "mocha", :require => false
8
+ gem "factory_girl_rails"
9
+ gem 'minitest-reporters'
10
+ gem 'minitest-rails'
11
+ gem 'minitest-spec-rails'
12
+ gem 'shoulda-matchers', require: false
13
+ gem "minitest-matchers_vaccine"
14
+ gem 'simplecov'
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,169 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ br_nfe (1.0.0)
5
+ activemodel (~> 4.2)
6
+ activesupport (~> 4.2)
7
+ nokogiri (~> 1.6)
8
+ rake (>= 0.8.7)
9
+ savon (~> 2.11)
10
+ signer
11
+
12
+ GEM
13
+ remote: http://rubygems.org/
14
+ specs:
15
+ actionmailer (4.2.3)
16
+ actionpack (= 4.2.3)
17
+ actionview (= 4.2.3)
18
+ activejob (= 4.2.3)
19
+ mail (~> 2.5, >= 2.5.4)
20
+ rails-dom-testing (~> 1.0, >= 1.0.5)
21
+ actionpack (4.2.3)
22
+ actionview (= 4.2.3)
23
+ activesupport (= 4.2.3)
24
+ rack (~> 1.6)
25
+ rack-test (~> 0.6.2)
26
+ rails-dom-testing (~> 1.0, >= 1.0.5)
27
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
28
+ actionview (4.2.3)
29
+ activesupport (= 4.2.3)
30
+ builder (~> 3.1)
31
+ erubis (~> 2.7.0)
32
+ rails-dom-testing (~> 1.0, >= 1.0.5)
33
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
34
+ activejob (4.2.3)
35
+ activesupport (= 4.2.3)
36
+ globalid (>= 0.3.0)
37
+ activemodel (4.2.3)
38
+ activesupport (= 4.2.3)
39
+ builder (~> 3.1)
40
+ activerecord (4.2.3)
41
+ activemodel (= 4.2.3)
42
+ activesupport (= 4.2.3)
43
+ arel (~> 6.0)
44
+ activesupport (4.2.3)
45
+ i18n (~> 0.7)
46
+ json (~> 1.7, >= 1.7.7)
47
+ minitest (~> 5.1)
48
+ thread_safe (~> 0.3, >= 0.3.4)
49
+ tzinfo (~> 1.1)
50
+ akami (1.3.1)
51
+ gyoku (>= 0.4.0)
52
+ nokogiri
53
+ ansi (1.5.0)
54
+ arel (6.0.2)
55
+ builder (3.2.2)
56
+ docile (1.1.5)
57
+ erubis (2.7.0)
58
+ factory_girl (4.5.0)
59
+ activesupport (>= 3.0.0)
60
+ factory_girl_rails (4.5.0)
61
+ factory_girl (~> 4.5.0)
62
+ railties (>= 3.0.0)
63
+ globalid (0.3.5)
64
+ activesupport (>= 4.1.0)
65
+ gyoku (1.3.1)
66
+ builder (>= 2.1.2)
67
+ httpi (2.4.1)
68
+ rack
69
+ i18n (0.7.0)
70
+ json (1.8.3)
71
+ loofah (2.0.2)
72
+ nokogiri (>= 1.5.9)
73
+ mail (2.6.3)
74
+ mime-types (>= 1.16, < 3)
75
+ metaclass (0.0.4)
76
+ mime-types (2.6.1)
77
+ mini_portile (0.6.2)
78
+ minitest (5.7.0)
79
+ minitest-matchers_vaccine (1.0.3)
80
+ minitest (~> 5.0)
81
+ minitest-rails (2.2.0)
82
+ minitest (~> 5.7)
83
+ railties (~> 4.1)
84
+ minitest-reporters (1.0.19)
85
+ ansi
86
+ builder
87
+ minitest (>= 5.0)
88
+ ruby-progressbar
89
+ minitest-spec-rails (5.2.2)
90
+ minitest (~> 5.0)
91
+ rails (~> 4.1)
92
+ mocha (1.1.0)
93
+ metaclass (~> 0.0.1)
94
+ nokogiri (1.6.6.2)
95
+ mini_portile (~> 0.6.0)
96
+ nori (2.6.0)
97
+ rack (1.6.4)
98
+ rack-test (0.6.3)
99
+ rack (>= 1.0)
100
+ rails (4.2.3)
101
+ actionmailer (= 4.2.3)
102
+ actionpack (= 4.2.3)
103
+ actionview (= 4.2.3)
104
+ activejob (= 4.2.3)
105
+ activemodel (= 4.2.3)
106
+ activerecord (= 4.2.3)
107
+ activesupport (= 4.2.3)
108
+ bundler (>= 1.3.0, < 2.0)
109
+ railties (= 4.2.3)
110
+ sprockets-rails
111
+ rails-deprecated_sanitizer (1.0.3)
112
+ activesupport (>= 4.2.0.alpha)
113
+ rails-dom-testing (1.0.6)
114
+ activesupport (>= 4.2.0.beta, < 5.0)
115
+ nokogiri (~> 1.6.0)
116
+ rails-deprecated_sanitizer (>= 1.0.1)
117
+ rails-html-sanitizer (1.0.2)
118
+ loofah (~> 2.0)
119
+ railties (4.2.3)
120
+ actionpack (= 4.2.3)
121
+ activesupport (= 4.2.3)
122
+ rake (>= 0.8.7)
123
+ thor (>= 0.18.1, < 2.0)
124
+ rake (10.4.2)
125
+ ruby-progressbar (1.7.5)
126
+ savon (2.11.1)
127
+ akami (~> 1.2)
128
+ builder (>= 2.1.2)
129
+ gyoku (~> 1.2)
130
+ httpi (~> 2.3)
131
+ nokogiri (>= 1.4.0)
132
+ nori (~> 2.4)
133
+ wasabi (~> 3.4)
134
+ shoulda-matchers (2.8.0)
135
+ activesupport (>= 3.0.0)
136
+ signer (1.4.2)
137
+ nokogiri (>= 1.5.1)
138
+ simplecov (0.10.0)
139
+ docile (~> 1.1.0)
140
+ json (~> 1.8)
141
+ simplecov-html (~> 0.10.0)
142
+ simplecov-html (0.10.0)
143
+ sprockets (3.2.0)
144
+ rack (~> 1.0)
145
+ sprockets-rails (2.3.2)
146
+ actionpack (>= 3.0)
147
+ activesupport (>= 3.0)
148
+ sprockets (>= 2.8, < 4.0)
149
+ thor (0.19.1)
150
+ thread_safe (0.3.5)
151
+ tzinfo (1.2.2)
152
+ thread_safe (~> 0.1)
153
+ wasabi (3.5.0)
154
+ httpi (~> 2.0)
155
+ nokogiri (>= 1.4.2)
156
+
157
+ PLATFORMS
158
+ ruby
159
+
160
+ DEPENDENCIES
161
+ br_nfe!
162
+ factory_girl_rails
163
+ minitest-matchers_vaccine
164
+ minitest-rails
165
+ minitest-reporters
166
+ minitest-spec-rails
167
+ mocha
168
+ shoulda-matchers
169
+ simplecov
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2015 Bruno M. Mergen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,6 @@
1
+ # **BrNFe**
2
+
3
+ ## Licença
4
+
5
+ - BSD
6
+ - Copyleft 2015 Bruno M. Mergen
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |task|
4
+ task.libs << %w(test lib)
5
+ task.pattern = 'test/**/*_test.rb'
6
+ end
7
+
8
+ desc "Open an irb session preloaded with this library"
9
+ task :console do
10
+ sh "irb -rubygems -I lib -r br_nfe.rb"
11
+ end
12
+
13
+ task :default => :test
data/br_nfe.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/br_nfe/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Bruno M. Mergen"]
6
+ gem.email = ["brunomergen@gmail.com"]
7
+ gem.description = %q{Emissão de Notas Fiscais Eletrônicas em Ruby}
8
+ gem.summary = %q{Emissão de Notas Fiscais Eletrônicas em Ruby}
9
+ gem.homepage = "https://github.com/Brunomm/br_nfe"
10
+ gem.license = "BSD"
11
+
12
+ gem.files = `git ls-files`.split($\).reject { |f| ['.pdf','.xls'].include?(File.extname(f)) }
13
+ gem.test_files = `git ls-files -- test/**/*`.split("\n")
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.name = "br_nfe"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = BrNfe::Version::CURRENT
18
+
19
+ gem.required_ruby_version = '>= 2.1'
20
+
21
+ gem.add_dependency "rake", '>= 0.8.7'
22
+ gem.add_dependency "activesupport", '~> 4.2'
23
+ gem.add_dependency "activemodel", '~> 4.2'
24
+ gem.add_dependency "nokogiri", "~> 1.6"
25
+ gem.add_dependency "savon", "~> 2.11"
26
+ gem.add_dependency "signer"
27
+
28
+ end
@@ -0,0 +1,62 @@
1
+ module BrNfe
2
+ class ActiveModelBase
3
+ include ActiveModel::Model
4
+
5
+ def initialize(attributes = {})
6
+ attributes = default_values.merge!(attributes)
7
+ assign_attributes(attributes)
8
+ yield self if block_given?
9
+ end
10
+
11
+ def assign_attributes(attributes)
12
+ attributes ||= {}
13
+ attributes.each do |name, value|
14
+ send("#{name}=", value)
15
+ end
16
+ end
17
+
18
+ def default_values
19
+ {}
20
+ end
21
+ protected
22
+
23
+ ##################### FORMATAÇÃO DE VALORES #####################
24
+ # Dependendo do WebService de emissão de nota, é necssário passar alguns valores
25
+ # em formatos diferentes.
26
+ # Os metodos a seguir neste bloco poderão ser sobrescritos para cada Webservice
27
+ # tendo assim, um padrão definido para montar os dados para envio.
28
+ #
29
+ def value_date(value)
30
+ value = Date.parse(value.to_s)
31
+ value.to_s(:br_nfe)
32
+ rescue
33
+ return ''
34
+ end
35
+
36
+ def value_date_time(data)
37
+ data_hora = DateTime.parse(data.to_s)
38
+ data_hora.to_s(:br_nfe)
39
+ rescue
40
+ return ''
41
+ end
42
+
43
+ # Irá retornar 1(true) e 2(false)
44
+ def value_true_false(value)
45
+ BrNfe.true_values.include?(value) ? '1' : '2'
46
+ end
47
+
48
+ # Deve receber um valor do tipo float
49
+ # Irá retornar o valor com a precisão
50
+ # Alguns WS convertem os valores para String com separador de milhar uma vírgula
51
+ #
52
+ def value_monetary(value, precision=2)
53
+ return unless value
54
+ value.to_f.round(2)
55
+ end
56
+
57
+ def value_amount(value, precision=2)
58
+ value_monetary(value, precision)
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,168 @@
1
+ module BrNfe
2
+ class Base < BrNfe::ActiveModelBase
3
+
4
+ include BrNfe::Helper::HaveEmitente
5
+
6
+ attr_accessor :certificado_password
7
+ attr_accessor :certificado_path
8
+ attr_accessor :certificado_value
9
+
10
+ validate :validar_emitente
11
+ validates :certificado, presence: true, if: :certificado_obrigatorio?
12
+
13
+ # Método que deve ser sobrescrito para as ações que necessitam do certificado para assinatura
14
+ def certificado_obrigatorio?
15
+ false
16
+ end
17
+
18
+ # Caso não tenha o certificado salvo em arquivo, pode setar a string do certificado direto pelo atributo certificado_value
19
+ # Caso tenha o certificado em arquivo, basta setar o atributo certificado_path e deixar o atributo certificado_value em branco
20
+ def certificado_value
21
+ @certificado_value ||= File.read(certificado_path)
22
+ end
23
+
24
+ attr_accessor :env
25
+
26
+ def env
27
+ @env ||= :production
28
+ end
29
+
30
+ def response
31
+ @response
32
+ end
33
+
34
+ def wsdl
35
+ raise "Não implementado."
36
+ end
37
+
38
+ def env_namespace
39
+ :soapenv
40
+ end
41
+
42
+ def method_wsdl
43
+ raise "Não implementado."
44
+ end
45
+
46
+ def xml_builder
47
+ raise "Não implementado."
48
+ end
49
+
50
+ def namespace_identifier
51
+ raise 'Não implementado.'
52
+ end
53
+
54
+ def namespaces
55
+ {}
56
+ end
57
+
58
+ def certificado
59
+ @certificado ||= OpenSSL::PKCS12.new(certificado_value, certificado_password)
60
+ rescue
61
+ end
62
+
63
+ def certificado=(value)
64
+ @certificado = value
65
+ end
66
+
67
+ def wsdl_encoding
68
+ "UTF-8"
69
+ end
70
+
71
+ def client_wsdl
72
+ @client_wsdl ||= Savon.client({
73
+ namespaces: namespaces,
74
+ env_namespace: env_namespace,
75
+ wsdl: wsdl,
76
+ namespace_identifier: namespace_identifier,
77
+ encoding: wsdl_encoding,
78
+ log: BrNfe.client_wsdl_log,
79
+ pretty_print_xml: BrNfe.client_wsdl_pretty_print_xml,
80
+ ssl_verify_mode: BrNfe.client_wsdl_ssl_verify_mode,
81
+ ssl_cert_file: BrNfe.client_wsdl_ssl_cert_file,
82
+ ssl_cert_key_file: BrNfe.client_wsdl_ssl_cert_key_file,
83
+ ssl_cert_key_password: BrNfe.client_wsdl_ssl_cert_key_password
84
+ })
85
+ end
86
+
87
+ private
88
+
89
+ def tag_cpf_cnpj(xml, cpf_cnpj)
90
+ cpf_cnpj = BrNfe::Helper::CpfCnpj.new(cpf_cnpj)
91
+ if cpf_cnpj.cnpj?
92
+ xml.Cnpj cpf_cnpj.sem_formatacao
93
+ elsif cpf_cnpj.cpf?
94
+ xml.Cpf cpf_cnpj.sem_formatacao
95
+ end
96
+ end
97
+
98
+
99
+ def assinatura_xml(data_xml, uri='')
100
+ data_xml = format_data_xml_for_signature(data_xml)
101
+ ass = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
102
+ xml.Signature(xmlns: 'http://www.w3.org/2000/09/xmldsig#') do |signature|
103
+
104
+ info = canonicalize(signed_info(data_xml, uri).doc.root())
105
+ signature.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( info.to_s )
106
+
107
+ signature.SignatureValue xml_signature_value(info)
108
+
109
+ signature.KeyInfo {
110
+ signature.X509Data {
111
+ signature.X509Certificate certificado.certificate.to_s.gsub(/\-\-\-\-\-[A-Z]+ CERTIFICATE\-\-\-\-\-/, "").gsub(/\n/,"")
112
+ }
113
+ }
114
+ end
115
+ end.doc.root
116
+ canonicalize ass
117
+ end
118
+
119
+ def signed_info(data_xml, uri='')
120
+ Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
121
+ xml.SignedInfo(xmlns: "http://www.w3.org/2000/09/xmldsig#") do |info|
122
+ info.CanonicalizationMethod(Algorithm: 'http://www.w3.org/2001/10/xml-exc-c14n#')
123
+ info.SignatureMethod(Algorithm: 'http://www.w3.org/2000/09/xmldsig#rsa-sha1')
124
+ info.Reference('URI' => uri){
125
+ info.Transforms{
126
+ info.Transform(:Algorithm => 'http://www.w3.org/2000/09/xmldsig#enveloped-signature')
127
+ info.Transform(:Algorithm => 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
128
+ }
129
+ info.DigestMethod(:Algorithm => 'http://www.w3.org/2000/09/xmldsig#sha1')
130
+ info.DigestValue xml_digest_value(data_xml)
131
+ }
132
+ end
133
+ end
134
+ end
135
+
136
+ def xml_signature_value(xml)
137
+ sign_canon = canonicalize(xml)
138
+ signature_hash = certificado.key.sign(OpenSSL::Digest::SHA1.new, sign_canon)
139
+ remove_quebras Base64.encode64( signature_hash )
140
+ end
141
+
142
+ def xml_digest_value(xml)
143
+ xml_canon = canonicalize(xml)
144
+ remove_quebras Base64.encode64(OpenSSL::Digest::SHA1.digest(xml_canon))
145
+ end
146
+
147
+
148
+ def canonicalize(xml)
149
+ xml = Nokogiri::XML(xml.to_s, &:noblanks)
150
+ xml.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
151
+ end
152
+
153
+ def remove_quebras(str)
154
+ str.gsub(/\n/,'').gsub(/\t/,'').strip
155
+ end
156
+
157
+ def format_data_xml_for_signature(data_xml)
158
+ data_xml
159
+ end
160
+
161
+ def validar_emitente
162
+ if emitente.invalid?
163
+ emitente.errors.full_messages.map{|msg| errors.add(:emitente, msg) }
164
+ end
165
+ end
166
+
167
+ end
168
+ end
@@ -0,0 +1,26 @@
1
+ module BrNfe
2
+ class CondicaoPagamento < BrNfe::ActiveModelBase
3
+
4
+ def initialize(attributes = {})
5
+ @parcelas = [] # Para poder utilizar o << para adicionar parcelas
6
+ super
7
+ end
8
+
9
+ def default_values
10
+ {condicao: 'A_VISTA'}
11
+ end
12
+
13
+ # A_VISTA ou A_PRAZO
14
+ attr_accessor :condicao
15
+
16
+ #
17
+ # EX Valor para parcelas = [{valor: 50.33, vencimento: '15/11/2016'}, {valor: '27.00', vencimento: '2016-11-15'}]
18
+ #
19
+ attr_accessor :parcelas
20
+
21
+ def parcelas
22
+ @parcelas = [@parcelas].flatten
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module BrNfe
2
+ class Destinatario < BrNfe::ActiveModelBase
3
+ include BrNfe::Helper::HaveAddress
4
+
5
+ attr_accessor :cpf_cnpj
6
+ attr_accessor :inscricao_municipal
7
+ attr_accessor :inscricao_estadual
8
+ attr_accessor :inscricao_suframa
9
+ attr_accessor :razao_social
10
+ attr_accessor :nome_fantasia
11
+ attr_accessor :telefone
12
+ attr_accessor :email
13
+
14
+ validates :cpf_cnpj, :razao_social, presence: true
15
+ validate :validar_endereco
16
+
17
+ def razao_social
18
+ "#{@razao_social}".to_valid_format_nf
19
+ end
20
+
21
+ def nome_fantasia
22
+ "#{@nome_fantasia}".to_valid_format_nf
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,40 @@
1
+ module BrNfe
2
+ class Emitente < BrNfe::ActiveModelBase
3
+ include BrNfe::Helper::HaveAddress
4
+
5
+ # Obrigatórios
6
+ attr_accessor :cnpj
7
+ attr_accessor :inscricao_municipal
8
+ attr_accessor :razao_social
9
+ attr_accessor :natureza_operacao
10
+
11
+ #Não obrigatórios
12
+ attr_accessor :nome_fantasia
13
+ attr_accessor :telefone
14
+ attr_accessor :email
15
+ attr_accessor :regime_especial_tributacao
16
+ attr_accessor :optante_simples_nacional
17
+ attr_accessor :incentivo_fiscal
18
+
19
+
20
+ validates :inscricao_municipal, :natureza_operacao, :cnpj, :razao_social, presence: true
21
+ validate :validar_endereco
22
+
23
+ def razao_social
24
+ "#{@razao_social}".to_valid_format_nf
25
+ end
26
+
27
+ def nome_fantasia
28
+ "#{@nome_fantasia}".to_valid_format_nf
29
+ end
30
+
31
+ def optante_simples_nacional?
32
+ BrNfe.true_values.include?(optante_simples_nacional)
33
+ end
34
+
35
+ def incentivo_fiscal?
36
+ BrNfe.true_values.include?(incentivo_fiscal)
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,44 @@
1
+ module BrNfe
2
+ class Endereco < BrNfe::ActiveModelBase
3
+
4
+ def default_values
5
+ {
6
+ codigo_pais: '1058',
7
+ nome_pais: 'BRASIL'
8
+ }
9
+ end
10
+
11
+ attr_accessor :logradouro
12
+ attr_accessor :numero
13
+ attr_accessor :complemento
14
+ attr_accessor :bairro
15
+ attr_accessor :nome_municipio
16
+ attr_accessor :codigo_municipio
17
+ attr_accessor :uf
18
+ attr_accessor :cep
19
+ attr_accessor :codigo_pais # defaul: 1058 (Brasil)
20
+ attr_accessor :nome_pais # defaul: BRASIL
21
+
22
+ validates :logradouro, :numero, :bairro, :codigo_municipio, :uf, :cep, presence: true
23
+
24
+ def logradouro
25
+ "#{@logradouro}".to_valid_format_nf
26
+ end
27
+
28
+ def complemento
29
+ "#{@complemento}".to_valid_format_nf
30
+ end
31
+
32
+ def bairro
33
+ "#{@bairro}".to_valid_format_nf
34
+ end
35
+
36
+ def nome_municipio
37
+ "#{@nome_municipio}".to_valid_format_nf
38
+ end
39
+
40
+ def nome_pais
41
+ "#{@nome_pais}".to_valid_format_nf
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,60 @@
1
+ module BrNfe
2
+ module Helper
3
+ class CpfCnpj
4
+
5
+ def initialize(cpf_cnpj)
6
+ @cpf_cnpj = ajusta_cpf_cnpj_com_zero("#{cpf_cnpj}")
7
+ end
8
+
9
+ def cpf?
10
+ cpf_ou_cnpj? == :cpf
11
+ end
12
+
13
+ def cnpj?
14
+ cpf_ou_cnpj? == :cnpj
15
+ end
16
+
17
+ def cpf_ou_cnpj?
18
+ sem_formatacao.size > 11 ? :cnpj : :cpf
19
+ end
20
+
21
+ def tipo_documento(tamanho = 2)
22
+ return '0' if sem_formatacao.blank?
23
+ sem_formatacao.size < 14 ? '1'.rjust(tamanho, '0') : '2'.rjust(tamanho, '0')
24
+ end
25
+
26
+ def sem_formatacao
27
+ @cpf_cnpj.gsub(/[\.]|[\-]|[\/]/,'')
28
+ end
29
+
30
+ def com_formatacao
31
+ cnpj? ? formata_cnpj : formata_cpf
32
+ end
33
+
34
+ def formatado_com_label
35
+ cnpj? ? "CNPJ #{formata_cnpj}" : "CPF #{formata_cpf}"
36
+ end
37
+
38
+ private
39
+
40
+ def ajusta_cpf_cnpj_com_zero(value)
41
+ return "" if value.blank?
42
+ if value.to_s.size <= 11
43
+ value.to_s.rjust(11, '0')
44
+ else
45
+ value.to_s.rjust(14, '0')
46
+ end
47
+ end
48
+
49
+ def formata_cpf
50
+ @cpf_cnpj.gsub!(/[\.]|[\-]|[\/]/,'')
51
+ "#{@cpf_cnpj[0..2]}.#{@cpf_cnpj[3..5]}.#{@cpf_cnpj[6..8]}-#{@cpf_cnpj[9..10]}"
52
+ end
53
+
54
+ def formata_cnpj
55
+ @cpf_cnpj.gsub!(/[\.]|[\-]|[\/]/,'')
56
+ "#{@cpf_cnpj[0..1]}.#{@cpf_cnpj[2..4]}.#{@cpf_cnpj[5..7]}/#{@cpf_cnpj[8..11]}-#{@cpf_cnpj[12..13]}"
57
+ end
58
+ end
59
+ end
60
+ end