nfse_sjc 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +4 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +22 -0
  8. data/README.md +130 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +7 -0
  11. data/bin/setup +7 -0
  12. data/etc/codegen/_signature.xml.erb +22 -0
  13. data/etc/codegen/cabecalho_v3.xml.erb +6 -0
  14. data/etc/codegen/cancelar_nfse_v3.xml.erb +21 -0
  15. data/etc/codegen/consultar_lote_rps_v3.xml.erb +15 -0
  16. data/etc/codegen/consultar_nfse_rps_v3.xml.erb +18 -0
  17. data/etc/codegen/consultar_nfse_v3.xml.erb +58 -0
  18. data/etc/codegen/consultar_situacao_lote_rps_v3.xml.erb +15 -0
  19. data/etc/codegen/recepcionar_lote_rps_v3.xml.erb +188 -0
  20. data/etc/schemas/cabecalho_v03.xsd +16 -0
  21. data/etc/schemas/servico_cancelar_nfse_envio_v03.xsd +19 -0
  22. data/etc/schemas/servico_cancelar_nfse_resposta_v03.xsd +13 -0
  23. data/etc/schemas/servico_consultar_lote_rps_envio_v03.xsd +23 -0
  24. data/etc/schemas/servico_consultar_lote_rps_resposta_v03.xsd +18 -0
  25. data/etc/schemas/servico_consultar_nfse_envio_v03.xsd +26 -0
  26. data/etc/schemas/servico_consultar_nfse_resposta_v03.xsd +19 -0
  27. data/etc/schemas/servico_consultar_nfse_rps_envio_v03.xsd +23 -0
  28. data/etc/schemas/servico_consultar_nfse_rps_resposta_v03.xsd +13 -0
  29. data/etc/schemas/servico_consultar_situacao_lote_rps_envio_v03.xsd +17 -0
  30. data/etc/schemas/servico_consultar_situacao_lote_rps_resposta_v03.xsd +16 -0
  31. data/etc/schemas/servico_enviar_lote_rps_envio_v03.xsd +14 -0
  32. data/etc/schemas/servico_enviar_lote_rps_resposta_v03.xsd +25 -0
  33. data/etc/schemas/tipos_v03.xsd +545 -0
  34. data/etc/schemas/xmldsig-core-schema20020212_v03.xsd +316 -0
  35. data/lib/nfse_sjc.rb +22 -0
  36. data/lib/nfse_sjc/client.rb +49 -0
  37. data/lib/nfse_sjc/config.rb +31 -0
  38. data/lib/nfse_sjc/dirs.rb +23 -0
  39. data/lib/nfse_sjc/document.rb +67 -0
  40. data/lib/nfse_sjc/errors/validation_error.rb +6 -0
  41. data/lib/nfse_sjc/parser.rb +15 -0
  42. data/lib/nfse_sjc/response_hash.rb +24 -0
  43. data/lib/nfse_sjc/schemas.rb +17 -0
  44. data/lib/nfse_sjc/version.rb +3 -0
  45. data/nfse_sjc.gemspec +32 -0
  46. metadata +175 -0
