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.
- 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
data/lib/br_nfe.rb
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'br_nfe/version'
|
|
3
|
+
require 'active_model'
|
|
4
|
+
require 'active_support/core_ext/class'
|
|
5
|
+
require 'active_support/core_ext/enumerable'
|
|
6
|
+
require 'active_support/core_ext/object'
|
|
7
|
+
require 'active_support/core_ext/string'
|
|
8
|
+
|
|
9
|
+
require "br_nfe/helper/string_methods"
|
|
10
|
+
|
|
11
|
+
require "signer"
|
|
12
|
+
require "savon"
|
|
13
|
+
|
|
14
|
+
require "br_nfe/helper/have_address"
|
|
15
|
+
require "br_nfe/helper/have_rps"
|
|
16
|
+
require "br_nfe/helper/have_emitente"
|
|
17
|
+
require "br_nfe/helper/have_destinatario"
|
|
18
|
+
require "br_nfe/helper/have_intermediario"
|
|
19
|
+
require "br_nfe/helper/have_condicao_pagamento"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Copyright (C) 2015 Bruno M. Mergen
|
|
24
|
+
#
|
|
25
|
+
# @author Bruno Mucelini Mergen <brunomergen@gmail.com>
|
|
26
|
+
#
|
|
27
|
+
#
|
|
28
|
+
module BrNfe
|
|
29
|
+
Time::DATE_FORMATS[:br_nfe] = "%Y-%m-%dT%H:%M:%S"
|
|
30
|
+
DateTime::DATE_FORMATS[:br_nfe] = "%Y-%m-%dT%H:%M:%S"
|
|
31
|
+
Date::DATE_FORMATS[:br_nfe] = "%Y-%m-%d"
|
|
32
|
+
|
|
33
|
+
def self.true_values
|
|
34
|
+
[true, :true, 'true', 't', :t, 1, '1', :TRUE, 'TRUE', 'T']
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
extend ActiveSupport::Autoload
|
|
38
|
+
autoload :ActiveModelBase
|
|
39
|
+
autoload :Endereco
|
|
40
|
+
autoload :Emitente
|
|
41
|
+
autoload :Destinatario
|
|
42
|
+
autoload :Response
|
|
43
|
+
autoload :Base
|
|
44
|
+
autoload :Seed
|
|
45
|
+
autoload :CondicaoPagamento
|
|
46
|
+
|
|
47
|
+
module Servico
|
|
48
|
+
extend ActiveSupport::Autoload
|
|
49
|
+
autoload :Intermediario
|
|
50
|
+
autoload :Rps
|
|
51
|
+
autoload :Base
|
|
52
|
+
|
|
53
|
+
module Response
|
|
54
|
+
extend ActiveSupport::Autoload
|
|
55
|
+
autoload :Default
|
|
56
|
+
autoload :NotaFiscal
|
|
57
|
+
end
|
|
58
|
+
module Betha
|
|
59
|
+
extend ActiveSupport::Autoload
|
|
60
|
+
autoload :Base
|
|
61
|
+
module V1
|
|
62
|
+
extend ActiveSupport::Autoload
|
|
63
|
+
autoload :Gateway
|
|
64
|
+
autoload :BuildResponse
|
|
65
|
+
autoload :ConsultaLoteRps
|
|
66
|
+
autoload :ConsultaNfse
|
|
67
|
+
autoload :ConsultaNfsPorRps
|
|
68
|
+
autoload :CancelamentoNfs
|
|
69
|
+
autoload :ConsultaSituacaoLoteRps
|
|
70
|
+
autoload :RecepcaoLoteRps
|
|
71
|
+
end
|
|
72
|
+
module V2
|
|
73
|
+
extend ActiveSupport::Autoload
|
|
74
|
+
autoload :Gateway
|
|
75
|
+
autoload :Response
|
|
76
|
+
autoload :CancelamentoNfs
|
|
77
|
+
autoload :ConsultaNfsePorRps
|
|
78
|
+
autoload :EnvioLoteRpsSincrono
|
|
79
|
+
autoload :GeraNfse
|
|
80
|
+
autoload :SubstituicaoNfse
|
|
81
|
+
autoload :ConsultaLoteRps
|
|
82
|
+
autoload :RecepcaoLoteRps
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
module Helper
|
|
88
|
+
extend ActiveSupport::Autoload
|
|
89
|
+
autoload :CpfCnpj
|
|
90
|
+
|
|
91
|
+
def self.only_number(value)
|
|
92
|
+
"#{value}".gsub(/[^0-9]/,'')
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
########################## CONFIGURAÇÕES ###########################
|
|
100
|
+
# Pode ser configurado
|
|
101
|
+
# BrNfe.setup do |config|
|
|
102
|
+
# config.endereco_class = MyCustomClassAddress
|
|
103
|
+
# end
|
|
104
|
+
# -----------------------------------------------------------------
|
|
105
|
+
|
|
106
|
+
mattr_accessor :endereco_class
|
|
107
|
+
@@endereco_class = BrNfe::Endereco
|
|
108
|
+
|
|
109
|
+
mattr_accessor :emitente_class
|
|
110
|
+
@@emitente_class = BrNfe::Emitente
|
|
111
|
+
|
|
112
|
+
mattr_accessor :destinatario_class
|
|
113
|
+
@@destinatario_class = BrNfe::Destinatario
|
|
114
|
+
|
|
115
|
+
mattr_accessor :intermediario_class
|
|
116
|
+
@@intermediario_class = BrNfe::Servico::Intermediario
|
|
117
|
+
|
|
118
|
+
mattr_accessor :condicao_pagamento_class
|
|
119
|
+
@@condicao_pagamento_class = BrNfe::CondicaoPagamento
|
|
120
|
+
|
|
121
|
+
mattr_accessor :rps_class
|
|
122
|
+
@@rps_class = BrNfe::Servico::Rps
|
|
123
|
+
|
|
124
|
+
# Configurações do Cliente WSDL
|
|
125
|
+
mattr_accessor :client_wsdl_ssl_verify_mode
|
|
126
|
+
@@client_wsdl_ssl_verify_mode = :none
|
|
127
|
+
|
|
128
|
+
mattr_accessor :client_wsdl_ssl_cert_file
|
|
129
|
+
mattr_accessor :client_wsdl_ssl_cert_key_file
|
|
130
|
+
mattr_accessor :client_wsdl_ssl_cert_key_password
|
|
131
|
+
|
|
132
|
+
mattr_accessor :client_wsdl_log
|
|
133
|
+
@@client_wsdl_log = false
|
|
134
|
+
|
|
135
|
+
mattr_accessor :client_wsdl_pretty_print_xml
|
|
136
|
+
@@client_wsdl_pretty_print_xml = false
|
|
137
|
+
|
|
138
|
+
def self.setup
|
|
139
|
+
yield self
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
######################### END CONFIGURAÇÕES #########################
|
|
143
|
+
|
|
144
|
+
include Helper
|
|
145
|
+
include Servico
|
|
146
|
+
end
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'br_nfe/helper/have_emitente_test'
|
|
3
|
+
|
|
4
|
+
describe BrNfe::Base do
|
|
5
|
+
subject { FactoryGirl.build(:br_nfe_base, emitente: emitente) }
|
|
6
|
+
let(:certificado) { Certificado.new }
|
|
7
|
+
let(:emitente) { FactoryGirl.build(:emitente) }
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
subject.stubs(:certificado).returns(certificado)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "#emitente" do
|
|
14
|
+
include BrNfeTest::HelperTest::HaveEmitenteTest
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe "#env" do
|
|
18
|
+
it "deve ter o valor :production por default" do
|
|
19
|
+
BrNfe::Base.new.env.must_equal :production
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "deve permitir a modificação do valor" do
|
|
23
|
+
BrNfe::Base.new(env: :test).env.must_equal :test
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "#certificado_value" do
|
|
28
|
+
it "se tiver algum valor setado deve retornar esse valor" do
|
|
29
|
+
subject.certificado_value = "algum valor"
|
|
30
|
+
subject.certificado_value.must_equal "algum valor"
|
|
31
|
+
end
|
|
32
|
+
it "se não tiver um valor deve carregar o arquivo setado no atributo certificado_path" do
|
|
33
|
+
subject.certificado_path = "algum/lugar.pfx"
|
|
34
|
+
File.expects(:read).with("algum/lugar.pfx").returns("valor do arquivo")
|
|
35
|
+
subject.certificado_value.must_equal "valor do arquivo"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "#response" do
|
|
40
|
+
it "deve retornar o valor da variavel @response" do
|
|
41
|
+
subject.instance_variable_set(:@response, 'valor')
|
|
42
|
+
subject.response.must_equal 'valor'
|
|
43
|
+
end
|
|
44
|
+
it "valor default" do
|
|
45
|
+
subject.response.must_be_nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "#wsdl" do
|
|
50
|
+
it "deve dar um erro por default" do
|
|
51
|
+
assert_raises RuntimeError do
|
|
52
|
+
subject.wsdl
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "#env_namespace" do
|
|
58
|
+
it "deve ser soapenv" do
|
|
59
|
+
subject.env_namespace.must_equal :soapenv
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe "#method_wsdl" do
|
|
64
|
+
it "deve dar um erro por default" do
|
|
65
|
+
assert_raises RuntimeError do
|
|
66
|
+
subject.method_wsdl
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe "#xml_builder" do
|
|
72
|
+
it "deve dar um erro por default" do
|
|
73
|
+
assert_raises RuntimeError do
|
|
74
|
+
subject.xml_builder
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe "#namespace_identifier" do
|
|
80
|
+
it "deve dar um erro por default" do
|
|
81
|
+
assert_raises RuntimeError do
|
|
82
|
+
subject.namespace_identifier
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe "#namespaces" do
|
|
88
|
+
it "valor padrão" do
|
|
89
|
+
subject.namespaces.must_equal({})
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe "#value_date" do
|
|
94
|
+
context "deve retornar no formato YYYY-MM-DD" do
|
|
95
|
+
it "Se passar uma string" do
|
|
96
|
+
subject.send(:value_date, '12/07/2018').must_equal '2018-07-12'
|
|
97
|
+
end
|
|
98
|
+
it "Se passar um objeto data" do
|
|
99
|
+
subject.send(:value_date, Date.parse('25/09/2000')).must_equal '2000-09-25'
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "se passar um valor inválido retorna uma string vazia" do
|
|
104
|
+
subject.send(:value_date, '25/09\00').must_equal ''
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
describe "#value_date_time" do
|
|
109
|
+
context "deve retornar no formato YYYY-MM-DDTHH:MM:SS" do
|
|
110
|
+
it "Se passar uma string" do
|
|
111
|
+
subject.send(:value_date_time, '12/07/2018').must_equal '2018-07-12T00:00:00'
|
|
112
|
+
end
|
|
113
|
+
it "Se passar um objeto data" do
|
|
114
|
+
subject.send(:value_date_time, DateTime.parse('25/09/2000 03:56:28')).must_equal '2000-09-25T03:56:28'
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "se passar um valor inválido retorna uma string vazia" do
|
|
119
|
+
subject.send(:value_date_time, '25/09\00').must_equal ''
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
describe "#canonicalize" do
|
|
124
|
+
it "deve cannonicalizar uma string xml" do
|
|
125
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'+"<TagRaiz>\n\t<TagFilho>Texo Tag \n\t\n\t Filho</TagFilho> \n</TagRaiz> "
|
|
126
|
+
subject.send(:canonicalize, xml).must_equal "<TagRaiz><TagFilho>Texo Tag \n\t\n\t Filho</TagFilho></TagRaiz>"
|
|
127
|
+
end
|
|
128
|
+
it "deve cannonicalizar um Document xml Nokogiri" do
|
|
129
|
+
xml = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
|
|
130
|
+
xml.TagRaiz{
|
|
131
|
+
xml.TagFilho "Texo Tag \n\t\n\t Filho"
|
|
132
|
+
}
|
|
133
|
+
end.doc
|
|
134
|
+
subject.send(:canonicalize, xml).must_equal "<TagRaiz><TagFilho>Texo Tag \n\t\n\t Filho</TagFilho></TagRaiz>"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
describe "#remove_quebras" do
|
|
139
|
+
it "deve remover as quebras de linhas e tabs de identação de uma string" do
|
|
140
|
+
str = " Uma \n\tString \n\tCom quebras "
|
|
141
|
+
subject.send(:remove_quebras, str).must_equal "Uma String Com quebras"
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
describe "Assinatura" do
|
|
146
|
+
let(:xml) { " <Um> <Xml> Com valor</Xml> \n\t</Um> " }
|
|
147
|
+
|
|
148
|
+
describe "#xml_digest_value" do
|
|
149
|
+
it "deve receber um xml, canonicalizar - codificar para base64 e remover as quebras" do
|
|
150
|
+
subject.expects(:remove_quebras).with("adQF8B5pegJ6uSDKv3qKnXCI5yQ=\n").returns("adQF8B5pegJ6uSDKv3qKnXCI5yQ=")
|
|
151
|
+
subject.send(:xml_digest_value, xml).must_equal 'adQF8B5pegJ6uSDKv3qKnXCI5yQ='
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
describe "#xml_signature_value" do
|
|
156
|
+
it "deve assinar um xml com o certificado" do
|
|
157
|
+
sh1 = OpenSSL::Digest::SHA1.new
|
|
158
|
+
OpenSSL::Digest::SHA1.stubs(:new).returns(sh1)
|
|
159
|
+
subject.certificado.key.expects(:sign).with(sh1, "<Um><Xml> Com valor</Xml></Um>").returns('mv\xBFH\xE3\xF5Z\x0F\xE1*0D')
|
|
160
|
+
|
|
161
|
+
subject.send(:xml_signature_value, xml).must_equal 'bXZceEJGSFx4RTNceEY1Wlx4MEZceEUxKjBE'
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
describe "#signed_info" do
|
|
166
|
+
it "deve gerar a estrutura da tag SignedInfo" do
|
|
167
|
+
subject.expects(:xml_digest_value).with(xml).returns("adQFGKGDJ6uSDKv3qKnXCI5yQ")
|
|
168
|
+
signed_info = Nokogiri::XML( subject.send(:signed_info, xml).doc.root.to_s )
|
|
169
|
+
|
|
170
|
+
signed_info.namespaces.must_equal({"xmlns"=>"http://www.w3.org/2000/09/xmldsig#"})
|
|
171
|
+
signed_info.remove_namespaces!
|
|
172
|
+
signed_info.xpath('SignedInfo/CanonicalizationMethod').first.attr("Algorithm").must_equal 'http://www.w3.org/2001/10/xml-exc-c14n#'
|
|
173
|
+
signed_info.xpath('SignedInfo/SignatureMethod').first.attr("Algorithm").must_equal 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
|
|
174
|
+
signed_info.xpath('SignedInfo/Reference').first.attr("URI").must_equal ''
|
|
175
|
+
signed_info.xpath('SignedInfo/Reference/Transforms/Transform').first.attr("Algorithm").must_equal 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'
|
|
176
|
+
signed_info.xpath('SignedInfo/Reference/Transforms/Transform').last.attr("Algorithm").must_equal 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
|
|
177
|
+
signed_info.xpath('SignedInfo/Reference/DigestMethod').first.attr("Algorithm").must_equal 'http://www.w3.org/2000/09/xmldsig#sha1'
|
|
178
|
+
signed_info.xpath('SignedInfo/Reference/DigestValue').first.text.must_equal 'adQFGKGDJ6uSDKv3qKnXCI5yQ'
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it "deve pegar a URI que for passada por parâmetro" do
|
|
182
|
+
signed_info = Nokogiri::XML( subject.send(:signed_info, xml, 'new_uri').doc.root.to_s )
|
|
183
|
+
|
|
184
|
+
signed_info.remove_namespaces!
|
|
185
|
+
signed_info.xpath('SignedInfo/Reference').first.attr("URI").must_equal 'new_uri'
|
|
186
|
+
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
describe "#assinatura_xml" do
|
|
192
|
+
let(:xml_signed_info) do
|
|
193
|
+
Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
|
|
194
|
+
xml.Signature(xmlns: 'http://www.w3.org/2000/09/xmldsig#') {
|
|
195
|
+
xml.Value 'STUBADO'
|
|
196
|
+
}
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it "deve gerar o xml" do
|
|
201
|
+
subject.stubs(:signed_info).with(xml, 'URI123').returns(xml_signed_info)
|
|
202
|
+
subject.expects(:xml_signature_value).with('<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><Value>STUBADO</Value></Signature>').returns("KEYFORINFOSIGNED")
|
|
203
|
+
|
|
204
|
+
assinatura = Nokogiri::XML( subject.send(:assinatura_xml, xml, 'URI123') )
|
|
205
|
+
|
|
206
|
+
assinatura.namespaces.must_equal({"xmlns"=>"http://www.w3.org/2000/09/xmldsig#"})
|
|
207
|
+
assinatura.remove_namespaces!
|
|
208
|
+
assinatura.xpath('Signature/Signature/Value').first.text.must_equal 'STUBADO'
|
|
209
|
+
assinatura.xpath('Signature/SignatureValue').first.text.must_equal 'KEYFORINFOSIGNED'
|
|
210
|
+
assinatura.xpath('Signature/KeyInfo/X509Data/X509Certificate').first.text.must_equal 'MCYwHAIBADADBgEAMAAwBB8AHwAwADAIMAMGAQADAQAwAwYBAAMBAA=='
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
describe "#certificado" do
|
|
215
|
+
before do
|
|
216
|
+
subject.unstub(:certificado)
|
|
217
|
+
end
|
|
218
|
+
it "deve ler o certificado PKCS12 do atributo certificado_value e com a senha do certificado_password" do
|
|
219
|
+
subject.assign_attributes(certificado_value: "CERTIFICADO", certificado_password: 'pWd123')
|
|
220
|
+
OpenSSL::PKCS12.expects(:new).with("CERTIFICADO", 'pWd123').returns('certificado')
|
|
221
|
+
subject.certificado.must_equal 'certificado'
|
|
222
|
+
end
|
|
223
|
+
it "se já tem um certificado na variavel @certificado não deve ler novamente do PKCS12" do
|
|
224
|
+
subject.instance_variable_set(:@certificado, certificado)
|
|
225
|
+
OpenSSL::PKCS12.expects(:new).never
|
|
226
|
+
subject.certificado.must_equal certificado
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
describe "#client_wsdl" do
|
|
231
|
+
before do
|
|
232
|
+
# Stub metodos para configuração do client WSDL
|
|
233
|
+
subject.stubs(:namespaces).returns('namespaces')
|
|
234
|
+
subject.stubs(:env_namespace).returns('env_namespace')
|
|
235
|
+
subject.stubs(:wsdl).returns('wsdl')
|
|
236
|
+
subject.stubs(:wsdl_encoding).returns('client_encoding')
|
|
237
|
+
subject.stubs(:namespace_identifier).returns('namespace_identifier')
|
|
238
|
+
# Ajusto a configuração da gem para testar
|
|
239
|
+
BrNfe.client_wsdl_log = 'client_wsdl_log'
|
|
240
|
+
BrNfe.client_wsdl_pretty_print_xml = 'client_wsdl_pretty_print_xml'
|
|
241
|
+
BrNfe.client_wsdl_ssl_verify_mode = 'client_wsdl_ssl_verify_mode'
|
|
242
|
+
BrNfe.client_wsdl_ssl_cert_file = 'client_wsdl_ssl_cert_file'
|
|
243
|
+
BrNfe.client_wsdl_ssl_cert_key_file = 'client_wsdl_ssl_cert_key_file'
|
|
244
|
+
BrNfe.client_wsdl_ssl_cert_key_password = 'client_wsdl_ssl_cert_key_password'
|
|
245
|
+
end
|
|
246
|
+
it "deve instanciar um Savon.client com a configuração adequada" do
|
|
247
|
+
subject.instance_variable_get(:@client_wsdl).must_be_nil
|
|
248
|
+
Savon.expects(:client).with({
|
|
249
|
+
namespaces: 'namespaces',
|
|
250
|
+
env_namespace: 'env_namespace',
|
|
251
|
+
wsdl: 'wsdl',
|
|
252
|
+
namespace_identifier: 'namespace_identifier',
|
|
253
|
+
log: 'client_wsdl_log',
|
|
254
|
+
encoding: 'client_encoding',
|
|
255
|
+
pretty_print_xml: 'client_wsdl_pretty_print_xml',
|
|
256
|
+
ssl_verify_mode: 'client_wsdl_ssl_verify_mode',
|
|
257
|
+
ssl_cert_file: 'client_wsdl_ssl_cert_file',
|
|
258
|
+
ssl_cert_key_file: 'client_wsdl_ssl_cert_key_file',
|
|
259
|
+
ssl_cert_key_password: 'client_wsdl_ssl_cert_key_password'
|
|
260
|
+
}).returns('client wsdl')
|
|
261
|
+
|
|
262
|
+
subject.client_wsdl.must_equal 'client wsdl'
|
|
263
|
+
subject.instance_variable_get(:@client_wsdl).must_equal 'client wsdl'
|
|
264
|
+
end
|
|
265
|
+
it "se ja tiver valor na variavel @client_wsdl deve manter esse valor" do
|
|
266
|
+
Savon.expects(:client).never
|
|
267
|
+
subject.instance_variable_set(:@client_wsdl, :valor_client_wsdl)
|
|
268
|
+
subject.client_wsdl.must_equal :valor_client_wsdl
|
|
269
|
+
subject.instance_variable_get(:@client_wsdl).must_equal :valor_client_wsdl
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
describe BrNfe::CondicaoPagamento do
|
|
4
|
+
subject { FactoryGirl.build(:condicao_pagamento) }
|
|
5
|
+
|
|
6
|
+
describe "#parcelas" do
|
|
7
|
+
it "deve inicializar como um vetor vazio" do
|
|
8
|
+
subject.class.new.parcelas.must_equal []
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "posso utilizar o << para adicionar valores" do
|
|
12
|
+
subject.parcelas << {valor: '1'}
|
|
13
|
+
subject.parcelas << {valor: '2'}
|
|
14
|
+
subject.parcelas.must_equal [{valor: '1'}, {valor: '2'}]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "sempre retorna um array" do
|
|
18
|
+
subject.parcelas = {valor: '2'}
|
|
19
|
+
subject.parcelas.must_equal [{valor: '2'}]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'br_nfe/helper/have_address_test.rb'
|
|
3
|
+
|
|
4
|
+
describe BrNfe::Destinatario do
|
|
5
|
+
subject { FactoryGirl.build(:destinatario, endereco: endereco) }
|
|
6
|
+
let(:endereco) { FactoryGirl.build(:endereco) }
|
|
7
|
+
|
|
8
|
+
describe "#endereco" do
|
|
9
|
+
include BrNfeTest::HelperTest::HaveAddressTest
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "#razao_social" do
|
|
13
|
+
it "deve retornar a string em maiusculoo e sem acentos" do
|
|
14
|
+
subject.razao_social = 'ó têxtú dève vìr SÉM ÀçÊnTÕ'
|
|
15
|
+
subject.razao_social.must_equal "O TEXTU DEVE VIR SEM ACENTO"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "#nome_fantasia" do
|
|
20
|
+
it "deve retornar a string em maiusculoo e sem acentos" do
|
|
21
|
+
subject.nome_fantasia = 'ó têxtú dève vìr SÉM ÀçÊnTÕ'
|
|
22
|
+
subject.nome_fantasia.must_equal "O TEXTU DEVE VIR SEM ACENTO"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'br_nfe/helper/have_address_test.rb'
|
|
3
|
+
|
|
4
|
+
describe BrNfe::Emitente do
|
|
5
|
+
subject { FactoryGirl.build(:emitente, endereco: endereco) }
|
|
6
|
+
let(:endereco) { FactoryGirl.build(:endereco) }
|
|
7
|
+
|
|
8
|
+
describe "#endereco" do
|
|
9
|
+
include BrNfeTest::HelperTest::HaveAddressTest
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "#razao_social" do
|
|
13
|
+
it "deve retornar a string em maiusculoo e sem acentos" do
|
|
14
|
+
subject.razao_social = 'ó têxtú dève vìr SÉM ÀçÊnTÕ'
|
|
15
|
+
subject.razao_social.must_equal "O TEXTU DEVE VIR SEM ACENTO"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "#nome_fantasia" do
|
|
20
|
+
it "deve retornar a string em maiusculoo e sem acentos" do
|
|
21
|
+
subject.nome_fantasia = 'ó têxtú dève vìr SÉM ÀçÊnTÕ'
|
|
22
|
+
subject.nome_fantasia.must_equal "O TEXTU DEVE VIR SEM ACENTO"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
describe BrNfe::Endereco do
|
|
4
|
+
subject { FactoryGirl.build(:endereco) }
|
|
5
|
+
|
|
6
|
+
describe "#default_values" do
|
|
7
|
+
it "for codigo_pais must equal to 1058 " do
|
|
8
|
+
BrNfe::Endereco.new().codigo_pais.must_equal '1058'
|
|
9
|
+
end
|
|
10
|
+
it "for nome_pais must equal to BRASIL " do
|
|
11
|
+
BrNfe::Endereco.new().nome_pais.must_equal 'BRASIL'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe "#logradouro" do
|
|
16
|
+
it "deve retornar a string em maiusculoo e sem acentos" do
|
|
17
|
+
subject.logradouro = 'ó têxtú dève vìr SÉM ÀçÊnTÕ'
|
|
18
|
+
subject.logradouro.must_equal "O TEXTU DEVE VIR SEM ACENTO"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "#complemento" do
|
|
23
|
+
it "deve retornar a string em maiusculoo e sem acentos" do
|
|
24
|
+
subject.complemento = 'ó têxtú dève vìr SÉM ÀçÊnTÕ'
|
|
25
|
+
subject.complemento.must_equal "O TEXTU DEVE VIR SEM ACENTO"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "#bairro" do
|
|
30
|
+
it "deve retornar a string em maiusculoo e sem acentos" do
|
|
31
|
+
subject.bairro = 'ó têxtú dève vìr SÉM ÀçÊnTÕ'
|
|
32
|
+
subject.bairro.must_equal "O TEXTU DEVE VIR SEM ACENTO"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "#nome_municipio" do
|
|
37
|
+
it "deve retornar a string em maiusculoo e sem acentos" do
|
|
38
|
+
subject.nome_municipio = 'ó têxtú dève vìr SÉM ÀçÊnTÕ'
|
|
39
|
+
subject.nome_municipio.must_equal "O TEXTU DEVE VIR SEM ACENTO"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "#nome_pais" do
|
|
44
|
+
it "deve retornar a string em maiusculoo e sem acentos" do
|
|
45
|
+
subject.nome_pais = 'ó têxtú dève vìr SÉM ÀçÊnTÕ'
|
|
46
|
+
subject.nome_pais.must_equal "O TEXTU DEVE VIR SEM ACENTO"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
|
|
2
|
+
module BrNfeTest
|
|
3
|
+
module HelperTest
|
|
4
|
+
module HaveAddressTest
|
|
5
|
+
class Address < BrNfe::Endereco
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def test_HaveAddressTest_Já_inicia_com_um_endereco
|
|
9
|
+
subject.class.new.endereco.class.must_equal BrNfe::Endereco
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_HaveAddressTest_Mesmo_setando_o_endereço_como_nil_retorna_um_novo_endereco
|
|
13
|
+
subject.endereco = nil
|
|
14
|
+
subject.endereco.class.must_equal BrNfe::Endereco
|
|
15
|
+
subject.endereco.class.wont_equal endereco
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_HaveAddressTest_deve_manter_o_objeto_endereco_se_ja_tiver
|
|
19
|
+
subject.endereco.must_equal endereco
|
|
20
|
+
endereco.cep = 'nova-www'
|
|
21
|
+
subject.endereco.cep.must_equal 'nova-www'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_HaveAddressTest_Se_setar_o_endereco_com_outra_class_deve_ignorar
|
|
25
|
+
subject.endereco = 7777
|
|
26
|
+
subject.endereco.must_equal endereco
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_HaveAddressTest_posso_setar_o_endereco_com_um_hash_com_os_parametros_do_endereço
|
|
30
|
+
endereco.assign_attributes(cep: '123456', logradouro: :rua_1, uf: :sc)
|
|
31
|
+
subject.endereco = {cep: '99999', logradouro: :rua_2, uf: :rs}
|
|
32
|
+
subject.endereco.cep.must_equal '99999'
|
|
33
|
+
subject.endereco.logradouro.must_equal 'RUA_2'
|
|
34
|
+
subject.endereco.uf.must_equal :rs
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def test_HaveAddressTest_posso_setar_o_endereco_com_um_bloco
|
|
38
|
+
endereco.assign_attributes(cep: '123456', logradouro: :rua_1, uf: :sc)
|
|
39
|
+
subject.endereco do |address|
|
|
40
|
+
address.cep = '99999'
|
|
41
|
+
address.logradouro = :rua_2
|
|
42
|
+
address.uf = :rs
|
|
43
|
+
end
|
|
44
|
+
subject.endereco.cep.must_equal '99999'
|
|
45
|
+
subject.endereco.logradouro.must_equal 'RUA_2'
|
|
46
|
+
subject.endereco.uf.must_equal :rs
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_HaveAddressTest_posso_mudar_o_objeto_endereco
|
|
50
|
+
novo_endereco = FactoryGirl.build(:endereco)
|
|
51
|
+
subject.endereco = novo_endereco
|
|
52
|
+
subject.endereco.must_equal novo_endereco
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test_HaveAddressTest_posso_modificar_a_class_do_address
|
|
56
|
+
BrNfe.endereco_class = Address
|
|
57
|
+
subject.endereco.class.must_equal Address
|
|
58
|
+
BrNfe.endereco_class = BrNfe::Endereco
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
module BrNfeTest
|
|
3
|
+
module HelperTest
|
|
4
|
+
module HaveCondicaoPagamentoTest
|
|
5
|
+
class NewClassCondicaoPagamento < BrNfe::CondicaoPagamento
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def test_HaveCondicaoPagamentoTest_deve_iniciar_o_condicao_pagamento_com_nil
|
|
9
|
+
subject.class.new.condicao_pagamento.must_be_nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_HaveCondicaoPagamentoTest_se_tiver_condicao_pagamento_posso_setalo_como_nil
|
|
13
|
+
subject.condicao_pagamento.wont_be_nil
|
|
14
|
+
subject.condicao_pagamento = nil
|
|
15
|
+
subject.condicao_pagamento.must_be_nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_HaveCondicaoPagamentoTest_deve_manter_o_objeto_condicao_pagamento_se_ja_tiver
|
|
19
|
+
subject.condicao_pagamento.must_equal condicao_pagamento
|
|
20
|
+
condicao_pagamento.condicao = 'nova-www'
|
|
21
|
+
subject.condicao_pagamento.condicao.must_equal 'nova-www'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_HaveCondicaoPagamentoTest_Se_setar_o_condicao_pagamento_com_outra_class_deve_ignorar
|
|
25
|
+
subject.condicao_pagamento = 7777
|
|
26
|
+
subject.condicao_pagamento.must_equal condicao_pagamento
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_HaveCondicaoPagamentoTest_posso_setar_o_condicao_pagamento_com_um_hash_com_os_parametros_do_condicao_pagamento
|
|
30
|
+
condicao_pagamento.assign_attributes(condicao: '123456')
|
|
31
|
+
subject.condicao_pagamento = {condicao: '99999'}
|
|
32
|
+
subject.condicao_pagamento.condicao.must_equal '99999'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_HaveCondicaoPagamentoTest_ao_setar_um_condicao_pagamento_com_um_hash_e_nao_tiver_um_condicao_pagamento_deve_instanciar_um_com_os_parametros
|
|
36
|
+
subject.condicao_pagamento = nil
|
|
37
|
+
subject.condicao_pagamento = {condicao: '99999'}
|
|
38
|
+
subject.condicao_pagamento.condicao.must_equal '99999'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_HaveCondicaoPagamentoTest_posso_setar_o_condicao_pagamento_com_um_bloco
|
|
42
|
+
condicao_pagamento.assign_attributes(condicao: '123456')
|
|
43
|
+
subject.condicao_pagamento do |address|
|
|
44
|
+
address.condicao = '99999'
|
|
45
|
+
end
|
|
46
|
+
subject.condicao_pagamento.condicao.must_equal '99999'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_HaveCondicaoPagamentoTest_ao_setar_um_condicao_pagamento_com_um_bloco_e_nao_tiver_um_condicao_pagamento_deve_instanciar_um_com_os_parametros
|
|
50
|
+
subject.condicao_pagamento = nil
|
|
51
|
+
subject.condicao_pagamento do |address|
|
|
52
|
+
address.condicao = '99999'
|
|
53
|
+
end
|
|
54
|
+
subject.condicao_pagamento.condicao.must_equal '99999'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_HaveCondicaoPagamentoTest_posso_mudar_o_objeto_condicao_pagamento
|
|
58
|
+
novo_condicao_pagamento = FactoryGirl.build(:condicao_pagamento)
|
|
59
|
+
subject.condicao_pagamento = novo_condicao_pagamento
|
|
60
|
+
subject.condicao_pagamento.must_equal novo_condicao_pagamento
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_HaveCondicaoPagamentoTest_posso_modificar_a_class_do_condicao_pagamento
|
|
64
|
+
BrNfe.condicao_pagamento_class = NewClassCondicaoPagamento
|
|
65
|
+
novo_objeto = subject.class.new(condicao_pagamento: {condicao: '123'})
|
|
66
|
+
novo_objeto.condicao_pagamento.class.must_equal NewClassCondicaoPagamento
|
|
67
|
+
BrNfe.condicao_pagamento_class = BrNfe::CondicaoPagamento
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|