br_nfe 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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