cobro_digital 1.7.2 → 1.9.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.
data/lib/cobro_digital.rb CHANGED
@@ -7,6 +7,10 @@ require "cobro_digital/transaccion"
7
7
  require "cobro_digital/micrositio"
8
8
  require "cobro_digital/meta"
9
9
  require "savon"
10
+ require "net/http"
11
+ require "uri"
12
+ require "digest"
13
+ require "json"
10
14
 
11
15
  module CobroDigital
12
16
 
@@ -19,6 +23,18 @@ module CobroDigital
19
23
 
20
24
  TIMEOUT = 300
21
25
 
26
+ # Nivel de log del cliente SOAP. Default `:error` para no filtrar el `sid`
27
+ # ni PII del pagador a los logs de la app. Subir a `:debug` solo para
28
+ # troubleshooting explícito (vía ENV['COBRODIGITAL_LOG_LEVEL']).
29
+ # Se sanea el string vacío (`COBRODIGITAL_LOG_LEVEL=`) que produciría `:""`.
30
+ _log_level = ENV['COBRODIGITAL_LOG_LEVEL'].to_s
31
+ LOG_LEVEL = (_log_level.empty? ? 'error' : _log_level).to_sym
32
+ DEBUG_LOG = (LOG_LEVEL == :debug)
33
+
34
+ # Nodo del mensaje SOAP que transporta credenciales (`sid`) y PII del pagador.
35
+ # Savon lo enmascara como `***FILTERED***` en el log, incluso en `:debug`.
36
+ LOG_FILTERS = [:parametros_de_entrada].freeze
37
+
22
38
  module Https
23
39
  POST = 'Post'
24
40
  GET = 'Get'
@@ -26,30 +42,45 @@ module CobroDigital
26
42
 
27
43
  class Client
28
44
 
45
+ # NOTA: `sid` y `request_xml` contienen datos sensibles (credencial del
46
+ # comercio y XML con sid + PII del pagador). No loguear estos accessors.
29
47
  attr_accessor :id_comercio, :sid, :client_to_use, :http_method, :pagadores, :boletas, :transacciones, :micrositios, :requests, :request_xml
30
48
 
31
49
  def initialize(attrs={})
32
50
  @id_comercio = attrs[:id_comercio]
33
51
  @sid = attrs[:sid]
34
- @client_to_use = attrs[:con_client].present? ? attrs[:con_client] : CobroDigital::SOAP
52
+ @client_to_use = attrs[:con_client].to_s.empty? ? CobroDigital::SOAP : attrs[:con_client]
35
53
  # @with_handshake = attrs[:handshake].present? ? attrs[:handshake] : true
36
54
  @pagadores = []
37
55
  @boletas = []
38
56
  @transacciones = []
39
57
  @micrositios = []
40
58
  @request_xml = nil
59
+
60
+ unless CobroDigital::CLIENTS.include?(@client_to_use)
61
+ raise ArgumentError, "client_to_use inválido: #{@client_to_use.inspect} (esperado uno de #{CobroDigital::CLIENTS.inspect})"
62
+ end
41
63
  end
42
64
 
43
65
  def soap_client(params)
66
+ # `log: true` para que se sigan registrando errores SOAP/HTTP; la
67
+ # verbosidad la controla `log_level` (default :error → no loguea el body).
68
+ # `filters` enmascara el nodo con sid + PII como ***FILTERED*** si algo se
69
+ # llega a loguear. ADVERTENCIA: con COBRODIGITAL_LOG_LEVEL=debug el XML
70
+ # formateado incluye el sid en claro — no habilitar debug en producción.
44
71
  client = Savon.client(
45
72
  wsdl: CobroDigital::WSDL,
46
- log_level: :debug,
47
- pretty_print_xml: true,
73
+ log: true,
74
+ log_level: CobroDigital::LOG_LEVEL,
75
+ filters: CobroDigital::LOG_FILTERS,
76
+ pretty_print_xml: CobroDigital::DEBUG_LOG,
48
77
  open_timeout: CobroDigital::TIMEOUT,
49
78
  read_timeout: CobroDigital::TIMEOUT
50
79
  )
51
80
  operation = client.operation(:webservice_cobrodigital)
52
81
  request = operation.build(message: { 'parametros_de_entrada' => params.to_json })
