fdis 0.1.14 → 0.1.26

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: 718f47667107fd56121df926c67529e7111390eef82e1d2959a864e3e0e2bd5b
4
- data.tar.gz: 8417ade616027659aa225814e9ee67720a7c4196ca200a0fc0fef0079442da9c
3
+ metadata.gz: a1b534667123cc70f0622248c6c6b2194b4f69c1a27872d26079868be2adcda7
4
+ data.tar.gz: 42b4311c762e9643a897bfad80c975af280ee72fe9d19dd404e520b092bd1672
5
5
  SHA512:
6
- metadata.gz: 4d67e2997a08e4eee366782a0087c319a0885619c74c35ee50b16af3ce741d47b4b9f0e7e53dd9e71182e921d00680aa01322fafbf6b8ad47ea7fc388eb46bd7
7
- data.tar.gz: 3d5176b9226584b67471a97537a535e6bb38a56b69fc369c695226f882ba3894a7a047d2f6fb24f51b808005b81506b2aa88eba0e23d3cf3f0a80aaa1b0a799a
6
+ metadata.gz: 6ff678375a904442611ddca5fae7ef536367c734fb6f413ab8b62b9cb61e3bea047851cad2c84b944dc960ef95ab58169ecb08a35fb546f52e95b383fc3e516e
7
+ data.tar.gz: fad74be66bc3414270e4fba4f8063d39128e26a152eaf5dfed8db3bffdcc5ea123d6788b0e7ba93b7f96d0c8e926f7e4397a4043b267f7009f5a2296f22c25cf
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,63 +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
- child_pago_relacionado['EquivalenciaDR'] = "1"
150
-
151
- child_pago_relacionado['MonedaDR'] = line.fetch(:moneda, 'MXN')
152
- child_pago_relacionado['NumParcialidad'] = (index + 1).to_s
153
-
154
- child_pago_relacionado['ImpSaldoAnt'] = (saldo_anterior).round(2).to_s
155
- child_pago_relacionado['ImpPagado'] = monto.round(2).to_s
156
- child_pago_relacionado['ImpSaldoInsoluto'] = (saldo_anterior - monto).round(2).to_s
157
- saldo_anterior -= monto
158
-
159
- if iva_id == 16 or iva_id == 8
160
- child_pago_relacionado['ObjetoImpDR'] = '02'
161
-
162
- impuestos_dr = Nokogiri::XML::Node.new "pago20:ImpuestosDR", xml
163
- traslados_dr = Nokogiri::XML::Node.new "pago20:TrasladosDR", xml
164
- traslado = Nokogiri::XML::Node.new "pago20:TrasladoDR", xml
165
- traslado['TipoFactorDR'] = 'Tasa'
166
- traslado['ImpuestoDR'] = '002'
167
-
168
- if iva_id == 16
169
- traslado['TasaOCuotaDR'] = '0.160000'
170
- t_subtotal = monto / 1.16
171
- t_tax = monto - t_subtotal
172
- else
173
- traslado['TasaOCuotaDR'] = '0.080000'
174
- t_subtotal = monto / 1.08
175
- t_tax = monto - t_subtotal
176
- 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
177
171
 
178
- traslado['BaseDR'] = t_subtotal.round(4).to_s #subtotal
179
- 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
180
175
 
181
- traslados_dr.add_child(traslado)
182
- impuestos_dr.add_child(traslados_dr)
183
- 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'
184
194
  else
185
- 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'
186
200
  end
187
201
 
188
- 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'
189
227
  end
190
228
 
229
+
230
+
191
231
  # puts '---------------- Xml resultante comprobante de pago -----------------------'
192
232
  # puts xml.to_xml
193
233
  # puts '--------------------------------------------------------'
@@ -240,9 +280,6 @@ module Fdis
240
280
  puts "-- Mensaje: #{json_response.message} --"
241
281
  puts "-- Body: "
242
282
  p json_response.body
