fm_timbrado_cfdi 0.0.1.alpha → 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/.travis.yml +4 -0
- data/Gemfile +1 -0
- data/README.md +12 -9
- data/fm_timbrado_cfdi.gemspec +1 -1
- data/lib/fm_timbrado_cfdi/fm_cliente.rb +32 -5
- data/lib/fm_timbrado_cfdi/fm_respuesta.rb +9 -11
- data/lib/fm_timbrado_cfdi/fm_respuesta_cancelacion.rb +29 -0
- data/lib/fm_timbrado_cfdi/fm_timbre.rb +60 -35
- data/lib/fm_timbrado_cfdi/version.rb +1 -1
- data/lib/fm_timbrado_cfdi.rb +21 -2
- data/spec/fixtures/certificados/20001000000200000192.cer +0 -0
- data/spec/fixtures/certificados/20001000000200000192.key +0 -0
- data/spec/fixtures/certificados/20001000000200000192.key.pem +15 -0
- data/spec/fixtures/soap_response.txt +2 -0
- data/spec/fixtures/soap_response_sin_xml.txt +2 -0
- data/spec/fm_timbrado_cfdi/fm_respuesta_spec.rb +29 -0
- data/spec/fm_timbrado_cfdi/fm_timbre_spec.rb +4 -2
- data/spec/fm_timbrado_cfdi_spec.rb +71 -16
- data/spec/spec_helper.rb +2 -0
- metadata +19 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2582e25a56146d9dc81168d01ee98697244367b
|
4
|
+
data.tar.gz: 2c34955c53b3db7c4c21f8540259510924421991
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb32a28f691f19aef58e428385bbc3299a4b0dcdc146fdfc790f787ffa23b1797c3b7d6ed93bd08046fd8c1964da7ec6b4354c00a8a03c7e3d1616d8ebed6813
|
7
|
+
data.tar.gz: 7de560ae159cc58026ad86e2a4b2e45894a523cc0996d3f0319d895f0d7fc0afc1918156c9c04296b312f10d12541bac9b61be1de4f22e86248b9c09bef2f76d
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
# FmTimbradoCfdi
|
2
|
+
[](https://travis-ci.org/LogicalBricks/fm_timbrado_cfdi)
|
3
|
+
[](https://codeclimate.com/github/LogicalBricks/fm_timbrado_cfdi)
|
4
|
+
[](https://coveralls.io/r/LogicalBricks/fm_timbrado_cfdi)
|
2
5
|
|
3
6
|
Implementa la conexión con el servicio de timbrado cfdi con el PAC Facturación Moderna [Guía de Desarrollo de FM](http://developers.facturacionmoderna.com).
|
4
7
|
|
@@ -22,7 +25,7 @@ o instala de forma independiente:
|
|
22
25
|
|
23
26
|
Para usar la gema es necesario realizar la configuración con los valores de conexión:
|
24
27
|
|
25
|
-
```
|
28
|
+
```ruby
|
26
29
|
FmTimbradoCfdi.configurar do |config|
|
27
30
|
config.user_id = 'user_id'
|
28
31
|
config.user_pass = 'password'
|
@@ -36,27 +39,27 @@ end # configurar
|
|
36
39
|
|
37
40
|
Y realizar la petición de timbrado:
|
38
41
|
|
39
|
-
```
|
42
|
+
```ruby
|
40
43
|
respuesta = FmTimbradoCfdi.timbra_cfdi_layout rfc, 'layout_file', false
|
41
|
-
=>
|
44
|
+
# => Petición sin generación del CBB
|
42
45
|
respuesta = FmTimbradoCfdi.timbra_cfdi_layout rfc, 'layout_file', true
|
43
|
-
=>
|
46
|
+
# => Petición con generación del CBB
|
44
47
|
```
|
45
48
|
|
46
49
|
Si cuentas con el XML sellado puedes hacer lo siguiente:
|
47
50
|
|
48
|
-
```
|
51
|
+
```ruby
|
49
52
|
respuesta = FmTimbradoCfdi.timbra_cfdi_xml 'archivo_xml', false
|
50
|
-
=>
|
53
|
+
# => Petición sin generación del CBB
|
51
54
|
respuesta = FmTimbradoCfdi.timbra_cfdi_xml 'archivo_xml', true
|
52
|
-
=>
|
55
|
+
# => Petición con generación del CBB
|
53
56
|
```
|
54
57
|
|
55
58
|
Para un método más general de timbrado que se encuentre más acorde a la documentación de [Facturación Moderna](http://developers.facturacionmoderna.com):
|
56
59
|
|
57
|
-
```
|
60
|
+
```ruby
|
58
61
|
respuesta = FmTimbradoCfdi.timbrar rfc_emisor, 'archivo_xml_o_layout', 'generarCBB' => false, 'generarPDF' => true, 'generarTXT' => false
|
59
|
-
=>
|
62
|
+
# => Generar la respuesta con formato PDF, pero sin formato CBB ni TXT
|
60
63
|
```
|
61
64
|
|
62
65
|
|
data/fm_timbrado_cfdi.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'fm_timbrado_cfdi/version'
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "fm_timbrado_cfdi"
|
8
8
|
gem.version = FmTimbradoCfdi::VERSION
|
9
|
-
gem.authors = ["Carlos García", "Hermes Ojeda Ruiz"]
|
9
|
+
gem.authors = ["Carlos García", "Hermes Ojeda Ruiz", "Crisóforo Gaspar Hernández @mitogh"]
|
10
10
|
gem.email = ["hermes.ojeda@logicalbricks.com"]
|
11
11
|
gem.homepage = "https://github.com/LogicalBricks/fm_timbrado_cfdi"
|
12
12
|
gem.summary = %q{Implementación en ruby de la conexión con el servicio de timbrado de cfdi con el PAC Facturación Moderna}
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'savon'
|
2
2
|
require 'fm_timbrado_cfdi/fm_respuesta'
|
3
|
+
require 'fm_timbrado_cfdi/fm_respuesta_cancelacion'
|
3
4
|
|
4
5
|
module FmTimbradoCfdi
|
5
6
|
class FmCliente
|
6
|
-
#attrs
|
7
7
|
attr_accessor :user_id, :user_pass, :namespace, :fm_wsdl, :endpoint, :ssl_verify_mode, :log, :log_level
|
8
8
|
|
9
9
|
def initialize
|
@@ -39,10 +39,37 @@ module FmTimbradoCfdi
|
|
39
39
|
FmRespuesta.new(response)
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
43
|
-
|
42
|
+
def subir_certificado(rfc, certificado, llave, password, opciones = {})
|
43
|
+
configurar_cliente
|
44
|
+
respuesta = @client.call(:activar_cancelacion,
|
45
|
+
message:
|
46
|
+
{ "param0" => {
|
47
|
+
"UserPass" => user_pass,
|
48
|
+
"UserID" => user_id,
|
49
|
+
"emisorRFC" => rfc,
|
50
|
+
"archivoCer" => Base64::encode64(certificado),
|
51
|
+
"archivoKey" => Base64::encode64(llave),
|
52
|
+
"clave" => password,
|
53
|
+
}.merge(opciones)
|
54
|
+
})
|
55
|
+
FmRespuestaCancelacion.new(respuesta)
|
44
56
|
end
|
45
57
|
|
58
|
+
def cancelar(rfc, uuid, opciones = {})
|
59
|
+
configurar_cliente
|
60
|
+
respuesta = @client.call(:request_cancelar_cfdi,
|
61
|
+
message:
|
62
|
+
{ "param0" => {
|
63
|
+
"UserPass" => user_pass,
|
64
|
+
"UserID" => user_id,
|
65
|
+
"emisorRFC" => rfc,
|
66
|
+
"uuid" => uuid,
|
67
|
+
}.merge(opciones)
|
68
|
+
})
|
69
|
+
FmRespuestaCancelacion.new(respuesta)
|
70
|
+
end
|
71
|
+
|
72
|
+
|
46
73
|
private
|
47
74
|
def configurar_cliente
|
48
75
|
@client = Savon.client(
|
@@ -55,5 +82,5 @@ module FmTimbradoCfdi
|
|
55
82
|
)
|
56
83
|
end
|
57
84
|
|
58
|
-
end
|
59
|
-
end
|
85
|
+
end
|
86
|
+
end
|
@@ -17,11 +17,11 @@ module FmTimbradoCfdi
|
|
17
17
|
@doc = Nokogiri::XML(savon_response.to_xml)
|
18
18
|
@xml = obtener_xml(@doc)
|
19
19
|
@no_csd_emisor = obtener_no_csd_emisor(@xml) if @xml
|
20
|
-
@timbre = obtener_timbre(@
|
20
|
+
@timbre = obtener_timbre(@xml)
|
21
21
|
@pdf = obtener_pdf(@doc)
|
22
22
|
@cbb = obtener_cbb(@doc)
|
23
23
|
else
|
24
|
-
@errors << savon_response.soap_fault.to_s if savon_response.soap_fault
|
24
|
+
@errors << savon_response.soap_fault.to_s if savon_response.soap_fault?
|
25
25
|
@doc = @xml = @no_csd_emisor = @timbre = @pdf = @cbb = nil
|
26
26
|
end
|
27
27
|
rescue Exception => e
|
@@ -34,27 +34,27 @@ module FmTimbradoCfdi
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def xml?
|
37
|
-
|
37
|
+
!!@xml
|
38
38
|
end
|
39
39
|
alias :xml_present? :xml?
|
40
40
|
|
41
41
|
def cbb?
|
42
|
-
|
42
|
+
!!@cbb
|
43
43
|
end
|
44
44
|
alias :cbb_present? :cbb?
|
45
45
|
|
46
46
|
def pdf?
|
47
|
-
|
47
|
+
!!@pdf
|
48
48
|
end
|
49
49
|
alias :pdf_present? :pdf?
|
50
50
|
|
51
51
|
def timbre?
|
52
|
-
|
52
|
+
!!@timbre
|
53
53
|
end
|
54
54
|
alias :timbre_present? :timbre?
|
55
55
|
|
56
56
|
def no_csd_emisor?
|
57
|
-
|
57
|
+
!!@no_csd_emisor
|
58
58
|
end
|
59
59
|
alias :no_csd_emisor_present? :no_csd_emisor?
|
60
60
|
|
@@ -69,10 +69,8 @@ module FmTimbradoCfdi
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
def obtener_timbre(
|
73
|
-
|
74
|
-
FmTimbre.new Base64::decode64( doc.xpath("//txt")[0].content )
|
75
|
-
end
|
72
|
+
def obtener_timbre(xml)
|
73
|
+
FmTimbre.new(xml) if xml
|
76
74
|
end
|
77
75
|
|
78
76
|
def obtener_pdf(doc)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'savon'
|
4
|
+
|
5
|
+
module FmTimbradoCfdi
|
6
|
+
class FmRespuestaCancelacion
|
7
|
+
attr_reader :error
|
8
|
+
def initialize(savon_response)
|
9
|
+
@respuesta = savon_response
|
10
|
+
unless valid?
|
11
|
+
#@error = @respuesta.http_error.to_s if @respuesta.http_error?
|
12
|
+
@error = @respuesta.to_s if @respuesta.soap_fault?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def codigo
|
17
|
+
@error.match(/\((.*)\).*/)[0] if @error
|
18
|
+
end
|
19
|
+
|
20
|
+
def mensaje
|
21
|
+
@error
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid?
|
25
|
+
@respuesta.success?
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -6,50 +6,75 @@ module FmTimbradoCfdi
|
|
6
6
|
attr_reader :no_certificado_sat, :fecha_timbrado, :uuid, :sello_sat, :sello_cfd, :fecha_comprobante, :serie, :folio, :trans_id
|
7
7
|
|
8
8
|
def initialize ( nodo_timbre )
|
9
|
-
parse( nodo_timbre )
|
10
|
-
end
|
11
|
-
|
9
|
+
parse( nodo_timbre )
|
10
|
+
end
|
11
|
+
|
12
12
|
def parse ( nodo_timbre )
|
13
|
-
|
14
|
-
|
13
|
+
xml = Nokogiri::XML(nodo_timbre)
|
14
|
+
ns = generar_namespaces(xml)
|
15
|
+
atributos.each do |variable|
|
16
|
+
instance_variable_set("@#{variable}", send("obtener_#{variable}", xml, ns))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def generar_namespaces(xml)
|
23
|
+
namespaces = xml.collect_namespaces
|
24
|
+
ns = {}
|
25
|
+
namespaces.each_pair do |key, value|
|
26
|
+
ns[key.sub(/^xmlns:/, '')] = value
|
27
|
+
end
|
28
|
+
ns
|
29
|
+
end
|
15
30
|
|
16
|
-
|
17
|
-
|
18
|
-
|
31
|
+
def atributos
|
32
|
+
[ 'trans_id',
|
33
|
+
'no_certificado_sat',
|
34
|
+
'fecha_timbrado',
|
35
|
+
'uuid',
|
36
|
+
'sello_sat',
|
37
|
+
'sello_cfd',
|
38
|
+
'fecha_comprobante',
|
39
|
+
'serie',
|
40
|
+
'folio' ]
|
41
|
+
end
|
19
42
|
|
20
|
-
|
21
|
-
|
22
|
-
|
43
|
+
def obtener_trans_id(xml,ns)
|
44
|
+
xml.xpath("//cfdi:Comprobante",ns).attribute('TransID').value rescue nil
|
45
|
+
end
|
23
46
|
|
24
|
-
|
25
|
-
|
26
|
-
|
47
|
+
def obtener_no_certificado_sat(xml, ns)
|
48
|
+
xml.xpath("//tfd:TimbreFiscalDigital", ns).attribute('noCertificadoSAT').value rescue nil
|
49
|
+
end
|
27
50
|
|
28
|
-
|
29
|
-
|
30
|
-
|
51
|
+
def obtener_uuid(xml,ns)
|
52
|
+
xml.xpath("//tfd:TimbreFiscalDigital", ns).attribute('UUID').value rescue nil
|
53
|
+
end
|
31
54
|
|
32
|
-
|
33
|
-
|
34
|
-
|
55
|
+
def obtener_fecha_timbrado(xml, ns)
|
56
|
+
xml.xpath("//tfd:TimbreFiscalDigital", ns).attribute('FechaTimbrado').value rescue nil
|
57
|
+
end
|
35
58
|
|
36
|
-
|
37
|
-
|
38
|
-
|
59
|
+
def obtener_sello_sat(xml, ns)
|
60
|
+
xml.xpath("//tfd:TimbreFiscalDigital", ns).attribute('selloSAT').value rescue nil
|
61
|
+
end
|
39
62
|
|
40
|
-
|
41
|
-
|
42
|
-
|
63
|
+
def obtener_fecha_comprobante(xml, ns)
|
64
|
+
xml.xpath("//cfdi:Comprobante", ns).attribute('fecha').value rescue nil
|
65
|
+
end
|
43
66
|
|
44
|
-
|
45
|
-
|
46
|
-
|
67
|
+
def obtener_sello_cfd(xml, ns)
|
68
|
+
xml.xpath("//tfd:TimbreFiscalDigital", ns).attribute('selloCFD').value rescue nil
|
69
|
+
end
|
47
70
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end # parse
|
71
|
+
def obtener_serie(xml, ns )
|
72
|
+
xml.xpath("//cfdi:Comprobante", ns).attribute('serie').value rescue nil
|
73
|
+
end
|
52
74
|
|
53
|
-
|
54
|
-
|
75
|
+
def obtener_folio(xml, ns)
|
76
|
+
xml.xpath("//cfdi:Comprobante", ns).attribute('folio').value rescue nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
55
80
|
|
data/lib/fm_timbrado_cfdi.rb
CHANGED
@@ -50,8 +50,27 @@ module FmTimbradoCfdi
|
|
50
50
|
respuesta = cliente.timbrar rfc, archivo, opciones
|
51
51
|
end
|
52
52
|
|
53
|
-
#
|
54
|
-
|
53
|
+
# Public: Envía CSD para que lo almacene el PAC
|
54
|
+
#
|
55
|
+
# rfc - Es el RFC del emisor
|
56
|
+
# certificado - El contenido del archivo de certificado
|
57
|
+
# llave - La llave privada del certificado
|
58
|
+
# password - Contraseña de la llave privada
|
59
|
+
#
|
60
|
+
# Regresa un objeto de tipo FmRespuestaCancelacion
|
61
|
+
def activar_cancelacion(rfc, certificado, llave, password)
|
62
|
+
respuesta = cliente.subir_certificado rfc, certificado, llave, password
|
63
|
+
end
|
64
|
+
alias :subir_certificado :activar_cancelacion
|
65
|
+
|
66
|
+
# Public: Envía una petición de cancelación de factura
|
67
|
+
#
|
68
|
+
# rfc - Es el RFC del emisor
|
69
|
+
# uuid - Es el identificador de la factura a cancelar
|
70
|
+
#
|
71
|
+
# Regresa una respuesta SOAP
|
72
|
+
def cancelar(rfc, uuid)
|
73
|
+
respuesta = cliente.cancelar(rfc, uuid)
|
55
74
|
end
|
56
75
|
|
57
76
|
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIICXQIBAAKBgQCumKgINyxzj6QCg/ThZHDYAecI/t5OKBzyt2xX5LuEwhLMLTIS
|
3
|
+
LeS52QreFCtHKfUmKSjGtpGVWJupOs6YVoPW8796bx8LfZgepBRsgKVO9XDpNerp
|
4
|
+
6i9qP6Q4+uczbVAXw8ipCgVBkDGILar1aumlyYqaijkvzbAyhFLdKtYIUwIDAQAB
|
5
|
+
AoGAdvLn35j/PsfInDIcXoZYXsGFDlrdR3AKsM2IEaVyn7K8rb/I0hvULU2SGtSw
|
6
|
+
223ZZ6M49ZCiRJY2jqfS4nRmoqYNRqxYhYt9r2caoqtyL2ZOsmFil1uuzueeYi0r
|
7
|
+
Sj6WvLwlmET+EC6acHBvvo5Y/hsZrtxCTWmOY9LFtn32+KECQQDYZ4l6VnwAc6gV
|
8
|
+
XPqedRrm7Htpam334lKKvomkSCdnYfcaUB6OZ0iGR5T43DLq0VbUk2Sj6L7LIRh/
|
9
|
+
2fAO6hzRAkEAzorPuHnoTuHhGcSU9KDgG6tuQ0YYM/kUktlwaKgTNURZB6BXXr8W
|
10
|
+
0i36pLuAJ/6wJB1GtgB7fem8g0eR3EmL4wJBAIqUQwWEvIPNjKWhlRxEAaY/aghn
|
11
|
+
j2ReGl2fBqWdTx51Lbg79lVa7qaO0GdNG44j4GbgvGH6ebO6zeWRupjScwECQQCH
|
12
|
+
30dg+0l4wx2bHvhCqaZkbXU+6li3sA75v/Mz1gW0z/6lhrSTTrALmlW9kt9u8Bwd
|
13
|
+
1eiTiGO05FOwJR/uQ6+zAkBkVwBY0+2ONgEff7gJKLNHEvG2DdQdDS+Pl1/udDyW
|
14
|
+
/GqzhGFeif2+IjROyLwsqbRD5hMynXVwc60YnMIcALNr
|
15
|
+
-----END RSA PRIVATE KEY-----
|
@@ -0,0 +1,2 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="https://t2demo.facturacionmoderna.com/timbrado/soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:requestTimbrarCFDIResponse><return xsi:type="SOAP-ENC:Struct"><xml xsi:type="xsd:string">PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGNmZGk6Q29tcHJvYmFudGUgeG1sbnM6Y2ZkaT0iaHR0cDovL3d3dy5zYXQuZ29iLm14L2NmZC8zIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3d3dy5zYXQuZ29iLm14L2NmZC8zIGh0dHA6Ly93d3cuc2F0LmdvYi5teC9zaXRpb19pbnRlcm5ldC9jZmQvMy9jZmR2MzIueHNkIiB2ZXJzaW9uPSIzLjIiIGZlY2hhPSIyMDEzLTEyLTI3VDE2OjEzOjQ2IiBmb2xpbz0iMTAxIiBzZXJpZT0iQTEiIHN1YlRvdGFsPSIxMDAuMDAiIGRlc2N1ZW50bz0iMC4wMCIgdG90YWw9IjExNi4wMCIgTW9uZWRhPSJNWE4iIFRpcG9DYW1iaW89IjAuMDAiIGNvbmRpY2lvbmVzRGVQYWdvPSJQYWdvIGVuIHVuYSBzb2xhIEV4aGliaWNpw7NuIiB0aXBvRGVDb21wcm9iYW50ZT0iaW5ncmVzbyIgbm9DZXJ0aWZpY2Fkbz0iMjAwMDEwMDAwMDAyMDAwMDAxOTIiIGNlcnRpZmljYWRvPSJNSUlFUmpDQ0F5NmdBd0lCQWdJVU1qQXdNREV3TURBd01EQXlNREF3TURBeE9USXdEUVlKS29aSWh2Y05BUUVGQlFBd2dnRmNNUm93R0FZRFZRUUREQkZCTGtNdUlESWdaR1VnY0hKMVpXSmhjekV2TUMwR0ExVUVDZ3dtVTJWeWRtbGphVzhnWkdVZ1FXUnRhVzVwYzNSeVlXTnB3N051SUZSeWFXSjFkR0Z5YVdFeE9EQTJCZ05WQkFzTUwwRmtiV2x1YVhOMGNtRmphY096YmlCa1pTQlRaV2QxY21sa1lXUWdaR1VnYkdFZ1NXNW1iM0p0WVdOcHc3TnVNU2t3SndZSktvWklodmNOQVFrQkZocGhjMmx6Ym1WMFFIQnlkV1ZpWVhNdWMyRjBMbWR2WWk1dGVERW1NQ1FHQTFVRUNRd2RRWFl1SUVocFpHRnNaMjhnTnpjc0lFTnZiQzRnUjNWbGNuSmxjbTh4RGpBTUJnTlZCQkVNQlRBMk16QXdNUXN3Q1FZRFZRUUdFd0pOV0RFWk1CY0dBMVVFQ0F3UVJHbHpkSEpwZEc4Z1JtVmtaWEpoYkRFU01CQUdBMVVFQnd3SlEyOTViMkZqdzZGdU1UUXdNZ1lKS29aSWh2Y05BUWtDRENWU1pYTndiMjV6WVdKc1pUb2dRWEpoWTJWc2FTQkhZVzVrWVhKaElFSmhkWFJwYzNSaE1CNFhEVEV5TVRBeU1qSXdORGd3TmxvWERURTJNVEF5TWpJd05EZ3dObG93Z2NBeElUQWZCZ05WQkFNVEdFVkVTVlJQVWtsQlRDQlRTVk5VUVNCVFFTQkVSU0JEVmpFaE1COEdBMVVFS1JNWVJVUkpWRTlTU1VGTUlGTkpVMVJCSUZOQklFUkZJRU5XTVNFd0h3WURWUVFLRXhoRlJFbFVUMUpKUVV3Z1UwbFRWRUVnVTBFZ1JFVWdRMVl4SlRBakJnTlZCQzBUSEVWVFNUa3lNRFF5TnpnNE5pQXZJRWhGUjFRM05qRXdNRE0wVXpJeEhqQWNCZ05WQkFVVEZTQXZJRWhGUjFRM05qRXdNRE5OUkVaU1RrNHdPVEVPTUF3R0ExVUVDeE1GUVcxcFoyRXdnWjh3RFFZSktvWklodmNOQVFFQkJRQURnWTBBTUlHSkFvR0JBSzZZcUFnM0xIT1BwQUtEOU9Ga2NOZ0I1d2orM2s0b0hQSzNiRmZrdTRUQ0Vzd3RNaEl0NUxuWkN0NFVLMGNwOVNZcEtNYTJrWlZZbTZrNnpwaFdnOWJ6djNwdkh3dDltQjZrRkd5QXBVNzFjT2sxNnVucUwyby9wRGo2NXpOdFVCZkR5S2tLQlVHUU1ZZ3RxdlZxNmFYSmlwcUtPUy9Oc0RLRVV0MHExZ2hUQWdNQkFBR2pIVEFiTUF3R0ExVWRFd0VCL3dRQ01BQXdDd1lEVlIwUEJBUURBZ2JBTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDZ0NDcFlEYm1OOG5wTFg2dkhDRUpBRi8xRzNLaHVBR1k0OHdWdDF2YTFZWFJ5NnlqK3RKWjlIWjNsOFRZN0o2bjEwWGtyYnplZE9Bckt5amRwZnFXYk5hYlpIdzZiMklsU044SHJIbGlpQUVvcjVod1RVSm5rZzZTMW5tMG1taXJJbnhDbVdvVlYrcXJFWC9YSHlsSitPaklxbC9HeVpySDlzRVBDWStMWUZmVmhPMFU3M2pLcWFqTUVlWnRXWXE1d3JvNFVoUFVobFlnd2hselVONlhOV3RpQzhvaGpFNlFKYWY4allSc0pqSHJhWkwyNTdPMW81VC8zVUxNSmhBU043UjIxMUZteUF1aVlzcThIM2J1UEUwa2wrRW1OOERVTnBURGtCOVhmMWJhNmdYWjBQUlhGMW9HVXd4dlg5RmlJNWVJYXUyUkxmeTlBZkpQY3BBWE4iIGZvcm1hRGVQYWdvPSJDb250YWRvIiBtZXRvZG9EZVBhZ289IkVmZWN0aXZvIiBOdW1DdGFQYWdvPSIwMDA5IC0gQmFuYW1leCIgTHVnYXJFeHBlZGljaW9uPSJTYW4gUGVkcm8gR2FyemEgR2FyY8OtYSIgc2VsbG89ImZXb1RaN1NUWlpCb09hbHJ4SnF0V0hDckxYYW4vMWE4RnNiMkpDNjhqc3pSZ3VKclkrdXpYVDAxd2ZWZ1ZmM2lCdFM2MVVjTStNVlk4R21UQWVPOE9OaVJMc3lMci9kYjk4aVdRWlZ0OFlha3dySVJlT1Z0UVdnS0pZR3Z5cmx6U1BVYWJsS0E5bUtaWTVVNGtNd0ZzVXZmWmdBR3N5UGRxV0JDaUV3OFU3VT0iPjxjZmRpOkVtaXNvciBub21icmU9IkNPTUVSQ0lBTElaQURPUkEgU0EgREUgQ1YiIHJmYz0iRVNJOTIwNDI3ODg2Ij48Y2ZkaTpEb21pY2lsaW9GaXNjYWwgY2FsbGU9IkNhbHphZGEgZGVsIFZhbGxlIiBub0V4dGVyaW9yPSI5MCIgbm9JbnRlcmlvcj0iaW50LTEwIiBjb2xvbmlhPSJDb2wuIERlbCBWYWxsZSIgbXVuaWNpcGlvPSJTYW4gUGVkcm8gR2FyemEgR2FyY2lhLiIgZXN0YWRvPSJOdWV2byBMZcOzbiIgcGFpcz0iTcOpeGljbyIgY29kaWdvUG9zdGFsPSI3Njg4OCIvPjxjZmRpOkV4cGVkaWRvRW4gY2FsbGU9IkNhbHphZGEgZGVsIFZhbGxlKFN1Y3Vyc2FsKSIgbm9FeHRlcmlvcj0iOTAiIG5vSW50ZXJpb3I9ImludC0xMCIgY29sb25pYT0iQ29sLiBEZWwgVmFsbGUiIG11bmljaXBpbz0iU2FuIFBlZHJvIEdhcnphIEdhcmNpYS4iIGVzdGFkbz0iTnVldm8gTGXDs24iIHBhaXM9Ik3DqXhpY28iIGNvZGlnb1Bvc3RhbD0iNzY4ODgiLz48Y2ZkaTpSZWdpbWVuRmlzY2FsIFJlZ2ltZW49IlBFUlNPTkEgTU9SQUwgUkVHSU1FTiBHRU5FUkFMIERFIExFWS4iLz48L2NmZGk6RW1pc29yPjxjZmRpOlJlY2VwdG9yIG5vbWJyZT0iUFVCTElDTyBFTiBHRU5FUkFMIiByZmM9IlhBWFgwMTAxMDEwMDAiPjxjZmRpOkRvbWljaWxpbyBjYWxsZT0iQ2FsbGUiIG5vRXh0ZXJpb3I9Ik51bSBFeHQiIG5vSW50ZXJpb3I9Ik51bSBJbnQiIGNvbG9uaWE9IkNvbG9uaWEiIG11bmljaXBpbz0iTXVuaWNpcGlvIiBlc3RhZG89IkVzdGFkbyIgcGFpcz0iUGFpcyIgY29kaWdvUG9zdGFsPSI2MDAwMCIvPjwvY2ZkaTpSZWNlcHRvcj48Y2ZkaTpDb25jZXB0b3M+PGNmZGk6Q29uY2VwdG8gbm9JZGVudGlmaWNhY2lvbj0iNzg5OTcwMSIgdW5pZGFkPSJQaWV6YSIgZGVzY3JpcGNpb249IkNhamEgZGUgQ2hvY29sYXRlcyIgY2FudGlkYWQ9IjEuMDAiIHZhbG9yVW5pdGFyaW89IjUwLjAwIiBpbXBvcnRlPSI1MC4wMCIvPjxjZmRpOkNvbmNlcHRvIHVuaWRhZD0iTm8gYXBsaWNhIiBkZXNjcmlwY2lvbj0iRW52aW8iIGNhbnRpZGFkPSIxLjAwIiB2YWxvclVuaXRhcmlvPSI1MC4wMCIgaW1wb3J0ZT0iNTAuMDAiLz48L2NmZGk6Q29uY2VwdG9zPjxjZmRpOkltcHVlc3RvcyB0b3RhbEltcHVlc3Rvc1JldGVuaWRvcz0iMjAwLjAwIiB0b3RhbEltcHVlc3Rvc1RyYXNsYWRhZG9zPSIxNi4wMCI+PGNmZGk6UmV0ZW5jaW9uZXM+PGNmZGk6UmV0ZW5jaW9uIGltcHVlc3RvPSJJU1IiIGltcG9ydGU9IjIwMC4wMCIvPjwvY2ZkaTpSZXRlbmNpb25lcz48Y2ZkaTpUcmFzbGFkb3M+PGNmZGk6VHJhc2xhZG8gaW1wdWVzdG89IklWQSIgdGFzYT0iMTYuMDAiIGltcG9ydGU9IjE2LjAwIi8+PC9jZmRpOlRyYXNsYWRvcz48L2NmZGk6SW1wdWVzdG9zPjxjZmRpOkNvbXBsZW1lbnRvPjx0ZmQ6VGltYnJlRmlzY2FsRGlnaXRhbCB4bWxuczp0ZmQ9Imh0dHA6Ly93d3cuc2F0LmdvYi5teC9UaW1icmVGaXNjYWxEaWdpdGFsIiB4c2k6c2NoZW1hTG9jYXRpb249Imh0dHA6Ly93d3cuc2F0LmdvYi5teC9UaW1icmVGaXNjYWxEaWdpdGFsIGh0dHA6Ly93d3cuc2F0LmdvYi5teC9UaW1icmVGaXNjYWxEaWdpdGFsL1RpbWJyZUZpc2NhbERpZ2l0YWwueHNkIiB2ZXJzaW9uPSIxLjAiIFVVSUQ9IjZGMzI4QjY1LTY1RDMtNDI3RS04NTYzLTZDQkFCRURBODZFQyIgRmVjaGFUaW1icmFkbz0iMjAxMy0xMi0yN1QxNjoxMzo0NiIgc2VsbG9DRkQ9ImZXb1RaN1NUWlpCb09hbHJ4SnF0V0hDckxYYW4vMWE4RnNiMkpDNjhqc3pSZ3VKclkrdXpYVDAxd2ZWZ1ZmM2lCdFM2MVVjTStNVlk4R21UQWVPOE9OaVJMc3lMci9kYjk4aVdRWlZ0OFlha3dySVJlT1Z0UVdnS0pZR3Z5cmx6U1BVYWJsS0E5bUtaWTVVNGtNd0ZzVXZmWmdBR3N5UGRxV0JDaUV3OFU3VT0iIG5vQ2VydGlmaWNhZG9TQVQ9IjIwMDAxMDAwMDAwMTAwMDA1NzYxIiBzZWxsb1NBVD0icEhyOXcwNWpwSnRGeVRUc0tURTRxYytsWW0rL3B6Y2VBOXNobXpEQXYrc0tlbU1wU3YyWjI2UFBiNlp1TFBEdUVKZGpsZ05leDJROUpmMXVxM2Z4aXdYSEZLM1JlK3paZHNYdWRjbTVjaTNNSU5VU21pNkpLVWx2OGpSajdRbGFHTFdqTWNsMFo5RjJ6RlMrQjljTDNzV1d1OWtrVEJYcjdFSHFHWmduaThJPSIvPjwvY2ZkaTpDb21wbGVtZW50bz48L2NmZGk6Q29tcHJvYmFudGU+Cg==</xml></return></ns1:requestTimbrarCFDIResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
|
@@ -0,0 +1,2 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="https://t2demo.facturacionmoderna.com/timbrado/soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:requestTimbrarCFDIResponse><return xsi:type="SOAP-ENC:Struct"></return></ns1:requestTimbrarCFDIResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
describe FmTimbradoCfdi::FmRespuesta do
|
6
|
+
context "respuesta no satisfactoria" do
|
7
|
+
let(:respuesta_cliente) do
|
8
|
+
prueba = OpenStruct.new
|
9
|
+
prueba.stub(:success?).and_return(false)
|
10
|
+
prueba.stub_chain(:soap_fault?).and_return(true)
|
11
|
+
prueba.stub_chain(:soap_fault, :to_s).and_return('Test Error')
|
12
|
+
prueba
|
13
|
+
end
|
14
|
+
let(:respuesta) { FmTimbradoCfdi::FmRespuesta.new(respuesta_cliente) }
|
15
|
+
it { expect(respuesta.valid?).to eq(false) }
|
16
|
+
it { expect(respuesta.xml?).to eq(false) }
|
17
|
+
it { expect(respuesta.pdf?).to eq(false) }
|
18
|
+
it { expect(respuesta.cbb?).to eq(false) }
|
19
|
+
it { expect(respuesta.timbre?).to eq(false) }
|
20
|
+
it { expect(respuesta.no_csd_emisor?).to eq(false) }
|
21
|
+
end
|
22
|
+
|
23
|
+
context "respuesta sin xml" do
|
24
|
+
let(:texto_respuesta){File.open('spec/fixtures/soap_response_sin_xml.txt').read}
|
25
|
+
let(:respuesta) { FmTimbradoCfdi::FmRespuesta.new(texto_respuesta) }
|
26
|
+
it { expect(respuesta.valid?).to eq(false) }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -3,8 +3,10 @@ require 'spec_helper'
|
|
3
3
|
|
4
4
|
describe FmTimbradoCfdi::FmTimbre do
|
5
5
|
context "debe crear un objeto válido" do
|
6
|
-
let(:
|
7
|
-
let(:
|
6
|
+
let(:plantilla){File.open('spec/fixtures/layout_example.txt').read}
|
7
|
+
let(:layout){ plantilla.gsub('--fecha-comprobante--', 'asignarFecha' )}
|
8
|
+
let(:respuesta){ FmTimbradoCfdi.timbra_cfdi_layout 'ESI920427886', layout }
|
9
|
+
let(:timbre) { FmTimbradoCfdi::FmTimbre.new(respuesta.xml)}
|
8
10
|
it { timbre.no_certificado_sat.should_not be_nil }
|
9
11
|
it { timbre.fecha_timbrado.should_not be_nil }
|
10
12
|
it { timbre.uuid.should_not be_nil }
|
@@ -10,7 +10,7 @@ describe FmTimbradoCfdi do
|
|
10
10
|
FmTimbradoCfdi.cliente.endpoint.should == 'https://t2demo.facturacionmoderna.com/timbrado/soap'
|
11
11
|
FmTimbradoCfdi.cliente.fm_wsdl.should == 'https://t2demo.facturacionmoderna.com/timbrado/wsdl'
|
12
12
|
end
|
13
|
-
end
|
13
|
+
end
|
14
14
|
|
15
15
|
|
16
16
|
describe ".timbra_cfdi_layout" do
|
@@ -91,29 +91,84 @@ describe FmTimbradoCfdi do
|
|
91
91
|
|
92
92
|
context 'timbrado incorrecto' do
|
93
93
|
it "no timbra el comprobante si tiene más de 72 horas de haber sido generado" do
|
94
|
-
fecha_comprobante = Time.now -
|
94
|
+
fecha_comprobante = Time.now - 120*3600
|
95
95
|
layout = File.open('spec/fixtures/layout_example.txt').read.gsub('--fecha-comprobante--', fecha_comprobante.strftime("%FT%T"))
|
96
96
|
respuesta = FmTimbradoCfdi.timbrar 'ESI920427886', layout
|
97
97
|
respuesta.should_not be_valid
|
98
98
|
end
|
99
99
|
end
|
100
|
-
end
|
101
100
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
101
|
+
context 'subir certificados' do
|
102
|
+
let(:archivo_certificado) { File.read('spec/fixtures/certificados/20001000000200000192.cer') }
|
103
|
+
let(:archivo_llave) { File.read('spec/fixtures/certificados/20001000000200000192.key') }
|
104
|
+
let(:password) { '12345678a' }
|
105
|
+
describe '.activar_cancelacion' do
|
106
|
+
context 'petición válida' do
|
107
|
+
let(:respuesta){ FmTimbradoCfdi.activar_cancelacion('ESI920427886', archivo_certificado, archivo_llave, password) }
|
108
|
+
it{ expect(respuesta.valid?).to eq(true) }
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'petición inválida' do
|
112
|
+
let(:respuesta){ FmTimbradoCfdi.activar_cancelacion('ESI920427886', archivo_llave, archivo_certificado, password) }
|
113
|
+
it{ expect(respuesta.valid?).to eq(false) }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '.subir_certificado' do
|
118
|
+
context 'petición válida' do
|
119
|
+
let(:respuesta){ FmTimbradoCfdi.subir_certificado('ESI920427886', archivo_certificado, archivo_llave, password) }
|
120
|
+
it{ expect(respuesta.valid?).to eq(true) }
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'petición inválida' do
|
124
|
+
let(:respuesta){ FmTimbradoCfdi.subir_certificado('ESI920427886', archivo_llave, archivo_certificado, password) }
|
125
|
+
it{ expect(respuesta.valid?).to eq(false) }
|
126
|
+
end
|
110
127
|
end
|
111
128
|
|
112
|
-
FmTimbradoCfdi.cliente.user_id.should == 'mi_usuario'
|
113
|
-
FmTimbradoCfdi.cliente.user_pass.should == 'secret'
|
114
|
-
FmTimbradoCfdi.cliente.namespace.should == 'http://logicalbricks.com/soap'
|
115
|
-
FmTimbradoCfdi.cliente.endpoint.should == 'http://logicalbricks.com/endpoint'
|
116
|
-
FmTimbradoCfdi.cliente.fm_wsdl.should == 'http://logicalbricks.com/wsdl'
|
117
129
|
end
|
130
|
+
|
131
|
+
describe ".cancelar" do
|
132
|
+
context "petición inválida" do
|
133
|
+
let(:respuesta){ FmTimbradoCfdi.cancelar('ESI920427886', 'asdasasdsa') }
|
134
|
+
it{ expect(respuesta.valid?).to eq(false) }
|
135
|
+
end
|
136
|
+
|
137
|
+
context "formato válido" do
|
138
|
+
let(:respuesta){ FmTimbradoCfdi.cancelar('ESI920427886', '00000000-0000-0000-0000-00000000000000') }
|
139
|
+
it{ expect(respuesta.valid?).to eq(false) }
|
140
|
+
end
|
141
|
+
|
142
|
+
context "peticion válida" do
|
143
|
+
let(:uuid) do
|
144
|
+
plantilla = File.open('spec/fixtures/layout_example.txt').read
|
145
|
+
layout = plantilla.gsub('--fecha-comprobante--', 'asignarFecha' )
|
146
|
+
respuesta = FmTimbradoCfdi.timbrar 'ESI920427886', layout
|
147
|
+
respuesta.timbre.uuid
|
148
|
+
end
|
149
|
+
let(:respuesta){ FmTimbradoCfdi.cancelar('ESI920427886', uuid) }
|
150
|
+
it{ expect(respuesta.valid?).to eq(true) }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe ".configurar" do
|
155
|
+
it "cambia los valores de conexión por los proporcionados" do
|
156
|
+
FmTimbradoCfdi.configurar do |config|
|
157
|
+
config.user_id = "mi_usuario"
|
158
|
+
config.user_pass = "secret"
|
159
|
+
config.namespace = "http://logicalbricks.com/soap"
|
160
|
+
config.endpoint = "http://logicalbricks.com/endpoint"
|
161
|
+
config.fm_wsdl = "http://logicalbricks.com/wsdl"
|
162
|
+
end
|
163
|
+
|
164
|
+
FmTimbradoCfdi.cliente.user_id.should == 'mi_usuario'
|
165
|
+
FmTimbradoCfdi.cliente.user_pass.should == 'secret'
|
166
|
+
FmTimbradoCfdi.cliente.namespace.should == 'http://logicalbricks.com/soap'
|
167
|
+
FmTimbradoCfdi.cliente.endpoint.should == 'http://logicalbricks.com/endpoint'
|
168
|
+
FmTimbradoCfdi.cliente.fm_wsdl.should == 'http://logicalbricks.com/wsdl'
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
118
172
|
end
|
119
173
|
|
174
|
+
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fm_timbrado_cfdi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos García
|
8
8
|
- Hermes Ojeda Ruiz
|
9
|
+
- Crisóforo Gaspar Hernández @mitogh
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2014-01-02 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: nokogiri
|
@@ -64,6 +65,7 @@ files:
|
|
64
65
|
- .gitignore
|
65
66
|
- .ruby-gemset
|
66
67
|
- .ruby-version
|
68
|
+
- .travis.yml
|
67
69
|
- Gemfile
|
68
70
|
- LICENSE.txt
|
69
71
|
- README.md
|
@@ -72,13 +74,20 @@ files:
|
|
72
74
|
- lib/fm_timbrado_cfdi.rb
|
73
75
|
- lib/fm_timbrado_cfdi/fm_cliente.rb
|
74
76
|
- lib/fm_timbrado_cfdi/fm_respuesta.rb
|
77
|
+
- lib/fm_timbrado_cfdi/fm_respuesta_cancelacion.rb
|
75
78
|
- lib/fm_timbrado_cfdi/fm_timbre.rb
|
76
79
|
- lib/fm_timbrado_cfdi/version.rb
|
80
|
+
- spec/fixtures/certificados/20001000000200000192.cer
|
81
|
+
- spec/fixtures/certificados/20001000000200000192.key
|
82
|
+
- spec/fixtures/certificados/20001000000200000192.key.pem
|
77
83
|
- spec/fixtures/constructora_layout_example.txt
|
78
84
|
- spec/fixtures/layout_example.txt
|
79
85
|
- spec/fixtures/layout_example.txt~
|
80
86
|
- spec/fixtures/pipes.txt
|
87
|
+
- spec/fixtures/soap_response.txt
|
88
|
+
- spec/fixtures/soap_response_sin_xml.txt
|
81
89
|
- spec/fixtures/timbre_example.txt
|
90
|
+
- spec/fm_timbrado_cfdi/fm_respuesta_spec.rb
|
82
91
|
- spec/fm_timbrado_cfdi/fm_timbre_spec.rb
|
83
92
|
- spec/fm_timbrado_cfdi_spec.rb
|
84
93
|
- spec/spec_helper.rb
|
@@ -96,9 +105,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
105
|
version: '0'
|
97
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
107
|
requirements:
|
99
|
-
- - '
|
108
|
+
- - '>='
|
100
109
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
110
|
+
version: '0'
|
102
111
|
requirements: []
|
103
112
|
rubyforge_project:
|
104
113
|
rubygems_version: 2.1.11
|
@@ -107,11 +116,17 @@ specification_version: 4
|
|
107
116
|
summary: Implementación en ruby de la conexión con el servicio de timbrado de cfdi
|
108
117
|
con el PAC Facturación Moderna
|
109
118
|
test_files:
|
119
|
+
- spec/fixtures/certificados/20001000000200000192.cer
|
120
|
+
- spec/fixtures/certificados/20001000000200000192.key
|
121
|
+
- spec/fixtures/certificados/20001000000200000192.key.pem
|
110
122
|
- spec/fixtures/constructora_layout_example.txt
|
111
123
|
- spec/fixtures/layout_example.txt
|
112
124
|
- spec/fixtures/layout_example.txt~
|
113
125
|
- spec/fixtures/pipes.txt
|
126
|
+
- spec/fixtures/soap_response.txt
|
127
|
+
- spec/fixtures/soap_response_sin_xml.txt
|
114
128
|
- spec/fixtures/timbre_example.txt
|
129
|
+
- spec/fm_timbrado_cfdi/fm_respuesta_spec.rb
|
115
130
|
- spec/fm_timbrado_cfdi/fm_timbre_spec.rb
|
116
131
|
- spec/fm_timbrado_cfdi_spec.rb
|
117
132
|
- spec/spec_helper.rb
|