82
+ # Contrato público: `@request_xml` siempre disponible tras el call. Retiene
83
+ # el XML con sid + PII en memoria — el consumidor no debe loguearlo.
53
84
  @request_xml = request.pretty
54
85
 
55
86
  client.call(:webservice_cobrodigital, message: { 'parametros_de_entrada' => params.to_json })
@@ -58,12 +89,12 @@ module CobroDigital
58
89
  def https_client(params)
59
90
  case http_method
60
91
  when CobroDigital::Https::POST
61
- uri = URI(CobroDigital::URI)
62
- req = "Net::HTTP::#{http_method}".constantize.new(uri)
92
+ uri = ::URI.parse(CobroDigital::URI)
93
+ req = Net::HTTP::Post.new(uri)
63
94
  req.set_form_data(params)
64
95
  when CobroDigital::Https::GET
65
- uri = URI([CobroDigital::URI, URI.encode_www_form(data)].join('?'))
66
- req = "Net::HTTP::#{http_method}".constantize.new(uri)
96
+ uri = ::URI.parse([CobroDigital::URI, ::URI.encode_www_form(params)].join('?'))
97
+ req = Net::HTTP::Get.new(uri)
67
98
  end
68
99
 
69
100
  Net::HTTP.start(
data/skill/SKILL.md ADDED
@@ -0,0 +1,87 @@
1
+ ---
2
+ name: cobro-digital
3
+ description: >-
4
+ Gema adaptadora del Web Service v3 de CobroDigital (pasarela de pago).
5
+ Modela las operaciones del WS — crear/editar/verificar pagadores, generar/
6
+ inhabilitar boletas, obtener código de barras, consultar transacciones y
7
+ actividad de micrositios, y agrupar operaciones en batch (meta) — y resuelve
8
+ el transporte SOAP (default, vía savon) o HTTPS hacia el endpoint del comercio.
9
+ Activala cuando trabajes con cobranzas/boletas/pagadores contra CobroDigital,
10
+ cuando integres o depures la comunicación con su webservice, o cuando un host
11
+ consuma la gema `cobro_digital`.
12
+ triggers:
13
+ - "cobrodigital"
14
+ - "cobro digital"
15
+ - "generar boleta"
16
+ - "crear pagador"
17
+ - "consultar transacciones cobrodigital"
18
+ - "webservice de pago cobrodigital"
19
+ - "gema cobro_digital"
20
+ ---
21
+
22
+ # cobro_digital
23
+
24
+ ## Qué es / cuándo usar
25
+
26
+ Adaptador Ruby del WS v3 de CobroDigital (pasarela de pago argentina). Úsalo
27
+ para invocar las operaciones del webservice desde un host Ruby/Rails. La gema
28
+ no persiste estado ni define excepciones propias: arma el payload, lo envía y
29
+ decodifica la respuesta.
30
+
31
+ ## Contrato resumido
32
+
33
+ **Patrón de uso:** cada operación es una subclase de `CobroDigital::Operador`
34
+ construida por un método de clase y ejecutada con `#call(id_comercio, sid)`.
35
+
36
+ ```ruby
37
+ op = CobroDigital::Boleta.generar(id, buscar, vencimientos, importes, concepto, plantilla)
38
+ op.call(comercio_id, comercio_sid) # ejecuta; guarda #response
39
+ op.parse_response # => { resultado: Bool, log: [..], datos: [..] }
40
+ ```
41
+
42
+ **Superficie pública** (detalle: [`docs/interface/interface.md`](../docs/interface/interface.md)):
43
+
44
+ - `CobroDigital::Pagador` — `.crear`, `.editar`, `.verificar`, `.codigo_electronico`, `.estructura_de_datos`
45
+ - `CobroDigital::Boleta` — `.generar`, `.inhabilitar`, `.obtener_codigo_de_barras`
46
+ - `CobroDigital::Transaccion` — `.consultar(desde, hasta, filtros)` + constantes `FILTRO_*`
47
+ - `CobroDigital::Micrositio` — `.consultar_actividad`
48
+ - `CobroDigital::Meta` — `.meta(objs)` (batch de operaciones en una llamada)
49
+ - `CobroDigital::Client` — transporte; `CobroDigital::VERSION`
50
+
51
+ **Config:** `ENV['ENDPOINT_COBRODIGITAL']` (default `https://cobro.digital:14365`)
52
+ y `ENV['COBRODIGITAL_LOG_LEVEL']` (default `error`). Credenciales `id_comercio`/`sid`
53
+ se pasan por argumento en cada `#call`, no por env.
54
+
55
+ **Gotchas:**
56
+ - `parse_response` **no levanta excepción** ante `resultado: false` — el unhappy
57
+ path se inspecciona vía `resultado`/`log`. Fallos de transporte propagan
58
+ `Savon::*` / `Net::HTTP` / `JSON::ParserError` sin envolver.
59
+ - El WS **no controla duplicados** (`crear_pagador` es no-idempotente): el
60
+ control de unicidad es del consumidor.
61
+ - `client_to_use` inválido (≠ `'soap'`/`'https'`) → `ArgumentError` en `Client.new`.
62
+ - **No usar `COBRODIGITAL_LOG_LEVEL=debug` en producción**: el XML formateado del
63
+ request expone el `sid` + PII del pagador.
64
+ - Requiere Ruby `>= 2.7, < 3.0` (stack savon 2.12). Desde v1.9.0 **no** depende de
65
+ ActiveSupport (solo stdlib).
66
+
67
+ ## Índice de artefactos
68
+
69
+ | capa | doc | estado |
70
+ |---|---|---|
71
+ | interfaz | [`docs/interface/interface.md`](../docs/interface/interface.md) | API Ruby pública |
72
+ | consumidas | [`docs/consumed/cobrodigital.md`](../docs/consumed/cobrodigital.md) | WS de CobroDigital (§a/§b/§d; §c/§e pendientes de enrich) |
73
+ | configuración | [`docs/config/configuracion.md`](../docs/config/configuracion.md) | inventario base |
74
+ | topología | [`docs/topology/topology.md`](../docs/topology/topology.md) | deps + modos de transporte |
75
+ | test | [`docs/test/testing.md`](../docs/test/testing.md) | RSpec (suite mínima) |
76
+ | comportamiento | [`docs/behavior/behavior.md`](../docs/behavior/behavior.md) | operación simple · batch meta |
77
+ | glosario | [`docs/glossary/glossary.md`](../docs/glossary/glossary.md) | términos del dominio |
78
+ | datos · api · errores · eventos · seguridad · multi-tenancy · data-lifecycle | — | n/a (ver Mapa de conocimiento en `AGENTS.md`) |
79
+ | release | — | pendiente (`/gem-release`) |
80
+
81
+ ## Uso correcto / gotchas
82
+
83
+ - Para varias operaciones en una sola llamada al WS, construí cada operación y
84
+ pasalas a `CobroDigital::Meta.meta([...])`.
85
+ - Las fechas de `Boleta.generar`, `Transaccion.consultar` y `Micrositio.consultar_actividad`
86
+ se formatean internamente a `%Y%m%d` — pasá objetos `Date`/`Time`, no strings.
87
+ - El handshake (`MD5` de `Time.now`) se regenera por request automáticamente.
data/skills.yml ADDED
@@ -0,0 +1,17 @@
1
+ mcps:
2
+ - github
3
+ - clickup
4
+ skills:
5
+ multi-vendor-feedback:
6
+ yard:
7
+ quality-code:
8
+ gem-release:
9
+ arch-structure:
10
+ arch-compose:
11
+ arch-enrich:
12
+ skill-feedback:
13
+ agent-issue:
14
+ bug-report:
15
+ dev-flow:
16
+ documentation-writer:
17
+ matrix-element:
metadata CHANGED
@@ -1,113 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cobro_digital
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.2
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - g.edera
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-11 00:00:00.000000000 Z
11
+ date: 2026-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 2.1.4
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 2.1.4
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: rake
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
17
  - - ">="
32
18
  - !ruby/object:Gem::Version
33
- version: 13.0.6
19
+ version: 13.2.1
34
20
  type: :development
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
24
  - - ">="
39
25
  - !ruby/object:Gem::Version
40
- version: 13.0.6
41
- - !ruby/object:Gem::Dependency
42
- name: savon
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 2.12.1
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 2.12.1
55
- - !ruby/object:Gem::Dependency
56
- name: nokogiri
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 1.10.10
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 1.10.10
26
+ version: 13.2.1
69
27
  - !ruby/object:Gem::Dependency
70
- name: wasabi
28
+ name: rspec
71
29
  requirement: !ruby/object:Gem::Requirement
72
30
  requirements:
73
31
  - - "~>"
74
32
  - !ruby/object:Gem::Version
75
- version: 3.5.0
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 3.5.0
83
- - !ruby/object:Gem::Dependency
84
- name: akami
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 1.3.1
90
- type: :runtime
33
+ version: '3.13'
34
+ type: :development
91
35
  prerelease: false
92
36
  version_requirements: !ruby/object:Gem::Requirement
93
37
  requirements:
94
38
  - - "~>"
95
39
  - !ruby/object:Gem::Version
96
- version: 1.3.1
40
+ version: '3.13'
97
41
  - !ruby/object:Gem::Dependency
98
- name: nori
42
+ name: savon
99
43
  requirement: !ruby/object:Gem::Requirement
100
44
  requirements:
101
45
  - - "~>"
102
46
  - !ruby/object:Gem::Version
103
- version: 2.6.0
47
+ version: 2.12.1
104
48
  type: :runtime
105
49
  prerelease: false
106
50
  version_requirements: !ruby/object:Gem::Requirement
107
51
  requirements:
108
52
  - - "~>"
109
53
  - !ruby/object:Gem::Version
110
- version: 2.6.0
54
+ version: 2.12.1
111
55
  description: Adaptador para el Web Service de CobroDigital
112
56
  email:
113
57
  - gab.edera@gmail.com
@@ -115,9 +59,13 @@ executables: []
115
59
  extensions: []
116
60
  extra_rdoc_files: []
117
61
  files:
62
+ - ".github/workflows/main.yml"
63
+ - ".github/workflows/release.yml"
118
64
  - ".gitignore"
119
65
  - ".rspec"
120
- - ".travis.yml"
66
+ - AGENTS.md
67
+ - CHANGELOG.md
68
+ - CLAUDE.md
121
69
  - CODE_OF_CONDUCT.md
122
70
  - Gemfile
123
71
  - LICENSE.txt
@@ -126,6 +74,13 @@ files:
126
74
  - bin/console
127
75
  - bin/setup
128
76
  - cobro_digital.gemspec
77
+ - docs/behavior/behavior.md
78
+ - docs/config/configuracion.md
79
+ - docs/consumed/cobrodigital.md
80
+ - docs/glossary/glossary.md
81
+ - docs/interface/interface.md
82
+ - docs/test/testing.md
83
+ - docs/topology/topology.md
129
84
  - lib/cobro_digital.rb
130
85
  - lib/cobro_digital/boleta.rb
131
86
  - lib/cobro_digital/meta.rb
@@ -134,11 +89,14 @@ files:
134
89
  - lib/cobro_digital/pagador.rb
135
90
  - lib/cobro_digital/transaccion.rb
136
91
  - lib/cobro_digital/version.rb
92
+ - skill/SKILL.md
93
+ - skills.yml
137
94
  homepage: https://github.com/gedera/cobrodigital
138
95
  licenses:
139
96
  - MIT
140
- metadata: {}
141
- post_install_message:
97
+ metadata:
98
+ documentation_uri: https://github.com/gedera/cobrodigital/blob/v1.9.0/skill
99
+ post_install_message:
142
100
  rdoc_options: []
143
101
  require_paths:
144
102
  - lib
@@ -146,15 +104,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
146
104
  requirements:
147
105
  - - ">="
148
106
  - !ruby/object:Gem::Version
149
- version: '0'
107
+ version: '2.7'
108
+ - - "<"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.0'
150
111
  required_rubygems_version: !ruby/object:Gem::Requirement
151
112
  requirements:
152
113
  - - ">="
153
114
  - !ruby/object:Gem::Version
154
115
  version: '0'
155
116
  requirements: []
156
- rubygems_version: 3.2.3
157
- signing_key:
117
+ rubygems_version: 3.1.6
118
+ signing_key:
158
119
  specification_version: 4
159
120
  summary: Adaptador CobroDigital
160
121
  test_files: []
data/.travis.yml DELETED
@@ -1,4 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 1.8.7
4
- before_install: gem install bundler -v 1.10.6