243
- # puts "-- Body --"
244
- # puts json_response.body
245
- # puts '---'
246
283
  response = JSON.parse(json_response.body)
247
284
 
248
285
  case json_response
@@ -293,180 +330,39 @@ module Fdis
293
330
 
294
331
  end
295
332
 
296
- # def nota_credito(params={})
297
- # # Sample params
298
- # # params = {
299
- # # uuid_relacionado: '',
300
- # # desc: '',
301
- # # motivo: 'dev, mod',
302
- # # series: '',
303
- # # folio: '',
304
- # # cp: '',
305
- # # time: '',
306
- # # receptor_razon: '',
307
- # # receptor_rfc: '',
308
- # # uso_cfdi: '',
309
- # # }
310
-
311
- # total = (params[:monto]).to_f
312
- # subtotal = total / 1.16
313
- # tax = total - subtotal
314
-
315
- # uri = @production ? URI("#{Fdis::UrlProduction}cfdi33/stamp/customv1/b64") : URI("#{Fdis::UrlDev}cfdi33/stamp/customv1/b64")
316
- # token = @production ? @production_token : @dev_token
317
- # time = params.fetch(:time, (Time.now).strftime("%Y-%m-%dT%H:%M:%S"))
318
-
319
-
320
- # base_doc = %(<?xml version="1.0" encoding="utf-8"?>
321
- # <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">
322
- # <cfdi:CfdiRelacionados TipoRelacion="01">
323
- # <cfdi:CfdiRelacionado UUID="#{params[:uuid_relacionado]}" />
324
- # </cfdi:CfdiRelacionados>
325
- # <cfdi:Emisor Rfc="#{@rfc}" Nombre="#{@razon}" RegimenFiscal="#{@regimen_fiscal}" />
326
- # <cfdi:Receptor Rfc="#{params[:receptor_rfc]}" Nombre="#{params[:receptor_razon]}" UsoCFDI="#{params.fetch(:uso_cfdi, 'G03')}" />
327
- # <cfdi:Conceptos>
328
- # <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)}">
329
- # <cfdi:Impuestos>
330
- # <cfdi:Traslados>
331
- # <cfdi:Traslado Base="#{subtotal.round(2)}" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="#{tax.round(2)}" />
332
- # </cfdi:Traslados>
333
- # </cfdi:Impuestos>
334
- # </cfdi:Concepto>
335
- # </cfdi:Conceptos>
336
- # <cfdi:Impuestos TotalImpuestosTrasladados="#{tax.round(2)}">
337
- # <cfdi:Traslados>
338
- # <cfdi:Traslado Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="#{tax.round(2)}" />
339
- # </cfdi:Traslados>
340
- # </cfdi:Impuestos>
341
- # </cfdi:Comprobante>
342
- # )
343
-
344
- # base_doc.delete!("\n")
345
- # base_doc.delete!("\t")
346
-
347
- # xml = Nokogiri::XML(base_doc)
348
- # comprobante = xml.at_xpath("//cfdi:Comprobante")
349
-
350
- # path = File.join(File.dirname(__FILE__), *%w[.. tmp])
351
- # id = SecureRandom.hex
352
-
353
- # FileUtils.mkdir_p(path) unless File.exist?(path)
354
- # File.write("#{path}/tmp_n_#{id}.xml", xml.to_xml)
355
- # xml_path = "#{path}/tmp_n_#{id}.xml"
356
- # cadena_path = File.join(File.dirname(__FILE__), *%w[.. cadena cadena33.xslt])
357
-
358
- # File.write("#{path}/pem_#{id}.pem", @pem)
359
- # key_pem_url = "#{path}/pem_#{id}.pem"
360
- # sello = %x[xsltproc #{cadena_path} #{xml_path} | openssl dgst -sha256 -sign #{key_pem_url} | openssl enc -base64 -A]
361
- # comprobante['Sello'] = sello
362
-
363
- # File.delete("#{xml_path}")
364
- # File.delete("#{key_pem_url}")
365
-
366
- # puts '------ nota antes de timbre -------'
367
- # puts xml.to_xml
368
-
369
- # base64_xml = Base64.encode64(xml.to_xml)
370
-
371
- # request = Net::HTTP::Post.new(uri)
372
- # request.basic_auth(token, "")
373
- # request.content_type = "application/json"
374
- # request["cache-control"] = 'no-cache'
375
- # request.body = JSON.dump({
376
- # "credentials" => {
377
- # "id" => "#{params[:folio]}",
378
- # "token" => token
379
- # },
380
- # "issuer" => {
381
- # "rfc" => @rfc
382
- # },
383
- # "document" => {
384
- # "ref-id": "#{params[:folio]}",
385
- # "certificate-number": @serial,
386
- # "section": "all",
387
- # "format": "xml",
388
- # "template": "letter",
389
- # "type": "application/xml",
390
- # "content": base64_xml
391
- # }
392
- # })
393
-
394
- # req_options = {
395
- # use_ssl: false,
396
- # }
397
-
398
- # json_response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
399
- # http.request(request)
400
- # end
401
-
402
-
403
- # puts "-- #{json_response.code} --"
404
- # puts "-- #{json_response.message} --"
405
- # # puts "-- Body --"
406
- # # puts json_response.body
407
- # # puts '---'
408
- # response = JSON.parse(json_response.body)
409
-
410
- # if json_response.code == '200'
411
- # decoded_xml = Nokogiri::XML(Base64.decode64(response['content']))
412
- # timbre = decoded_xml.at_xpath("//cfdi:Complemento").children.first
413
-
414
- # response = {
415
- # status: 200,
416
- # message_error: '',
417
- # xml: decoded_xml.to_xml,
418
- # uuid: response['uuid'],
419
- # fecha_timbrado: timbre['FechaTimbrado'],
420
- # sello_cfd: timbre['SelloCFD'],
421
- # sello_sat: timbre['SelloSAT'],
422
- # no_certificado_sat: timbre['NoCertificadoSAT'],
423
- # }
424
- # return response
425
- # else
426
- # response = {
427
- # status: json_response.code,
428
- # message_error: "Error message: #{json_response.message}, #{response['message']} #{response['error_details']}",
429
- # xml: '',
430
- # uuid: '',
431
- # fecha_timbrado: '',
432
- # sello_cfd: '',
433
- # sello_sat: '',
434
- # no_certificado_sat: '',
435
- # }
436
- # return response
437
- # end
438
-
439
-
440
- # end
333
+
441
334
 
