br_nfe 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +169 -0
- data/LICENSE +20 -0
- data/README.markdown +6 -0
- data/Rakefile +13 -0
- data/br_nfe.gemspec +28 -0
- data/lib/br_nfe/active_model_base.rb +62 -0
- data/lib/br_nfe/base.rb +168 -0
- data/lib/br_nfe/condicao_pagamento.rb +26 -0
- data/lib/br_nfe/destinatario.rb +26 -0
- data/lib/br_nfe/emitente.rb +40 -0
- data/lib/br_nfe/endereco.rb +44 -0
- data/lib/br_nfe/helper/cpf_cnpj.rb +60 -0
- data/lib/br_nfe/helper/have_address.rb +29 -0
- data/lib/br_nfe/helper/have_condicao_pagamento.rb +24 -0
- data/lib/br_nfe/helper/have_destinatario.rb +18 -0
- data/lib/br_nfe/helper/have_emitente.rb +20 -0
- data/lib/br_nfe/helper/have_intermediario.rb +24 -0
- data/lib/br_nfe/helper/have_rps.rb +27 -0
- data/lib/br_nfe/helper/string_methods.rb +21 -0
- data/lib/br_nfe/seed.rb +195 -0
- data/lib/br_nfe/servico/base.rb +35 -0
- data/lib/br_nfe/servico/betha/base.rb +74 -0
- data/lib/br_nfe/servico/betha/v1/build_response.rb +219 -0
- data/lib/br_nfe/servico/betha/v1/cancelamento_nfs.rb +52 -0
- data/lib/br_nfe/servico/betha/v1/consulta_lote_rps.rb +31 -0
- data/lib/br_nfe/servico/betha/v1/consulta_nfs_por_rps.rb +34 -0
- data/lib/br_nfe/servico/betha/v1/consulta_nfse.rb +50 -0
- data/lib/br_nfe/servico/betha/v1/consulta_situacao_lote_rps.rb +18 -0
- data/lib/br_nfe/servico/betha/v1/gateway.rb +115 -0
- data/lib/br_nfe/servico/betha/v1/recepcao_lote_rps.rb +89 -0
- data/lib/br_nfe/servico/betha/v2/cancelamento_nfs.rb +25 -0
- data/lib/br_nfe/servico/betha/v2/consulta_lote_rps.rb +27 -0
- data/lib/br_nfe/servico/betha/v2/consulta_nfse_por_rps.rb +27 -0
- data/lib/br_nfe/servico/betha/v2/envio_lote_rps_sincrono.rb +26 -0
- data/lib/br_nfe/servico/betha/v2/gateway.rb +198 -0
- data/lib/br_nfe/servico/betha/v2/gera_nfse.rb +25 -0
- data/lib/br_nfe/servico/betha/v2/recepcao_lote_rps.rb +47 -0
- data/lib/br_nfe/servico/betha/v2/response.rb +23 -0
- data/lib/br_nfe/servico/betha/v2/substituicao_nfse.rb +39 -0
- data/lib/br_nfe/servico/intermediario.rb +17 -0
- data/lib/br_nfe/servico/response/default.rb +34 -0
- data/lib/br_nfe/servico/response/nota_fiscal.rb +73 -0
- data/lib/br_nfe/servico/rps.rb +103 -0
- data/lib/br_nfe/version.rb +8 -0
- data/lib/br_nfe.rb +146 -0
- data/test/br_nfe/base_test.rb +274 -0
- data/test/br_nfe/condicao_pagamento_test.rb +23 -0
- data/test/br_nfe/destinatario_test.rb +26 -0
- data/test/br_nfe/emitente_test.rb +26 -0
- data/test/br_nfe/endereco_test.rb +50 -0
- data/test/br_nfe/helper/have_address_test.rb +62 -0
- data/test/br_nfe/helper/have_condicao_pagamento_test.rb +71 -0
- data/test/br_nfe/helper/have_destinatario_test.rb +64 -0
- data/test/br_nfe/helper/have_emitente_test.rb +63 -0
- data/test/br_nfe/helper/have_intermediario_test.rb +77 -0
- data/test/br_nfe/helper/have_rps_test.rb +59 -0
- data/test/br_nfe/servico/base_test.rb +23 -0
- data/test/br_nfe/servico/betha/base_test.rb +106 -0
- data/test/br_nfe/servico/betha/v1/build_response_test.rb +558 -0
- data/test/br_nfe/servico/betha/v1/cancelamento_nfs_test.rb +62 -0
- data/test/br_nfe/servico/betha/v1/consulta_lote_rps_test.rb +42 -0
- data/test/br_nfe/servico/betha/v1/consulta_nfs_por_rps_test.rb +68 -0
- data/test/br_nfe/servico/betha/v1/consulta_nfse_test.rb +57 -0
- data/test/br_nfe/servico/betha/v1/consulta_situacao_lote_rps_test.rb +27 -0
- data/test/br_nfe/servico/betha/v1/gateway_test.rb +174 -0
- data/test/br_nfe/servico/betha/v1/recepcao_lote_rps_test.rb +235 -0
- data/test/br_nfe/servico/response/default_test.rb +54 -0
- data/test/br_nfe/servico/response/nota_fiscal_test.rb +41 -0
- data/test/br_nfe/servico/rps_test.rb +214 -0
- data/test/certificado.rb +12 -0
- data/test/factories/base.rb +5 -0
- data/test/factories/condicao_pagamento.rb +10 -0
- data/test/factories/destinatario.rb +11 -0
- data/test/factories/emitente.rb +15 -0
- data/test/factories/endereco.rb +12 -0
- data/test/factories/servico/base.rb +5 -0
- data/test/factories/servico/betha/base.rb +5 -0
- data/test/factories/servico/betha/v1/build_response.rb +6 -0
- data/test/factories/servico/betha/v1/cancelamento_nfs.rb +7 -0
- data/test/factories/servico/betha/v1/consulta_lote_rps.rb +6 -0
- data/test/factories/servico/betha/v1/consulta_nfs_por_rps.rb +6 -0
- data/test/factories/servico/betha/v1/consulta_nfse.rb +8 -0
- data/test/factories/servico/betha/v1/consulta_situacao_lote_rps.rb +6 -0
- data/test/factories/servico/betha/v1/gateway.rb +5 -0
- data/test/factories/servico/betha/v1/recepcao_lote_rps.rb +6 -0
- data/test/factories/servico/intermediario.rb +7 -0
- data/test/factories/servico/response/default.rb +10 -0
- data/test/factories/servico/response/nota_fiscal.rb +47 -0
- data/test/factories/servico/rps.rb +44 -0
- data/test/test_helper.rb +39 -0
- 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
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
|
data/lib/br_nfe/base.rb
ADDED
@@ -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
|