fm_timbrado_cfdi 0.0.1.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +74 -0
- data/Rakefile +6 -0
- data/fm_timbrado_cfdi.gemspec +24 -0
- data/lib/fm_timbrado_cfdi/fm_cliente.rb +59 -0
- data/lib/fm_timbrado_cfdi/fm_respuesta.rb +100 -0
- data/lib/fm_timbrado_cfdi/fm_timbre.rb +55 -0
- data/lib/fm_timbrado_cfdi/version.rb +3 -0
- data/lib/fm_timbrado_cfdi.rb +57 -0
- data/spec/fixtures/constructora_layout_example.txt +108 -0
- data/spec/fixtures/layout_example.txt +13 -0
- data/spec/fixtures/layout_example.txt~ +13 -0
- data/spec/fixtures/pipes.txt +13 -0
- data/spec/fixtures/timbre_example.txt +9 -0
- data/spec/fm_timbrado_cfdi/fm_timbre_spec.rb +14 -0
- data/spec/fm_timbrado_cfdi_spec.rb +119 -0
- data/spec/spec_helper.rb +2 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3f2b840f296b634da2bbba4dde5e1fc075cb9c70
|
4
|
+
data.tar.gz: 5af90d177466131f1d1085a0bd2961f5febc5fc7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2ab5cbf56f9372c4789b95275809a45291fea49926d3e43d32ecca900b513428f92f5800b1c7999b302d5abe5a4bbbd6b83de0b7812905d4dd5e57ce77b586a9
|
7
|
+
data.tar.gz: abd639e1e09925c9f75bfe37e405c012f0fa65d041c838cb26097d24900f85884bbb9095c062c95140d69e627770c873edb62031782e059b780a65144f04843d
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
fm_timbrado_cfdi
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0-p353
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Carlos García
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# FmTimbradoCfdi
|
2
|
+
|
3
|
+
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
|
+
|
5
|
+
No incluye ninguna funcionalidad de sellado.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Agrega esto al Gemfile de tu aplicación:
|
10
|
+
|
11
|
+
gem 'fm_timbrado_cfdi'
|
12
|
+
|
13
|
+
Y ejecuta:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
o instala de forma independiente:
|
18
|
+
|
19
|
+
$ gem install fm_timbrado_cfdi
|
20
|
+
|
21
|
+
## Uso
|
22
|
+
|
23
|
+
Para usar la gema es necesario realizar la configuración con los valores de conexión:
|
24
|
+
|
25
|
+
```
|
26
|
+
FmTimbradoCfdi.configurar do |config|
|
27
|
+
config.user_id = 'user_id'
|
28
|
+
config.user_pass = 'password'
|
29
|
+
config.namespace = 'http://serviciondetimrado...'
|
30
|
+
config.endpoint = 'http://serviciondetimrado...'
|
31
|
+
config.fm_wsdl = 'http://serviciondetimrado...'
|
32
|
+
config.log = 'path_to_log'
|
33
|
+
config.ssl_verify_mode = true
|
34
|
+
end # configurar
|
35
|
+
```
|
36
|
+
|
37
|
+
Y realizar la petición de timbrado:
|
38
|
+
|
39
|
+
```
|
40
|
+
respuesta = FmTimbradoCfdi.timbra_cfdi_layout rfc, 'layout_file', false
|
41
|
+
=> # Petición sin generación del CBB
|
42
|
+
respuesta = FmTimbradoCfdi.timbra_cfdi_layout rfc, 'layout_file', true
|
43
|
+
=> # Petición con generación del CBB
|
44
|
+
```
|
45
|
+
|
46
|
+
Si cuentas con el XML sellado puedes hacer lo siguiente:
|
47
|
+
|
48
|
+
```
|
49
|
+
respuesta = FmTimbradoCfdi.timbra_cfdi_xml 'archivo_xml', false
|
50
|
+
=> # Petición sin generación del CBB
|
51
|
+
respuesta = FmTimbradoCfdi.timbra_cfdi_xml 'archivo_xml', true
|
52
|
+
=> # Petición con generación del CBB
|
53
|
+
```
|
54
|
+
|
55
|
+
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
|
+
|
57
|
+
```
|
58
|
+
respuesta = FmTimbradoCfdi.timbrar rfc_emisor, 'archivo_xml_o_layout', 'generarCBB' => false, 'generarPDF' => true, 'generarTXT' => false
|
59
|
+
=> # Generar la respuesta con formato PDF, pero sin formato CBB ni TXT
|
60
|
+
```
|
61
|
+
|
62
|
+
|
63
|
+
El archivo de layout y el XML son string.
|
64
|
+
|
65
|
+
|
66
|
+
## Contribuciones
|
67
|
+
|
68
|
+
1. 'Forkea' el repositorio
|
69
|
+
2. Crea una rama con tu funcionalidad (`git checkout -b my-new-feature`)
|
70
|
+
3. Envía tus cambios (`git commit -am 'Add some feature'`)
|
71
|
+
4. 'Pushea' a la rama (`git push origin my-new-feature`)
|
72
|
+
5. Crea un 'Pull request'
|
73
|
+
|
74
|
+
Esta gema fue creada por LogicalBricks Solutions.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fm_timbrado_cfdi/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "fm_timbrado_cfdi"
|
8
|
+
gem.version = FmTimbradoCfdi::VERSION
|
9
|
+
gem.authors = ["Carlos García", "Hermes Ojeda Ruiz"]
|
10
|
+
gem.email = ["hermes.ojeda@logicalbricks.com"]
|
11
|
+
gem.homepage = "https://github.com/LogicalBricks/fm_timbrado_cfdi"
|
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}
|
13
|
+
gem.description = "Implementación en Ruby de la Conexión con el Servicio de Timbrado de CFDI con el PAC: Facturación Moderna"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency "nokogiri"
|
21
|
+
gem.add_dependency "savon"
|
22
|
+
|
23
|
+
gem.add_development_dependency "rspec"
|
24
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'savon'
|
2
|
+
require 'fm_timbrado_cfdi/fm_respuesta'
|
3
|
+
|
4
|
+
module FmTimbradoCfdi
|
5
|
+
class FmCliente
|
6
|
+
#attrs
|
7
|
+
attr_accessor :user_id, :user_pass, :namespace, :fm_wsdl, :endpoint, :ssl_verify_mode, :log, :log_level
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
# La configuracion por default es la del ambiente de pruebas de FM
|
11
|
+
# Datos de acceso al webservice
|
12
|
+
@user_id = 'UsuarioPruebasWS'
|
13
|
+
@user_pass = 'b9ec2afa3361a59af4b4d102d3f704eabdf097d4'
|
14
|
+
# Datos del webservise de prueba
|
15
|
+
@namespace = "https://t2demo.facturacionmoderna.com/timbrado/soap"
|
16
|
+
@endpoint = "https://t2demo.facturacionmoderna.com/timbrado/soap"
|
17
|
+
@fm_wsdl = "https://t2demo.facturacionmoderna.com/timbrado/wsdl"
|
18
|
+
|
19
|
+
#Opciones adicionales
|
20
|
+
@log = false
|
21
|
+
@log_level = :error
|
22
|
+
@ssl_verify_mode = :none
|
23
|
+
end
|
24
|
+
|
25
|
+
def timbrar(rfc, documento, opciones={})
|
26
|
+
text_to_cfdi = Base64::encode64( documento )
|
27
|
+
# Realizamos la peticion
|
28
|
+
configurar_cliente
|
29
|
+
response = @client.call(:request_timbrar_cfdi,
|
30
|
+
message:
|
31
|
+
{ "param0" => {
|
32
|
+
"UserPass" => user_pass,
|
33
|
+
"UserID" => user_id,
|
34
|
+
"emisorRFC" => rfc,
|
35
|
+
"text2CFDI" => text_to_cfdi,
|
36
|
+
}.merge(opciones)
|
37
|
+
}
|
38
|
+
)
|
39
|
+
FmRespuesta.new(response)
|
40
|
+
end
|
41
|
+
|
42
|
+
def peticion_timbrar rfc_emisor, documento, generar_cbb
|
43
|
+
timbrar(rfc_emisor, documento, 'generarCBB' => generar_cbb)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def configurar_cliente
|
48
|
+
@client = Savon.client(
|
49
|
+
ssl_verify_mode: ssl_verify_mode,
|
50
|
+
wsdl: fm_wsdl,
|
51
|
+
endpoint: endpoint,
|
52
|
+
raise_errors: false,
|
53
|
+
log_level: log_level,
|
54
|
+
log: log
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
end #class
|
59
|
+
end#module
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'savon'
|
4
|
+
require 'fm_timbrado_cfdi/fm_timbre'
|
5
|
+
|
6
|
+
module FmTimbradoCfdi
|
7
|
+
class FmRespuesta
|
8
|
+
attr_reader :errors, :pdf, :xml, :cbb, :timbre, :no_csd_emisor
|
9
|
+
def initialize(savon_response)
|
10
|
+
parse(savon_response)
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse (savon_response)
|
14
|
+
@errors = []
|
15
|
+
begin
|
16
|
+
if savon_response.success? then
|
17
|
+
@doc = Nokogiri::XML(savon_response.to_xml)
|
18
|
+
@xml = obtener_xml(@doc)
|
19
|
+
@no_csd_emisor = obtener_no_csd_emisor(@xml) if @xml
|
20
|
+
@timbre = obtener_timbre(@doc)
|
21
|
+
@pdf = obtener_pdf(@doc)
|
22
|
+
@cbb = obtener_cbb(@doc)
|
23
|
+
else
|
24
|
+
@errors << savon_response.soap_fault.to_s if savon_response.soap_fault.present?
|
25
|
+
@doc = @xml = @no_csd_emisor = @timbre = @pdf = @cbb = nil
|
26
|
+
end
|
27
|
+
rescue Exception => e
|
28
|
+
@errors << "No se ha podido realizar el parseo de la respuesta. #{e.message}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def valid?
|
33
|
+
@errors.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
def xml?
|
37
|
+
@xml
|
38
|
+
end
|
39
|
+
alias :xml_present? :xml?
|
40
|
+
|
41
|
+
def cbb?
|
42
|
+
@cbb
|
43
|
+
end
|
44
|
+
alias :cbb_present? :cbb?
|
45
|
+
|
46
|
+
def pdf?
|
47
|
+
@pdf
|
48
|
+
end
|
49
|
+
alias :pdf_present? :pdf?
|
50
|
+
|
51
|
+
def timbre?
|
52
|
+
@timbre
|
53
|
+
end
|
54
|
+
alias :timbre_present? :timbre?
|
55
|
+
|
56
|
+
def no_csd_emisor?
|
57
|
+
@no_csd_emisor
|
58
|
+
end
|
59
|
+
alias :no_csd_emisor_present? :no_csd_emisor?
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def obtener_xml(doc)
|
64
|
+
unless doc.xpath("//xml").empty? then
|
65
|
+
Base64::decode64 doc.xpath("//xml")[0].content
|
66
|
+
else
|
67
|
+
@errors << "No se ha encontrado el nodo xml"
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def obtener_timbre(doc)
|
73
|
+
unless doc.xpath("//txt").empty?
|
74
|
+
FmTimbre.new Base64::decode64( doc.xpath("//txt")[0].content )
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def obtener_pdf(doc)
|
79
|
+
unless doc.xpath("//pdf").empty?
|
80
|
+
Base64::decode64 doc.xpath("//pdf")[0].content
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def obtener_cbb(doc)
|
85
|
+
unless doc.xpath("//png").empty?
|
86
|
+
Base64::decode64 doc.xpath("//png")[0].content
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def obtener_no_csd_emisor(xml)
|
91
|
+
begin
|
92
|
+
factura_xml = Nokogiri::XML(xml)
|
93
|
+
factura_xml.xpath("//cfdi:Comprobante").attribute('noCertificado').value
|
94
|
+
rescue Exception => e
|
95
|
+
@errors << "No se ha podido obtener el CSD del emisor"
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module FmTimbradoCfdi
|
5
|
+
class FmTimbre
|
6
|
+
attr_reader :no_certificado_sat, :fecha_timbrado, :uuid, :sello_sat, :sello_cfd, :fecha_comprobante, :serie, :folio, :trans_id
|
7
|
+
|
8
|
+
def initialize ( nodo_timbre )
|
9
|
+
parse( nodo_timbre )
|
10
|
+
end # initialize
|
11
|
+
|
12
|
+
def parse ( nodo_timbre )
|
13
|
+
valores = nodo_timbre.split("\n")
|
14
|
+
return unless valores.size == 9
|
15
|
+
|
16
|
+
# TransID
|
17
|
+
temp_value = valores[0].chomp.split('|')
|
18
|
+
@trans_id = temp_value[1] if temp_value.size > 1
|
19
|
+
|
20
|
+
# noCertificadoSAT
|
21
|
+
temp_value = valores[1].chomp.split('|')
|
22
|
+
@no_certificado_sat = temp_value[1] if temp_value.size > 1
|
23
|
+
|
24
|
+
# FechaTimbrado
|
25
|
+
temp_value = valores[2].chomp.split('|')
|
26
|
+
@fecha_timbrado = temp_value[1] if temp_value.size > 1
|
27
|
+
|
28
|
+
# uuid
|
29
|
+
temp_value = valores[3].chomp.split('|')
|
30
|
+
@uuid = temp_value[1] if temp_value.size > 1
|
31
|
+
|
32
|
+
# selloSAT
|
33
|
+
temp_value = valores[4].chomp.split('|')
|
34
|
+
@sello_sat = temp_value[1] if temp_value.size > 1
|
35
|
+
|
36
|
+
# selloCFD
|
37
|
+
temp_value = valores[5].chomp.split('|')
|
38
|
+
@sello_cfd = temp_value[1] if temp_value.size > 1
|
39
|
+
|
40
|
+
# Fecha
|
41
|
+
temp_value = valores[6].chomp.split('|')
|
42
|
+
@fecha_comprobante = temp_value[1] if temp_value.size > 1
|
43
|
+
|
44
|
+
# Serie
|
45
|
+
temp_value = valores[7].chomp.split('|')
|
46
|
+
@serie = temp_value[1] if temp_value.size > 1
|
47
|
+
|
48
|
+
# folio
|
49
|
+
temp_value = valores[8].chomp.split('|')
|
50
|
+
@folio = temp_value[1] if temp_value.size > 1
|
51
|
+
end # parse
|
52
|
+
|
53
|
+
end # class
|
54
|
+
end # module
|
55
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "fm_timbrado_cfdi/version"
|
2
|
+
require "fm_timbrado_cfdi/fm_cliente"
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'base64'
|
5
|
+
|
6
|
+
module FmTimbradoCfdi
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def configurar
|
10
|
+
yield cliente
|
11
|
+
end
|
12
|
+
|
13
|
+
def cliente
|
14
|
+
@cliente ||= FmCliente.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# Public: Envía un archivo al PAC para ser timbrado en formato xml
|
18
|
+
#
|
19
|
+
# xml - Es el archivo XML sellado como un string
|
20
|
+
# generar_cbb - Es una bandera que indica si debe generarse el código cbb, por default es false
|
21
|
+
#
|
22
|
+
# Regresa un objeto tipo FMRespuesta que contiene el xml certificado, el timbre y la representación en pdf o el cbb en png
|
23
|
+
def timbra_cfdi_xml (xml, generar_cbb = false)
|
24
|
+
factura_xml = Nokogiri::XML(xml)
|
25
|
+
#procesar rfc del emisor
|
26
|
+
emisor = factura_xml.xpath("//cfdi:Emisor")
|
27
|
+
rfc = emisor[0]['rfc']
|
28
|
+
respuesta = cliente.timbrar rfc, factura_xml.to_s, 'generarCBB' => generar_cbb
|
29
|
+
end
|
30
|
+
|
31
|
+
# Public: Envía un archivo al PAC para ser timbrado en formato layout
|
32
|
+
#
|
33
|
+
# rfc - Es el RFC del emisor
|
34
|
+
# layout - Es el archivo layout a ser timbrado como un string
|
35
|
+
# generar_cbb - Es una bandera que indica si debe generarse el código cbb, por default es false
|
36
|
+
#
|
37
|
+
# Regresa un objeto tipo FMRespuesta que contiene el xml certificado, el timbre y la representación en pdf o el cbb en png
|
38
|
+
def timbra_cfdi_layout (rfc, layout, generar_cbb = false)
|
39
|
+
respuesta = cliente.timbrar rfc, layout, 'generarCBB' => generar_cbb
|
40
|
+
end
|
41
|
+
|
42
|
+
# Public: Envía un archivo al PAC para ser timbrado tanto en formato layout como en formato XML
|
43
|
+
#
|
44
|
+
# rfc - Es el RFC del emisor
|
45
|
+
# archivo - Es el archivo a ser timbrado como un string
|
46
|
+
# opciones - Es un hash de opciones que deben coincidir con los parámetros recibidos por Facturación Moderna para el timbrado
|
47
|
+
#
|
48
|
+
# Regresa un objeto tipo FMRespuesta que contiene el xml certificado, el timbre y la representación en pdf o el cbb en png
|
49
|
+
def timbrar (rfc, archivo, opciones= {})
|
50
|
+
respuesta = cliente.timbrar rfc, archivo, opciones
|
51
|
+
end
|
52
|
+
|
53
|
+
#no implementado todavía
|
54
|
+
def cancela_cfdi (uuid)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
[Encabezado]
|
2
|
+
|
3
|
+
serie|
|
4
|
+
fecha|--fecha-comprobante--
|
5
|
+
folio|
|
6
|
+
tipoDeComprobante|egreso
|
7
|
+
formaDePago|PAGO EN UNA SOLA EXHIBICIÓN
|
8
|
+
metodoDePago|Transferencía Electrónica
|
9
|
+
condicionesDePago|Contado
|
10
|
+
NumCtaPago|0098-HSBC
|
11
|
+
subTotal|862068.97
|
12
|
+
descuento|0.00
|
13
|
+
total|735344.84
|
14
|
+
Moneda|MXN
|
15
|
+
noCertificado|
|
16
|
+
LugarExpedicion|Nuevo León, México.
|
17
|
+
|
18
|
+
[Datos Adicionales]
|
19
|
+
|
20
|
+
tipoDocumento|Factura
|
21
|
+
numeropedido|
|
22
|
+
observaciones|Efectos Fiscales al Pago
|
23
|
+
|
24
|
+
[Emisor]
|
25
|
+
|
26
|
+
rfc|ESI920427886
|
27
|
+
nombre|EMPRESA DE MUESTRA S.A de C.V.
|
28
|
+
RegimenFiscal|REGIMEN GENERAL DE LEY
|
29
|
+
|
30
|
+
[DomicilioFiscal]
|
31
|
+
|
32
|
+
calle|Calle
|
33
|
+
noExterior|Número Ext.
|
34
|
+
noInterior|Número Int.
|
35
|
+
colonia|Colonia
|
36
|
+
localidad|Localidad
|
37
|
+
municipio|Municipio
|
38
|
+
estado|NUEVO LEON
|
39
|
+
pais|México
|
40
|
+
codigoPostal|66260
|
41
|
+
|
42
|
+
[ExpedidoEn]
|
43
|
+
calle|Calle sucursal
|
44
|
+
noExterior|
|
45
|
+
noInterior|
|
46
|
+
colonia|
|
47
|
+
localidad|
|
48
|
+
municipio|Nuevo León
|
49
|
+
estado|Nuevo León
|
50
|
+
pais|México
|
51
|
+
codigoPostal|77000
|
52
|
+
|
53
|
+
[Receptor]
|
54
|
+
rfc|GHR090615KH8
|
55
|
+
nombre|GOBIERNO DEL EDO DE OAXACA
|
56
|
+
|
57
|
+
[Domicilio]
|
58
|
+
calle|AVE BATALLON DE SAN PATRICIO
|
59
|
+
noExterior|1000
|
60
|
+
noInterior|1000
|
61
|
+
colonia|RESIDENCIAL SAN AGUSTIN
|
62
|
+
localidad|SAN PEDRO GARZA GARCIA
|
63
|
+
municipio|
|
64
|
+
estado|NUEVO LEON
|
65
|
+
pais|MEXICO
|
66
|
+
codigoPostal|66260
|
67
|
+
|
68
|
+
[DatosAdicionales]
|
69
|
+
|
70
|
+
noCliente|09871
|
71
|
+
email|edgar.duran@facturacionmoderna.com
|
72
|
+
|
73
|
+
|
74
|
+
[Concepto]
|
75
|
+
|
76
|
+
cantidad|1
|
77
|
+
unidad|No aplica
|
78
|
+
noIdentificacion|
|
79
|
+
descripcion|RECIBI DE LA TESORERIA MUNICIPAL DEL H. AYUNTAMIENTO DE SANTA MARIA OZOLOTEPEC, MIAHUATLAN, OAXACA, CON CARGO A LOS RECURSOS DEL RAMO GENERAL 33, ESPECIFICAMENTE DEL FONDO III.- FONDO PARA LA INFRAESTRUCTURA SOCIAL MUNICIPAL, EJERCICIO PRESUPUESTAL 2012, LA CANTIDAD DE $ 551,000.00 (QUINIENTOS CINCUENTA Y UN MIL PESOS 00/100 M.N.) POR CONCEPTO DEL PAGO DE LA ESTIMACION NUMERO UNO, RELATIVO A LA OBRA: CONSTRUCCION DEL SISTEMA DE AGUA POTABLE 2a. ETAPA, UBICADA EN LA LOCALIDAD DE SAN PABLO, MUNICIPIO DE SANTA MARIA OZOLOTEPEC, DISTRITO DE MIAHUATLAN, REGION DE LA SIERRA SUR, ESTADO DE OAXACA, SEGUN CONTRATO DE OBRA PUBLICA A PRECIOS UNITARIOS Y TIEMPO DETERMINADO No. MSM/AD/FISM/424-013/2012 DE FECHA: 01 DE MARZO DEL DOS MIL DOCE Y SEGUN OFICIO DE NOTIFICACION DE APROBACION Y AUTORIZACION DE OBRA NUM. R33/FISM/424/013/20012 DE FECHA: DIECINUEVE DE FEBRERO DEL DOS MIL DOCE, CORRESPONDIENTE A LA CUENTA AGUA POTABLE, TENIENDO UN PERIODO DE EJECUCION DE ACUERDO AL CONTRATO DEL 02 DE MARZO DEL 2012 AL 30 DE ABRIL DEL 2012, CON PERIODO DE EJECUCION DE LOS TRABAJOS DE LA PRESENTE ESTIMACION DEL 02 DE MARZO DEL 2012 AL 31 DE MARZO DEL 2012.
|
80
|
+
valorUnitario|862068.97
|
81
|
+
importe|862068.97
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
[ImpuestoTrasladado]
|
86
|
+
|
87
|
+
impuesto|IVA
|
88
|
+
importe|137931.04
|
89
|
+
tasa|16.00
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
[RetencionLocal]
|
94
|
+
ImpLocRetenido|Amortización de anticipo
|
95
|
+
TasadeRetencion|30
|
96
|
+
Importe|258620.69
|
97
|
+
|
98
|
+
[RetencionLocal]
|
99
|
+
ImpLocRetenido|Inspección y Vigilancia
|
100
|
+
TasadeRetencion|0.5
|
101
|
+
Importe|4310.34
|
102
|
+
|
103
|
+
[RetencionLocal]
|
104
|
+
ImpLocRetenido|Retención 2 al millar
|
105
|
+
TasadeRetencion|0.2
|
106
|
+
Importe|1724.14
|
107
|
+
|
108
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
A1|101|--fecha-comprobante--|San Pedro Garza García|ingreso|Contado|Efectivo|Pago en una sola Exhibición|0009 - Banamex|100.00|0.00|116.00|MXN|0.00||
|
2
|
+
ESI920427886|COMERCIALIZADORA SA DE CV|PERSONA MORAL REGIMEN GENERAL DE LEY.
|
3
|
+
Calzada del Valle|90|int-10|Col. Del Valle||San Pedro Garza Garcia.|Nuevo León|México|76888
|
4
|
+
Calzada del Valle(Sucursal)|90|int-10|Col. Del Valle||San Pedro Garza Garcia.|Nuevo León|México|76888
|
5
|
+
XAXX010101000|PUBLICO EN GENERAL
|
6
|
+
Calle|Num Ext|Num Int|Colonia||Municipio|Estado|Pais|60000
|
7
|
+
CONCEPTOS|2
|
8
|
+
7899701|Pieza|Caja de Chocolates|1.00|50.00|50.00
|
9
|
+
|No aplica|Envio|1.00|50.00|50.00
|
10
|
+
IMPUESTOS_TRASLADADOS|1
|
11
|
+
IVA|16.00|16.00
|
12
|
+
IMPUESTOS_RETENIDOS|1
|
13
|
+
ISR|200.00
|
@@ -0,0 +1,13 @@
|
|
1
|
+
AX|101|2012-10-26T09:12:00|San Pedro Garza García|ingreso|Contado|Efectivo|Pago en una sola Exhibición|0009 - Banamex|100.00|0.00|116.00|MXN|0.00|20001000000100001703|
|
2
|
+
ESI920427886|COMERCIALIZADORA SA DE CV|PERSONA MORAL REGIMEN GENERAL DE LEY.
|
3
|
+
Calzada del Valle|90|int-10|Col. Del Valle||San Pedro Garza Garcia.|Nuevo León|México|76888
|
4
|
+
Calzada del Valle(Sucursal)|90|int-10|Col. Del Valle||San Pedro Garza Garcia.|Nuevo León|México|76888
|
5
|
+
XAXX010101000|PUBLICO EN GENERAL
|
6
|
+
Calle|Num Ext|Num Int|Colonia||Municipio|Estado|Pais|60000
|
7
|
+
CONCEPTOS|2
|
8
|
+
7899701|Pieza|Caja de Chocolates|1.00|50.00|50.00
|
9
|
+
|No aplica|Envio|1.00|50.00|50.00
|
10
|
+
IMPUESTOS_TRASLADADOS|1
|
11
|
+
IVA|16.00|16.00
|
12
|
+
IMPUESTOS_RETENIDOS|1
|
13
|
+
ISR|200.00
|
@@ -0,0 +1,13 @@
|
|
1
|
+
AX|101|2012-12-18T15:32:32|San Pedro Garza García|ingreso|Contado|Efectivo|Pago en una sola Exhibición|0009 - Banamex|100.00|0.00|116.00|MXN|0.00|20001000000100001703|
|
2
|
+
ESI920427886|COMERCIALIZADORA SA DE CV|PERSONA MORAL REGIMEN GENERAL DE LEY.
|
3
|
+
Calzada del Valle|90|int-10|Col. Del Valle||San Pedro Garza Garcia.|Nuevo León|México|76888
|
4
|
+
Calzada del Valle(Sucursal)|90|int-10|Col. Del Valle||San Pedro Garza Garcia.|Nuevo León|México|76888
|
5
|
+
XAXX010101000|PUBLICO EN GENERAL
|
6
|
+
Calle|Num Ext|Num Int|Colonia||Municipio|Estado|Pais|60000
|
7
|
+
CONCEPTOS|2
|
8
|
+
7899701|Pieza|Caja de Chocolates|1.00|50.00|50.00
|
9
|
+
|No aplica|Envio|1.00|50.00|50.00
|
10
|
+
IMPUESTOS_TRASLADADOS|1
|
11
|
+
IVA|16.00|16.00
|
12
|
+
IMPUESTOS_RETENIDOS|1
|
13
|
+
ISR|200.00
|
@@ -0,0 +1,9 @@
|
|
1
|
+
TransID|
|
2
|
+
noCertificadoSAT|00001000000200365214
|
3
|
+
FechaTimbrado|2013-01-02T20:17:00
|
4
|
+
UUID|8E70642F-4E77-4AE8-A289-6434AE7AF327
|
5
|
+
selloSAT|wz9vUIm0qYSM8SfVUdj0RDTychEuZOw00hKsYI2JiU1ulD0zKEB6WyMnlfYWJjZ+xBHESYZhZ26DXiNUoOilEsQnmf6mE3SELlBLiOvuoNzvJAWxx8JXdpfqG2Vcwl4r57O+4Sc26GqA8OIa7pfONmlTgmBNYwovIMm8t7jsmFY=
|
6
|
+
selloCFD|CbIFn71OXDw0htZ2Z2Pn90hHEMKciPNbfvStyACY7v5fr/cEw+QZBRm0kzQe+mkaDmgQsKUD6ol3LtV6VAfSqeim/nom98SvYxENgkrK9I7OgCKMobuNXyR+N10w1nJY4uDZXkBLiUbDsMiO3jcCAgm+/Hn7pN5TM9X2EsPDwMQ=
|
7
|
+
Fecha|2013-01-02T20:12:20
|
8
|
+
Serie|
|
9
|
+
Folio|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe FmTimbradoCfdi::FmTimbre do
|
5
|
+
context "debe crear un objeto válido" do
|
6
|
+
let(:timbre_as_text) { File.open('spec/fixtures/timbre_example.txt').read }
|
7
|
+
let(:timbre) { FmTimbradoCfdi::FmTimbre.new timbre_as_text }
|
8
|
+
it { timbre.no_certificado_sat.should_not be_nil }
|
9
|
+
it { timbre.fecha_timbrado.should_not be_nil }
|
10
|
+
it { timbre.uuid.should_not be_nil }
|
11
|
+
it { timbre.sello_sat.should_not be_nil }
|
12
|
+
it { timbre.sello_cfd.should_not be_nil }
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe FmTimbradoCfdi do
|
5
|
+
describe ".cliente" do
|
6
|
+
it "Por default el cliente debe cargar la configuración del ambiente de pruebas" do
|
7
|
+
FmTimbradoCfdi.cliente.user_id.should == 'UsuarioPruebasWS'
|
8
|
+
FmTimbradoCfdi.cliente.user_pass.should == 'b9ec2afa3361a59af4b4d102d3f704eabdf097d4'
|
9
|
+
FmTimbradoCfdi.cliente.namespace.should == 'https://t2demo.facturacionmoderna.com/timbrado/soap'
|
10
|
+
FmTimbradoCfdi.cliente.endpoint.should == 'https://t2demo.facturacionmoderna.com/timbrado/soap'
|
11
|
+
FmTimbradoCfdi.cliente.fm_wsdl.should == 'https://t2demo.facturacionmoderna.com/timbrado/wsdl'
|
12
|
+
end
|
13
|
+
end #describe .cliente"
|
14
|
+
|
15
|
+
|
16
|
+
describe ".timbra_cfdi_layout" do
|
17
|
+
context "timbrado correcto" do
|
18
|
+
context 'archivo de prueba simple' do
|
19
|
+
let(:plantilla){File.open('spec/fixtures/layout_example.txt').read}
|
20
|
+
let(:layout){ plantilla.gsub('--fecha-comprobante--', 'asignarFecha' )}
|
21
|
+
let(:respuesta){ FmTimbradoCfdi.timbra_cfdi_layout 'ESI920427886', layout }
|
22
|
+
it { respuesta.should be_valid }
|
23
|
+
it { respuesta.should be_xml }
|
24
|
+
|
25
|
+
context "formato cbb" do
|
26
|
+
let(:respuesta){ FmTimbradoCfdi.timbra_cfdi_layout 'ESI920427886', layout, true}
|
27
|
+
it { respuesta.should be_valid }
|
28
|
+
it { respuesta.should be_xml }
|
29
|
+
it { respuesta.should be_cbb }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'archivo de constructoras' do
|
35
|
+
let(:plantilla){File.open('spec/fixtures/constructora_layout_example.txt').read}
|
36
|
+
let(:layout){plantilla.gsub('--fecha-comprobante--', 'asignarFecha')}
|
37
|
+
let(:respuesta){ FmTimbradoCfdi.timbra_cfdi_layout 'ESI920427886', layout }
|
38
|
+
it { respuesta.should be_valid }
|
39
|
+
it { respuesta.should be_xml }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe ".timbrar" do
|
44
|
+
context "timbrado correcto" do
|
45
|
+
context 'archivo de prueba simple' do
|
46
|
+
let(:plantilla){File.open('spec/fixtures/layout_example.txt').read}
|
47
|
+
let(:layout){ plantilla.gsub('--fecha-comprobante--', 'asignarFecha' )}
|
48
|
+
let(:respuesta){ FmTimbradoCfdi.timbrar 'ESI920427886', layout }
|
49
|
+
it { respuesta.should be_valid }
|
50
|
+
it { respuesta.should be_xml }
|
51
|
+
|
52
|
+
context "formato cbb" do
|
53
|
+
let(:respuesta){ FmTimbradoCfdi.timbrar 'ESI920427886', layout, 'generarCBB' => true }
|
54
|
+
it { respuesta.should be_valid }
|
55
|
+
it { respuesta.should be_xml }
|
56
|
+
it { respuesta.should be_cbb }
|
57
|
+
end
|
58
|
+
|
59
|
+
context "formato txt" do
|
60
|
+
let(:respuesta){ FmTimbradoCfdi.timbrar 'ESI920427886', layout, 'generarTXT' => true }
|
61
|
+
it { respuesta.should be_valid }
|
62
|
+
it { respuesta.should be_xml }
|
63
|
+
it { respuesta.should be_timbre }
|
64
|
+
end
|
65
|
+
|
66
|
+
context "formato pdf" do
|
67
|
+
let(:respuesta){ FmTimbradoCfdi.timbrar 'ESI920427886', layout, 'generarPDF' => true }
|
68
|
+
it { respuesta.should be_valid }
|
69
|
+
it { respuesta.should be_xml }
|
70
|
+
it { respuesta.should be_pdf }
|
71
|
+
end
|
72
|
+
|
73
|
+
context "formato pdf, pero no cbb, ni txt" do
|
74
|
+
let(:respuesta){ FmTimbradoCfdi.timbrar 'ESI920427886', layout, 'generarPDF' => true, 'generarCBB' => false, 'generarTXT' => false }
|
75
|
+
it { respuesta.should be_valid }
|
76
|
+
it { respuesta.should be_xml }
|
77
|
+
it { respuesta.should be_pdf }
|
78
|
+
it { respuesta.should_not be_cbb }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'archivo de constructoras' do
|
84
|
+
let(:plantilla){File.open('spec/fixtures/constructora_layout_example.txt').read}
|
85
|
+
let(:layout){plantilla.gsub('--fecha-comprobante--', 'asignarFecha')}
|
86
|
+
let(:respuesta){ FmTimbradoCfdi.timbrar 'ESI920427886', layout }
|
87
|
+
it { respuesta.should be_valid }
|
88
|
+
it { respuesta.should be_xml }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'timbrado incorrecto' do
|
93
|
+
it "no timbra el comprobante si tiene más de 72 horas de haber sido generado" do
|
94
|
+
fecha_comprobante = Time.now - 73*3600
|
95
|
+
layout = File.open('spec/fixtures/layout_example.txt').read.gsub('--fecha-comprobante--', fecha_comprobante.strftime("%FT%T"))
|
96
|
+
respuesta = FmTimbradoCfdi.timbrar 'ESI920427886', layout
|
97
|
+
respuesta.should_not be_valid
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe ".configurar" do
|
103
|
+
it "cambia los valores de conexión por los proporcionados" do
|
104
|
+
FmTimbradoCfdi.configurar do |config|
|
105
|
+
config.user_id = "mi_usuario"
|
106
|
+
config.user_pass = "secret"
|
107
|
+
config.namespace = "http://logicalbricks.com/soap"
|
108
|
+
config.endpoint = "http://logicalbricks.com/endpoint"
|
109
|
+
config.fm_wsdl = "http://logicalbricks.com/wsdl"
|
110
|
+
end
|
111
|
+
|
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
|
+
end
|
118
|
+
end
|
119
|
+
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fm_timbrado_cfdi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.alpha
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Carlos García
|
8
|
+
- Hermes Ojeda Ruiz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-12-26 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: savon
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
description: 'Implementación en Ruby de la Conexión con el Servicio de Timbrado de
|
57
|
+
CFDI con el PAC: Facturación Moderna'
|
58
|
+
email:
|
59
|
+
- hermes.ojeda@logicalbricks.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- .gitignore
|
65
|
+
- .ruby-gemset
|
66
|
+
- .ruby-version
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- fm_timbrado_cfdi.gemspec
|
72
|
+
- lib/fm_timbrado_cfdi.rb
|
73
|
+
- lib/fm_timbrado_cfdi/fm_cliente.rb
|
74
|
+
- lib/fm_timbrado_cfdi/fm_respuesta.rb
|
75
|
+
- lib/fm_timbrado_cfdi/fm_timbre.rb
|
76
|
+
- lib/fm_timbrado_cfdi/version.rb
|
77
|
+
- spec/fixtures/constructora_layout_example.txt
|
78
|
+
- spec/fixtures/layout_example.txt
|
79
|
+
- spec/fixtures/layout_example.txt~
|
80
|
+
- spec/fixtures/pipes.txt
|
81
|
+
- spec/fixtures/timbre_example.txt
|
82
|
+
- spec/fm_timbrado_cfdi/fm_timbre_spec.rb
|
83
|
+
- spec/fm_timbrado_cfdi_spec.rb
|
84
|
+
- spec/spec_helper.rb
|
85
|
+
homepage: https://github.com/LogicalBricks/fm_timbrado_cfdi
|
86
|
+
licenses: []
|
87
|
+
metadata: {}
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - '>'
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 1.3.1
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 2.1.11
|
105
|
+
signing_key:
|
106
|
+
specification_version: 4
|
107
|
+
summary: Implementación en ruby de la conexión con el servicio de timbrado de cfdi
|
108
|
+
con el PAC Facturación Moderna
|
109
|
+
test_files:
|
110
|
+
- spec/fixtures/constructora_layout_example.txt
|
111
|
+
- spec/fixtures/layout_example.txt
|
112
|
+
- spec/fixtures/layout_example.txt~
|
113
|
+
- spec/fixtures/pipes.txt
|
114
|
+
- spec/fixtures/timbre_example.txt
|
115
|
+
- spec/fm_timbrado_cfdi/fm_timbre_spec.rb
|
116
|
+
- spec/fm_timbrado_cfdi_spec.rb
|
117
|
+
- spec/spec_helper.rb
|
118
|
+
has_rdoc:
|