fm_timbrado_cfdi 0.0.1.alpha → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/LogicalBricks/fm_timbrado_cfdi.png?branch=master)](https://travis-ci.org/LogicalBricks/fm_timbrado_cfdi)
|
3
|
+
[![Code Climate](https://codeclimate.com/github/LogicalBricks/fm_timbrado_cfdi.png)](https://codeclimate.com/github/LogicalBricks/fm_timbrado_cfdi)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/LogicalBricks/fm_timbrado_cfdi/badge.png)](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
|