fdis 0.1.13 → 0.1.25

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 55cdd771437f58ffe637393722e309f104dc9304aaf7bf759aebe1e19632d329
4
- data.tar.gz: 449f09143d7035310ca4e6fdfd4c93cbcb2d05b35c392ffa8b5c4ba692e3282f
3
+ metadata.gz: b056d0d3aaf443e6e969baea7afb73b0d90cc7ec99c95a2827f5c9834762f656
4
+ data.tar.gz: e9b4d06ba55a6af625df12b5e93f3989b524ac52b206b0585748e732d6bb2ae1
5
5
  SHA512:
6
- metadata.gz: a1990467ff61ef7199a86530e40d5cad383ecfbe4b0bb93fee5227924c7805b07403f4cea8a4ea6e4689bcf2d331982a58b0a7a9e48de31cae872d5dbe5070e7
7
- data.tar.gz: fe792241a47295b3cc7edc0706a467c53fb0de3e3d97638d8c969bf804c6ad40b81251c3af2fbcb05aadc773ef9d6359c4229f79daf9e71978b1da8894c87580
6
+ metadata.gz: 9d85382c62b566e459137b8274ebe8886db0c36171ea9c70cc9b5642282bd473cc32a8fb70068a164fc314b22a8e0a55a7c94cd53e4a05b3a9d0822476f1b242
7
+ data.tar.gz: 0ad178a5f2de1d64467da08e31aece93f6937c0696a25eaee719c4ee8fd0dbdf13013eb3f80ca5c24e18ca776e326fafbfefcf029306e8aa9f5277922f267fa3
data/lib/fdis/config.rb CHANGED
@@ -77,7 +77,7 @@ module Fdis
77
77
 
78
78
 
79
79
  UrlPro = "https://v4.cfdis.mx/api/Cfdi"
80
- UrlDev = "https://v4.cfdis.mx/api/Cfdi/Timbrar40"
80
+ UrlCancel = "https://v4.cfdis.mx/api/CfdiCancelacion/Cancelar"
81
81
 
