sw_fac 0.3.58.1 → 0.3.63

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: 5eae8e8ff634c17390c533c6b652bdc12c7ac27be0ee4436111ba340d2ff1cad
4
- data.tar.gz: 4b39fc66e28f553a5bd85911fdb6cf29a631d115fa690b946b62ff0ddf6fd558
3
+ metadata.gz: ff59c51cb10373fbc6e32713380a3f4b375e90f962086d71254ca11075e39ada
4
+ data.tar.gz: 9add1352a09c499c0201b83d9bd73853494d34e1dab295e8bcd46ed4a205155b
5
5
  SHA512:
6
- metadata.gz: 3933c3d8948006205e8373caccb6797083e12127b8cc6125ba692b40af58d65302c89df7fec1c0293e5c02f7935a6a7809977346e13f5099a702fdc3f3ede89d
7
- data.tar.gz: d410c5841b3cd3deec5ca6cae62bff2c847db723c8d5f88e489736fd4b664b742b0fa1348570a3832f8e5647891f9fa7530699108aa7581df16541541b3134eb
6
+ metadata.gz: 75815faa0da46d83cf5d1aba0e8b730f08a0b76a1ca762c7d9a294e265ea64035d728f7f51c925b4bb714e3b1e31f626d95b58c506ec743d53693038b5ebfc50
7
+ data.tar.gz: b209ef695f4fe7857801a2d2921f478f2e2a0f1d4de340f43af04dd31454539c06dd06dd5b9d3bd0c37eed0192de8c3227a11a86e43b7f18f4c3390c6e3150b5
data/lib/sw_fac/config.rb CHANGED
@@ -25,7 +25,10 @@ module SwFac
25
25
  def key_to_pem
26
26
  puts "---- SwFacturacion:config:key_to_pem"
27
27
 
28
+ puts "-- 1"
28
29
  @pem = %x[openssl pkcs8 -inform DER -in #{@doc_key_path} -passin pass:#{@key_pass}]
30
+ # @pem = %x[openssl rsa -inform DER -in #{@doc_key_path} -passin pass:#{@key_pass}]
31
+ puts "-- 2"
29
32
  @pem_cadena = @pem.clone
30
33
  @pem_cadena.slice!("-----BEGIN PRIVATE KEY-----")
31
34
  @pem_cadena.slice!("-----END PRIVATE KEY-----")
@@ -74,6 +77,9 @@ module SwFac
74
77
  <cfdi:Receptor /><cfdi:Conceptos></cfdi:Conceptos>
75
78
  <cfdi:Impuestos></cfdi:Impuestos></cfdi:Comprobante>)
76
79
 
80
+ DocBaseCero = %(<?xml version="1.0" encoding="utf-8"?><cfdi:Comprobante xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd" Version="3.3" xmlns:cfdi="http://www.sat.gob.mx/cfd/3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><cfdi:Emisor />
81
+ <cfdi:Receptor /><cfdi:Conceptos></cfdi:Conceptos></cfdi:Comprobante>)
82
+
77
83
  Doc_concepto = %(<cfdi:Concepto ClaveProdServ="25172504" NoIdentificacion="COST37125R17" Cantidad="1" ClaveUnidad="H87" Unidad="Pieza" Descripcion="Producto de prueba" ValorUnitario="1000.00" Importe="1000.00"><cfdi:Impuestos><cfdi:Traslados><cfdi:Traslado Base="1000.00" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="160.00" /></cfdi:Traslados></cfdi:Impuestos></cfdi:Concepto>)
78
84
 
79
85
 
@@ -12,7 +12,8 @@ module SwFac
12
12
  # receptor_rfc: 'XAXX010101000',
13
13
  # forma_pago: '01',
14
14
  # total: 100.00,
15
- # time: '',
15
+ # time_pago: '',
16
+ # time_now: '',
16
17
  # modena: '',
17
18
  # line_items: [
18
19
  # {
@@ -36,9 +37,16 @@ module SwFac
36
37
  raise 'Error SW - la suma de los complementos de pago es mayor al total reportado'
37
38
  end
38
39
 
40
+ unless params[:time_pago] and params[:time_pago].size > 0
41
+ raise "Error SW - la fecha de timbrado debe de estar presente"
42
+ end
43
+
44
+
45
+
39
46
  uri = @production ? URI("#{SwFac::UrlProduction}cfdi33/stamp/customv1/b64") : URI("#{SwFac::UrlDev}cfdi33/stamp/customv1/b64")
