cfdi40 0.0.1.alfa → 0.0.2
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +10 -5
- data/README_es-MX.md +62 -0
- data/cfdi40.gemspec +2 -2
- data/lib/cfdi40/comprobante.rb +215 -20
- data/lib/cfdi40/concepto.rb +126 -0
- data/lib/cfdi40/conceptos.rb +4 -0
- data/lib/cfdi40/emisor.rb +7 -0
- data/lib/cfdi40/impuestos.rb +28 -0
- data/lib/cfdi40/node.rb +122 -0
- data/lib/cfdi40/receptor.rb +11 -0
- data/lib/cfdi40/sat_csd.rb +83 -0
- data/lib/cfdi40/schema_validator.rb +29 -0
- data/lib/cfdi40/traslado.rb +9 -0
- data/lib/cfdi40/traslados.rb +17 -0
- data/lib/cfdi40/version.rb +1 -1
- data/lib/cfdi40.rb +12 -0
- data/lib/xsd/README.md +30 -0
- data/lib/xsd/catCFDI.xsd +162329 -0
- data/lib/xsd/cfdv40.xsd +856 -0
- data/lib/xsd/tdCFDI.xsd +157 -0
- data/lib/xslt/CartaPorte20.xslt +615 -0
- data/lib/xslt/GastosHidrocarburos10.xslt +171 -0
- data/lib/xslt/IngresosHidrocarburos.xslt +39 -0
- data/lib/xslt/Pagos20.xslt +233 -0
- data/lib/xslt/TuristaPasajeroExtranjero.xslt +40 -0
- data/lib/xslt/aerolineas.xslt +50 -0
- data/lib/xslt/cadenaoriginal.xslt +405 -0
- data/lib/xslt/cadenaoriginal_local.xslt +405 -0
- data/lib/xslt/certificadodedestruccion.xslt +60 -0
- data/lib/xslt/cfdiregistrofiscal.xslt +19 -0
- data/lib/xslt/consumodeCombustibles11.xslt +94 -0
- data/lib/xslt/detallista.xslt +42 -0
- data/lib/xslt/divisas.xslt +13 -0
- data/lib/xslt/donat11.xslt +13 -0
- data/lib/xslt/iedu.xslt +26 -0
- data/lib/xslt/implocal.xslt +39 -0
- data/lib/xslt/ine11.xslt +30 -0
- data/lib/xslt/leyendasFisc.xslt +28 -0
- data/lib/xslt/nomina12.xslt +412 -0
- data/lib/xslt/notariospublicos.xslt +301 -0
- data/lib/xslt/obrasarteantiguedades.xslt +33 -0
- data/lib/xslt/pagoenespecie.xslt +39 -0
- data/lib/xslt/pfic.xslt +13 -0
- data/lib/xslt/renovacionysustitucionvehiculos.xslt +152 -0
- data/lib/xslt/servicioparcialconstruccion.xslt +44 -0
- data/lib/xslt/utilerias.xslt +22 -0
- data/lib/xslt/valesdedespensa.xslt +70 -0
- data/lib/xslt/vehiculousado.xslt +63 -0
- metadata +50 -13
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module Cfdi40
|
|
2
|
+
class SatCsd
|
|
3
|
+
attr_reader :x509_cert
|
|
4
|
+
attr_reader :private_key
|
|
5
|
+
|
|
6
|
+
def cert_path=(path)
|
|
7
|
+
@cert_path = path
|
|
8
|
+
@x509_cert = OpenSSL::X509::Certificate.new(File.read(path))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def cert_der=(data)
|
|
12
|
+
@x509_cert = OpenSSL::X509::Certificate.new(data)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def load_private_key(key_path, key_pass)
|
|
16
|
+
key_pem = load_key_to_pem(File.read(key_path))
|
|
17
|
+
@private_key = OpenSSL::PKey::RSA.new(key_pem, key_pass)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def set_crypted_private_key(key_der, key_pass)
|
|
21
|
+
key_pem = load_key_to_pem(key_der)
|
|
22
|
+
@private_key = OpenSSL::PKey::RSA.new(key_pem, key_pass)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def rfc
|
|
26
|
+
return unless subject_data
|
|
27
|
+
|
|
28
|
+
unique_identifier = subject_data.select { |data| data[0] == "x500UniqueIdentifier" }.first
|
|
29
|
+
return unless unique_identifier
|
|
30
|
+
|
|
31
|
+
unique_identifier[1]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def name
|
|
35
|
+
return unless subject_data
|
|
36
|
+
|
|
37
|
+
subject_name = subject_data.select { |data| data[0] == "name" }.first
|
|
38
|
+
return unless subject_name
|
|
39
|
+
|
|
40
|
+
subject_name[1]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def no_certificado
|
|
44
|
+
return unless x509_cert
|
|
45
|
+
|
|
46
|
+
s = ''
|
|
47
|
+
x509_cert.serial.to_s(16).split('').each_with_index do |c, i|
|
|
48
|
+
next if i.even?
|
|
49
|
+
|
|
50
|
+
s += c
|
|
51
|
+
end
|
|
52
|
+
s
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def cert64
|
|
56
|
+
return unless x509_cert
|
|
57
|
+
|
|
58
|
+
Base64.strict_encode64 x509_cert.to_der
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def valid_pair?
|
|
62
|
+
return false unless x509_cert && private_key
|
|
63
|
+
|
|
64
|
+
x509_cert.check_private_key private_key
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def subject_data
|
|
70
|
+
return unless x509_cert
|
|
71
|
+
|
|
72
|
+
x509_cert.subject.to_a
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def load_key_to_pem(key_der)
|
|
76
|
+
array_key_pem = []
|
|
77
|
+
array_key_pem << '-----BEGIN ENCRYPTED PRIVATE KEY-----'
|
|
78
|
+
array_key_pem += Base64.strict_encode64(key_der).scan(/.{1,64}/)
|
|
79
|
+
array_key_pem << '-----END ENCRYPTED PRIVATE KEY-----'
|
|
80
|
+
array_key_pem.join("\n")
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Validates Schema Using xsd files
|
|
2
|
+
module Cfdi40
|
|
3
|
+
class SchemaValidator
|
|
4
|
+
# options = Nokogiri::XML::ParseOptions.new.nononet
|
|
5
|
+
# schema = Nokogiri::XML::Schema(Net::HTTP.get('www.sat.gob.mx', '/sitio_internet/cfd/4/cfdv40.xsd'), options)
|
|
6
|
+
# schema = Nokogiri::XML::Schema(File.open("/home/israel/git/cfdi40/lib/xsd/cfdv40.xsd"), options)
|
|
7
|
+
|
|
8
|
+
attr_reader :errors
|
|
9
|
+
LOCAL_XSD_PATH = File.join(File.dirname(__FILE__), '..', 'xsd', 'cfdv40.xsd')
|
|
10
|
+
|
|
11
|
+
# Param xml is xml string
|
|
12
|
+
def initialize(xml)
|
|
13
|
+
@xml_doc = Nokogiri::XML(xml)
|
|
14
|
+
@schema = Nokogiri::XML::Schema(File.open(LOCAL_XSD_PATH))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def valid?
|
|
18
|
+
validate unless defined?(@errors)
|
|
19
|
+
|
|
20
|
+
@errors.empty?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def validate
|
|
26
|
+
@errors = @schema.validate(@xml_doc)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module Cfdi40
|
|
2
|
+
class Traslado < Node
|
|
3
|
+
define_attribute :base, xml_attribute: 'Base', format: :t_Importe
|
|
4
|
+
define_attribute :impuesto, xml_attribute: 'Impuesto'
|
|
5
|
+
define_attribute :tipo_factor, xml_attribute: 'TipoFactor', default: 'Tasa'
|
|
6
|
+
define_attribute :tasa_o_cuota, xml_attribute: 'TasaOCuota', format: :t_Importe
|
|
7
|
+
define_attribute :importe, xml_attribute: 'Importe', format: :t_Importe
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Cfdi40
|
|
2
|
+
class Traslados < Node
|
|
3
|
+
def traslado_iva
|
|
4
|
+
return @traslado_iva if defined?(@traslado_iva)
|
|
5
|
+
|
|
6
|
+
@traslado_iva = Traslado.new
|
|
7
|
+
# TODO: FIX magic number
|
|
8
|
+
@traslado_iva.impuesto = '002'
|
|
9
|
+
self.children_nodes << @traslado_iva
|
|
10
|
+
@traslado_iva
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def traslado_nodes
|
|
14
|
+
children_nodes
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/cfdi40/version.rb
CHANGED
data/lib/cfdi40.rb
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "nokogiri"
|
|
4
|
+
require "base64"
|
|
5
|
+
require "openssl"
|
|
4
6
|
require_relative "cfdi40/version"
|
|
7
|
+
require_relative "cfdi40/schema_validator"
|
|
8
|
+
require_relative "cfdi40/sat_csd"
|
|
9
|
+
require_relative "cfdi40/node"
|
|
5
10
|
require_relative "cfdi40/comprobante"
|
|
11
|
+
require_relative "cfdi40/emisor"
|
|
12
|
+
require_relative "cfdi40/receptor"
|
|
13
|
+
require_relative "cfdi40/conceptos"
|
|
14
|
+
require_relative "cfdi40/concepto"
|
|
15
|
+
require_relative "cfdi40/impuestos"
|
|
16
|
+
require_relative "cfdi40/traslados"
|
|
17
|
+
require_relative "cfdi40/traslado"
|
|
6
18
|
|
|
7
19
|
# Leading module and entry point for all features and classes
|
|
8
20
|
#
|
data/lib/xsd/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Local XSD files
|
|
2
|
+
|
|
3
|
+
## Why?
|
|
4
|
+
|
|
5
|
+
In order to avoid innecesary and redundant reading from SAT site the
|
|
6
|
+
file `cfdv40.xsd` referenced in cfdi standard, has been
|
|
7
|
+
prepared for local access.
|
|
8
|
+
|
|
9
|
+
The `cfdv40.xsd` has been modified to reference the local files
|
|
10
|
+
`tdCFDI.xsd`, `catCFDI.xsd` which are imported schemas. The schema
|
|
11
|
+
`catCFDI.xsd` has 5.8MB
|
|
12
|
+
|
|
13
|
+
## Use external files
|
|
14
|
+
|
|
15
|
+
If you want to use the schema in the original location must enable the
|
|
16
|
+
external references for Nokogiri:
|
|
17
|
+
|
|
18
|
+
require 'net/http'
|
|
19
|
+
|
|
20
|
+
xml_doc = Nokogiri::XML(xml_string)
|
|
21
|
+
|
|
22
|
+
options = Nokogiri::XML::ParseOptions.new.nononet
|
|
23
|
+
schema = Nokogiri::XML::Schema(Net::HTTP.get('www.sat.gob.mx', '/sitio_internet/cfd/4/cfdv40.xsd'), options)
|
|
24
|
+
|
|
25
|
+
schema.validate(xml_doc)
|
|
26
|
+
|
|
27
|
+
References:
|
|
28
|
+
|
|
29
|
+
https://nokogiri.org/rdoc/Nokogiri/XML/Schema.html
|
|
30
|
+
https://nokogiri.org/rdoc/Nokogiri/XML/ParseOptions.html
|