trevol 0.1.0
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 +7 -0
- data/CHANGELOG.md +15 -0
- data/GENERADO.md +14 -0
- data/LICENSE +21 -0
- data/README.md +173 -0
- data/lib/trevol/client.rb +94 -0
- data/lib/trevol/errors.rb +152 -0
- data/lib/trevol/llave.rb +21 -0
- data/lib/trevol/paginacion.rb +41 -0
- data/lib/trevol/transporte.rb +173 -0
- data/lib/trevol/webhook.rb +100 -0
- data/lib/trevol.rb +18 -0
- data/lib/trevol_generado/api/balance_api.rb +220 -0
- data/lib/trevol_generado/api/credit_notes_api.rb +671 -0
- data/lib/trevol_generado/api/debit_notes_api.rb +671 -0
- data/lib/trevol_generado/api/equivalent_document_adjustments_api.rb +691 -0
- data/lib/trevol_generado/api/equivalent_documents_api.rb +698 -0
- data/lib/trevol_generado/api/events_api.rb +231 -0
- data/lib/trevol_generado/api/general_api.rb +201 -0
- data/lib/trevol_generado/api/invoices_api.rb +736 -0
- data/lib/trevol_generado/api/payroll_adjustments_api.rb +637 -0
- data/lib/trevol_generado/api/payrolls_api.rb +637 -0
- data/lib/trevol_generado/api/radian_events_api.rb +431 -0
- data/lib/trevol_generado/api/requests_api.rb +97 -0
- data/lib/trevol_generado/api/support_document_adjustments_api.rb +565 -0
- data/lib/trevol_generado/api/support_documents_api.rb +565 -0
- data/lib/trevol_generado/api/webhook_endpoints_api.rb +556 -0
- data/lib/trevol_generado/api_client.rb +441 -0
- data/lib/trevol_generado/api_error.rb +58 -0
- data/lib/trevol_generado/api_model_base.rb +88 -0
- data/lib/trevol_generado/configuration.rb +392 -0
- data/lib/trevol_generado/models/acquirer.rb +209 -0
- data/lib/trevol_generado/models/air_collection.rb +205 -0
- data/lib/trevol_generado/models/air_extension.rb +216 -0
- data/lib/trevol_generado/models/allowance_charge.rb +250 -0
- data/lib/trevol_generado/models/alternative_currency.rb +180 -0
- data/lib/trevol_generado/models/balance.rb +244 -0
- data/lib/trevol_generado/models/balance_event_data.rb +172 -0
- data/lib/trevol_generado/models/balance_transaction.rb +265 -0
- data/lib/trevol_generado/models/balance_transaction_company.rb +172 -0
- data/lib/trevol_generado/models/balance_transaction_document.rb +173 -0
- data/lib/trevol_generado/models/balance_transaction_list.rb +191 -0
- data/lib/trevol_generado/models/carrier.rb +219 -0
- data/lib/trevol_generado/models/certificate_event_data.rb +180 -0
- data/lib/trevol_generado/models/cinema_extension.rb +214 -0
- data/lib/trevol_generado/models/cinema_screening.rb +256 -0
- data/lib/trevol_generado/models/company.rb +267 -0
- data/lib/trevol_generado/models/company_key.rb +182 -0
- data/lib/trevol_generado/models/company_numbering.rb +201 -0
- data/lib/trevol_generado/models/consumption.rb +246 -0
- data/lib/trevol_generado/models/consumption_adjustment.rb +204 -0
- data/lib/trevol_generado/models/contingency.rb +160 -0
- data/lib/trevol_generado/models/credit_note_list.rb +191 -0
- data/lib/trevol_generado/models/currency.rb +241 -0
- data/lib/trevol_generado/models/customer.rb +360 -0
- data/lib/trevol_generado/models/debit_note_list.rb +191 -0
- data/lib/trevol_generado/models/deleted_object.rb +178 -0
- data/lib/trevol_generado/models/delivery.rb +200 -0
- data/lib/trevol_generado/models/delivery_email.rb +181 -0
- data/lib/trevol_generado/models/delivery_terms.rb +169 -0
- data/lib/trevol_generado/models/dian_result.rb +182 -0
- data/lib/trevol_generado/models/dian_rule.rb +216 -0
- data/lib/trevol_generado/models/document.rb +432 -0
- data/lib/trevol_generado/models/document_event_data.rb +315 -0
- data/lib/trevol_generado/models/document_reference.rb +169 -0
- data/lib/trevol_generado/models/document_totals.rb +299 -0
- data/lib/trevol_generado/models/document_totals_currency.rb +197 -0
- data/lib/trevol_generado/models/document_totals_item.rb +196 -0
- data/lib/trevol_generado/models/document_totals_tax.rb +197 -0
- data/lib/trevol_generado/models/document_totals_withholding.rb +206 -0
- data/lib/trevol_generado/models/equivalent_adjustment_item.rb +374 -0
- data/lib/trevol_generado/models/equivalent_document.rb +470 -0
- data/lib/trevol_generado/models/equivalent_document_adjustment.rb +440 -0
- data/lib/trevol_generado/models/equivalent_document_adjustment_input.rb +388 -0
- data/lib/trevol_generado/models/equivalent_document_adjustment_list.rb +191 -0
- data/lib/trevol_generado/models/equivalent_document_contingency.rb +181 -0
- data/lib/trevol_generado/models/equivalent_document_contingency_backup.rb +171 -0
- data/lib/trevol_generado/models/equivalent_document_event_data.rb +313 -0
- data/lib/trevol_generado/models/equivalent_document_input.rb +365 -0
- data/lib/trevol_generado/models/equivalent_document_list.rb +191 -0
- data/lib/trevol_generado/models/equivalent_document_reference.rb +241 -0
- data/lib/trevol_generado/models/equivalent_item.rb +387 -0
- data/lib/trevol_generado/models/event.rb +223 -0
- data/lib/trevol_generado/models/event_claim.rb +170 -0
- data/lib/trevol_generado/models/event_delivery.rb +178 -0
- data/lib/trevol_generado/models/event_delivery_email.rb +161 -0
- data/lib/trevol_generado/models/event_dian_result.rb +173 -0
- data/lib/trevol_generado/models/event_dian_rule.rb +170 -0
- data/lib/trevol_generado/models/event_document_error.rb +170 -0
- data/lib/trevol_generado/models/event_equivalent_document_ref.rb +161 -0
- data/lib/trevol_generado/models/event_error.rb +170 -0
- data/lib/trevol_generado/models/event_invoice_ref.rb +161 -0
- data/lib/trevol_generado/models/event_list.rb +191 -0
- data/lib/trevol_generado/models/event_payroll_ref.rb +160 -0
- data/lib/trevol_generado/models/event_radian_invoice_ref.rb +181 -0
- data/lib/trevol_generado/models/event_resend_input.rb +177 -0
- data/lib/trevol_generado/models/event_support_document_ref.rb +161 -0
- data/lib/trevol_generado/models/extension.rb +215 -0
- data/lib/trevol_generado/models/foreign_address.rb +218 -0
- data/lib/trevol_generado/models/free_of_charge.rb +170 -0
- data/lib/trevol_generado/models/game.rb +203 -0
- data/lib/trevol_generado/models/game_credit.rb +204 -0
- data/lib/trevol_generado/models/games_extension.rb +216 -0
- data/lib/trevol_generado/models/games_venue.rb +204 -0
- data/lib/trevol_generado/models/interoperability.rb +205 -0
- data/lib/trevol_generado/models/interoperability_collection.rb +171 -0
- data/lib/trevol_generado/models/interoperability_data.rb +186 -0
- data/lib/trevol_generado/models/invoice_input.rb +364 -0
- data/lib/trevol_generado/models/invoice_list.rb +191 -0
- data/lib/trevol_generado/models/invoice_reference.rb +198 -0
- data/lib/trevol_generado/models/item.rb +439 -0
- data/lib/trevol_generado/models/item_allowance.rb +190 -0
- data/lib/trevol_generado/models/item_consignment.rb +286 -0
- data/lib/trevol_generado/models/item_mandator.rb +231 -0
- data/lib/trevol_generado/models/item_notary.rb +204 -0
- data/lib/trevol_generado/models/item_property.rb +223 -0
- data/lib/trevol_generado/models/item_tax.rb +246 -0
- data/lib/trevol_generado/models/item_withholding.rb +214 -0
- data/lib/trevol_generado/models/meter.rb +233 -0
- data/lib/trevol_generado/models/note_input.rb +329 -0
- data/lib/trevol_generado/models/numbering.rb +178 -0
- data/lib/trevol_generado/models/numbering_expiring_event_data.rb +209 -0
- data/lib/trevol_generado/models/numbering_low_event_data.rb +209 -0
- data/lib/trevol_generado/models/origin_note.rb +230 -0
- data/lib/trevol_generado/models/payment.rb +232 -0
- data/lib/trevol_generado/models/payment_method.rb +187 -0
- data/lib/trevol_generado/models/payroll.rb +455 -0
- data/lib/trevol_generado/models/payroll_adjustment.rb +467 -0
- data/lib/trevol_generado/models/payroll_adjustment_input.rb +362 -0
- data/lib/trevol_generado/models/payroll_adjustment_list.rb +191 -0
- data/lib/trevol_generado/models/payroll_basic.rb +204 -0
- data/lib/trevol_generado/models/payroll_compensated_vacation.rb +204 -0
- data/lib/trevol_generado/models/payroll_compensation.rb +205 -0
- data/lib/trevol_generado/models/payroll_deductions.rb +370 -0
- data/lib/trevol_generado/models/payroll_disability.rb +249 -0
- data/lib/trevol_generado/models/payroll_earnings.rb +406 -0
- data/lib/trevol_generado/models/payroll_employee.rb +437 -0
- data/lib/trevol_generado/models/payroll_employer.rb +238 -0
- data/lib/trevol_generado/models/payroll_epctv_bonus.rb +191 -0
- data/lib/trevol_generado/models/payroll_event_data.rb +303 -0
- data/lib/trevol_generado/models/payroll_files.rb +179 -0
- data/lib/trevol_generado/models/payroll_input.rb +420 -0
- data/lib/trevol_generado/models/payroll_leaves.rb +184 -0
- data/lib/trevol_generado/models/payroll_list.rb +191 -0
- data/lib/trevol_generado/models/payroll_loan.rb +204 -0
- data/lib/trevol_generado/models/payroll_novelty.rb +177 -0
- data/lib/trevol_generado/models/payroll_other_concept.rb +197 -0
- data/lib/trevol_generado/models/payroll_overtime.rb +262 -0
- data/lib/trevol_generado/models/payroll_paid_period.rb +222 -0
- data/lib/trevol_generado/models/payroll_payment.rb +215 -0
- data/lib/trevol_generado/models/payroll_percent_amount.rb +205 -0
- data/lib/trevol_generado/models/payroll_period.rb +247 -0
- data/lib/trevol_generado/models/payroll_place.rb +179 -0
- data/lib/trevol_generado/models/payroll_reference.rb +188 -0
- data/lib/trevol_generado/models/payroll_salary_amounts.rb +171 -0
- data/lib/trevol_generado/models/payroll_sanction.rb +205 -0
- data/lib/trevol_generado/models/payroll_service_bonus.rb +214 -0
- data/lib/trevol_generado/models/payroll_severance.rb +232 -0
- data/lib/trevol_generado/models/payroll_solidarity_fund.rb +191 -0
- data/lib/trevol_generado/models/payroll_totals.rb +188 -0
- data/lib/trevol_generado/models/payroll_transport.rb +181 -0
- data/lib/trevol_generado/models/payroll_unpaid_period.rb +195 -0
- data/lib/trevol_generado/models/payroll_vacation.rb +173 -0
- data/lib/trevol_generado/models/payroll_workplace.rb +188 -0
- data/lib/trevol_generado/models/period.rb +169 -0
- data/lib/trevol_generado/models/physical_document.rb +179 -0
- data/lib/trevol_generado/models/pos.rb +186 -0
- data/lib/trevol_generado/models/pos_buyer.rb +181 -0
- data/lib/trevol_generado/models/pos_register.rb +269 -0
- data/lib/trevol_generado/models/prepayment.rb +248 -0
- data/lib/trevol_generado/models/preview.rb +195 -0
- data/lib/trevol_generado/models/problem.rb +329 -0
- data/lib/trevol_generado/models/problem_error.rb +178 -0
- data/lib/trevol_generado/models/public_services_extension.rb +385 -0
- data/lib/trevol_generado/models/radian_event.rb +359 -0
- data/lib/trevol_generado/models/radian_event_data.rb +289 -0
- data/lib/trevol_generado/models/radian_event_input.rb +284 -0
- data/lib/trevol_generado/models/radian_event_invoice.rb +208 -0
- data/lib/trevol_generado/models/radian_event_list.rb +191 -0
- data/lib/trevol_generado/models/received_invoice.rb +200 -0
- data/lib/trevol_generado/models/received_invoice_issuer.rb +190 -0
- data/lib/trevol_generado/models/references.rb +182 -0
- data/lib/trevol_generado/models/request_list.rb +191 -0
- data/lib/trevol_generado/models/request_log.rb +275 -0
- data/lib/trevol_generado/models/seller.rb +385 -0
- data/lib/trevol_generado/models/shipment.rb +178 -0
- data/lib/trevol_generado/models/show_event.rb +276 -0
- data/lib/trevol_generado/models/show_extension.rb +203 -0
- data/lib/trevol_generado/models/show_producer.rb +212 -0
- data/lib/trevol_generado/models/standard_code.rb +169 -0
- data/lib/trevol_generado/models/stock_exchange_extension.rb +320 -0
- data/lib/trevol_generado/models/stock_exchange_prices.rb +169 -0
- data/lib/trevol_generado/models/support_adjustment_item.rb +295 -0
- data/lib/trevol_generado/models/support_adjustment_reference.rb +188 -0
- data/lib/trevol_generado/models/support_currency.rb +231 -0
- data/lib/trevol_generado/models/support_document.rb +401 -0
- data/lib/trevol_generado/models/support_document_adjustment.rb +409 -0
- data/lib/trevol_generado/models/support_document_adjustment_input.rb +331 -0
- data/lib/trevol_generado/models/support_document_adjustment_list.rb +191 -0
- data/lib/trevol_generado/models/support_document_delivery.rb +199 -0
- data/lib/trevol_generado/models/support_document_event_data.rb +305 -0
- data/lib/trevol_generado/models/support_document_input.rb +331 -0
- data/lib/trevol_generado/models/support_document_list.rb +191 -0
- data/lib/trevol_generado/models/support_document_reference.rb +198 -0
- data/lib/trevol_generado/models/support_item.rb +317 -0
- data/lib/trevol_generado/models/support_item_charge.rb +180 -0
- data/lib/trevol_generado/models/support_item_tax.rb +197 -0
- data/lib/trevol_generado/models/support_item_withholding.rb +205 -0
- data/lib/trevol_generado/models/tacit_acceptance.rb +224 -0
- data/lib/trevol_generado/models/tacit_acceptance_rule.rb +226 -0
- data/lib/trevol_generado/models/test_event_data.rb +171 -0
- data/lib/trevol_generado/models/third_party_charge.rb +277 -0
- data/lib/trevol_generado/models/third_party_company.rb +203 -0
- data/lib/trevol_generado/models/top_up.rb +199 -0
- data/lib/trevol_generado/models/top_up_buyer.rb +352 -0
- data/lib/trevol_generado/models/top_up_input.rb +187 -0
- data/lib/trevol_generado/models/top_up_wompi.rb +209 -0
- data/lib/trevol_generado/models/transport_extension.rb +281 -0
- data/lib/trevol_generado/models/webhook_delivery.rb +267 -0
- data/lib/trevol_generado/models/webhook_delivery_attempt.rb +192 -0
- data/lib/trevol_generado/models/webhook_delivery_list.rb +191 -0
- data/lib/trevol_generado/models/webhook_endpoint.rb +317 -0
- data/lib/trevol_generado/models/webhook_endpoint_input.rb +229 -0
- data/lib/trevol_generado/models/webhook_endpoint_list.rb +191 -0
- data/lib/trevol_generado/models/webhook_endpoint_rotate_input.rb +160 -0
- data/lib/trevol_generado/models/webhook_endpoint_update.rb +227 -0
- data/lib/trevol_generado/models/withholding.rb +224 -0
- data/lib/trevol_generado/tablas.rb +243 -0
- data/lib/trevol_generado/version.rb +15 -0
- data/lib/trevol_generado.rb +251 -0
- metadata +386 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
require 'securerandom'
|
|
5
|
+
require_relative 'errors'
|
|
6
|
+
|
|
7
|
+
module Trevol
|
|
8
|
+
# El transporte: lo que hace que las llamadas se comporten igual en los 7 SDK (docs/api/43 §2.6.2 a §2.6.5).
|
|
9
|
+
#
|
|
10
|
+
# Es un middleware de Faraday (el punto de extensión del código generado): pone las cabeceras y la Idempotency-Key, reintenta y convierte
|
|
11
|
+
# toda respuesta que no es 2xx en un error tipado que atraviesa el código generado sin envolverse (`ApiClient#call_api` solo atrapa
|
|
12
|
+
# `Faraday::TimeoutError` y `Faraday::ConnectionFailed`, y convierte en `ApiError` lo que le llega como respuesta).
|
|
13
|
+
class Transporte < Faraday::Middleware
|
|
14
|
+
ESTADOS_REINTENTABLES = [429, 500, 502, 503, 504].freeze
|
|
15
|
+
CODES_EN_CURSO = %w[request_in_progress previous_event_pending].freeze
|
|
16
|
+
PROBLEMA = 'application/problem+json'
|
|
17
|
+
ACCEPT = {
|
|
18
|
+
'pdf' => "application/pdf, #{PROBLEMA}", 'xml' => "application/xml, #{PROBLEMA}", 'zip' => "application/zip, #{PROBLEMA}"
|
|
19
|
+
}.tap { |h| h.default = "application/json, #{PROBLEMA}" }.freeze
|
|
20
|
+
CLAVE_VALIDA = /\A[!-~]{1,255}\z/
|
|
21
|
+
|
|
22
|
+
# Qué pasó en un intento: `tipo` :respuesta (con `estado`) o :red (sin respuesta). `retry_after` en segundos, ya resuelto.
|
|
23
|
+
Resultado = Struct.new(:tipo, :estado, :code, :retryable, :retry_after, keyword_init: true)
|
|
24
|
+
Decision = Struct.new(:reintentar, :espera, :motivo)
|
|
25
|
+
|
|
26
|
+
# Lo que necesita el middleware. La llave nunca sale en un inspect.
|
|
27
|
+
Opciones = Struct.new(:llave, :api_version, :user_agent, :max_reintentos, :max_retry_after, :ruta_base, :dormir, :azar, :uuid, :ahora, keyword_init: true) do
|
|
28
|
+
def inspect = "#<Trevol::Transporte::Opciones api_version=#{api_version.inspect} max_reintentos=#{max_reintentos.inspect}>"
|
|
29
|
+
alias_method :to_s, :inspect
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
# La espera propia antes del intento siguiente: 0,5 · 2^(intento−1), con tope de 8 s, por un factor al azar en [0,75; 1].
|
|
34
|
+
def espera_propia(intento, azar)
|
|
35
|
+
[0.5 * (2**(intento - 1)), 8.0].min * (0.75 + (0.25 * azar))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Función PURA: ¿se reintenta y cuánto se espera? Las mismas reglas y los mismos casos (`pruebas/datos/transporte.json`) en los 7 SDK.
|
|
39
|
+
def decidir(intento:, reintento:, max_reintentos:, max_retry_after:, azar:, resultado:)
|
|
40
|
+
r = resultado
|
|
41
|
+
return Decision.new(false, nil, 'exito') if r.tipo == :respuesta && r.estado && r.estado >= 200 && r.estado < 300
|
|
42
|
+
|
|
43
|
+
reintentable =
|
|
44
|
+
if r.tipo == :red
|
|
45
|
+
reintento == 'seguro'
|
|
46
|
+
elsif reintento == 'solo_429'
|
|
47
|
+
r.estado == 429
|
|
48
|
+
elsif r.estado == 402
|
|
49
|
+
false
|
|
50
|
+
else
|
|
51
|
+
ESTADOS_REINTENTABLES.include?(r.estado) || CODES_EN_CURSO.include?(r.code) || r.retryable == true
|
|
52
|
+
end
|
|
53
|
+
return Decision.new(false, nil, nil) unless reintentable
|
|
54
|
+
return Decision.new(false, nil, 'agotado') if intento > max_reintentos
|
|
55
|
+
|
|
56
|
+
propia = espera_propia(intento, azar)
|
|
57
|
+
pedida = r.tipo == :respuesta && r.retry_after && r.retry_after.positive? ? r.retry_after : 0.0
|
|
58
|
+
return Decision.new(false, nil, 'retry_after_excede') if pedida > max_retry_after
|
|
59
|
+
|
|
60
|
+
Decision.new(true, [pedida, propia].max, nil)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def validar_clave(clave)
|
|
64
|
+
return if clave.is_a?(String) && CLAVE_VALIDA.match?(clave)
|
|
65
|
+
|
|
66
|
+
raise ConfigurationError, 'La idempotency_key debe tener de 1 a 255 caracteres ASCII visibles (sin espacios).'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# La operación (tablas) de un método y una ruta SIN el prefijo /v1. Las rutas fijas ganan a las plantillas
|
|
70
|
+
# (GET /radian_events/tacit_acceptance frente a GET /radian_events/{id}).
|
|
71
|
+
def operacion(metodo, ruta)
|
|
72
|
+
indices[:exactas]["#{metodo} #{ruta}"] ||
|
|
73
|
+
indices[:plantillas].find { |o, re| o[:metodo] == metodo && re.match?(ruta) }&.first
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def indices
|
|
79
|
+
@indices ||= begin
|
|
80
|
+
exactas = {}
|
|
81
|
+
plantillas = []
|
|
82
|
+
TrevolGenerado::Tablas::OPERACIONES.each do |o|
|
|
83
|
+
if o[:ruta].include?('{')
|
|
84
|
+
plantillas << [o, Regexp.new("\\A#{Regexp.escape(o[:ruta]).gsub(/\\\{[a-z_]+\\\}/, '[^/]+')}\\z")]
|
|
85
|
+
else
|
|
86
|
+
exactas["#{o[:metodo]} #{o[:ruta]}"] = o
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
{ exactas: exactas, plantillas: plantillas }
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def initialize(app, opciones)
|
|
95
|
+
super(app)
|
|
96
|
+
@o = opciones
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def call(env)
|
|
100
|
+
metodo = env.method.to_s.upcase
|
|
101
|
+
ruta = env.url.path
|
|
102
|
+
ruta = ruta.delete_prefix(@o.ruta_base) unless @o.ruta_base.to_s.empty?
|
|
103
|
+
op = self.class.operacion(metodo, ruta)
|
|
104
|
+
reintento = op ? op[:reintento] : (metodo == 'GET' ? 'seguro' : 'solo_429')
|
|
105
|
+
|
|
106
|
+
# La Idempotency-Key: una por llamada, la misma en todos los reintentos.
|
|
107
|
+
clave = nil
|
|
108
|
+
if op && op[:idempotente]
|
|
109
|
+
dada = env.request_headers['Idempotency-Key']
|
|
110
|
+
if dada.nil?
|
|
111
|
+
clave = @o.uuid.call
|
|
112
|
+
else
|
|
113
|
+
self.class.validar_clave(dada)
|
|
114
|
+
clave = dada
|
|
115
|
+
end
|
|
116
|
+
env.request_headers['Idempotency-Key'] = clave
|
|
117
|
+
else
|
|
118
|
+
env.request_headers.delete('Idempotency-Key')
|
|
119
|
+
end
|
|
120
|
+
h = env.request_headers
|
|
121
|
+
h['Authorization'] = "Bearer #{@o.llave}"
|
|
122
|
+
h['Trevol-Version'] = @o.api_version
|
|
123
|
+
h['User-Agent'] = @o.user_agent
|
|
124
|
+
h['Accept'] = ACCEPT[op && op[:binario]]
|
|
125
|
+
|
|
126
|
+
cuerpo_pedido = env.body
|
|
127
|
+
destino = env.request.on_data # descarga en flujo: se junta por intento y solo la 2xx llega a quien la pidió
|
|
128
|
+
intento = 0
|
|
129
|
+
loop do
|
|
130
|
+
intento += 1
|
|
131
|
+
env.body = cuerpo_pedido
|
|
132
|
+
trozos = []
|
|
133
|
+
env.request.on_data = proc { |trozo, *| trozos << trozo.dup } if destino
|
|
134
|
+
respuesta = nil
|
|
135
|
+
causa = nil
|
|
136
|
+
begin
|
|
137
|
+
respuesta = @app.call(env)
|
|
138
|
+
rescue Faraday::ConnectionFailed, Faraday::TimeoutError, Faraday::SSLError => e
|
|
139
|
+
causa = e
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if respuesta
|
|
143
|
+
estado = respuesta.status
|
|
144
|
+
if estado >= 200 && estado < 300
|
|
145
|
+
if destino
|
|
146
|
+
total = 0
|
|
147
|
+
trozos.each { |t| total += t.bytesize; destino.call(t, total) }
|
|
148
|
+
env.request.on_data = destino
|
|
149
|
+
end
|
|
150
|
+
return respuesta
|
|
151
|
+
end
|
|
152
|
+
texto = respuesta.body.to_s
|
|
153
|
+
texto = trozos.join if texto.empty? && !trozos.empty?
|
|
154
|
+
error = Errores.de_respuesta(estado, texto.dup.force_encoding('UTF-8').scrub, respuesta.headers, clave, @o.ahora.call)
|
|
155
|
+
decision = self.class.decidir(
|
|
156
|
+
intento: intento, reintento: reintento, max_reintentos: @o.max_reintentos, max_retry_after: @o.max_retry_after, azar: @o.azar.call,
|
|
157
|
+
resultado: Resultado.new(tipo: :respuesta, estado: estado, code: error.code, retryable: error.retryable, retry_after: error.retry_after)
|
|
158
|
+
)
|
|
159
|
+
raise error unless decision.reintentar
|
|
160
|
+
else
|
|
161
|
+
decision = self.class.decidir(
|
|
162
|
+
intento: intento, reintento: reintento, max_reintentos: @o.max_reintentos, max_retry_after: @o.max_retry_after, azar: @o.azar.call,
|
|
163
|
+
resultado: Resultado.new(tipo: :red)
|
|
164
|
+
)
|
|
165
|
+
unless decision.reintentar
|
|
166
|
+
raise APIConnectionError.new("No pude conectar con la API de Trevol (#{causa.message.to_s[0, 200]}).", idempotency_key: clave), cause: causa
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
@o.dormir.call(decision.espera || 0.0)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'base64'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'standardwebhooks'
|
|
6
|
+
require_relative 'errors'
|
|
7
|
+
|
|
8
|
+
module Trevol
|
|
9
|
+
# Verificación de webhooks (docs/api/43 §2.6.9): Standard Webhooks sobre el CUERPO CRUDO (`request.raw_post`, `request.body.read`).
|
|
10
|
+
#
|
|
11
|
+
# La firma esperada la calcula la biblioteca abierta `standardwebhooks` (`StandardWebhooks::Webhook#sign`); la tolerancia de 5 minutos
|
|
12
|
+
# (con reloj inyectable en las pruebas), las cabeceras (en cualquier caja) y la comparación en tiempo constante son de este SDK: la
|
|
13
|
+
# biblioteca no deja inyectar el reloj, solo acepta cabeceras en minúsculas y entrega un Hash en vez del evento generado.
|
|
14
|
+
class Webhook
|
|
15
|
+
TOLERANCIA = 300 # segundos, hacia atrás y hacia adelante
|
|
16
|
+
NOMBRES = %w[webhook-id webhook-timestamp webhook-signature].freeze
|
|
17
|
+
|
|
18
|
+
# @param secret [String] el secreto del endpoint (`whsec_…`), que se muestra una sola vez al crearlo o rotarlo
|
|
19
|
+
# @param ahora [#call, nil] solo para pruebas: el reloj, en segundos
|
|
20
|
+
def initialize(secret, ahora: nil)
|
|
21
|
+
secret = secret.to_s.strip
|
|
22
|
+
raise ConfigurationError, 'Falta el secreto del webhook (whsec_…). Se muestra una sola vez al crear o rotar el endpoint.' if secret.empty? || secret == 'whsec_'
|
|
23
|
+
|
|
24
|
+
sin_prefijo = secret.delete_prefix('whsec_')
|
|
25
|
+
crudo = begin
|
|
26
|
+
Base64.strict_decode64(sin_prefijo)
|
|
27
|
+
rescue ArgumentError
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
raise ConfigurationError, 'El secreto del webhook no tiene el formato esperado (whsec_ + base64).' if crudo.nil? || crudo.empty?
|
|
31
|
+
|
|
32
|
+
@firmador = StandardWebhooks::Webhook.new(secret)
|
|
33
|
+
@ahora = ahora || -> { Time.now.to_i }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Las tres cabeceras en minúsculas, venga lo que venga (un Hash, `request.headers`, una lista de pares, valores en arreglo).
|
|
37
|
+
# La primera repetida gana.
|
|
38
|
+
def self.normalizar_cabeceras(cabeceras)
|
|
39
|
+
pares = cabeceras.respond_to?(:each_pair) ? cabeceras.each_pair.to_a : Array(cabeceras)
|
|
40
|
+
salida = {}
|
|
41
|
+
pares.each do |k, v|
|
|
42
|
+
nombre = k.to_s.downcase.tr('_', '-').sub(/\Ahttp-/, '')
|
|
43
|
+
v = v.first if v.is_a?(Array)
|
|
44
|
+
salida[nombre] ||= v.to_s if NOMBRES.include?(nombre) && !v.nil?
|
|
45
|
+
end
|
|
46
|
+
salida
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Verifica la firma y la fecha de una entrega y devuelve el evento (`TrevolGenerado::Event`).
|
|
50
|
+
# Lanza `Trevol::WebhookVerificationError` si algo no cuadra.
|
|
51
|
+
#
|
|
52
|
+
# Ojo: la verificación NO evita repeticiones dentro de los 5 minutos ni los reintentos de entrega: deduplica por `webhook-id`.
|
|
53
|
+
def verify(body, headers)
|
|
54
|
+
unless body.is_a?(String)
|
|
55
|
+
raise WebhookVerificationError.new(
|
|
56
|
+
'El cuerpo del webhook debe ser el CUERPO CRUDO (String), no un objeto ya parseado: la firma se calcula sobre los bytes exactos. ' \
|
|
57
|
+
'En Rails usa request.raw_post; en Sinatra, request.body.read.', :cuerpo
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
texto = body.dup.force_encoding('UTF-8')
|
|
61
|
+
raise WebhookVerificationError.new('El cuerpo del webhook no es UTF-8.', :cuerpo) unless texto.valid_encoding?
|
|
62
|
+
|
|
63
|
+
h = self.class.normalizar_cabeceras(headers)
|
|
64
|
+
NOMBRES.each do |n|
|
|
65
|
+
raise WebhookVerificationError.new("Falta la cabecera #{n}.", :cabeceras) if h[n].to_s.empty?
|
|
66
|
+
end
|
|
67
|
+
raise WebhookVerificationError.new('El webhook-timestamp no es un número de segundos.', :fecha) unless h['webhook-timestamp'].match?(/\A[0-9]{1,12}\z/)
|
|
68
|
+
|
|
69
|
+
marca = h['webhook-timestamp'].to_i
|
|
70
|
+
if (@ahora.call - marca).abs > TOLERANCIA
|
|
71
|
+
raise WebhookVerificationError.new('La fecha del webhook está fuera de la tolerancia de 5 minutos.', :fecha)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
esperada = @firmador.sign(h['webhook-id'], marca.to_s, texto).split(',', 2)[1].to_s
|
|
75
|
+
coincide = false
|
|
76
|
+
h['webhook-signature'].split(' ').each do |firma|
|
|
77
|
+
version, valor = firma.split(',', 2)
|
|
78
|
+
coincide = true if version == 'v1' && valor && StandardWebhooks.secure_compare(esperada, valor) # basta una válida (rotación del secreto)
|
|
79
|
+
end
|
|
80
|
+
unless coincide
|
|
81
|
+
raise WebhookVerificationError.new('La firma del webhook no coincide: revisa el secreto y que el cuerpo sea el crudo, sin reescribir.', :firma)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
begin
|
|
85
|
+
TrevolGenerado::Event.build_from_hash(JSON.parse(texto, symbolize_names: true))
|
|
86
|
+
rescue StandardError
|
|
87
|
+
raise WebhookVerificationError.new('El cuerpo firmado no es un evento válido.', :cuerpo)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# El `data` del evento como el modelo de su `type` (p. ej. `TrevolGenerado::DocumentEventData` para `invoice.accepted`). nil si el tipo
|
|
92
|
+
# es nuevo y este SDK todavía no lo conoce: el evento no se pierde, `evento.data` sigue ahí como Hash.
|
|
93
|
+
def event_data(evento)
|
|
94
|
+
nombre = TrevolGenerado::Tablas::EVENTO_MODELOS[evento.type.to_s]
|
|
95
|
+
return nil if nombre.nil? || evento.data.nil?
|
|
96
|
+
|
|
97
|
+
TrevolGenerado.const_get(nombre).build_from_hash(evento.data)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
data/lib/trevol.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SDK de Ruby para la API de Trevol. Documentación: https://platform.trevol.si/docs
|
|
4
|
+
require 'trevol_generado'
|
|
5
|
+
require 'trevol_generado/tablas'
|
|
6
|
+
require_relative 'trevol/errors'
|
|
7
|
+
require_relative 'trevol/llave'
|
|
8
|
+
require_relative 'trevol/paginacion'
|
|
9
|
+
require_relative 'trevol/transporte'
|
|
10
|
+
require_relative 'trevol/webhook'
|
|
11
|
+
|
|
12
|
+
module Trevol
|
|
13
|
+
# La versión de este SDK y la de la API con que se generó (el valor de Trevol-Version por defecto).
|
|
14
|
+
VERSION = TrevolGenerado::Tablas::VERSION
|
|
15
|
+
API_VERSION = TrevolGenerado::Tablas::API_VERSION
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
require_relative 'trevol/client'
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
#API de Trevol
|
|
3
|
+
|
|
4
|
+
#Trevol API. Documentación: https://platform.trevol.si/docs
|
|
5
|
+
|
|
6
|
+
The version of the OpenAPI document: 2026-10-22
|
|
7
|
+
|
|
8
|
+
Generated by: https://openapi-generator.tech
|
|
9
|
+
Generator version: 7.26.0
|
|
10
|
+
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
require 'cgi'
|
|
14
|
+
|
|
15
|
+
module TrevolGenerado
|
|
16
|
+
class BalanceApi
|
|
17
|
+
attr_accessor :api_client
|
|
18
|
+
|
|
19
|
+
def initialize(api_client = ApiClient.default)
|
|
20
|
+
@api_client = api_client
|
|
21
|
+
end
|
|
22
|
+
# Preparar una recarga del saldo (para el widget de Wompi)
|
|
23
|
+
# Prepara una recarga del saldo de la cuenta y devuelve lo que necesita el widget de Wompi (`WidgetCheckout`: `publicKey`, `currency`, `amountInCents`, `reference`, `signature: {integrity}` y `expirationTime`). El pago se hace en el widget; cuando Wompi lo aprueba, Trevol abona el saldo (y la factura de la recarga sale a nombre de `buyer`). Preparar no mueve saldo y la firma vence en una hora: si el widget venció, prepara otra. Solo llaves de escritura; exige `Idempotency-Key` (repetir con la misma clave devuelve la MISMA recarga). Sin `buyer`, la factura va a nombre de la empresa de la llave con sus datos (NIT, DV, razón social, correo, teléfono, dirección y municipio); si no alcanzan, 422 en `buyer.*`. El monto va entre la recarga mínima y la máxima (422 `top_up_below_minimum` / `top_up_above_maximum` con `minimum_cop` / `maximum_cop`). Es dinero real con cualquier llave (también `test`): el saldo es uno solo. Hasta 20 por llave cada 10 minutos (429).
|
|
24
|
+
# @param top_up_input [TopUpInput]
|
|
25
|
+
# @param [Hash] opts the optional parameters
|
|
26
|
+
# @option opts [String] :idempotency_key Obligatoria: 1 a 255 caracteres ASCII visibles, única por pedido (7 días).
|
|
27
|
+
# @return [TopUp]
|
|
28
|
+
def create_balance_top_up(top_up_input, opts = {})
|
|
29
|
+
data, _status_code, _headers = create_balance_top_up_with_http_info(top_up_input, opts)
|
|
30
|
+
data
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Preparar una recarga del saldo (para el widget de Wompi)
|
|
34
|
+
# Prepara una recarga del saldo de la cuenta y devuelve lo que necesita el widget de Wompi (`WidgetCheckout`: `publicKey`, `currency`, `amountInCents`, `reference`, `signature: {integrity}` y `expirationTime`). El pago se hace en el widget; cuando Wompi lo aprueba, Trevol abona el saldo (y la factura de la recarga sale a nombre de `buyer`). Preparar no mueve saldo y la firma vence en una hora: si el widget venció, prepara otra. Solo llaves de escritura; exige `Idempotency-Key` (repetir con la misma clave devuelve la MISMA recarga). Sin `buyer`, la factura va a nombre de la empresa de la llave con sus datos (NIT, DV, razón social, correo, teléfono, dirección y municipio); si no alcanzan, 422 en `buyer.*`. El monto va entre la recarga mínima y la máxima (422 `top_up_below_minimum` / `top_up_above_maximum` con `minimum_cop` / `maximum_cop`). Es dinero real con cualquier llave (también `test`): el saldo es uno solo. Hasta 20 por llave cada 10 minutos (429).
|
|
35
|
+
# @param top_up_input [TopUpInput]
|
|
36
|
+
# @param [Hash] opts the optional parameters
|
|
37
|
+
# @option opts [String] :idempotency_key Obligatoria: 1 a 255 caracteres ASCII visibles, única por pedido (7 días).
|
|
38
|
+
# @return [Array<(TopUp, Integer, Hash)>] TopUp data, response status code and response headers
|
|
39
|
+
def create_balance_top_up_with_http_info(top_up_input, opts = {})
|
|
40
|
+
if @api_client.config.debugging
|
|
41
|
+
@api_client.config.logger.debug 'Calling API: BalanceApi.create_balance_top_up ...'
|
|
42
|
+
end
|
|
43
|
+
# verify the required parameter 'top_up_input' is set
|
|
44
|
+
if @api_client.config.client_side_validation && top_up_input.nil?
|
|
45
|
+
fail ArgumentError, "Missing the required parameter 'top_up_input' when calling BalanceApi.create_balance_top_up"
|
|
46
|
+
end
|
|
47
|
+
# resource path
|
|
48
|
+
local_var_path = '/balance/top_ups'
|
|
49
|
+
|
|
50
|
+
# query parameters
|
|
51
|
+
query_params = opts[:query_params] || {}
|
|
52
|
+
|
|
53
|
+
# header parameters
|
|
54
|
+
header_params = opts[:header_params] || {}
|
|
55
|
+
# HTTP header 'Accept' (if needed)
|
|
56
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json', 'application/problem+json']) unless header_params['Accept']
|
|
57
|
+
# HTTP header 'Content-Type'
|
|
58
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
59
|
+
if !content_type.nil?
|
|
60
|
+
header_params['Content-Type'] = content_type
|
|
61
|
+
end
|
|
62
|
+
header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
|
|
63
|
+
|
|
64
|
+
# form parameters
|
|
65
|
+
form_params = opts[:form_params] || {}
|
|
66
|
+
|
|
67
|
+
# http body (model)
|
|
68
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(top_up_input)
|
|
69
|
+
|
|
70
|
+
# return_type
|
|
71
|
+
return_type = opts[:debug_return_type] || 'TopUp'
|
|
72
|
+
|
|
73
|
+
# auth_names
|
|
74
|
+
auth_names = opts[:debug_auth_names] || ['llave']
|
|
75
|
+
|
|
76
|
+
new_options = opts.merge(
|
|
77
|
+
:operation => :"BalanceApi.create_balance_top_up",
|
|
78
|
+
:header_params => header_params,
|
|
79
|
+
:query_params => query_params,
|
|
80
|
+
:form_params => form_params,
|
|
81
|
+
:body => post_body,
|
|
82
|
+
:auth_names => auth_names,
|
|
83
|
+
:return_type => return_type
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
87
|
+
if @api_client.config.debugging
|
|
88
|
+
@api_client.config.logger.debug "API called: BalanceApi#create_balance_top_up\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
89
|
+
end
|
|
90
|
+
return data, status_code, headers
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Los movimientos del saldo de la cuenta
|
|
94
|
+
# Los movimientos del saldo de la cuenta (de todas sus empresas), del más nuevo al más viejo: lo mismo que «Saldo y recargas» en la app. Un documento es UNA fila (`type: document`) con su `status`: `pending` (apartado mientras la DIAN lo valida), `charged` (validado y cobrado) o `released` (la DIAN lo rechazó: no se cobró y `amount` es 0); `company` dice qué empresa lo emitió. Lo demás es una fila por movimiento: `top_up` (recarga, con su `reference`), `top_up_reversal`, `bonus`, `adjustment`, `license_fee`, `expiration` u `other`. `amount` es lo que el movimiento hizo con el disponible, con signo; `available_after`, el disponible justo después. Filtro `type`: `all` (por defecto), `documents`, `funding` (todo lo que no es un documento) o `top_ups`. Paginación por cursor: `limit` (1 a 100, 25 por defecto) y `starting_after` (el `id` de la última fila que tienes).
|
|
95
|
+
# @param [Hash] opts the optional parameters
|
|
96
|
+
# @option opts [Integer] :limit (default to 25)
|
|
97
|
+
# @option opts [String] :starting_after
|
|
98
|
+
# @option opts [String] :type (default to 'all')
|
|
99
|
+
# @return [BalanceTransactionList]
|
|
100
|
+
def list_balance_transactions(opts = {})
|
|
101
|
+
data, _status_code, _headers = list_balance_transactions_with_http_info(opts)
|
|
102
|
+
data
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Los movimientos del saldo de la cuenta
|
|
106
|
+
# Los movimientos del saldo de la cuenta (de todas sus empresas), del más nuevo al más viejo: lo mismo que «Saldo y recargas» en la app. Un documento es UNA fila (`type: document`) con su `status`: `pending` (apartado mientras la DIAN lo valida), `charged` (validado y cobrado) o `released` (la DIAN lo rechazó: no se cobró y `amount` es 0); `company` dice qué empresa lo emitió. Lo demás es una fila por movimiento: `top_up` (recarga, con su `reference`), `top_up_reversal`, `bonus`, `adjustment`, `license_fee`, `expiration` u `other`. `amount` es lo que el movimiento hizo con el disponible, con signo; `available_after`, el disponible justo después. Filtro `type`: `all` (por defecto), `documents`, `funding` (todo lo que no es un documento) o `top_ups`. Paginación por cursor: `limit` (1 a 100, 25 por defecto) y `starting_after` (el `id` de la última fila que tienes).
|
|
107
|
+
# @param [Hash] opts the optional parameters
|
|
108
|
+
# @option opts [Integer] :limit (default to 25)
|
|
109
|
+
# @option opts [String] :starting_after
|
|
110
|
+
# @option opts [String] :type (default to 'all')
|
|
111
|
+
# @return [Array<(BalanceTransactionList, Integer, Hash)>] BalanceTransactionList data, response status code and response headers
|
|
112
|
+
def list_balance_transactions_with_http_info(opts = {})
|
|
113
|
+
if @api_client.config.debugging
|
|
114
|
+
@api_client.config.logger.debug 'Calling API: BalanceApi.list_balance_transactions ...'
|
|
115
|
+
end
|
|
116
|
+
allowable_values = ["all", "documents", "funding", "top_ups", "unknown_default_open_api"]
|
|
117
|
+
if @api_client.config.client_side_validation && opts[:'type'] && !allowable_values.include?(opts[:'type'])
|
|
118
|
+
fail ArgumentError, "invalid value for \"type\", must be one of #{allowable_values}"
|
|
119
|
+
end
|
|
120
|
+
# resource path
|
|
121
|
+
local_var_path = '/balance/transactions'
|
|
122
|
+
|
|
123
|
+
# query parameters
|
|
124
|
+
query_params = opts[:query_params] || {}
|
|
125
|
+
query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
|
|
126
|
+
query_params[:'starting_after'] = opts[:'starting_after'] if !opts[:'starting_after'].nil?
|
|
127
|
+
query_params[:'type'] = opts[:'type'] if !opts[:'type'].nil?
|
|
128
|
+
|
|
129
|
+
# header parameters
|
|
130
|
+
header_params = opts[:header_params] || {}
|
|
131
|
+
# HTTP header 'Accept' (if needed)
|
|
132
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json', 'application/problem+json']) unless header_params['Accept']
|
|
133
|
+
|
|
134
|
+
# form parameters
|
|
135
|
+
form_params = opts[:form_params] || {}
|
|
136
|
+
|
|
137
|
+
# http body (model)
|
|
138
|
+
post_body = opts[:debug_body]
|
|
139
|
+
|
|
140
|
+
# return_type
|
|
141
|
+
return_type = opts[:debug_return_type] || 'BalanceTransactionList'
|
|
142
|
+
|
|
143
|
+
# auth_names
|
|
144
|
+
auth_names = opts[:debug_auth_names] || ['llave']
|
|
145
|
+
|
|
146
|
+
new_options = opts.merge(
|
|
147
|
+
:operation => :"BalanceApi.list_balance_transactions",
|
|
148
|
+
:header_params => header_params,
|
|
149
|
+
:query_params => query_params,
|
|
150
|
+
:form_params => form_params,
|
|
151
|
+
:body => post_body,
|
|
152
|
+
:auth_names => auth_names,
|
|
153
|
+
:return_type => return_type
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
157
|
+
if @api_client.config.debugging
|
|
158
|
+
@api_client.config.logger.debug "API called: BalanceApi#list_balance_transactions\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
159
|
+
end
|
|
160
|
+
return data, status_code, headers
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# El saldo de la cuenta (lo comparten sus empresas)
|
|
164
|
+
# El saldo prepago de Trevol. Es de la **cuenta**, no de la empresa: todas las empresas de la cuenta lo comparten (`shared: true`) y cualquier llave de cualquiera de ellas, de lectura o de escritura, `test` o `live`, ve el mismo. Solo lo que se emite en producción (llaves `live`) lo consume; la habilitación (`test`) no cobra. `available` es lo que se puede gastar (en pesos); `held`, lo apartado por documentos que la DIAN todavía valida; `overdraft`, cuánto puede bajar `available` de cero al apartar un documento; `low_threshold`, el umbral del aviso de saldo bajo (el 20 % de la última recarga; `null` sin recargas). `level`: `empty` con `available` ≤ 0, `low` por debajo de `low_threshold`, si no `ok`. Con `available` por debajo del precio de un documento, emitir en producción responde 402 `insufficient_balance`. El evento `balance.low` avisa por webhook.
|
|
165
|
+
# @param [Hash] opts the optional parameters
|
|
166
|
+
# @return [Balance]
|
|
167
|
+
def retrieve_balance(opts = {})
|
|
168
|
+
data, _status_code, _headers = retrieve_balance_with_http_info(opts)
|
|
169
|
+
data
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# El saldo de la cuenta (lo comparten sus empresas)
|
|
173
|
+
# El saldo prepago de Trevol. Es de la **cuenta**, no de la empresa: todas las empresas de la cuenta lo comparten (`shared: true`) y cualquier llave de cualquiera de ellas, de lectura o de escritura, `test` o `live`, ve el mismo. Solo lo que se emite en producción (llaves `live`) lo consume; la habilitación (`test`) no cobra. `available` es lo que se puede gastar (en pesos); `held`, lo apartado por documentos que la DIAN todavía valida; `overdraft`, cuánto puede bajar `available` de cero al apartar un documento; `low_threshold`, el umbral del aviso de saldo bajo (el 20 % de la última recarga; `null` sin recargas). `level`: `empty` con `available` ≤ 0, `low` por debajo de `low_threshold`, si no `ok`. Con `available` por debajo del precio de un documento, emitir en producción responde 402 `insufficient_balance`. El evento `balance.low` avisa por webhook.
|
|
174
|
+
# @param [Hash] opts the optional parameters
|
|
175
|
+
# @return [Array<(Balance, Integer, Hash)>] Balance data, response status code and response headers
|
|
176
|
+
def retrieve_balance_with_http_info(opts = {})
|
|
177
|
+
if @api_client.config.debugging
|
|
178
|
+
@api_client.config.logger.debug 'Calling API: BalanceApi.retrieve_balance ...'
|
|
179
|
+
end
|
|
180
|
+
# resource path
|
|
181
|
+
local_var_path = '/balance'
|
|
182
|
+
|
|
183
|
+
# query parameters
|
|
184
|
+
query_params = opts[:query_params] || {}
|
|
185
|
+
|
|
186
|
+
# header parameters
|
|
187
|
+
header_params = opts[:header_params] || {}
|
|
188
|
+
# HTTP header 'Accept' (if needed)
|
|
189
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json', 'application/problem+json']) unless header_params['Accept']
|
|
190
|
+
|
|
191
|
+
# form parameters
|
|
192
|
+
form_params = opts[:form_params] || {}
|
|
193
|
+
|
|
194
|
+
# http body (model)
|
|
195
|
+
post_body = opts[:debug_body]
|
|
196
|
+
|
|
197
|
+
# return_type
|
|
198
|
+
return_type = opts[:debug_return_type] || 'Balance'
|
|
199
|
+
|
|
200
|
+
# auth_names
|
|
201
|
+
auth_names = opts[:debug_auth_names] || ['llave']
|
|
202
|
+
|
|
203
|
+
new_options = opts.merge(
|
|
204
|
+
:operation => :"BalanceApi.retrieve_balance",
|
|
205
|
+
:header_params => header_params,
|
|
206
|
+
:query_params => query_params,
|
|
207
|
+
:form_params => form_params,
|
|
208
|
+
:body => post_body,
|
|
209
|
+
:auth_names => auth_names,
|
|
210
|
+
:return_type => return_type
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
|
|
214
|
+
if @api_client.config.debugging
|
|
215
|
+
@api_client.config.logger.debug "API called: BalanceApi#retrieve_balance\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
216
|
+
end
|
|
217
|
+
return data, status_code, headers
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|