82
82
  DocBase = %(<?xml version="1.0" encoding="utf-8"?>
83
83
  <cfdi:Comprobante xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd" Version="4.0" xmlns:cfdi="http://www.sat.gob.mx/cfd/4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
@@ -15,6 +15,9 @@ module Fdis
15
15
  # iva_id: 16,8,0,
16
16
  # forma_pago: '01',
17
17
  # total: 100.00,
18
+ # monto_pago: 50.0,
19
+ # saldo_anterior: 100.0,
20
+ # num_parcialidad: '1',
18
21
  # time_pago: '',
19
22
  # time_now: '',
20
23
  # modena: '',
@@ -45,6 +48,10 @@ module Fdis
45
48
  raise "Error Fdis - la fecha de timbrado debe de estar presente"
46
49
  end
47
50
 
51
+ if params[:num_parcialidad].empty?
52
+ raise "Error Fdis - Se debe registrar el número de parcialidad que corresponde al pago"
53
+ end
54
+
48
55
 
49
56
 
50
57
 
@@ -67,8 +74,14 @@ module Fdis
67
74
  <pago20:Pagos Version="2.0">
68
75
  <pago20:Totales MontoTotalPagos="" />
69
76
 
70
- <pago20:Pago FechaPago="" FormaDePagoP="01" MonedaP="MXN" TipoCambioP="1" Monto="">
71
- </pago20:Pago>
77
+ <pago20:Pago FechaPago="" FormaDePagoP="" MonedaP="MXN" Monto="" TipoCambioP="1">
78
+
79
+ <pago20:DoctoRelacionado IdDocumento="" MonedaDR="MXN" NumParcialidad="" ImpSaldoAnt="" ImpPagado="" ImpSaldoInsoluto="" ObjetoImpDR="02" EquivalenciaDR="1">
80
+
81
+
82
+ </pago20:DoctoRelacionado>
83
+
84
+ </pago20:Pago>
72
85
 
73
86
  </pago10:Pagos>
74
87
 
@@ -103,13 +116,15 @@ module Fdis
103
116
 
104
117
 
105
118
  # totales
106
- total = params[:total].to_f
119
+ total = params[:monto_pago].to_f
107
120
  iva_id = params.fetch(:iva_id, 16)
108
121
 
109
122
  pago_totales = xml.at_xpath("//pago20:Totales")
110
123
  pago_totales['MontoTotalPagos'] = total.round(2).to_s # total
111
124
 
112
125
 
126
+
127
+
113
128
  if iva_id == 0
114
129
  subtotal = total
115
130
  iva = 0.00
@@ -131,62 +146,88 @@ module Fdis
131
146
  pago_totales['TotalTrasladosImpuestoIVA16'] = iva.round(2).to_s # iva
132
147
  end
133
148
 
149
+
150
+ # pagos = xml.at_xpath("//pago20:Pagos")
151
+
134
152
  # pago
135
153
  child_pago = xml.at_xpath("//pago20:Pago")
154
+
136
155
  child_pago['FechaPago'] = time_pago
137
156
  child_pago['FormaDePagoP'] = params[:forma_pago].to_s
138
157
  child_pago['MonedaP'] = params.fetch(:moneda, 'MXN')
139
158
  child_pago['Monto'] = total.round(2).to_s
159
+ child_pago['TipoCambioP'] = "1"
140
160
 
141
- saldo_anterior = total
142
-
143
- params[:line_items].each_with_index do |line, index|
144
- monto = line[:monto].to_f
145
- child_pago_relacionado = Nokogiri::XML::Node.new "pago20:DoctoRelacionado", xml
146
- child_pago_relacionado['IdDocumento'] = params[:uuid]
147
- child_pago_relacionado['Serie'] = "Depo"
148
- child_pago_relacionado['Folio'] = line[:id].to_s
149
-
150
- child_pago_relacionado['MonedaDR'] = line.fetch(:moneda, 'MXN')
151
- child_pago_relacionado['NumParcialidad'] = (index + 1).to_s
152
-
153
- child_pago_relacionado['ImpSaldoAnt'] = (saldo_anterior).round(2).to_s
154
- child_pago_relacionado['ImpPagado'] = monto.round(2).to_s
155
- child_pago_relacionado['ImpSaldoInsoluto'] = (saldo_anterior - monto).round(2).to_s
156
- saldo_anterior -= monto
157
-
158
- if iva_id == 16 or iva_id == 8
159
- child_pago_relacionado['ObjetoImpDR'] = '02'
160
-
161
- impuestos_dr = Nokogiri::XML::Node.new "pago20:ImpuestosDR", xml
162
- traslados_dr = Nokogiri::XML::Node.new "pago20:TrasladosDR", xml
163
- traslado = Nokogiri::XML::Node.new "pago20:TrasladoDR", xml
164
- traslado['TipoFactorDR'] = 'Tasa'
165
- traslado['ImpuestoDR'] = '002'
166
-
167
- if iva_id == 16
168
- traslado['TasaOCuotaDR'] = '0.160000'
169
- t_subtotal = monto / 1.16
170
- t_tax = monto - t_subtotal
171
- else
172
- traslado['TasaOCuotaDR'] = '0.080000'
173
- t_subtotal = monto / 1.08
174
- t_tax = monto - t_subtotal
175
- end
161
+ child_pago_relacionado = xml.at_xpath("//pago20:DoctoRelacionado")
162
+
163
+ child_pago_relacionado['IdDocumento'] = params[:uuid]
164
+ child_pago_relacionado['MonedaDR'] = 'MXN'
165
+ child_pago_relacionado['NumParcialidad'] = params[:num_parcialidad]
166
+ child_pago_relacionado['Serie'] = "Depo"
167
+ child_pago_relacionado['Folio'] = params[:folio]
168
+ child_pago_relacionado['EquivalenciaDR'] = "1"
169
+
170
+ saldo_anterior = params[:saldo_anterior].to_f
176
171
 
177
- traslado['BaseDR'] = t_subtotal.round(4).to_s #subtotal
178
- traslado['ImporteDR'] = t_tax.round(4).to_s # tax
172
+ child_pago_relacionado['ImpSaldoAnt'] = saldo_anterior.round(2).to_s
173
+ child_pago_relacionado['ImpPagado'] = total.round(2).to_s
174
+ child_pago_relacionado['ImpSaldoInsoluto'] = (saldo_anterior - total).round(2).to_s
179
175
 
180
- traslados_dr.add_child(traslado)
181
- impuestos_dr.add_child(traslados_dr)
182
- child_pago_relacionado.add_child(impuestos_dr)
176
+ if iva_id == 16 or iva_id == 8
177
+ child_pago_relacionado['ObjetoImpDR'] = '02'
178
+
179
+ impuestos_dr = Nokogiri::XML::Node.new "pago20:ImpuestosDR", xml
180
+ traslados_dr = Nokogiri::XML::Node.new "pago20:TrasladosDR", xml
181
+ traslado = Nokogiri::XML::Node.new "pago20:TrasladoDR", xml
182
+
183
+ impuestos_p = Nokogiri::XML::Node.new "pago20:ImpuestosP", xml
184
+ traslados_p = Nokogiri::XML::Node.new "pago20:TrasladosP", xml
185
+ traslado_p = Nokogiri::XML::Node.new "pago20:TrasladoP", xml
186
+
187
+
188
+ if iva_id == 16
189
+ traslado['TasaOCuotaDR'] = '0.160000'
190
+ # t_subtotal = total / 1.16
191
+ # t_tax = total - t_subtotal
192
+
193
+ traslado_p['TasaOCuotaP'] = '0.160000'
183
194
  else
184
- child_pago_relacionado['ObjetoImpDR'] = '01'
195
+ traslado['TasaOCuotaDR'] = '0.080000'
196
+ # t_subtotal = total / 1.08
197
+ # t_tax = total - t_subtotal
198
+
199
+ traslado_p['TasaOCuotaP'] = '0.080000'
185
200
  end
186
201
 
187
- child_pago.add_child(child_pago_relacionado)
202
+ traslado['TipoFactorDR'] = 'Tasa'
203
+ traslado['ImpuestoDR'] = '002'
204
+
205
+ traslado['BaseDR'] = subtotal.round(4).to_s #subtotal
206
+ traslado['ImporteDR'] = iva.round(4).to_s # tax
207
+
208
+
209
+
210
+ traslado_p['BaseP'] = subtotal.round(4).to_s
211
+ traslado_p['ImpuestoP'] = '002'
212
+ traslado_p['TipoFactorP'] = 'Tasa'
213
+ traslado_p['ImporteP'] = iva.round(4).to_s # tax
214
+
215
+
216
+
217
+ traslados_dr.add_child(traslado)
218
+ impuestos_dr.add_child(traslados_dr)
219
+ child_pago_relacionado.add_child(impuestos_dr)
220
+
221
+ traslados_p.add_child(traslado_p)
222
+ impuestos_p.add_child(traslados_p)
223
+
224
+ child_pago.add_child(impuestos_p)
225
+ else
226
+ child_pago_relacionado['ObjetoImpDR'] = '01'
188
227
  end
189
228
 
229
+
230
+
190
231
  # puts '---------------- Xml resultante comprobante de pago -----------------------'
191
232
  # puts xml.to_xml
192
233
  # puts '--------------------------------------------------------'
@@ -239,9 +280,6 @@ module Fdis
239
280
  puts "-- Mensaje: #{json_response.message} --"
240
281
  puts "-- Body: "
241
282
  p json_response.body
242
- # puts "-- Body --"
243
- # puts json_response.body
244
- # puts '---'
245
283
  response = JSON.parse(json_response.body)
246
284
 
247
285
  case json_response
@@ -292,180 +330,39 @@ module Fdis
292
330
 
293
331
  end
294
332
 
295
- # def nota_credito(params={})
296
- # # Sample params
297
- # # params = {
298
- # # uuid_relacionado: '',
299
- # # desc: '',
300
- # # motivo: 'dev, mod',
301
- # # series: '',
302
- # # folio: '',
303
- # # cp: '',
304
- # # time: '',
305
- # # receptor_razon: '',
306
- # # receptor_rfc: '',
307
- # # uso_cfdi: '',
308
- # # }
309
-
310
- # total = (params[:monto]).to_f
311
- # subtotal = total / 1.16
312
- # tax = total - subtotal
313
-
314
- # uri = @production ? URI("#{Fdis::UrlProduction}cfdi33/stamp/customv1/b64") : URI("#{Fdis::UrlDev}cfdi33/stamp/customv1/b64")
315
- # token = @production ? @production_token : @dev_token
316
- # time = params.fetch(:time, (Time.now).strftime("%Y-%m-%dT%H:%M:%S"))
317
-
318
-
319
- # base_doc = %(<?xml version="1.0" encoding="utf-8"?>
320
- # <cfdi:Comprobante xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd" Version="3.3" Serie="#{params.fetch(:series, 'N')}" Folio="#{params[:folio]}" Fecha="#{time}" FormaPago="99" NoCertificado="#{@serial}" Certificado="#{@cadena}" SubTotal="#{subtotal.round(2)}" Moneda="#{params.fetch(:moneda, 'MXN')}" Total="#{total.round(2)}" TipoDeComprobante="E" MetodoPago="PUE" LugarExpedicion="#{params[:cp]}" xmlns:cfdi="http://www.sat.gob.mx/cfd/3">
321
- # <cfdi:CfdiRelacionados TipoRelacion="01">
322
- # <cfdi:CfdiRelacionado UUID="#{params[:uuid_relacionado]}" />
323
- # </cfdi:CfdiRelacionados>
324
- # <cfdi:Emisor Rfc="#{@rfc}" Nombre="#{@razon}" RegimenFiscal="#{@regimen_fiscal}" />
325
- # <cfdi:Receptor Rfc="#{params[:receptor_rfc]}" Nombre="#{params[:receptor_razon]}" UsoCFDI="#{params.fetch(:uso_cfdi, 'G03')}" />
326
- # <cfdi:Conceptos>
327
- # <cfdi:Concepto ClaveUnidad="ACT" ClaveProdServ="84111506" NoIdentificacion="C" Cantidad="1.00" Unidad="Pieza" Descripcion="#{params.fetch(:desc, 'DICTAMEN CC FACTURA ORIGEN 0')}" ValorUnitario="#{subtotal.round(2)}" Importe="#{subtotal.round(2)}">
328
- # <cfdi:Impuestos>
329
- # <cfdi:Traslados>
330
- # <cfdi:Traslado Base="#{subtotal.round(2)}" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="#{tax.round(2)}" />
331
- # </cfdi:Traslados>
332
- # </cfdi:Impuestos>
333
- # </cfdi:Concepto>
334
- # </cfdi:Conceptos>
335
- # <cfdi:Impuestos TotalImpuestosTrasladados="#{tax.round(2)}">
336
- # <cfdi:Traslados>
337
- # <cfdi:Traslado Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="#{tax.round(2)}" />
338
- # </cfdi:Traslados>
339
- # </cfdi:Impuestos>
340
- # </cfdi:Comprobante>
341
- # )
342
-
343
- # base_doc.delete!("\n")
344
- # base_doc.delete!("\t")
345
-
346
- # xml = Nokogiri::XML(base_doc)
347
- # comprobante = xml.at_xpath("//cfdi:Comprobante")
348
-
349
- # path = File.join(File.dirname(__FILE__), *%w[.. tmp])
350
- # id = SecureRandom.hex
351
-
352
- # FileUtils.mkdir_p(path) unless File.exist?(path)
353
- # File.write("#{path}/tmp_n_#{id}.xml", xml.to_xml)
354
- # xml_path = "#{path}/tmp_n_#{id}.xml"
355
- # cadena_path = File.join(File.dirname(__FILE__), *%w[.. cadena cadena33.xslt])
356
-
357
- # File.write("#{path}/pem_#{id}.pem", @pem)
358
- # key_pem_url = "#{path}/pem_#{id}.pem"
359
- # sello = %x[xsltproc #{cadena_path} #{xml_path} | openssl dgst -sha256 -sign #{key_pem_url} | openssl enc -base64 -A]
360
- # comprobante['Sello'] = sello
361
-
362
- # File.delete("#{xml_path}")
363
- # File.delete("#{key_pem_url}")
364
-
365
- # puts '------ nota antes de timbre -------'
366
- # puts xml.to_xml
367
-
368
- # base64_xml = Base64.encode64(xml.to_xml)
369
-
370
- # request = Net::HTTP::Post.new(uri)
371
- # request.basic_auth(token, "")
372
- # request.content_type = "application/json"
373
- # request["cache-control"] = 'no-cache'
374
- # request.body = JSON.dump({
375
- # "credentials" => {
376
- # "id" => "#{params[:folio]}",
377
- # "token" => token
378
- # },
379
- # "issuer" => {
380
- # "rfc" => @rfc
381
- # },
382
- # "document" => {
383
- # "ref-id": "#{params[:folio]}",
384
- # "certificate-number": @serial,
385
- # "section": "all",
386
- # "format": "xml",
387
- # "template": "letter",
388
- # "type": "application/xml",
389
- # "content": base64_xml
390
- # }
391
- # })
392
-
393
- # req_options = {
394
- # use_ssl: false,
395
- # }
396
-
397
- # json_response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
398
- # http.request(request)
399
- # end
400
-
401
-
402
- # puts "-- #{json_response.code} --"
403
- # puts "-- #{json_response.message} --"
404
- # # puts "-- Body --"
405
- # # puts json_response.body
406
- # # puts '---'
407
- # response = JSON.parse(json_response.body)
408
-
409
- # if json_response.code == '200'
410
- # decoded_xml = Nokogiri::XML(Base64.decode64(response['content']))
411
- # timbre = decoded_xml.at_xpath("//cfdi:Complemento").children.first
412
-
413
- # response = {
414
- # status: 200,
415
- # message_error: '',
416
- # xml: decoded_xml.to_xml,
417
- # uuid: response['uuid'],
418
- # fecha_timbrado: timbre['FechaTimbrado'],
419
- # sello_cfd: timbre['SelloCFD'],
420
- # sello_sat: timbre['SelloSAT'],
421
- # no_certificado_sat: timbre['NoCertificadoSAT'],
422
- # }
423
- # return response
424
- # else
425
- # response = {
426
- # status: json_response.code,
427
- # message_error: "Error message: #{json_response.message}, #{response['message']} #{response['error_details']}",
428
- # xml: '',
429
- # uuid: '',
430
- # fecha_timbrado: '',
431
- # sello_cfd: '',
432
- # sello_sat: '',
433
- # no_certificado_sat: '',
434
- # }
435
- # return response
436
- # end
437
-
438
-
439
- # end
333
+
440
334
 
441
335
  def cancela_doc(params={})
336
+ puts "---- Fdis:facturacion:cancela_doc"
337
+
442
338
  # Sample params
443
339
  # params = {
444
340
  # uuid: '',
445
- # rfc_emisor: '',
341
+ # rfcReceptor: 'XAXX010101000',
342
+ # total_sale: 100.0,
446
343
  # motivo: '02',
344
+ # uuid_sustituye: '',
447
345
  # key_password: '', # optional
448
346
  # cer_cadena: '', # optional
449
347
  # key_pem: '' # optional
450
348
  # }
451
349
 
452
- uri = @production ? URI("#{Fdis::UrlProduction}cfdi33/cancel/csd") : URI("#{Fdis::UrlDev}cfdi33/cancel/csd")
453
- token = @production ? @production_token : @dev_token
454
- # time = params.fetch(:time, (Time.now).strftime("%Y-%m-%dT%H:%M:%S"))
455
-
456
350
 
351
+ uri = URI(Fdis::UrlCancel)
457
352
  request = Net::HTTP::Post.new(uri)
458
- request["Authorization"] = "bearer #{token}"
459
353
  request.content_type = "application/json"
460
- request["Cache-Control"] = 'no-cache'
461
- request["Postman-Token"] = '30b35bb8-534d-51c7-6a5c-e2c98a0c9395'
354
+
462
355
  request.body = JSON.dump({
463
- 'uuid': params[:uuid],
464
- "password": params.fetch(:key_password, @key_pass),
465
- "rfc": params.fetch(:rfc_emisor, @rfc),
466
- "motivo": '02',
467
- "b64Cer": params.fetch(:cer_cadena, @cadena),
468
- "b64Key": params.fetch(:key_pem, @pem_cadena)
356
+ rfcEmisor: @rfc,
357
+ rfcReceptor: params[:rfcReceptor],
358
+ keyPassword: @key_pass,
359
+ totalCfdi: params[:total_sale],
360
+ uuid: params[:uuid],
361
+ motivoCancelacion: params.fetch(:motivo, '02'),
362
+ FolioFiscalSustituye: params.fetch(:uuid_sustituye, SecureRandom.uuid.upcase),
363
+ testMode: !@production,
364
+ base64CerFile: params.fetch(:cer_cadena, @cadena),
365
+ base64KeyFile: params.fetch(:key_pem, @pem_cadena),
469
366
  })
470
367
 
471
368
  req_options = {
@@ -476,33 +373,47 @@ module Fdis
476
373
  http.request(request)
477
374
  end
478
375
 
479
- puts "-- #{json_response.code} --"
480
- puts "-- #{json_response.message} --"
481
- # puts "-- Body --"
482
- # puts json_response.body
483
- # puts '---'
484
- response = JSON.parse(json_response.body)
376
+ puts "---- Fdis: request"
377
+ puts "-- body: #{request.body} --"
485
378
 
486
- if json_response.code == '200'
487
- decoded_xml = response['data']['acuse']
379
+ puts "---- Fdis: Respuesta"
380
+ puts "-- Codigo: #{json_response.code} --"
381
+ puts "-- Mensaje: #{json_response.message} --"
382
+ puts "-- Body: "
383
+ p json_response.body
488
384
 
489
- response = {
490
- status: 200,
491
- message_error: '',
492
- xml: decoded_xml,
493
- }
385
+ response = JSON.parse(json_response.body)
494
386
 
495
- return response
496
- else
387
+ case json_response
388
+ when Net::HTTPSuccess, Net::HTTPRedirection
389
+ if response['success'] == true
390
+ acuse = response['acuseCancelacion']
391
+ response = {
392
+ status: 200,
393
+ message_error: '',
394
+ xml: acuse,
395
+ }
497
396
 
498
- response ={
499
- status: json_response.code,
500
- message_error: "Error message: #{json_response.message}, #{response['message']} #{response['error_details']}",
501
- xml: '',
502
- }
397
+ return response
398
+ else
399
+ response = {
400
+ status: 400,
401
+ message_error: "Error: #{response['errors']}",
402
+ xml: '',
403
+
404
+ }
405
+ return response
406
+ end
503
407
 
408
+ else
409
+ response = {
410
+ status: 400,
411
+ message_error: "Error: #{response['errors']}",
412
+ xml: '',
413
+
414
+ }
504
415
  return response
505
- end
416
+ end
506
417
 
507
418
  end
508
419
 
@@ -874,206 +785,6 @@ module Fdis
874
785
 
875
786
  end
876
787
 
877
- def timbra_doc_cero(params={})
878
- puts "---- Fdis:facturacion:timbra_doc_cero"
879
- # params = {
880
- # moneda: 'MXN',
881
- # series: 'FA',
882
- # folio: '003',
883
- # forma_pago: '',
884
- # metodo_pago: 'PUE',
885
- # cp: '47180',
886
- # receptor_razon: 'Car zone',
887
- # receptor_rfc: '',
888
- # uso_cfdi: 'G03',
889
- # time: "%Y-%m-%dT%H:%M:%S",
890
- # line_items: [
891
- # {
892
- # clave_prod_serv: '78181500',
893
- # clave_unidad: 'E48',
894
- # unidad: 'Servicio',
895
- # sku: 'serv001',
896
- # cantidad: 1,
897
- # descripcion: 'Servicio mano de obra',
898
- # valor_unitario: 100.00,
899
- # # Optional parameters
900
- # },
901
- # ]
902
-
903
- # }
904
-
905
- uri = @production ? URI("#{Fdis::UrlProduction}cfdi33/stamp/customv1/b64") : URI("#{Fdis::UrlDev}cfdi33/stamp/customv1/b64")
906
- token = @production ? @production_token : @dev_token
907
- time = params.fetch(:time, (Time.now).strftime("%Y-%m-%dT%H:%M:%S"))
908
-
909
- xml = Nokogiri::XML(Fdis::DocBase)
910
- comprobante = xml.at_xpath("//cfdi:Comprobante")
911
- comprobante['TipoCambio'] = '1'
912
- comprobante['TipoDeComprobante'] = 'I'
913
- comprobante['Serie'] = params.fetch(:series, 'FA').to_s
914
- comprobante['Folio'] = params.fetch(:folio, '1').to_s
915
- comprobante['Fecha'] = time.to_s
916
- comprobante['FormaPago'] = params.fetch(:forma_pago, '01')
917
- comprobante['MetodoPago'] = params.fetch(:metodo_pago, 'PUE')
918
- comprobante['LugarExpedicion'] = params.fetch(:cp, '55555')
919
- comprobante['NoCertificado'] = @serial
920
- comprobante['Certificado'] = @cadena
921
-
922
- emisor = xml.at_xpath("//cfdi:Emisor")
923
- emisor['Nombre'] = @razon
924
- emisor['RegimenFiscal'] = @regimen_fiscal
925
- emisor['Rfc'] = @rfc
926
-
927
- receptor = xml.at_xpath("//cfdi:Receptor")
928
- receptor['Nombre'] = params.fetch(:receptor_razon, '')
929
- receptor['Rfc'] = params.fetch(:receptor_rfc, 'XAXX010101000')
930
- receptor['UsoCFDI'] = params.fetch(:uso_cfdi, 'G03')
931
-
932
-
933
- # impuestos = xml.at_xpath("//cfdi:Impuestos")
934
- # traslados = Nokogiri::XML::Node.new "cfdi:Traslados", xml
935
-
936
-
937
- puts '--- Fdis time -----'
938
- puts time
939
- puts '--------'
940
-
941
- conceptos = xml.at_xpath("//cfdi:Conceptos")
942
-
943
- line_items = params[:line_items]
944
-
945
- suma_total = 0.00
946
-
947
- line_items.each do |line|
948
-
949
- valor_unitario = line[:valor_unitario].to_f
950
- cantidad = line[:cantidad].to_f
951
- total_line = cantidad * valor_unitario
952
-
953
- suma_total += total_line
954
-
955
- ## Creando y poblando CFDI:CONCEPTO
956
- child_concepto = Nokogiri::XML::Node.new "cfdi:Concepto", xml
957
- child_concepto['ClaveProdServ'] = line[:clave_prod_serv].to_s
958
- child_concepto['NoIdentificacion'] = line[:sku].to_s
959
- child_concepto['ClaveUnidad'] = line[:clave_unidad].to_s
960
- child_concepto['Unidad'] = line[:unidad].to_s
961
- child_concepto['Descripcion'] = line[:descripcion].to_s
962
- child_concepto['Cantidad'] = cantidad.to_s
963
- child_concepto['ValorUnitario'] = valor_unitario.round(4).to_s
964
- child_concepto['Importe'] = total_line.round(4).to_s
965
-
966
-
967
- # Joining all up
968
- conceptos.add_child(child_concepto)
969
-
970
-
971
- end
972
-
973
- puts '------ Totales -----'
974
- puts "Subtotal = #{suma_total}"
975
- puts "Total = #{suma_total}"
976
-
977
- comprobante['Moneda'] = params.fetch(:moneda, 'MXN')
978
- comprobante['SubTotal'] = suma_total.round(2).to_s
979
- comprobante['Total'] = suma_total.round(2).to_s
980
-
981
-
982
-
983
- path = File.join(File.dirname(__FILE__), *%w[.. tmp])
984
- id = SecureRandom.hex
985
-
986
- FileUtils.mkdir_p(path) unless File.exist?(path)
987
- File.write("#{path}/tmp_#{id}.xml", xml.to_xml)
988
- xml_path = "#{path}/tmp_#{id}.xml"
989
- cadena_path = File.join(File.dirname(__FILE__), *%w[.. cadena cadena33.xslt])
990
-
991
- # puts File.read(cadena_path)
992
- File.write("#{path}/pem_#{id}.pem", @pem)
993
- key_pem_url = "#{path}/pem_#{id}.pem"
994
- sello = %x[xsltproc #{cadena_path} #{xml_path} | openssl dgst -sha256 -sign #{key_pem_url} | openssl enc -base64 -A]
995
- comprobante['Sello'] = sello
996
-
997
- File.delete("#{xml_path}")
998
- File.delete("#{key_pem_url}")
999
-
1000
- puts '---- Fdis GEM comprobante sin timbrar ------'
1001
- puts xml.to_xml
1002
- puts '-------------------------'
1003
-
1004
- base64_xml = Base64.encode64(xml.to_xml)
1005
- request = Net::HTTP::Post.new(uri)
1006
- request.basic_auth(token, "")
1007
- request.content_type = "application/json"
1008
- request["cache-control"] = 'no-cache'
1009
- request.body = JSON.dump({
1010
- "credentials" => {
1011
- "id" => params.fetch(:folio).to_s,
1012
- "token" => token
1013
- },
1014
- "issuer" => {
1015
- "rfc" => emisor['Rfc']
1016
- },
1017
- "document" => {
1018
- "ref-id": params.fetch(:folio).to_s,
1019
- "certificate-number": comprobante['NoCertificado'],
1020
- "section": "all",
1021
- "format": "xml",
1022
- "template": "letter",
1023
- "type": "application/xml",
1024
- "content": base64_xml
1025
- }
1026
- })
1027
-
1028
- req_options = {
1029
- use_ssl: false,
1030
- }
1031
-
1032
- json_response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
1033
- http.request(request)
1034
- end
1035
-
1036
- puts "-- Fdis API reponse..."
1037
- puts "-- Response code: #{json_response.code} --"
1038
- puts "-- Response body: #{json_response.body} --"
1039
- puts "-- Response message: #{json_response.message} --"
1040
-
1041
- response = JSON.parse(json_response.body)
1042
-
1043
- if json_response.code == '200'
1044
- decoded_xml = Nokogiri::XML(Base64.decode64(response['content']))
1045
- timbre = decoded_xml.at_xpath("//cfdi:Complemento").children.first
1046
-
1047
- response = {
1048
- status: 200,
1049
- message_error: '',
1050
- xml: decoded_xml.to_xml,
1051
- uuid: response['uuid'],
1052
- fecha_timbrado: timbre['FechaTimbrado'],
1053
- sello_cfd: timbre['SelloCFD'],
1054
- sello_sat: timbre['SelloSAT'],
1055
- no_certificado_sat: timbre['NoCertificadoSAT'],
1056
- }
1057
-
1058
- return response
1059
- else
1060
-
1061
- response ={
1062
- status: json_response.code,
1063
- message_error: "Error message: #{json_response.message}, #{response['message']} #{response['error_details']}",
1064
- xml: '',
1065
- uuid: '',
1066
- fecha_timbrado: '',
1067
- sello_cfd: '',
1068
- sello_sat: '',
1069
- no_certificado_sat: '',
1070
- }
1071
-
1072
- return response
1073
- end
1074
-
1075
-
1076
- end
1077
788
 
1078
789
 
1079
790
  end
data/lib/fdis/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Fdis
2
- VERSION = "0.1.13"
2
+ VERSION = "0.1.25"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fdis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Angel Padilla