40
47
  token = @production ? @production_token : @dev_token
41
- time = params.fetch(:time, (Time.now).strftime("%Y-%m-%dT%H:%M:%S"))
48
+ time_now = params.fetch(:time_now, (Time.now).strftime("%Y-%m-%dT%H:%M:%S"))
49
+ time_pago = params[:time_pago]
42
50
 
43
51
 
44
52
  base_doc = %(<?xml version="1.0" encoding="UTF-8"?>
@@ -57,13 +65,13 @@ module SwFac
57
65
  </cfdi:Comprobante>)
58
66
 
59
67
  base_doc.delete!("\n")
60
- base_doc.delete!("\t")
68
+ base_doc.delete!("\t")
61
69
 
62
- xml = Nokogiri::XML(base_doc)
70
+ xml = Nokogiri::XML(base_doc)
63
71
  comprobante = xml.at_xpath("//cfdi:Comprobante")
64
72
  comprobante['Serie'] = 'P'
65
73
  comprobante['Folio'] = params[:venta_folio].to_s
66
- comprobante['Fecha'] = time
74
+ comprobante['Fecha'] = time_now
67
75
  comprobante['LugarExpedicion'] = params[:cp].to_s
68
76
  comprobante['NoCertificado'] = @serial
69
77
  comprobante['Certificado'] = @cadena
@@ -76,7 +84,7 @@ module SwFac
76
84
  receptor['Rfc'] = params[:receptor_rfc].to_s
77
85
 
78
86
  child_pago = xml.at_xpath("//pago10:Pago")
79
- child_pago['FechaPago'] = time
87
+ child_pago['FechaPago'] = time_pago
80
88
  child_pago['FormaDePagoP'] = params[:forma_pago].to_s
81
89
  child_pago['MonedaP'] = params.fetch(:moneda, 'MXN')
82
90
  child_pago['Monto'] = params[:total].round(2).to_s
@@ -84,19 +92,19 @@ module SwFac
84
92
  saldo_anterior = params[:total]
85
93
 
86
94
  params[:line_items].each_with_index do |line, index|
87
- monto = line[:monto].to_f
88
- child_pago_relacionado = Nokogiri::XML::Node.new "pago10:DoctoRelacionado", xml
89
- child_pago_relacionado['IdDocumento'] = params[:uuid]
90
- child_pago_relacionado['MonedaDR'] = line.fetch(:moneda, 'MXN')
91
- child_pago_relacionado['MetodoDePagoDR'] = 'PPD'
92
- child_pago_relacionado['NumParcialidad'] = (index + 1).to_s
93
-
94
- child_pago_relacionado['ImpSaldoAnt'] = (saldo_anterior).round(2).to_s
95
- child_pago_relacionado['ImpPagado'] = monto.round(2).to_s
96
- child_pago_relacionado['ImpSaldoInsoluto'] = (saldo_anterior - monto).round(2).to_s
97
- saldo_anterior -= monto
98
-
99
- child_pago.add_child(child_pago_relacionado)
95
+ monto = line[:monto].to_f
96
+ child_pago_relacionado = Nokogiri::XML::Node.new "pago10:DoctoRelacionado", xml
97
+ child_pago_relacionado['IdDocumento'] = params[:uuid]
98
+ child_pago_relacionado['MonedaDR'] = line.fetch(:moneda, 'MXN')
99
+ child_pago_relacionado['MetodoDePagoDR'] = 'PPD'
100
+ child_pago_relacionado['NumParcialidad'] = (index + 1).to_s
101
+
102
+ child_pago_relacionado['ImpSaldoAnt'] = (saldo_anterior).round(2).to_s
103
+ child_pago_relacionado['ImpPagado'] = monto.round(2).to_s
104
+ child_pago_relacionado['ImpSaldoInsoluto'] = (saldo_anterior - monto).round(2).to_s
105
+ saldo_anterior -= monto
106
+
107
+ child_pago.add_child(child_pago_relacionado)
100
108
  end
101
109
 
102
110
  # puts '---------------- Xml resultante comprobante de pago -----------------------'
@@ -122,7 +130,7 @@ module SwFac
122
130
  # puts '------ comprobante de pago antes de timbre -------'
123
131
  # puts xml.to_xml
124
132
 
125
- base64_xml = Base64.encode64(xml.to_xml)
133
+ base64_xml = Base64.encode64(xml.to_xml)
126
134
  request = Net::HTTP::Post.new(uri)
