fdis 0.1.14 → 0.1.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 718f47667107fd56121df926c67529e7111390eef82e1d2959a864e3e0e2bd5b
4
- data.tar.gz: 8417ade616027659aa225814e9ee67720a7c4196ca200a0fc0fef0079442da9c
3
+ metadata.gz: b056d0d3aaf443e6e969baea7afb73b0d90cc7ec99c95a2827f5c9834762f656
4
+ data.tar.gz: e9b4d06ba55a6af625df12b5e93f3989b524ac52b206b0585748e732d6bb2ae1
5
5
  SHA512:
6
- metadata.gz: 4d67e2997a08e4eee366782a0087c319a0885619c74c35ee50b16af3ce741d47b4b9f0e7e53dd9e71182e921d00680aa01322fafbf6b8ad47ea7fc388eb46bd7
7
- data.tar.gz: 3d5176b9226584b67471a97537a535e6bb38a56b69fc369c695226f882ba3894a7a047d2f6fb24f51b808005b81506b2aa88eba0e23d3cf3f0a80aaa1b0a799a
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,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
 
@@ -875,206 +785,6 @@ module Fdis
875
785
 
876
786
  end
877
787
 
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
788
 
1079
789
 
1080
790
  end
data/lib/fdis/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Fdis
2
- VERSION = "0.1.14"
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.14
4
+ version: 0.1.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Angel Padilla