442
335
  def cancela_doc(params={})
336
+ puts "---- Fdis:facturacion:cancela_doc"
337
+
443
338
  # Sample params
444
339
  # params = {
445
340
  # uuid: '',
446
- # rfc_emisor: '',
341
+ # rfcReceptor: 'XAXX010101000',
342
+ # total_sale: 100.0,
447
343
  # motivo: '02',
344
+ # uuid_sustituye: '',
448
345
  # key_password: '', # optional
449
346
  # cer_cadena: '', # optional
450
347
  # key_pem: '' # optional
451
348
  # }
452
349
 
453
- uri = @production ? URI("#{Fdis::UrlProduction}cfdi33/cancel/csd") : URI("#{Fdis::UrlDev}cfdi33/cancel/csd")
454
- token = @production ? @production_token : @dev_token
455
- # time = params.fetch(:time, (Time.now).strftime("%Y-%m-%dT%H:%M:%S"))
456
-
457
350
 
351
+ uri = URI(Fdis::UrlCancel)
458
352
  request = Net::HTTP::Post.new(uri)
459
- request["Authorization"] = "bearer #{token}"
460
353
  request.content_type = "application/json"
461
- request["Cache-Control"] = 'no-cache'
462
- request["Postman-Token"] = '30b35bb8-534d-51c7-6a5c-e2c98a0c9395'
354
+
463
355
  request.body = JSON.dump({
464
- 'uuid': params[:uuid],
465
- "password": params.fetch(:key_password, @key_pass),
466
- "rfc": params.fetch(:rfc_emisor, @rfc),
467
- "motivo": '02',
468
- "b64Cer": params.fetch(:cer_cadena, @cadena),
469
- "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),
470
366
  })