127
135
  request.basic_auth(token, "")
128
136
  request.content_type = "application/json"
@@ -147,7 +155,7 @@ module SwFac
147
155
  })
148
156
 
149
157
  req_options = {
150
- use_ssl: false,
158
+ use_ssl: false,
151
159
  }
152
160
 
153
161
  json_response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
@@ -341,6 +349,7 @@ module SwFac
341
349
  # params = {
342
350
  # uuid: '',
343
351
  # rfc_emisor: '',
352
+ # motivo: '02',
344
353
  # key_password: '', # optional
345
354
  # cer_cadena: '', # optional
346
355
  # key_pem: '' # optional
@@ -360,6 +369,7 @@ module SwFac
360
369
  'uuid': params[:uuid],
361
370
  "password": params.fetch(:key_password, @key_pass),
362
371
  "rfc": params.fetch(:rfc_emisor, @rfc),
372
+ "motivo": '02',
363
373
  "b64Cer": params.fetch(:cer_cadena, @cadena),
364
374
  "b64Key": params.fetch(:key_pem, @pem_cadena)
365
375
  })
@@ -402,6 +412,46 @@ module SwFac
402
412
 
403
413
  end
404
414
 
415
+ def timbra_v4(params={})
416
+ puts "---- SwFacturacion:facturacion:timbra_v4"
417
+
418
+ ### sample params
419
+ #
420
+ # params = {
421
+ # moneda: 'MXN',
422
+ # series: 'FA',
423
+ # folio: '003',
424
+ # forma_pago: '',
425
+ # metodo_pago: 'PUE',
426
+ # cp: '47180',
427
+ # receptor_razon: 'Car zone',
428
+ # receptor_rfc: '',
429
+ # receptor_regimen: '',
430
+ # uso_cfdi: 'G03',
431
+ # time: "%Y-%m-%dT%H:%M:%S",
432
+ # line_items: [
433
+ # {
434
+ # clave_prod_serv: '78181500',
435
+ # clave_unidad: 'E48',
436
+ # unidad: 'Servicio',
437
+ # sku: 'serv001',
438
+ # cantidad: 1,
439
+ # descripcion: 'Servicio mano de obra',
440
+ # valor_unitario: 100.00,
441
+ # descuento: 0.00,
442
+ # tax_included: true,
443
+ # retencion_iva: 0, 6, 16
444
+ # # Optional parameters
445
+ # },
446
+ # ]
447
+
448
+ # }
449
+
450
+ uri = @production ? URI("#{SwFac::UrlProduction}cfdi33/stamp/customv1/b64") : URI("#{SwFac::UrlDev}cfdi33/stamp/customv1/b64")
451
+ token = @production ? @production_token : @dev_token
452
+ time = params.fetch(:time, (Time.now).strftime("%Y-%m-%dT%H:%M:%S"))
453
+ end
454
+
405
455
  def timbra_doc(params={})
406
456
  ### sample params
407
457
  #
@@ -644,8 +694,8 @@ module SwFac
644
694
  id = SecureRandom.hex
645
695
 
646
696
  FileUtils.mkdir_p(path) unless File.exist?(path)
647
- File.write("#{path}/tmp_#{id}.xml", xml.to_xml)
648
- xml_path = "#{path}/tmp_#{id}.xml"
697
+ File.write("#{path}/tmp_#{id}.xml", xml.to_xml)
698
+ xml_path = "#{path}/tmp_#{id}.xml"
649
699
  cadena_path = File.join(File.dirname(__FILE__), *%w[.. cadena cadena33.xslt])
650
700
 
651
701
  # puts File.read(cadena_path)
@@ -734,6 +784,207 @@ module SwFac
734
784
 
735
785
 
736
786
 