@@ -0,0 +1,316 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Schema for XML Signatures
3
+ http://www.w3.org/2000/09/xmldsig#
4
+ $Revision: 1.7 $ on $Date: 2007/09/20 19:06:50 $ by $Author: p052373 $
5
+
6
+ Copyright 2001 The Internet Society and W3C (Massachusetts Institute
7
+ of Technology, Institut National de Recherche en Informatique et en
8
+ Automatique, Keio University). All Rights Reserved.
9
+ http://www.w3.org/Consortium/Legal/
10
+
11
+ This document is governed by the W3C Software License [1] as described
12
+ in the FAQ [2].
13
+
14
+ [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
15
+ [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
16
+ -->
17
+
18
+ <!--
19
+
20
+ Download em 23/02/2007
21
+ Link:
22
+ http://www.w3.org/TR/xmldsig-core/#sec-Schema
23
+ http://www.w3.org/TR/xmldsig-core/xmldsig-core-schema_v03.xsd
24
+
25
+ -->
26
+
27
+ <schema xmlns="http://www.w3.org/2001/XMLSchema"
28
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
29
+ targetNamespace="http://www.w3.org/2000/09/xmldsig#"
30
+ version="0.1" elementFormDefault="qualified">
31
+
32
+ <!-- Basic Types Defined for Signatures -->
33
+
34
+ <simpleType name="CryptoBinary">
35
+ <restriction base="base64Binary">
36
+ </restriction>
37
+ </simpleType>
38
+
39
+ <!-- Start Signature -->
40
+
41
+ <element name="Signature" type="ds:SignatureType"/>
42
+ <complexType name="SignatureType">
43
+ <sequence>
44
+ <element ref="ds:SignedInfo"/>
45
+ <element ref="ds:SignatureValue"/>
46
+ <element ref="ds:KeyInfo" minOccurs="0"/>
47
+ <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
48
+ </sequence>
49
+ <attribute name="Id" type="ID" use="optional"/>
50
+ </complexType>
51
+
52
+ <element name="SignatureValue" type="ds:SignatureValueType"/>
53
+ <complexType name="SignatureValueType">
54
+ <simpleContent>
55
+ <extension base="base64Binary">
56
+ <attribute name="Id" type="ID" use="optional"/>
57
+ </extension>
58
+ </simpleContent>
59
+ </complexType>
60
+
61
+ <!-- Start SignedInfo -->
62
+
63
+ <element name="SignedInfo" type="ds:SignedInfoType"/>
64
+ <complexType name="SignedInfoType">
65
+ <sequence>
66
+ <element ref="ds:CanonicalizationMethod"/>
67
+ <element ref="ds:SignatureMethod"/>
68
+ <element ref="ds:Reference" maxOccurs="unbounded"/>
69
+ </sequence>
70
+ <attribute name="Id" type="ID" use="optional"/>
71
+ </complexType>
72
+
73
+ <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/>
74
+ <complexType name="CanonicalizationMethodType" mixed="true">
75
+ <sequence>
76
+ <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
77
+ <!-- (0,unbounded) elements from (1,1) namespace -->
78
+ </sequence>
79
+ <attribute name="Algorithm" type="anyURI" use="required"/>
80
+ </complexType>
81
+
82
+ <element name="SignatureMethod" type="ds:SignatureMethodType"/>
83
+ <complexType name="SignatureMethodType" mixed="true">
84
+ <sequence>
85
+ <element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/>
86
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
87
+ <!-- (0,unbounded) elements from (1,1) external namespace -->
88
+ </sequence>
89
+ <attribute name="Algorithm" type="anyURI" use="required"/>
90
+ </complexType>
91
+
92
+ <!-- Start Reference -->
93
+
94
+ <element name="Reference" type="ds:ReferenceType"/>
95
+ <complexType name="ReferenceType">
96
+ <sequence>
97
+ <element ref="ds:Transforms" minOccurs="0"/>
98
+ <element ref="ds:DigestMethod"/>
99
+ <element ref="ds:DigestValue"/>
100
+ </sequence>
101
+ <attribute name="Id" type="ID" use="optional"/>
102
+ <attribute name="URI" type="anyURI" use="optional"/>
103
+ <attribute name="Type" type="anyURI" use="optional"/>
104
+ </complexType>
105
+
106
+ <element name="Transforms" type="ds:TransformsType"/>
107
+ <complexType name="TransformsType">
108
+ <sequence>
109
+ <element ref="ds:Transform" maxOccurs="unbounded"/>
110
+ </sequence>
111
+ </complexType>
112
+
113
+ <element name="Transform" type="ds:TransformType"/>
114
+ <complexType name="TransformType" mixed="true">
115
+ <choice minOccurs="0" maxOccurs="unbounded">
116
+ <any namespace="##other" processContents="lax"/>
117
+ <!-- (1,1) elements from (0,unbounded) namespaces -->
118
+ <element name="XPath" type="string"/>
119
+ </choice>
120
+ <attribute name="Algorithm" type="anyURI" use="required"/>
121
+ </complexType>
122
+
123
+ <!-- End Reference -->
124
+
125
+ <element name="DigestMethod" type="ds:DigestMethodType"/>
126
+ <complexType name="DigestMethodType" mixed="true">
127
+ <sequence>
128
+ <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
129
+ </sequence>
130
+ <attribute name="Algorithm" type="anyURI" use="required"/>
131
+ </complexType>
132
+
133
+ <element name="DigestValue" type="ds:DigestValueType"/>
134
+ <simpleType name="DigestValueType">
135
+ <restriction base="base64Binary"/>
136
+ </simpleType>
137
+
138
+ <!-- End SignedInfo -->
139
+
140
+ <!-- Start KeyInfo -->
141
+
142
+ <element name="KeyInfo" type="ds:KeyInfoType"/>
143
+ <complexType name="KeyInfoType" mixed="true">
144
+ <choice maxOccurs="unbounded">
145
+ <element ref="ds:KeyName"/>
146
+ <element ref="ds:KeyValue"/>
147
+ <element ref="ds:RetrievalMethod"/>
148
+ <element ref="ds:X509Data"/>
149
+ <element ref="ds:PGPData"/>
150
+ <element ref="ds:SPKIData"/>
151
+ <element ref="ds:MgmtData"/>
152
+ <any processContents="lax" namespace="##other"/>
153
+ <!-- (1,1) elements from (0,unbounded) namespaces -->
154
+ </choice>
155
+ <attribute name="Id" type="ID" use="optional"/>
156
+ </complexType>
157
+
158
+ <element name="KeyName" type="string"/>
159
+ <element name="MgmtData" type="string"/>
160
+
161
+ <element name="KeyValue" type="ds:KeyValueType"/>
162
+ <complexType name="KeyValueType" mixed="true">
163
+ <choice>
164
+ <element ref="ds:DSAKeyValue"/>
165
+ <element ref="ds:RSAKeyValue"/>
166
+ <any namespace="##other" processContents="lax"/>
167
+ </choice>
168
+ </complexType>
169
+
170
+ <element name="RetrievalMethod" type="ds:RetrievalMethodType"/>
171
+ <complexType name="RetrievalMethodType">
172
+ <sequence>
173
+ <element ref="ds:Transforms" minOccurs="0"/>
174
+ </sequence>
175
+ <attribute name="URI" type="anyURI"/>
176
+ <attribute name="Type" type="anyURI" use="optional"/>
177
+ </complexType>
178
+
179
+ <!-- Start X509Data -->
180
+
181
+ <element name="X509Data" type="ds:X509DataType"/>
182
+ <complexType name="X509DataType">
183
+ <sequence maxOccurs="unbounded">
184
+ <choice>
185
+ <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
186
+ <element name="X509SKI" type="base64Binary"/>
187
+ <element name="X509SubjectName" type="string"/>
188
+ <element name="X509Certificate" type="base64Binary"/>
189
+ <element name="X509CRL" type="base64Binary"/>
190
+ <any namespace="##other" processContents="lax"/>
191
+ </choice>
192
+ </sequence>
193
+ </complexType>
194
+
195
+ <complexType name="X509IssuerSerialType">
196
+ <sequence>
197
+ <element name="X509IssuerName" type="string"/>
198
+ <element name="X509SerialNumber" type="integer"/>
199
+ </sequence>
200
+ </complexType>
201
+
202
+ <!-- End X509Data -->
203
+
204
+ <!-- Begin PGPData -->
205
+
206
+ <element name="PGPData" type="ds:PGPDataType"/>
207
+ <complexType name="PGPDataType">
208
+ <choice>
209
+ <sequence>
210
+ <element name="PGPKeyID" type="base64Binary"/>
211
+ <element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/>
212
+ <any namespace="##other" processContents="lax" minOccurs="0"
213
+ maxOccurs="unbounded"/>
214
+ </sequence>
215
+ <sequence>
216
+ <element name="PGPKeyPacket" type="base64Binary"/>
217
+ <any namespace="##other" processContents="lax" minOccurs="0"
218
+ maxOccurs="unbounded"/>
219
+ </sequence>
220
+ </choice>
221
+ </complexType>
222
+
223
+ <!-- End PGPData -->
224
+
225
+ <!-- Begin SPKIData -->
226
+
227
+ <element name="SPKIData" type="ds:SPKIDataType"/>
228
+ <complexType name="SPKIDataType">
229
+ <sequence maxOccurs="unbounded">
230
+ <element name="SPKISexp" type="base64Binary"/>
231
+ <any namespace="##other" processContents="lax" minOccurs="0"/>
232
+ </sequence>
233
+ </complexType>
234
+
235
+ <!-- End SPKIData -->
236
+
237
+ <!-- End KeyInfo -->
238
+
239
+ <!-- Start Object (Manifest, SignatureProperty) -->
240
+
241
+ <element name="Object" type="ds:ObjectType"/>
242
+ <complexType name="ObjectType" mixed="true">
243
+ <sequence minOccurs="0" maxOccurs="unbounded">
244
+ <any namespace="##any" processContents="lax"/>
245
+ </sequence>
246
+ <attribute name="Id" type="ID" use="optional"/>
247
+ <attribute name="MimeType" type="string" use="optional"/> <!-- add a grep facet -->
248
+ <attribute name="Encoding" type="anyURI" use="optional"/>
249
+ </complexType>
250
+
251
+ <element name="Manifest" type="ds:ManifestType"/>
252
+ <complexType name="ManifestType">
253
+ <sequence>
254
+ <element ref="ds:Reference" maxOccurs="unbounded"/>
255
+ </sequence>
256
+ <attribute name="Id" type="ID" use="optional"/>
257
+ </complexType>
258
+
259
+ <element name="SignatureProperties" type="ds:SignaturePropertiesType"/>
260
+ <complexType name="SignaturePropertiesType">
261
+ <sequence>
262
+ <element ref="ds:SignatureProperty" maxOccurs="unbounded"/>
263
+ </sequence>
264
+ <attribute name="Id" type="ID" use="optional"/>
265
+ </complexType>
266
+
267
+ <element name="SignatureProperty" type="ds:SignaturePropertyType"/>
268
+ <complexType name="SignaturePropertyType" mixed="true">
269
+ <choice maxOccurs="unbounded">
270
+ <any namespace="##other" processContents="lax"/>
271
+ <!-- (1,1) elements from (1,unbounded) namespaces -->
272
+ </choice>
273
+ <attribute name="Target" type="anyURI" use="required"/>
274
+ <attribute name="Id" type="ID" use="optional"/>
275
+ </complexType>
276
+
277
+ <!-- End Object (Manifest, SignatureProperty) -->
278
+
279
+ <!-- Start Algorithm Parameters -->
280
+
281
+ <simpleType name="HMACOutputLengthType">
282
+ <restriction base="integer"/>
283
+ </simpleType>
284
+
285
+ <!-- Start KeyValue Element-types -->
286
+
287
+ <element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
288
+ <complexType name="DSAKeyValueType">
289
+ <sequence>
290
+ <sequence minOccurs="0">
291
+ <element name="P" type="ds:CryptoBinary"/>
292
+ <element name="Q" type="ds:CryptoBinary"/>
293
+ </sequence>
294
+ <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
295
+ <element name="Y" type="ds:CryptoBinary"/>
296
+ <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
297
+ <sequence minOccurs="0">
298
+ <element name="Seed" type="ds:CryptoBinary"/>
299
+ <element name="PgenCounter" type="ds:CryptoBinary"/>
300
+ </sequence>
301
+ </sequence>
302
+ </complexType>
303
+
304
+ <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
305
+ <complexType name="RSAKeyValueType">
306
+ <sequence>
307
+ <element name="Modulus" type="ds:CryptoBinary"/>
308
+ <element name="Exponent" type="ds:CryptoBinary"/>
309
+ </sequence>
310
+ </complexType>
311
+
312
+ <!-- End KeyValue Element-types -->
313
+
314
+ <!-- End Signature -->
315
+
316
+ </schema>
@@ -0,0 +1,22 @@
1
+ require 'nokogiri'
2
+ require 'savon'
3
+
4
+ require_relative 'nfse_sjc/dirs'
5
+ require_relative 'nfse_sjc/config'
6
+ require_relative 'nfse_sjc/schemas'
7
+ require_relative 'nfse_sjc/errors/validation_error'
8
+ require_relative 'nfse_sjc/response_hash'
9
+ require_relative 'nfse_sjc/parser'
10
+ require_relative 'nfse_sjc/document'
11
+ require_relative 'nfse_sjc/version'
12
+ require_relative 'nfse_sjc/client'
13
+
14
+ module NfseSjc
15
+ def self.config(at: nil)
16
+ if block_given?
17
+ yield Config
18
+ else
19
+ Config.to_h(at: at)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,49 @@
1
+ module NfseSjc
2
+ class Client
3
+ PARAM_KEYS = [:pretty_print_xml, :log, :wsdl, :ssl_cert_file,
4
+ :ssl_cert_key_file, :ssl_cert_key_password].freeze
5
+
6
+ def initialize(params = {})
7
+ @savon = Savon.client slice(params, *PARAM_KEYS).merge(NfseSjc.config(at: PARAM_KEYS))
8
+ @parser = Parser.new
9
+ @header = Document.new(Dirs.template('cabecalho_v3.xml.erb'), {}).to_xml.freeze
10
+ end
11
+
12
+ def call(method, params)
13
+ schema = Schemas.get_schema("#{method}.xml.erb")
14
+ schema_path = File.join Dirs.etc, 'schemas', schema
15
+ xsd = Nokogiri::XML::Schema(File.open schema_path)
16
+ document = Document.new(Dirs.template("#{method}.xml.erb"), params).to_signed_xml
17
+
18
+ errors = xsd.validate(Nokogiri::XML(document))
19
+
20
+ if errors.any?
21
+ message = errors.map do |err|
22
+ "* #{err}".gsub('{http://www.ginfes.com.br/tipos_v03.xsd}','').gsub('Element ', '')
23
+ end.join("\n")
24
+
25
+ raise NfseSjc::Errors::ValidationError.new("XML with invalid or incorrect data according to schema #{schema}, found errors:\n #{message}")
26
+ else
27
+ response = @savon.call(method, message: {
28
+ arg0: @header,
29
+ arg1: document
30
+ })
31
+
32
+ @parser.parse(response.body[:"#{method}_response"][:return])
33
+ end
34
+ end
35
+
36
+ def method_missing(name, *args, &block)
37
+ call(name, *args, &block)
38
+ end
39
+
40
+ private
41
+
42
+ def slice(hash, *keys)
43
+ keys.each_with_object({}) do |key, red|
44
+ red[key] = hash[key] if hash.has_key?(key)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
@@ -0,0 +1,31 @@
1
+ module NfseSjc
2
+ module Config
3
+ class << self
4
+ def self.default_attr(attr_name, env_path)
5
+ attr_writer attr_name
6
+ class_eval <<-RUBY
7
+ def #{attr_name}
8
+ @#{attr_name} ||= ENV['#{env_path}']
9
+ end
10
+ RUBY
11
+ end
12
+
13
+ default_attr :wsdl, 'NFSE_SJC_WSDL_URI'
14
+ default_attr :ssl_cert_file, 'NFSE_SJC_SSL_CERT_FILE'
15
+ default_attr :ssl_cert_key_file, 'NFSE_SJC_SSL_CERT_KEY_FILE'
16
+ default_attr :ssl_cert_key_password, 'NFSE_SJC_SSL_CERT_KEY_PASSWORD'
17
+ default_attr :log, 'NFSE_SJC_LOG'
18
+ default_attr :pretty_print_xml, 'NFSE_SJC_PRETTY_XML_LOG'
19
+ default_attr :xmlsec_binary_path, 'NFSE_SJC_XMLSEC_BINARY_PATH'
20
+
21
+ def to_h(at: nil)
22
+ %i(wsdl ssl_cert_file ssl_cert_key_file ssl_cert_key_password log pretty_print_xml xmlsec_binary_path).select do |prop|
23
+ at.blank? || at.include?(prop)
24
+ end.map do |meth|
25
+ val = send(meth)
26
+ [meth, val] if val
27
+ end.compact.to_h
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ module NfseSjc
2
+ module Dirs
3
+ def self.root
4
+ File.join(File.dirname(__dir__), '..')
5
+ end
6
+
7
+ def self.bin
8
+ File.join root, 'bin'
9
+ end
10
+
11
+ def self.lib
12
+ File.join root, 'lib'
13
+ end
14
+
15
+ def self.etc
16
+ File.join root, 'etc'
17
+ end
18
+
19
+ def self.template(filename)
20
+ File.join etc, 'codegen', filename
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,67 @@
1
+ require 'erubis'
2
+ require 'tempfile'
3
+
4
+ module NfseSjc
5
+ class Document
6
+ def initialize(filepath, params = {})
7
+ @params = params
8
+ @template = load_template(filepath)
9
+ end
10
+
11
+ def to_xml
12
+ @template.result(binding)
13
+ end
14
+
15
+ def to_signed_xml
16
+ unsigned_xml = to_xml
17
+
18
+ unsigned_temp_xml = Tempfile.new('unsigned-xml')
19
+ signed_temp_xml = Tempfile.new('signed-xml')
20
+ result = ''
21
+
22
+ begin
23
+ unsigned_temp_xml.write(unsigned_xml)
24
+ unsigned_temp_xml.rewind
25
+
26
+ %x{#{NfseSjc.config[:xmlsec_binary_path]} --sign --privkey-pem '#{NfseSjc.config[:ssl_cert_key_file]}','#{NfseSjc.config[:ssl_cert_file]}' --output '#{signed_temp_xml.path}' --pwd '#{NfseSjc.config[:ssl_cert_key_password]}' '#{unsigned_temp_xml.path}'}
27
+
28
+ signed_temp_xml.rewind
29
+ result = signed_temp_xml.read
30
+ ensure
31
+ signed_temp_xml.close
32
+ unsigned_temp_xml.close
33
+
34
+ signed_temp_xml.unlink
35
+ unsigned_temp_xml.unlink
36
+ end
37
+
38
+ result
39
+ end
40
+
41
+ protected
42
+
43
+ def render(filepath, params = {}, of: ::NfseSjc::Document)
44
+ of.new(NfseSjc::Dirs.template(filepath), params).to_xml
45
+ end
46
+
47
+ def param(*path, with: @params)
48
+ value = with
49
+ path.each do |segment|
50
+ value = value[segment]
51
+ break if value.nil?
52
+ end
53
+ return value
54
+ end
55
+
56
+ def if_param(*path, with: @params)
57
+ value = param(*path, with: with)
58
+ yield value unless value.nil? || (value.respond_to?(:empty) && value.empty?)
59
+ end
60
+
61
+ private
62
+ def load_template(filepath)
63
+ cachepath = File.join(Dir.tmpdir, "#{File.basename(filepath)}.cache")
64
+ Erubis::FastEruby.load_file(filepath, cachename: cachepath)
65
+ end
66
+ end
67
+ end