471
367
 
472
368
  req_options = {
@@ -477,33 +373,47 @@ module Fdis
477
373
  http.request(request)
478
374
  end
479
375
 
480
- puts "-- #{json_response.code} --"
481
- puts "-- #{json_response.message} --"
482
- # puts "-- Body --"
483
- # puts json_response.body
484
- # puts '---'
485
- response = JSON.parse(json_response.body)
376
+ puts "---- Fdis: request"
377
+ puts "-- body: #{request.body} --"
486
378
 
487
- if json_response.code == '200'
488
- 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
489
384
 
490
- response = {
491
- status: 200,
492
- message_error: '',
493
- xml: decoded_xml,
494
- }
385
+ response = JSON.parse(json_response.body)
495
386
 
496
- return response
497
- 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
+ }
498
396
 
499
- response ={
500
- status: json_response.code,
501
- message_error: "Error message: #{json_response.message}, #{response['message']} #{response['error_details']}",
502
- xml: '',
503
- }
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
504
407
 
408
+ else
409
+ response = {
410
+ status: 400,
411
+ message_error: "Error: #{response['errors']}",
412
+ xml: '',
413
+
414
+ }
505
415
  return response
506
- end
416
+ end
507
417
 
508
418
  end
509
419
 
@@ -594,10 +504,12 @@ module Fdis
594
504
  receptor['DomicilioFiscalReceptor'] = params.fetch(:receptor_cp, '47180')
595
505
  if params[:receptor_razon] == 'XAXX010101000'
596
506
  receptor['UsoCFDI'] = 'S01'
507
+ receptor['RegimenFiscalReceptor'] = '616'
597
508
  else
598
509
  receptor['UsoCFDI'] = params.fetch(:uso_cfdi, 'G03')
510
+ # receptor['RegimenFiscalReceptor'] = params.fetch(:receptor_regimen, '616')
511
+ receptor['RegimenFiscalReceptor'] = params[:receptor_regimen]
599
512
  end
600
- receptor['RegimenFiscalReceptor'] = params.fetch(:receptor_regimen, '616')
601
513
 
602
514
  # retencion_iva = params.fetch(:retencion_iva, 0)
603
515
 
@@ -823,7 +735,7 @@ module Fdis
823
735
  puts "-- Codigo: #{json_response.code} --"
824
736
  puts "-- Mensaje: #{json_response.message} --"
825
737
  puts "-- Body: "
826
- p json_response.body
738
+ puts json_response.body
827
739
 
828
740
  response = JSON.parse(json_response.body)
829
741
 
@@ -875,206 +787,6 @@ module Fdis
875
787
 
876
788
  end
877
789
 