787
+ end
788
+
789
+ def timbra_doc_cero(params={})
790
+ puts "---- SwFacturacion:facturacion:timbra_doc_cero"
791
+ # params = {
792
+ # moneda: 'MXN',
793
+ # series: 'FA',
794
+ # folio: '003',
795
+ # forma_pago: '',
796
+ # metodo_pago: 'PUE',
797
+ # cp: '47180',
798
+ # receptor_razon: 'Car zone',
799
+ # receptor_rfc: '',
800
+ # uso_cfdi: 'G03',
801
+ # time: "%Y-%m-%dT%H:%M:%S",
802
+ # line_items: [
803
+ # {
804
+ # clave_prod_serv: '78181500',
805
+ # clave_unidad: 'E48',
806
+ # unidad: 'Servicio',
807
+ # sku: 'serv001',
808
+ # cantidad: 1,
809
+ # descripcion: 'Servicio mano de obra',
810
+ # valor_unitario: 100.00,
811
+ # # Optional parameters
812
+ # },
813
+ # ]
814
+
815
+ # }
816
+
817
+ uri = @production ? URI("#{SwFac::UrlProduction}cfdi33/stamp/customv1/b64") : URI("#{SwFac::UrlDev}cfdi33/stamp/customv1/b64")
818
+ token = @production ? @production_token : @dev_token
819
+ time = params.fetch(:time, (Time.now).strftime("%Y-%m-%dT%H:%M:%S"))
820
+
821
+ xml = Nokogiri::XML(SwFac::DocBaseCero)
822
+ comprobante = xml.at_xpath("//cfdi:Comprobante")
823
+ comprobante['TipoCambio'] = '1'
824
+ comprobante['TipoDeComprobante'] = 'I'
825
+ comprobante['Serie'] = params.fetch(:series, 'FA').to_s
826
+ comprobante['Folio'] = params.fetch(:folio, '1').to_s
827
+ comprobante['Fecha'] = time.to_s
828
+ comprobante['FormaPago'] = params.fetch(:forma_pago, '01')
829
+ comprobante['MetodoPago'] = params.fetch(:metodo_pago, 'PUE')
830
+ comprobante['LugarExpedicion'] = params.fetch(:cp, '55555')
831
+ comprobante['NoCertificado'] = @serial
832
+ comprobante['Certificado'] = @cadena
833
+
834
+ emisor = xml.at_xpath("//cfdi:Emisor")
835
+ emisor['Nombre'] = @razon
836
+ emisor['RegimenFiscal'] = @regimen_fiscal
837
+ emisor['Rfc'] = @rfc
838
+
839
+ receptor = xml.at_xpath("//cfdi:Receptor")
840
+ receptor['Nombre'] = params.fetch(:receptor_razon, '')
841
+ receptor['Rfc'] = params.fetch(:receptor_rfc, 'XAXX010101000')
842
+ receptor['UsoCFDI'] = params.fetch(:uso_cfdi, 'G03')
843
+
844
+
845
+ # impuestos = xml.at_xpath("//cfdi:Impuestos")
846
+ # traslados = Nokogiri::XML::Node.new "cfdi:Traslados", xml
847
+
848
+
849
+ puts '--- sw_fac time -----'
850
+ puts time
851
+ puts '--------'
852
+
853
+ conceptos = xml.at_xpath("//cfdi:Conceptos")
854
+
855
+ line_items = params[:line_items]
856
+
857
+ suma_total = 0.00
858
+
859
+ line_items.each do |line|
860
+
861
+ valor_unitario = line[:valor_unitario].to_f
862
+ cantidad = line[:cantidad].to_f
863
+ total_line = cantidad * valor_unitario
864
+
865
+ suma_total += total_line
866
+
867
+ ## Creando y poblando CFDI:CONCEPTO
868
+ child_concepto = Nokogiri::XML::Node.new "cfdi:Concepto", xml
869
+ child_concepto['ClaveProdServ'] = line[:clave_prod_serv].to_s
870
+ child_concepto['NoIdentificacion'] = line[:sku].to_s
871
+ child_concepto['ClaveUnidad'] = line[:clave_unidad].to_s
872
+ child_concepto['Unidad'] = line[:unidad].to_s
873
+ child_concepto['Descripcion'] = line[:descripcion].to_s
874
+ child_concepto['Cantidad'] = cantidad.to_s
875
+ child_concepto['ValorUnitario'] = valor_unitario.round(4).to_s
876
+ child_concepto['Importe'] = total_line.round(4).to_s
877
+
878
+
879
+ # Joining all up
880
+ conceptos.add_child(child_concepto)
881
+
882
+
883
+ end
884
+
885
+ puts '------ Totales -----'
886
+ puts "Subtotal = #{suma_total}"
887
+ puts "Total = #{suma_total}"
888
+
889
+ comprobante['Moneda'] = params.fetch(:moneda, 'MXN')
890
+ comprobante['SubTotal'] = suma_total.round(2).to_s
891
+ comprobante['Total'] = suma_total.round(2).to_s
892
+
893
+
894
+
895
+ path = File.join(File.dirname(__FILE__), *%w[.. tmp])
896
+ id = SecureRandom.hex
897
+
898
+ FileUtils.mkdir_p(path) unless File.exist?(path)
899
+ File.write("#{path}/tmp_#{id}.xml", xml.to_xml)
900
+ xml_path = "#{path}/tmp_#{id}.xml"
901
+ cadena_path = File.join(File.dirname(__FILE__), *%w[.. cadena cadena33.xslt])
902
+
903
+ # puts File.read(cadena_path)
904
+ File.write("#{path}/pem_#{id}.pem", @pem)
905
+ key_pem_url = "#{path}/pem_#{id}.pem"
906
+ sello = %x[xsltproc #{cadena_path} #{xml_path} | openssl dgst -sha256 -sign #{key_pem_url} | openssl enc -base64 -A]
907
+ comprobante['Sello'] = sello
908
+
909
+ File.delete("#{xml_path}")
910
+ File.delete("#{key_pem_url}")
911
+
912
+ puts '---- SW GEM comprobante sin timbrar ------'
913
+ puts xml.to_xml
914
+ puts '-------------------------'
915
+
916
+ base64_xml = Base64.encode64(xml.to_xml)
917
+ request = Net::HTTP::Post.new(uri)
918
+ request.basic_auth(token, "")
919
+ request.content_type = "application/json"
920
+ request["cache-control"] = 'no-cache'
921
+ request.body = JSON.dump({
922
+ "credentials" => {
923
+ "id" => params.fetch(:folio).to_s,
924
+ "token" => token
925
+ },
926
+ "issuer" => {
927
+ "rfc" => emisor['Rfc']
928
+ },
929
+ "document" => {
930
+ "ref-id": params.fetch(:folio).to_s,
931
+ "certificate-number": comprobante['NoCertificado'],
932
+ "section": "all",
933
+ "format": "xml",
934
+ "template": "letter",
935
+ "type": "application/xml",
936
+ "content": base64_xml
937
+ }
938
+ })
939
+
940
+ req_options = {
941
+ use_ssl: false,
942
+ }
943
+
944
+ json_response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
945
+ http.request(request)
946
+ end
947
+
948
+ puts "-- SW API reponse..."
949
+ puts "-- Response code: #{json_response.code} --"
950
+ puts "-- Response body: #{json_response.body} --"
951
+ puts "-- Response message: #{json_response.message} --"
952
+
953
+ response = JSON.parse(json_response.body)
954
+
955
+ if json_response.code == '200'
956
+ decoded_xml = Nokogiri::XML(Base64.decode64(response['content']))
957
+ timbre = decoded_xml.at_xpath("//cfdi:Complemento").children.first
958
+
959
+ response = {
960
+ status: 200,
961
+ message_error: '',
962
+ xml: decoded_xml.to_xml,
963
+ uuid: response['uuid'],
964
+ fecha_timbrado: timbre['FechaTimbrado'],
965
+ sello_cfd: timbre['SelloCFD'],
966
+ sello_sat: timbre['SelloSAT'],
967
+ no_certificado_sat: timbre['NoCertificadoSAT'],
968
+ }
969
+
970
+ return response
971
+ else
972
+
973
+ response ={
974
+ status: json_response.code,
975
+ message_error: "Error message: #{json_response.message}, #{response['message']} #{response['error_details']}",
976
+ xml: '',
977
+ uuid: '',
978
+ fecha_timbrado: '',
979
+ sello_cfd: '',
980
+ sello_sat: '',
981
+ no_certificado_sat: '',
982
+ }
983
+
984
+ return response
985
+ end
986
+
987
+
737
988
  end
738
989
 
739
990
 
@@ -1,3 +1,3 @@
1
1
  module SwFac
2
- VERSION = "0.3.58.1"
2
+ VERSION = "0.3.63"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sw_fac
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.58.1
4
+ version: 0.3.63
5
5
  platform: ruby
6
6
  authors:
7
7
  - Angel Padilla
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-26 00:00:00.000000000 Z
11
+ date: 2022-09-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -129,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
129
  - !ruby/object:Gem::Version
130
130
  version: '0'
131
131
  requirements: []
132
- rubygems_version: 3.0.3
132
+ rubygems_version: 3.0.1
133
133
  signing_key:
134
134
  specification_version: 4
135
135
  summary: Gem used to fetch the Smarter Web API