@veriko-mx/sdk 0.4.10 → 0.4.12

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +237 -41
  3. package/dist/cjs/client.d.ts +6 -3
  4. package/dist/cjs/client.d.ts.map +1 -1
  5. package/dist/cjs/client.js +6 -3
  6. package/dist/cjs/client.js.map +1 -1
  7. package/dist/cjs/generated/openapi.d.ts +835 -33
  8. package/dist/cjs/generated/openapi.d.ts.map +1 -1
  9. package/dist/cjs/http.d.ts +2 -0
  10. package/dist/cjs/http.d.ts.map +1 -1
  11. package/dist/cjs/http.js +1 -1
  12. package/dist/cjs/http.js.map +1 -1
  13. package/dist/cjs/index.d.ts +2 -2
  14. package/dist/cjs/index.d.ts.map +1 -1
  15. package/dist/cjs/index.js +6 -2
  16. package/dist/cjs/index.js.map +1 -1
  17. package/dist/cjs/resources.d.ts +88 -4
  18. package/dist/cjs/resources.d.ts.map +1 -1
  19. package/dist/cjs/resources.js +166 -8
  20. package/dist/cjs/resources.js.map +1 -1
  21. package/dist/cjs/types.d.ts +129 -13
  22. package/dist/cjs/types.d.ts.map +1 -1
  23. package/dist/cjs/types.js +6 -0
  24. package/dist/cjs/types.js.map +1 -1
  25. package/dist/cjs/webhooks.d.ts +41 -1
  26. package/dist/cjs/webhooks.d.ts.map +1 -1
  27. package/dist/cjs/webhooks.js +94 -6
  28. package/dist/cjs/webhooks.js.map +1 -1
  29. package/dist/esm/client.d.ts +6 -3
  30. package/dist/esm/client.d.ts.map +1 -1
  31. package/dist/esm/client.js +6 -3
  32. package/dist/esm/client.js.map +1 -1
  33. package/dist/esm/generated/openapi.d.ts +835 -33
  34. package/dist/esm/generated/openapi.d.ts.map +1 -1
  35. package/dist/esm/http.d.ts +2 -0
  36. package/dist/esm/http.d.ts.map +1 -1
  37. package/dist/esm/http.js +1 -1
  38. package/dist/esm/http.js.map +1 -1
  39. package/dist/esm/index.d.ts +2 -2
  40. package/dist/esm/index.d.ts.map +1 -1
  41. package/dist/esm/index.js +1 -1
  42. package/dist/esm/index.js.map +1 -1
  43. package/dist/esm/resources.d.ts +88 -4
  44. package/dist/esm/resources.d.ts.map +1 -1
  45. package/dist/esm/resources.js +166 -8
  46. package/dist/esm/resources.js.map +1 -1
  47. package/dist/esm/types.d.ts +129 -13
  48. package/dist/esm/types.d.ts.map +1 -1
  49. package/dist/esm/types.js +6 -0
  50. package/dist/esm/types.js.map +1 -1
  51. package/dist/esm/webhooks.d.ts +41 -1
  52. package/dist/esm/webhooks.d.ts.map +1 -1
  53. package/dist/esm/webhooks.js +91 -5
  54. package/dist/esm/webhooks.js.map +1 -1
  55. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,57 @@ versiones según [SemVer](https://semver.org/lang/es/).
7
7
 
8
8
  Sin cambios todavía.
9
9
 
10
+ ## [0.4.12] — 2026-10-02
11
+
12
+ ### Añadido
13
+
14
+ - `validations.recheck()` (`POST /v1/validations/{id}/recheck`): vuelve a consultar a Banxico el
15
+ estado de pago de una validación `valid` creada hace 72 horas como máximo, sin consumir cuota.
16
+ Devuelve `RecheckResult` con la validación y con `checkedAt`, `changed` y `previousStatus`. Si
17
+ Banxico reporta la devolución, la validación pasa a `returned`. No se reintenta sola.
18
+ - `validations.preparePurge()` y `validations.executePurge()`: el borrado definitivo de una
19
+ validación, en dos pasos. Devuelven `PurgePreparation` y `PurgeResult`. `executePurge()` no se
20
+ reintenta sola. Los tipos de `Validation` añaden `purged_at`.
21
+ - `cuentasCandidatas` en `validateTransfer()`, `validations.validate()`, `validations.validateOcr()`,
22
+ `validations.enqueue()` y `validations.enqueueOcr()`: de 2 a 3 cuentas en una sola validación y con
23
+ una sola unidad de cuota. Los tipos de `Validation` añaden `candidate_match`, con la posición y los
24
+ últimos 4 dígitos de la cuenta que coincidió.
25
+ - `retainImage` en `validations.validateOcr()` y `validations.enqueueOcr()`, y `image_retained` en los
26
+ tipos de `Validation`: con `retainImage: false` la plataforma no conserva el archivo del
27
+ comprobante.
28
+ - El evento `validation.returned` en `WEBHOOK_EVENTS`, que avisa cuando una validación `valid` pasa
29
+ después a `returned`, y `payment_status` (`PaymentStatus`) en `evento.data.attributes`.
30
+
31
+ ### Cambiado
32
+
33
+ - `cuentaBeneficiaria` deja de ser obligatoria cuando se envía `cuentasCandidatas`. Sin ninguna de
34
+ las dos, el SDK lanza `InvalidRequestError` con `cuenta_required`, y con las dos, con
35
+ `cuenta_y_candidatas_excluyentes`. En los dos casos no llama a la API.
36
+
37
+ ## [0.4.11] — 2026-10-01
38
+
39
+ ### Añadido
40
+
41
+ - `clientRef` en `validateTransfer()`, `validations.validate()`, `validations.validateOcr()`,
42
+ `validations.enqueue()` y `validations.enqueueOcr()`: una referencia propia de 1 a 64 caracteres
43
+ que vuelve en `attributes.client_ref`.
44
+ - El filtro `clientRef`, de coincidencia exacta, en `validations.list()`, `validations.iter()`,
45
+ `validations.stats()` y `validations.export()`.
46
+ - Los tipos de `Validation` añaden `client_ref`, `duplicate_of` y `account_conflict`.
47
+ - `verifyWebhookTimestamped()` comprueba la cabecera `X-Webhook-Signature-Timestamped`
48
+ (`t=<segundos>,v1=<hex>`): compara en tiempo constante el HMAC-SHA256 de `<t>.<cuerpo>` con cada
49
+ `v1` y rechaza la entrega cuando `t` se aleja del reloj más de `toleranceSeconds`, 300 por
50
+ omisión. `timestampedSignatureFromHeaders()` encuentra la cabecera en cualquiera de sus grafías.
51
+ `verifyWebhook()` no cambia.
52
+ - `parseWebhook()` entrega el `client_ref` en `evento.data.attributes` cuando el webhook de
53
+ validación lo trae.
54
+
55
+ ### Cambiado
56
+
57
+ - `cuentaBeneficiaria` es obligatoria en `validateTransfer()`, `validations.validate()` y
58
+ `validations.enqueue()`. Sin ella, el SDK lanza `InvalidRequestError` con `cuenta_required` y no
59
+ llama a la API.
60
+
10
61
  ## [0.4.10] — 2026-09-29
11
62
 
12
63
  ### Cambiado
package/README.md CHANGED
@@ -46,25 +46,27 @@ La API consulta el CEP y devuelve un veredicto en el campo `status`:
46
46
  | `invalid` | Los datos enviados no forman una consulta válida |
47
47
  | `error` | Fallo durante el procesamiento; el motivo viaja en `error_code` |
48
48
 
49
- Con veredicto `valid`, el comprobante queda disponible en XML y en PDF.
49
+ Con veredicto `valid`, el comprobante queda disponible en XML y en PDF. Un `valid` es el veredicto
50
+ del momento de la consulta: Banxico puede reportar la devolución hasta 72 horas después, y la
51
+ validación pasa a `returned`.
50
52
 
51
53
  ## Las familias de operaciones
52
54
 
53
- El cliente agrupa las 66 operaciones M2M de la API en once familias:
54
-
55
- | familia | qué cubre |
56
- | ---------------------- | --------------------------------------------------------------------------------------------------------------------- |
57
- | `client.validations` | Validar por campos o por imagen, consultar, listar, exportar, la política de reintentos y la descarga del comprobante |
58
- | `client.webhooks` | Registrar endpoints, rotar su secreto, enviar un evento de prueba y leer el historial de entregas |
59
- | `client.catalog` | Catálogo de bancos SPEI, banco emisor de una tarjeta y estado del servicio de Banxico |
60
- | `client.beneficiaries` | Cuentas beneficiarias guardadas y la importación masiva, como ciclo completo |
61
- | `client.usage` | Cuota de validaciones, límites de tasa y registro de actividad de la API |
62
- | `client.account` | Perfil y política de reintentos predeterminada de la cuenta |
63
- | `client.dashboard` | Resumen del panel |
64
- | `client.plans` | Catálogo y comparación de planes públicos, sin clave de API |
65
- | `client.insights` | Resumen, tendencias, bancos y beneficiarios principales |
66
- | `client.finance` | Resumen, estado de cuenta, vistas previas y descargas financieras |
67
- | `client.billing` | Suscripción activa |
55
+ El cliente agrupa las 69 operaciones M2M de la API en once familias:
56
+
57
+ | familia | qué cubre |
58
+ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
59
+ | `client.validations` | Validar por campos o por imagen, consultar, listar, exportar, revisar el estado de pago, borrar, la política de reintentos y la descarga del comprobante |
60
+ | `client.webhooks` | Registrar endpoints, rotar su secreto, enviar un evento de prueba y leer el historial de entregas |
61
+ | `client.catalog` | Catálogo de bancos SPEI, banco emisor de una tarjeta y estado del servicio de Banxico |
62
+ | `client.beneficiaries` | Cuentas beneficiarias guardadas y la importación masiva, como ciclo completo |
63
+ | `client.usage` | Cuota de validaciones, límites de tasa y registro de actividad de la API |
64
+ | `client.account` | Perfil y política de reintentos predeterminada de la cuenta |
65
+ | `client.dashboard` | Resumen del panel |
66
+ | `client.plans` | Catálogo y comparación de planes públicos, sin clave de API |
67
+ | `client.insights` | Resumen, tendencias, bancos y beneficiarios principales |
68
+ | `client.finance` | Resumen, estado de cuenta, vistas previas y descargas financieras |
69
+ | `client.billing` | Suscripción activa |
68
70
 
69
71
  Las tres operaciones de uso más frecuente están también en la raíz del cliente, como atajo:
70
72
  `validateTransfer()`, `getValidation()` y `getCep()`.
@@ -99,9 +101,11 @@ const client = new Veriko({ apiKey: 'veriko_tu_clave_aqui' });
99
101
 
100
102
  ## Validar una transferencia
101
103
 
102
- La operación exige la fecha de envío, el importe y **la clave de rastreo o la referencia
103
- numérica**. Enviar las dos precisa la búsqueda. El banco emisor, el receptor y la cuenta
104
- beneficiaria son opcionales y mejoran la identificación.
104
+ La operación exige la fecha de envío, el importe, la cuenta beneficiaria y **la clave de rastreo
105
+ o la referencia numérica**. Enviar las dos precisa la búsqueda. El banco emisor y el receptor son
106
+ opcionales y mejoran la identificación. La API rechaza con `422` (`preflight_failed`) una petición
107
+ sin cuenta: no la busca entre los beneficiarios guardados. Cuando no se sabe cuál fue la cuenta,
108
+ `cuentasCandidatas` sustituye a `cuentaBeneficiaria`.
105
109
 
106
110
  ```ts
107
111
  import { Veriko } from '@veriko-mx/sdk';
@@ -141,6 +145,8 @@ El SDK lee el archivo y lo codifica en base64. `imageUrl` recibe un comprobante
141
145
  HTTPS, y si se envían `image` e `imageUrl`, la API sólo considera `image`. Formatos: JPEG, PNG, WebP
142
146
  o PDF de 1 a 3 páginas, de hasta 12 MB.
143
147
 
148
+ `cuentasCandidatas` reemplaza a `cuentaBeneficiaria` cuando la imagen no muestra la cuenta.
149
+
144
150
  El comprobante de una validación por OCR se descarga con `client.validations.image(id)`.
145
151
 
146
152
  ### Sin esperar al veredicto
@@ -170,6 +176,82 @@ El tiempo de espera se fija con `timeoutMs` (cinco minutos por omisión) y la pa
170
176
 
171
177
  La alternativa a sondear es suscribirse al webhook `validation.completed`.
172
178
 
179
+ ### Referencia propia
180
+
181
+ `clientRef` es una referencia propia de 1 a 64 caracteres, sin saltos de línea ni emoji. Sirve para
182
+ relacionar la validación con un pedido propio. No debe contener datos personales.
183
+
184
+ ```ts
185
+ const validation = await client.validateTransfer({
186
+ fecha: '2025-03-15',
187
+ monto: 15000.5,
188
+ claveRastreo: 'MXBA20250315001234',
189
+ cuentaBeneficiaria: '012180004412345678',
190
+ clientRef: 'orden-4812',
191
+ });
192
+ console.log(validation.attributes.client_ref); // orden-4812
193
+
194
+ const page = await client.validations.list({ clientRef: 'orden-4812' });
195
+ ```
196
+
197
+ `validateOcr()`, `enqueue()` y `enqueueOcr()` también la aceptan. Vuelve en
198
+ `attributes.client_ref`, en los listados y en los webhooks de validación, y `list()`, `stats()` y
199
+ `export()` la usan como filtro de coincidencia exacta. En un webhook, `parseWebhook()` la entrega en
200
+ `evento.data.attributes.client_ref`. La API rechaza con `422` (`invalid_client_ref`) una referencia
201
+ que no cumple las reglas.
202
+
203
+ ### Duplicado y conflicto de cuenta
204
+
205
+ `attributes.duplicate_of` trae el `id` y el `created_at` de una validación previa `valid`, de la
206
+ misma cuenta y con la misma clave de rastreo. `attributes.account_conflict` trae los últimos 4
207
+ dígitos de la cuenta enviada (`sent_last4`) y de la que muestra la imagen (`read_last4`) en una
208
+ validación por OCR. Ninguno cambia el veredicto, y los dos están ausentes cuando la API no los
209
+ informa.
210
+
211
+ ### Varias cuentas candidatas
212
+
213
+ `cuentasCandidatas` lleva de 2 a 3 cuentas en una sola validación, con una sola unidad de cuota.
214
+
215
+ ```ts
216
+ const validation = await client.validateTransfer({
217
+ fecha: '2025-03-15',
218
+ monto: 15000.5,
219
+ claveRastreo: 'MXBA20250315001234',
220
+ cuentasCandidatas: ['012180004412345678', '002010077777777771'],
221
+ });
222
+
223
+ console.log(validation.attributes.candidate_match?.index); // posición en la lista enviada, desde 0
224
+ console.log(validation.attributes.candidate_match?.account_last4); // 7771
225
+ ```
226
+
227
+ `validateOcr()`, `enqueue()` y `enqueueOcr()` también la aceptan. La API consulta las cuentas en el
228
+ orden enviado y adopta la primera que coincide con la transferencia. `attributes.candidate_match`
229
+ trae su posición y sus últimos 4 dígitos, y la cuenta completa queda en
230
+ `attributes.normalized_data.cuenta_beneficiaria`. El veredicto no cambia.
231
+
232
+ Se envía una de las dos formas, no las dos: el tipo de los argumentos lo impide, y con
233
+ `cuentaBeneficiaria` y `cuentasCandidatas` juntas, o sin ninguna, el SDK lanza
234
+ `InvalidRequestError` (`cuenta_y_candidatas_excluyentes` o `cuenta_required`) y no llama a la API.
235
+ Una lista que no cumple se rechaza con `422` (`cuentas_candidatas_invalidas`).
236
+
237
+ ### Conservar el comprobante
238
+
239
+ La plataforma conserva el archivo de una validación por imagen, y `client.validations.image(id)` lo
240
+ descarga. Con `retainImage: false` lo borra en cuanto la validación llega a un estado terminal del
241
+ que ya no lo necesita. El veredicto y los datos extraídos se conservan.
242
+
243
+ ```ts
244
+ const validation = await client.validations.validateOcr({
245
+ image: 'comprobante.png',
246
+ retainImage: false,
247
+ });
248
+ console.log(validation.attributes.image_retained); // false
249
+ ```
250
+
251
+ `enqueueOcr()` también acepta `retainImage`. `image()` responde `410` con `image_not_retained`
252
+ cuando el archivo no se conserva, y la API rechaza con `422` (`invalid_retain_image`) un valor que
253
+ no es booleano.
254
+
173
255
  ### Listar y recorrer el historial
174
256
 
175
257
  ```ts
@@ -186,7 +268,7 @@ for await (const item of client.validations.iter({ from: '2025-03-01', to: '2025
186
268
  `totalPages` y `hasNext`.
187
269
 
188
270
  Los filtros (`status`, `type`, `from`, `to`, `search`, `playground`, `withDeleted`, `batchId`,
189
- `bank`, `amountMin`, `amountMax` y `retryState`) van en `camelCase`. `status` acepta un estado o una
271
+ `bank`, `amountMin`, `amountMax`, `clientRef` y `retryState`) van en `camelCase`. `status` acepta un estado o una
190
272
  lista, y `withDeleted: true` devuelve sólo las validaciones retiradas, mientras que `false` devuelve
191
273
  sólo las activas.
192
274
 
@@ -215,6 +297,59 @@ con `cep_not_available` y el SDK lanza `NotFoundError`.
215
297
  Las descargas y las exportaciones devuelven el archivo y no un enlace: `content`, `contentType` y
216
298
  el `filename` que propone la API en `Content-Disposition`.
217
299
 
300
+ ## Revisar el pago después
301
+
302
+ `client.validations.recheck(id)` vuelve a consultar a Banxico el estado de pago de una validación
303
+ `valid` creada hace 72 horas como máximo, sin consumir cuota.
304
+
305
+ ```ts
306
+ const result = await client.validations.recheck(validation.id);
307
+
308
+ console.log(result.changed); // true si pasó de valid a returned
309
+ console.log(result.previousStatus); // 'valid'
310
+ console.log(result.validation.attributes.status); // 'returned'
311
+ ```
312
+
313
+ Si Banxico reporta `devuelto` o `en_proceso_devolucion`, la validación pasa a `returned`, conserva su
314
+ CEP y la API emite el webhook `validation.returned`. El estado del pago queda en
315
+ `attributes.banxico_result._payment_status`. Una validación que ya estaba en `returned` responde su
316
+ estado actual sin consultar a Banxico, y `checkedAt` vale `null`.
317
+
318
+ Cada validación admite una consulta cada 10 minutos: antes, el SDK lanza `RateLimitError` con
319
+ `recheck_rate_limited`, y `retryAfter` trae los segundos que faltan. Una validación en otro estado,
320
+ o con más de 72 horas, lanza `InvalidRequestError` con `recheck_not_eligible` o
321
+ `recheck_window_expired`. Si Banxico no entrega un estado legible, lanza `ServerError` con
322
+ `recheck_unavailable`: la validación conserva su intervalo y se puede reintentar de inmediato.
323
+
324
+ ## Borrar una validación
325
+
326
+ `client.validations.delete(id)` retira una validación del historial, pero el registro, el CEP, los
327
+ datos extraídos y el archivo del comprobante siguen existiendo. El borrado definitivo los elimina en
328
+ dos pasos: el primero describe lo que se borraría y emite un token de un solo uso, y el segundo lo
329
+ confirma.
330
+
331
+ ```ts
332
+ const preparation = await client.validations.preparePurge(validation.id);
333
+
334
+ console.log(preparation.attributes.will_delete); // lo que se borraría
335
+ console.log(preparation.attributes.expires_in); // segundos de vigencia del token
336
+
337
+ const result = await client.validations.executePurge(validation.id, {
338
+ confirmationToken: preparation.attributes.confirmation_token,
339
+ });
340
+ console.log(result.attributes.purged_at, result.attributes.file_removal);
341
+ ```
342
+
343
+ **El borrado es irreversible y no devuelve cuota.** La validación queda como una lápida: conserva el
344
+ veredicto, las fechas y el monto, y trae `attributes.purged_at`. Después, el CEP, el comprobante, los
345
+ reintentos y `recheck()` responden `410` con `validation_purged`. `file_removal` vale `pending`
346
+ cuando algún archivo no se pudo borrar en ese momento y el barrido diario lo termina.
347
+
348
+ Una validación en curso lanza `ConflictError` con `purge_validation_in_progress`. Un token vencido,
349
+ mal formado o de otra validación lanza `InvalidRequestError`, y uno ya usado, `ConflictError` con
350
+ `confirmation_token_already_used`. Si la respuesta de `executePurge()` no llega,
351
+ `client.getValidation(id)` dice si el borrado se completó.
352
+
218
353
  ## Registrar un webhook
219
354
 
220
355
  ```ts
@@ -370,6 +505,32 @@ para decidir el código de respuesta aparte. La comparación es en tiempo consta
370
505
 
371
506
  El receptor completo está en [`examples/express-webhook.mjs`](examples/express-webhook.mjs).
372
507
 
508
+ ### Una devolución posterior
509
+
510
+ `validation.returned` avisa cuando una validación que había salido `valid` pasa después a
511
+ `returned`. El endpoint recibe sólo los eventos a los que se suscribió, así que hay que añadirlo
512
+ además de `validation.completed`:
513
+
514
+ ```ts
515
+ const endpoint = await client.webhooks.create({
516
+ url: 'https://miapp.example.com/hooks/pagos',
517
+ events: ['validation.completed', 'validation.returned'],
518
+ });
519
+ ```
520
+
521
+ El cuerpo es el de `validation.completed` más `attributes.payment_status`, que `parseWebhook()`
522
+ entrega en `evento.data.attributes.payment_status`:
523
+
524
+ ```ts
525
+ if (evento.event === 'validation.returned') {
526
+ console.log(evento.data?.attributes.payment_status?.code); // devuelto o en_proceso_devolucion
527
+ }
528
+ ```
529
+
530
+ `checked_at` es el instante de la consulta. En el resto de los eventos `payment_status` está
531
+ ausente. El evento no se emite al crear la validación: una operación que llega ya devuelta se
532
+ entrega con `validation.completed` y `status=returned`.
533
+
373
534
  ### Lo que Banxico confirmó
374
535
 
375
536
  Cuando `banxico_status` es `valid`, o `returned` con CEP descargado, `evento.data.attributes`
@@ -378,24 +539,58 @@ del beneficiario (enmascarada a los últimos 4 dígitos), tal como los confirmó
378
539
  contra el pedido antes de liberar la mercancía: la imagen de un comprobante puede mostrar un monto
379
540
  distinto al que Banxico confirmó.
380
541
 
381
- ### Las cuatro cabeceras de una entrega
542
+ ### Las cinco cabeceras de una entrega
382
543
 
383
- | cabecera | contenido |
384
- | ---------------------- | ----------------------------------------------------- |
385
- | `X-Webhook-Signature` | `sha256=` seguido del HMAC en hexadecimal |
386
- | `X-Veriko-Event` | Tipo de evento, por ejemplo `validation.completed` |
387
- | `X-Veriko-Delivery-Id` | Identificador de la entrega, estable entre reintentos |
388
- | `X-Veriko-Timestamp` | Momento del envío, ISO 8601 con sufijo `Z` |
544
+ | cabecera | contenido |
545
+ | --------------------------------- | ------------------------------------------------------------------------ |
546
+ | `X-Webhook-Signature` | `sha256=` seguido del HMAC en hexadecimal |
547
+ | `X-Webhook-Signature-Timestamped` | `t=<segundos>,v1=<hex>`: firma de `<t>.<cuerpo>` con la hora del intento |
548
+ | `X-Veriko-Event` | Tipo de evento, por ejemplo `validation.completed` |
549
+ | `X-Veriko-Delivery-Id` | Identificador de la entrega, estable entre reintentos |
550
+ | `X-Veriko-Timestamp` | Momento del envío, ISO 8601 con sufijo `Z` |
389
551
 
390
552
  El `Delivery-Id` es el valor que permite descartar entregas repetidas.
391
553
 
554
+ ### Firma con marca de tiempo
555
+
556
+ `X-Webhook-Signature-Timestamped` firma la hora del intento junto con el cuerpo, de modo que el
557
+ receptor puede descartar una entrega vieja que alguien vuelva a enviar. `X-Webhook-Signature` no
558
+ cambia.
559
+
560
+ ```ts
561
+ import { verifyWebhookTimestamped } from '@veriko-mx/sdk';
562
+
563
+ if (
564
+ !verifyWebhookTimestamped(
565
+ request.body, // el cuerpo crudo
566
+ request.get('X-Webhook-Signature-Timestamped'),
567
+ SECRET,
568
+ )
569
+ ) {
570
+ return response.sendStatus(400);
571
+ }
572
+ ```
573
+
574
+ `verifyWebhookTimestamped(payload, header, secret, { toleranceSeconds, now })` devuelve `true` o
575
+ `false`. Calcula el HMAC-SHA256 de `<t>.<cuerpo>`, lo compara en tiempo constante con cada `v1` de
576
+ la cabecera y rechaza la entrega si `t` se aleja del reloj del receptor más de `toleranceSeconds`,
577
+ 300 por omisión. `now` fija la hora actual con un `Date`, para las pruebas.
578
+ `timestampedSignatureFromHeaders(headers)` encuentra la cabecera en cualquiera de sus grafías.
579
+
580
+ La ventana se aplica a `t`, la hora del intento, y no al campo `timestamp` del cuerpo, que es la hora
581
+ del evento. Un reintento llega hasta unas 8,6 horas después del evento, pero lleva una `t` recién
582
+ generada. Medir la ventana contra el `timestamp` del cuerpo rechazaría reintentos legítimos. La
583
+ ventana no sustituye a la deduplicación: guarda el `Delivery-Id` al menos 24 horas.
584
+
392
585
  ## Reintentos
393
586
 
394
587
  Hay dos mecanismos distintos con el mismo nombre.
395
588
 
396
589
  **Los del cliente** repiten una petición que falló por causas pasajeras. El SDK reintenta los
397
590
  `5xx`, el `408` y el `429`, y respeta el `Retry-After` de la respuesta cuando lo trae. El resto de
398
- los `4xx` no se reintenta, porque la petición hay que corregirla antes de repetirla.
591
+ los `4xx` no se reintenta, porque la petición hay que corregirla antes de repetirla. `recheck()` y
592
+ `executePurge()` no se reintentan solas: la primera tiene su propio tope de una consulta cada 10
593
+ minutos, y el borrado es irreversible.
399
594
 
400
595
  ```ts
401
596
  const client = new Veriko({ maxRetries: 3 }); // 0 los desactiva; por omisión son 2
@@ -473,18 +668,19 @@ try {
473
668
  }
474
669
  ```
475
670
 
476
- | excepción | estado |
477
- | ---------------------------- | ----------------------------------------------- |
478
- | `AuthenticationError` | `401` |
479
- | `ForbiddenError` | `403` |
480
- | `NotFoundError` | `404` |
481
- | `ConflictError` | `409` |
482
- | `InvalidRequestError` | `400`, `413`, `422` |
483
- | `RateLimitError` | `429` |
484
- | `ServerError` | `5xx` |
485
- | `ConnectionError` | Sin respuesta, con los reintentos agotados |
486
- | `TimeoutError` | `waitFor()` o `importWait()` agotaron su tiempo |
487
- | `SignatureVerificationError` | La firma de un webhook no cuadra |
671
+ | excepción | estado |
672
+ | ---------------------------- | -------------------------------------------------- |
673
+ | `AuthenticationError` | `401` |
674
+ | `ForbiddenError` | `403` |
675
+ | `NotFoundError` | `404` |
676
+ | `ConflictError` | `409` |
677
+ | `InvalidRequestError` | `400`, `413`, `422` |
678
+ | `RateLimitError` | `429` |
679
+ | `ServerError` | `5xx` |
680
+ | `ApiError` | Cualquier otro estado de la API, por ejemplo `410` |
681
+ | `ConnectionError` | Sin respuesta, con los reintentos agotados |
682
+ | `TimeoutError` | `waitFor()` o `importWait()` agotaron su tiempo |
683
+ | `SignatureVerificationError` | La firma de un webhook no cuadra |
488
684
 
489
685
  Cada error de la API trae `requestId`, que identifica la petición en los registros del sistema.
490
686
 
@@ -516,7 +712,7 @@ completos, por si hace falta una operación que el SDK todavía no envuelve.
516
712
 
517
713
  ## Superficie M2M
518
714
 
519
- El SDK cubre exactamente las 66 operaciones del spec público: `security: []` para las públicas y
715
+ El SDK cubre exactamente las 69 operaciones del spec público: `security: []` para las públicas y
520
716
  `ApiKeyAuth` para las autenticadas.
521
717
 
522
718
  Entre ellas están el perfil y su política de reintentos, el resumen del panel, los dos endpoints
@@ -7,7 +7,7 @@ export declare const DEFAULT_TIMEOUT_MS = 30000;
7
7
  export declare const API_KEY_ENV_VAR = "VERIKO_API_KEY";
8
8
  export declare const BASE_URL_ENV_VAR = "VERIKO_BASE_URL";
9
9
  /** La versión que viaja en el `User-Agent`. `test/client.test.ts` la compara con `package.json`. */
10
- export declare const VERSION = "0.4.10";
10
+ export declare const VERSION = "0.4.12";
11
11
  export interface VerikoOptions {
12
12
  /** La clave de API. Por omisión, `VERIKO_API_KEY`. */
13
13
  apiKey?: string;
@@ -95,8 +95,11 @@ export declare class Veriko {
95
95
  * Devuelve el veredicto en `attributes.status`: `valid`, `not_found`,
96
96
  * `cep_unavailable`, `returned` o `error`.
97
97
  *
98
- * La operación exige `claveRastreo` o `referenciaNumerica`. Enviar las dos
99
- * precisa la búsqueda. La fecha es la de envío, en `YYYY-MM-DD`.
98
+ * La operación exige `cuentaBeneficiaria`, o `cuentasCandidatas` cuando no se
99
+ * sabe cuál fue la cuenta (una de las dos, no las dos), y `claveRastreo` o
100
+ * `referenciaNumerica`. Enviar las dos últimas precisa la búsqueda. La fecha
101
+ * es la de envío, en `YYYY-MM-DD`. `clientRef` es una referencia propia que
102
+ * vuelve en la validación y en los webhooks.
100
103
  *
101
104
  * Un `not_found` inmediato no equivale a una transferencia inexistente: un
102
105
  * CEP tarda en publicarse. `retryPolicy` deja a la API consultando de nuevo y
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAEnE,OAAO,EAAiB,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EACL,OAAO,EACP,aAAa,EACb,OAAO,EACP,OAAO,EACP,SAAS,EACT,OAAO,EACP,QAAQ,EACR,KAAK,EACL,KAAK,EACL,WAAW,EACX,QAAQ,EACT,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,oBAAoB,EACpB,sBAAsB,EACtB,UAAU,EACV,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,gBAAgB,6BAA6B,CAAC;AAC3D,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAChD,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAElD,oGAAoG;AACpG,eAAO,MAAM,OAAO,WAAW,CAAC;AAEhC,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IAEtC,kDAAkD;IAClD,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yBAAyB;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;gBAEd,OAAO,GAAE,aAAkB;IA+BvC,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;;;;;;;;;;;;;OAeG;IACH,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC;IAIrE;;;;;;;OAOG;IACH,aAAa,CACX,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,kBAAkB,CAAC;IAI9B;;;;;;OAMG;IACH,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,SAAS,CAAA;KAAO,GAAG,OAAO,CAAC,WAAW,CAAC;CAGzF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAEnE,OAAO,EAAiB,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EACL,OAAO,EACP,aAAa,EACb,OAAO,EACP,OAAO,EACP,SAAS,EACT,OAAO,EACP,QAAQ,EACR,KAAK,EACL,KAAK,EACL,WAAW,EACX,QAAQ,EACT,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,oBAAoB,EACpB,sBAAsB,EACtB,UAAU,EACV,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,gBAAgB,6BAA6B,CAAC;AAC3D,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAChD,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAElD,oGAAoG;AACpG,eAAO,MAAM,OAAO,WAAW,CAAC;AAEhC,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IAEtC,kDAAkD;IAClD,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yBAAyB;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;gBAEd,OAAO,GAAE,aAAkB;IA+BvC,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC;IAIrE;;;;;;;OAOG;IACH,aAAa,CACX,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,kBAAkB,CAAC;IAI9B;;;;;;OAMG;IACH,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,SAAS,CAAA;KAAO,GAAG,OAAO,CAAC,WAAW,CAAC;CAGzF"}
@@ -9,7 +9,7 @@ exports.DEFAULT_TIMEOUT_MS = 30_000;
9
9
  exports.API_KEY_ENV_VAR = 'VERIKO_API_KEY';
10
10
  exports.BASE_URL_ENV_VAR = 'VERIKO_BASE_URL';
11
11
  /** La versión que viaja en el `User-Agent`. `test/client.test.ts` la compara con `package.json`. */
12
- exports.VERSION = '0.4.10';
12
+ exports.VERSION = '0.4.12';
13
13
  /**
14
14
  * Cliente de la API de Veriko.
15
15
  *
@@ -107,8 +107,11 @@ class Veriko {
107
107
  * Devuelve el veredicto en `attributes.status`: `valid`, `not_found`,
108
108
  * `cep_unavailable`, `returned` o `error`.
109
109
  *
110
- * La operación exige `claveRastreo` o `referenciaNumerica`. Enviar las dos
111
- * precisa la búsqueda. La fecha es la de envío, en `YYYY-MM-DD`.
110
+ * La operación exige `cuentaBeneficiaria`, o `cuentasCandidatas` cuando no se
111
+ * sabe cuál fue la cuenta (una de las dos, no las dos), y `claveRastreo` o
112
+ * `referenciaNumerica`. Enviar las dos últimas precisa la búsqueda. La fecha
113
+ * es la de envío, en `YYYY-MM-DD`. `clientRef` es una referencia propia que
114
+ * vuelve en la validación y en los webhooks.
112
115
  *
113
116
  * Un `not_found` inmediato no equivale a una transferencia inexistente: un
114
117
  * CEP tarda en publicarse. `retryPolicy` deja a la API consultando de nuevo y
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}