878
- def timbra_doc_cero(params={})
879
- puts "---- Fdis:facturacion:timbra_doc_cero"
880
- # params = {
881
- # moneda: 'MXN',
882
- # series: 'FA',
883
- # folio: '003',
884
- # forma_pago: '',
885
- # metodo_pago: 'PUE',
886
- # cp: '47180',
887
- # receptor_razon: 'Car zone',
888
- # receptor_rfc: '',
889
- # uso_cfdi: 'G03',
890
- # time: "%Y-%m-%dT%H:%M:%S",
891
- # line_items: [
892
- # {
893
- # clave_prod_serv: '78181500',
894
- # clave_unidad: 'E48',
895
- # unidad: 'Servicio',
896
- # sku: 'serv001',
897
- # cantidad: 1,
898
- # descripcion: 'Servicio mano de obra',
899
- # valor_unitario: 100.00,
900
- # # Optional parameters
901
- # },
902
- # ]
903
-
904
- # }
905
-
906
- uri = @production ? URI("#{Fdis::UrlProduction}cfdi33/stamp/customv1/b64") : URI("#{Fdis::UrlDev}cfdi33/stamp/customv1/b64")
907
- token = @production ? @production_token : @dev_token
908
- time = params.fetch(:time, (Time.now).strftime("%Y-%m-%dT%H:%M:%S"))
909
-
910
- xml = Nokogiri::XML(Fdis::DocBase)
911
- comprobante = xml.at_xpath("//cfdi:Comprobante")
912
- comprobante['TipoCambio'] = '1'
913
- comprobante['TipoDeComprobante'] = 'I'
914
- comprobante['Serie'] = params.fetch(:series, 'FA').to_s
915
- comprobante['Folio'] = params.fetch(:folio, '1').to_s
916
- comprobante['Fecha'] = time.to_s
917
- comprobante['FormaPago'] = params.fetch(:forma_pago, '01')
918
- comprobante['MetodoPago'] = params.fetch(:metodo_pago, 'PUE')
919
- comprobante['LugarExpedicion'] = params.fetch(:cp, '55555')
920
- comprobante['NoCertificado'] = @serial
921
- comprobante['Certificado'] = @cadena
922
-
923
- emisor = xml.at_xpath("//cfdi:Emisor")
924
- emisor['Nombre'] = @razon
925
- emisor['RegimenFiscal'] = @regimen_fiscal
926
- emisor['Rfc'] = @rfc
927
-
928
- receptor = xml.at_xpath("//cfdi:Receptor")
929
- receptor['Nombre'] = params.fetch(:receptor_razon, '')
930
- receptor['Rfc'] = params.fetch(:receptor_rfc, 'XAXX010101000')
931
- receptor['UsoCFDI'] = params.fetch(:uso_cfdi, 'G03')
932
-
933
-
934
- # impuestos = xml.at_xpath("//cfdi:Impuestos")
935
- # traslados = Nokogiri::XML::Node.new "cfdi:Traslados", xml
936
-
937
-
938
- puts '--- Fdis time -----'
939
- puts time
940
- puts '--------'
941
-
942
- conceptos = xml.at_xpath("//cfdi:Conceptos")
943
-
944
- line_items = params[:line_items]
945
-
946
- suma_total = 0.00
947
-
948
- line_items.each do |line|
949
-
950
- valor_unitario = line[:valor_unitario].to_f
951
- cantidad = line[:cantidad].to_f
952
- total_line = cantidad * valor_unitario
953
-
954
- suma_total += total_line
955
-
956
- ## Creando y poblando CFDI:CONCEPTO
957
- child_concepto = Nokogiri::XML::Node.new "cfdi:Concepto", xml
958
- child_concepto['ClaveProdServ'] = line[:clave_prod_serv].to_s
959
- child_concepto['NoIdentificacion'] = line[:sku].to_s
960
- child_concepto['ClaveUnidad'] = line[:clave_unidad].to_s
961
- child_concepto['Unidad'] = line[:unidad].to_s
962
- child_concepto['Descripcion'] = line[:descripcion].to_s
963
- child_concepto['Cantidad'] = cantidad.to_s
964
- child_concepto['ValorUnitario'] = valor_unitario.round(4).to_s
965
- child_concepto['Importe'] = total_line.round(4).to_s
966
-
967
-
968
- # Joining all up
969
- conceptos.add_child(child_concepto)
970
-
971
-
972
- end
973
-
974
- puts '------ Totales -----'
975
- puts "Subtotal = #{suma_total}"
976
- puts "Total = #{suma_total}"
977
-
978
- comprobante['Moneda'] = params.fetch(:moneda, 'MXN')
979
- comprobante['SubTotal'] = suma_total.round(2).to_s
980
- comprobante['Total'] = suma_total.round(2).to_s
981
-
982
-
983
-
984
- path = File.join(File.dirname(__FILE__), *%w[.. tmp])
985
- id = SecureRandom.hex
986
-
987
- FileUtils.mkdir_p(path) unless File.exist?(path)
988
- File.write("#{path}/tmp_#{id}.xml", xml.to_xml)
989
- xml_path = "#{path}/tmp_#{id}.xml"
990
- cadena_path = File.join(File.dirname(__FILE__), *%w[.. cadena cadena33.xslt])
991
-
992
- # puts File.read(cadena_path)
993
- File.write("#{path}/pem_#{id}.pem", @pem)
994
- key_pem_url = "#{path}/pem_#{id}.pem"
995
- sello = %x[xsltproc #{cadena_path} #{xml_path} | openssl dgst -sha256 -sign #{key_pem_url} | openssl enc -base64 -A]
996
- comprobante['Sello'] = sello
997
-
998
- File.delete("#{xml_path}")
999
- File.delete("#{key_pem_url}")
1000
-
1001
- puts '---- Fdis GEM comprobante sin timbrar ------'
1002
- puts xml.to_xml
1003
- puts '-------------------------'
1004
-
1005
- base64_xml = Base64.encode64(xml.to_xml)
1006
- request = Net::HTTP::Post.new(uri)
1007
- request.basic_auth(token, "")
1008
- request.content_type = "application/json"
1009
- request["cache-control"] = 'no-cache'
1010
- request.body = JSON.dump({
1011
- "credentials" => {
1012
- "id" => params.fetch(:folio).to_s,
1013
- "token" => token
1014
- },
1015
- "issuer" => {
1016
- "rfc" => emisor['Rfc']
1017
- },
1018
- "document" => {
1019
- "ref-id": params.fetch(:folio).to_s,
1020
- "certificate-number": comprobante['NoCertificado'],
1021
- "section": "all",
1022
- "format": "xml",
1023
- "template": "letter",
1024
- "type": "application/xml",
1025
- "content": base64_xml
1026
- }
1027
- })
1028
-
1029
- req_options = {
1030
- use_ssl: false,
1031
- }
1032
-
1033
- json_response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
1034
- http.request(request)
1035
- end
1036
-
1037
- puts "-- Fdis API reponse..."
1038
- puts "-- Response code: #{json_response.code} --"
1039
- puts "-- Response body: #{json_response.body} --"
1040
- puts "-- Response message: #{json_response.message} --"
1041
-
1042
- response = JSON.parse(json_response.body)
1043
-
1044
- if json_response.code == '200'
1045
- decoded_xml = Nokogiri::XML(Base64.decode64(response['content']))
1046
- timbre = decoded_xml.at_xpath("//cfdi:Complemento").children.first
1047
-
1048
- response = {
1049
- status: 200,
1050
- message_error: '',
1051
- xml: decoded_xml.to_xml,
1052
- uuid: response['uuid'],
1053
- fecha_timbrado: timbre['FechaTimbrado'],
1054
- sello_cfd: timbre['SelloCFD'],
1055
- sello_sat: timbre['SelloSAT'],
1056
- no_certificado_sat: timbre['NoCertificadoSAT'],
1057
- }
1058
-
1059
- return response
1060
- else
1061
-
1062
- response ={
1063
- status: json_response.code,
1064
- message_error: "Error message: #{json_response.message}, #{response['message']} #{response['error_details']}",
1065
- xml: '',
1066
- uuid: '',
1067
- fecha_timbrado: '',
1068
- sello_cfd: '',
1069
- sello_sat: '',
1070
- no_certificado_sat: '',
1071
- }
1072
-
1073
- return response
1074
- end
1075
-
1076
-
1077
- end
1078
790
 
1079
791
 
1080
792
  end
data/lib/fdis/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Fdis
2
- VERSION = "0.1.14"
2
+ VERSION = "0.1.26"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fdis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.14
4
+ version: 0.1.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - Angel Padilla
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-02 00:00:00.000000000 Z
11
+ date: 2022-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler