@ar-agents/mercadopago 0.10.0 → 0.12.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.
- package/CHANGELOG.md +55 -0
- package/MIGRATION.md +176 -0
- package/cookbook/09-otel-wired.ts +155 -0
- package/cookbook/README.md +1 -0
- package/dist/audit-B9Nhj3PH.d.cts +294 -0
- package/dist/audit-B9Nhj3PH.d.ts +294 -0
- package/dist/index.cjs +588 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +270 -194
- package/dist/index.d.ts +270 -194
- package/dist/index.js +581 -5
- package/dist/index.js.map +1 -1
- package/dist/vercel-kv.cjs +81 -0
- package/dist/vercel-kv.cjs.map +1 -1
- package/dist/vercel-kv.d.cts +38 -2
- package/dist/vercel-kv.d.ts +38 -2
- package/dist/vercel-kv.js +81 -1
- package/dist/vercel-kv.js.map +1 -1
- package/package.json +4 -3
- package/tools.manifest.json +1 -1
- package/dist/state-C6Wzb_XX.d.cts +0 -106
- package/dist/state-C6Wzb_XX.d.ts +0 -106
package/dist/index.cjs
CHANGED
|
@@ -228,6 +228,23 @@ var DEFAULT_BASE_URL = "https://api.mercadopago.com";
|
|
|
228
228
|
function sleep(ms) {
|
|
229
229
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
230
230
|
}
|
|
231
|
+
function randomUuid() {
|
|
232
|
+
const c = globalThis.crypto;
|
|
233
|
+
if (c?.randomUUID) {
|
|
234
|
+
return c.randomUUID();
|
|
235
|
+
}
|
|
236
|
+
if (c?.getRandomValues) {
|
|
237
|
+
const bytes = new Uint8Array(16);
|
|
238
|
+
c.getRandomValues(bytes);
|
|
239
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
240
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
241
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
242
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
243
|
+
}
|
|
244
|
+
throw new Error(
|
|
245
|
+
"MercadoPagoClient: no Web Crypto available for idempotency key generation. This shouldn't happen on Node 19+, Edge Runtime, or modern browsers."
|
|
246
|
+
);
|
|
247
|
+
}
|
|
231
248
|
var MercadoPagoClient = class {
|
|
232
249
|
accessToken;
|
|
233
250
|
baseUrl;
|
|
@@ -271,8 +288,10 @@ var MercadoPagoClient = class {
|
|
|
271
288
|
Authorization: `Bearer ${this.accessToken}`,
|
|
272
289
|
"Content-Type": "application/json"
|
|
273
290
|
};
|
|
274
|
-
|
|
275
|
-
|
|
291
|
+
const isMutatingPost = method === "POST";
|
|
292
|
+
const idempotencyKey = options?.idempotencyKey ?? (isMutatingPost ? randomUuid() : void 0);
|
|
293
|
+
if (idempotencyKey) {
|
|
294
|
+
headers["X-Idempotency-Key"] = idempotencyKey;
|
|
276
295
|
}
|
|
277
296
|
const trace = this.traceContext?.();
|
|
278
297
|
if (trace?.traceId && trace?.spanId) {
|
|
@@ -2429,6 +2448,377 @@ function paginateSubscriptionPayments(client, preapprovalId, opts = {}) {
|
|
|
2429
2448
|
);
|
|
2430
2449
|
}
|
|
2431
2450
|
|
|
2451
|
+
// src/tax-id.ts
|
|
2452
|
+
function validateTaxId(input, type) {
|
|
2453
|
+
switch (type) {
|
|
2454
|
+
case "DNI":
|
|
2455
|
+
return validateAR_DNI(input);
|
|
2456
|
+
case "CUIT":
|
|
2457
|
+
case "CUIL":
|
|
2458
|
+
return validateAR_CUIT(input, type);
|
|
2459
|
+
case "CPF":
|
|
2460
|
+
return validateBR_CPF(input);
|
|
2461
|
+
case "CNPJ":
|
|
2462
|
+
return validateBR_CNPJ(input);
|
|
2463
|
+
case "RFC":
|
|
2464
|
+
return validateMX_RFC(input);
|
|
2465
|
+
case "RUT_CL":
|
|
2466
|
+
return validateCL_RUT(input);
|
|
2467
|
+
case "NIT":
|
|
2468
|
+
return validateCO_NIT(input);
|
|
2469
|
+
case "RUT_UY":
|
|
2470
|
+
return validateUY_RUT(input);
|
|
2471
|
+
case "RUC":
|
|
2472
|
+
return validatePE_RUC(input);
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
function validateAR_DNI(input) {
|
|
2476
|
+
const normalized = (input ?? "").replace(/\D/g, "");
|
|
2477
|
+
if (normalized.length === 0) {
|
|
2478
|
+
return failure(normalized, "DNI", "AR", "DNI vac\xEDo.");
|
|
2479
|
+
}
|
|
2480
|
+
if (normalized.length < 7 || normalized.length > 8) {
|
|
2481
|
+
return failure(
|
|
2482
|
+
normalized,
|
|
2483
|
+
"DNI",
|
|
2484
|
+
"AR",
|
|
2485
|
+
`Debe tener 7 u 8 d\xEDgitos; recib\xED ${normalized.length}.`
|
|
2486
|
+
);
|
|
2487
|
+
}
|
|
2488
|
+
return {
|
|
2489
|
+
valid: true,
|
|
2490
|
+
normalized,
|
|
2491
|
+
formatted: normalized.replace(/^(\d{1,2})(\d{3})(\d{3})$/, "$1.$2.$3"),
|
|
2492
|
+
type: "DNI",
|
|
2493
|
+
country: "AR",
|
|
2494
|
+
error: null
|
|
2495
|
+
};
|
|
2496
|
+
}
|
|
2497
|
+
var AR_CHECK_WEIGHTS = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
|
|
2498
|
+
function validateAR_CUIT(input, type) {
|
|
2499
|
+
const normalized = (input ?? "").replace(/\D/g, "");
|
|
2500
|
+
if (normalized.length !== 11) {
|
|
2501
|
+
return failure(
|
|
2502
|
+
normalized,
|
|
2503
|
+
type,
|
|
2504
|
+
"AR",
|
|
2505
|
+
`Debe tener 11 d\xEDgitos; recib\xED ${normalized.length}.`
|
|
2506
|
+
);
|
|
2507
|
+
}
|
|
2508
|
+
const sum = AR_CHECK_WEIGHTS.reduce(
|
|
2509
|
+
(acc, w, i) => acc + w * Number(normalized[i]),
|
|
2510
|
+
0
|
|
2511
|
+
);
|
|
2512
|
+
const remainder = sum % 11;
|
|
2513
|
+
const expected = remainder === 0 ? 0 : remainder === 1 ? 9 : 11 - remainder;
|
|
2514
|
+
const actual = Number(normalized[10]);
|
|
2515
|
+
if (actual !== expected) {
|
|
2516
|
+
return failure(
|
|
2517
|
+
normalized,
|
|
2518
|
+
type,
|
|
2519
|
+
"AR",
|
|
2520
|
+
`D\xEDgito verificador inv\xE1lido. Esperado: ${expected}, recibido: ${actual}.`
|
|
2521
|
+
);
|
|
2522
|
+
}
|
|
2523
|
+
return {
|
|
2524
|
+
valid: true,
|
|
2525
|
+
normalized,
|
|
2526
|
+
formatted: `${normalized.slice(0, 2)}-${normalized.slice(2, 10)}-${normalized.slice(10)}`,
|
|
2527
|
+
type,
|
|
2528
|
+
country: "AR",
|
|
2529
|
+
error: null
|
|
2530
|
+
};
|
|
2531
|
+
}
|
|
2532
|
+
function validateBR_CPF(input) {
|
|
2533
|
+
const normalized = (input ?? "").replace(/\D/g, "");
|
|
2534
|
+
if (normalized.length !== 11) {
|
|
2535
|
+
return failure(
|
|
2536
|
+
normalized,
|
|
2537
|
+
"CPF",
|
|
2538
|
+
"BR",
|
|
2539
|
+
`Debe tener 11 d\xEDgitos; recib\xED ${normalized.length}.`
|
|
2540
|
+
);
|
|
2541
|
+
}
|
|
2542
|
+
if (/^(\d)\1{10}$/.test(normalized)) {
|
|
2543
|
+
return failure(normalized, "CPF", "BR", "CPF inv\xE1lido (todos los d\xEDgitos iguales).");
|
|
2544
|
+
}
|
|
2545
|
+
const computeDigit = (slice, weights) => {
|
|
2546
|
+
const sum = weights.reduce((acc, w, i) => acc + w * Number(slice[i]), 0);
|
|
2547
|
+
const r = sum * 10 % 11;
|
|
2548
|
+
return r === 10 ? 0 : r;
|
|
2549
|
+
};
|
|
2550
|
+
const d1 = computeDigit(normalized.slice(0, 9), [10, 9, 8, 7, 6, 5, 4, 3, 2]);
|
|
2551
|
+
const d2 = computeDigit(
|
|
2552
|
+
normalized.slice(0, 10),
|
|
2553
|
+
[11, 10, 9, 8, 7, 6, 5, 4, 3, 2]
|
|
2554
|
+
);
|
|
2555
|
+
if (d1 !== Number(normalized[9]) || d2 !== Number(normalized[10])) {
|
|
2556
|
+
return failure(normalized, "CPF", "BR", "D\xEDgitos verificadores inv\xE1lidos.");
|
|
2557
|
+
}
|
|
2558
|
+
return {
|
|
2559
|
+
valid: true,
|
|
2560
|
+
normalized,
|
|
2561
|
+
formatted: normalized.replace(
|
|
2562
|
+
/^(\d{3})(\d{3})(\d{3})(\d{2})$/,
|
|
2563
|
+
"$1.$2.$3-$4"
|
|
2564
|
+
),
|
|
2565
|
+
type: "CPF",
|
|
2566
|
+
country: "BR",
|
|
2567
|
+
error: null
|
|
2568
|
+
};
|
|
2569
|
+
}
|
|
2570
|
+
function validateBR_CNPJ(input) {
|
|
2571
|
+
const normalized = (input ?? "").replace(/\D/g, "");
|
|
2572
|
+
if (normalized.length !== 14) {
|
|
2573
|
+
return failure(
|
|
2574
|
+
normalized,
|
|
2575
|
+
"CNPJ",
|
|
2576
|
+
"BR",
|
|
2577
|
+
`Debe tener 14 d\xEDgitos; recib\xED ${normalized.length}.`
|
|
2578
|
+
);
|
|
2579
|
+
}
|
|
2580
|
+
if (/^(\d)\1{13}$/.test(normalized)) {
|
|
2581
|
+
return failure(normalized, "CNPJ", "BR", "CNPJ inv\xE1lido (todos los d\xEDgitos iguales).");
|
|
2582
|
+
}
|
|
2583
|
+
const computeDigit = (slice, weights) => {
|
|
2584
|
+
const sum = weights.reduce((acc, w, i) => acc + w * Number(slice[i]), 0);
|
|
2585
|
+
const r = sum % 11;
|
|
2586
|
+
return r < 2 ? 0 : 11 - r;
|
|
2587
|
+
};
|
|
2588
|
+
const w1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
2589
|
+
const w2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
2590
|
+
const d1 = computeDigit(normalized.slice(0, 12), w1);
|
|
2591
|
+
const d2 = computeDigit(normalized.slice(0, 13), w2);
|
|
2592
|
+
if (d1 !== Number(normalized[12]) || d2 !== Number(normalized[13])) {
|
|
2593
|
+
return failure(normalized, "CNPJ", "BR", "D\xEDgitos verificadores inv\xE1lidos.");
|
|
2594
|
+
}
|
|
2595
|
+
return {
|
|
2596
|
+
valid: true,
|
|
2597
|
+
normalized,
|
|
2598
|
+
formatted: normalized.replace(
|
|
2599
|
+
/^(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})$/,
|
|
2600
|
+
"$1.$2.$3/$4-$5"
|
|
2601
|
+
),
|
|
2602
|
+
type: "CNPJ",
|
|
2603
|
+
country: "BR",
|
|
2604
|
+
error: null
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
function validateMX_RFC(input) {
|
|
2608
|
+
const normalized = (input ?? "").trim().toUpperCase().replace(/[\s-]/g, "");
|
|
2609
|
+
const pfPattern = /^[A-ZÑ&]{4}\d{6}[A-Z\d]{3}$/;
|
|
2610
|
+
const pmPattern = /^[A-ZÑ&]{3}\d{6}[A-Z\d]{3}$/;
|
|
2611
|
+
if (!pfPattern.test(normalized) && !pmPattern.test(normalized)) {
|
|
2612
|
+
return failure(
|
|
2613
|
+
normalized,
|
|
2614
|
+
"RFC",
|
|
2615
|
+
"MX",
|
|
2616
|
+
"RFC mal formado. Persona f\xEDsica: 4 letras + YYMMDD + 3 alfanum\xE9ricos. Persona moral: 3 letras + YYMMDD + 3 alfanum\xE9ricos."
|
|
2617
|
+
);
|
|
2618
|
+
}
|
|
2619
|
+
return {
|
|
2620
|
+
valid: true,
|
|
2621
|
+
normalized,
|
|
2622
|
+
formatted: normalized,
|
|
2623
|
+
type: "RFC",
|
|
2624
|
+
country: "MX",
|
|
2625
|
+
error: null
|
|
2626
|
+
};
|
|
2627
|
+
}
|
|
2628
|
+
function validateCL_RUT(input) {
|
|
2629
|
+
const cleaned = (input ?? "").replace(/[^0-9kK]/g, "").toUpperCase();
|
|
2630
|
+
if (cleaned.length < 2) {
|
|
2631
|
+
return failure(cleaned, "RUT_CL", "CL", "RUT vac\xEDo o muy corto.");
|
|
2632
|
+
}
|
|
2633
|
+
const body = cleaned.slice(0, -1);
|
|
2634
|
+
const dv = cleaned.slice(-1);
|
|
2635
|
+
if (!/^\d+$/.test(body)) {
|
|
2636
|
+
return failure(cleaned, "RUT_CL", "CL", "Cuerpo del RUT debe ser num\xE9rico.");
|
|
2637
|
+
}
|
|
2638
|
+
let sum = 0;
|
|
2639
|
+
let multiplier = 2;
|
|
2640
|
+
for (let i = body.length - 1; i >= 0; i--) {
|
|
2641
|
+
sum += Number(body[i]) * multiplier;
|
|
2642
|
+
multiplier = multiplier === 7 ? 2 : multiplier + 1;
|
|
2643
|
+
}
|
|
2644
|
+
const r = 11 - sum % 11;
|
|
2645
|
+
const expected = r === 11 ? "0" : r === 10 ? "K" : String(r);
|
|
2646
|
+
if (dv !== expected) {
|
|
2647
|
+
return failure(
|
|
2648
|
+
cleaned,
|
|
2649
|
+
"RUT_CL",
|
|
2650
|
+
"CL",
|
|
2651
|
+
`D\xEDgito verificador inv\xE1lido. Esperado: ${expected}, recibido: ${dv}.`
|
|
2652
|
+
);
|
|
2653
|
+
}
|
|
2654
|
+
return {
|
|
2655
|
+
valid: true,
|
|
2656
|
+
normalized: cleaned,
|
|
2657
|
+
formatted: `${formatThousands(body)}-${dv}`,
|
|
2658
|
+
type: "RUT_CL",
|
|
2659
|
+
country: "CL",
|
|
2660
|
+
error: null
|
|
2661
|
+
};
|
|
2662
|
+
}
|
|
2663
|
+
var CO_NIT_WEIGHTS = [3, 7, 13, 17, 19, 23, 29, 37, 41, 43, 47, 53, 59, 67, 71];
|
|
2664
|
+
function validateCO_NIT(input) {
|
|
2665
|
+
const cleaned = (input ?? "").replace(/[^0-9-]/g, "");
|
|
2666
|
+
const parts = cleaned.split("-");
|
|
2667
|
+
if (parts.length !== 2 || !/^\d+$/.test(parts[0]) || !/^\d$/.test(parts[1])) {
|
|
2668
|
+
return failure(
|
|
2669
|
+
cleaned,
|
|
2670
|
+
"NIT",
|
|
2671
|
+
"CO",
|
|
2672
|
+
"NIT debe tener formato: d\xEDgitos + '-' + d\xEDgito verificador."
|
|
2673
|
+
);
|
|
2674
|
+
}
|
|
2675
|
+
const body = parts[0];
|
|
2676
|
+
const dv = Number(parts[1]);
|
|
2677
|
+
if (body.length > CO_NIT_WEIGHTS.length) {
|
|
2678
|
+
return failure(cleaned, "NIT", "CO", "NIT excesivamente largo.");
|
|
2679
|
+
}
|
|
2680
|
+
let sum = 0;
|
|
2681
|
+
for (let i = 0; i < body.length; i++) {
|
|
2682
|
+
sum += Number(body[body.length - 1 - i]) * CO_NIT_WEIGHTS[i];
|
|
2683
|
+
}
|
|
2684
|
+
const r = sum % 11;
|
|
2685
|
+
const expected = r > 1 ? 11 - r : r;
|
|
2686
|
+
if (dv !== expected) {
|
|
2687
|
+
return failure(
|
|
2688
|
+
cleaned,
|
|
2689
|
+
"NIT",
|
|
2690
|
+
"CO",
|
|
2691
|
+
`D\xEDgito verificador inv\xE1lido. Esperado: ${expected}, recibido: ${dv}.`
|
|
2692
|
+
);
|
|
2693
|
+
}
|
|
2694
|
+
return {
|
|
2695
|
+
valid: true,
|
|
2696
|
+
normalized: body + parts[1],
|
|
2697
|
+
formatted: cleaned,
|
|
2698
|
+
type: "NIT",
|
|
2699
|
+
country: "CO",
|
|
2700
|
+
error: null
|
|
2701
|
+
};
|
|
2702
|
+
}
|
|
2703
|
+
var UY_RUT_WEIGHTS = [4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
2704
|
+
function validateUY_RUT(input) {
|
|
2705
|
+
const normalized = (input ?? "").replace(/\D/g, "");
|
|
2706
|
+
if (normalized.length !== 12) {
|
|
2707
|
+
return failure(
|
|
2708
|
+
normalized,
|
|
2709
|
+
"RUT_UY",
|
|
2710
|
+
"UY",
|
|
2711
|
+
`Debe tener 12 d\xEDgitos; recib\xED ${normalized.length}.`
|
|
2712
|
+
);
|
|
2713
|
+
}
|
|
2714
|
+
let sum = 0;
|
|
2715
|
+
for (let i = 0; i < 11; i++) {
|
|
2716
|
+
sum += Number(normalized[i]) * UY_RUT_WEIGHTS[i];
|
|
2717
|
+
}
|
|
2718
|
+
const r = sum % 11;
|
|
2719
|
+
const expected = r === 0 ? 0 : 11 - r;
|
|
2720
|
+
if (Number(normalized[11]) !== expected) {
|
|
2721
|
+
return failure(
|
|
2722
|
+
normalized,
|
|
2723
|
+
"RUT_UY",
|
|
2724
|
+
"UY",
|
|
2725
|
+
`D\xEDgito verificador inv\xE1lido. Esperado: ${expected}, recibido: ${normalized[11]}.`
|
|
2726
|
+
);
|
|
2727
|
+
}
|
|
2728
|
+
return {
|
|
2729
|
+
valid: true,
|
|
2730
|
+
normalized,
|
|
2731
|
+
formatted: normalized.replace(
|
|
2732
|
+
/^(\d{2})(\d{6})(\d{3})(\d{1})$/,
|
|
2733
|
+
"$1$2$3$4"
|
|
2734
|
+
),
|
|
2735
|
+
type: "RUT_UY",
|
|
2736
|
+
country: "UY",
|
|
2737
|
+
error: null
|
|
2738
|
+
};
|
|
2739
|
+
}
|
|
2740
|
+
var PE_RUC_WEIGHTS = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
|
|
2741
|
+
function validatePE_RUC(input) {
|
|
2742
|
+
const normalized = (input ?? "").replace(/\D/g, "");
|
|
2743
|
+
if (normalized.length !== 11) {
|
|
2744
|
+
return failure(
|
|
2745
|
+
normalized,
|
|
2746
|
+
"RUC",
|
|
2747
|
+
"PE",
|
|
2748
|
+
`Debe tener 11 d\xEDgitos; recib\xED ${normalized.length}.`
|
|
2749
|
+
);
|
|
2750
|
+
}
|
|
2751
|
+
const prefix = normalized.slice(0, 2);
|
|
2752
|
+
if (!["10", "15", "17", "20"].includes(prefix)) {
|
|
2753
|
+
return failure(
|
|
2754
|
+
normalized,
|
|
2755
|
+
"RUC",
|
|
2756
|
+
"PE",
|
|
2757
|
+
`Prefijo ${prefix} no v\xE1lido. Debe ser 10, 15, 17 o 20.`
|
|
2758
|
+
);
|
|
2759
|
+
}
|
|
2760
|
+
let sum = 0;
|
|
2761
|
+
for (let i = 0; i < 10; i++) {
|
|
2762
|
+
sum += Number(normalized[i]) * PE_RUC_WEIGHTS[i];
|
|
2763
|
+
}
|
|
2764
|
+
const r = 11 - sum % 11;
|
|
2765
|
+
const expected = r === 11 ? 0 : r === 10 ? 1 : r;
|
|
2766
|
+
if (Number(normalized[10]) !== expected) {
|
|
2767
|
+
return failure(
|
|
2768
|
+
normalized,
|
|
2769
|
+
"RUC",
|
|
2770
|
+
"PE",
|
|
2771
|
+
`D\xEDgito verificador inv\xE1lido. Esperado: ${expected}, recibido: ${normalized[10]}.`
|
|
2772
|
+
);
|
|
2773
|
+
}
|
|
2774
|
+
return {
|
|
2775
|
+
valid: true,
|
|
2776
|
+
normalized,
|
|
2777
|
+
formatted: normalized,
|
|
2778
|
+
type: "RUC",
|
|
2779
|
+
country: "PE",
|
|
2780
|
+
error: null
|
|
2781
|
+
};
|
|
2782
|
+
}
|
|
2783
|
+
function failure(normalized, type, country, error) {
|
|
2784
|
+
return {
|
|
2785
|
+
valid: false,
|
|
2786
|
+
normalized,
|
|
2787
|
+
formatted: null,
|
|
2788
|
+
type,
|
|
2789
|
+
country,
|
|
2790
|
+
error
|
|
2791
|
+
};
|
|
2792
|
+
}
|
|
2793
|
+
function formatThousands(s) {
|
|
2794
|
+
return s.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
|
|
2795
|
+
}
|
|
2796
|
+
function detectAndValidate(input, country) {
|
|
2797
|
+
const cleaned = input.replace(/\D/g, "");
|
|
2798
|
+
switch (country) {
|
|
2799
|
+
case "AR": {
|
|
2800
|
+
if (cleaned.length === 7 || cleaned.length === 8) return validateTaxId(input, "DNI");
|
|
2801
|
+
if (cleaned.length === 11) return validateTaxId(input, "CUIT");
|
|
2802
|
+
return null;
|
|
2803
|
+
}
|
|
2804
|
+
case "BR": {
|
|
2805
|
+
if (cleaned.length === 11) return validateTaxId(input, "CPF");
|
|
2806
|
+
if (cleaned.length === 14) return validateTaxId(input, "CNPJ");
|
|
2807
|
+
return null;
|
|
2808
|
+
}
|
|
2809
|
+
case "MX":
|
|
2810
|
+
return validateTaxId(input, "RFC");
|
|
2811
|
+
case "CL":
|
|
2812
|
+
return validateTaxId(input, "RUT_CL");
|
|
2813
|
+
case "CO":
|
|
2814
|
+
return validateTaxId(input, "NIT");
|
|
2815
|
+
case "UY":
|
|
2816
|
+
return validateTaxId(input, "RUT_UY");
|
|
2817
|
+
case "PE":
|
|
2818
|
+
return validateTaxId(input, "RUC");
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2432
2822
|
// src/test-cards.ts
|
|
2433
2823
|
var TEST_CARDS_AR = {
|
|
2434
2824
|
VISA_CREDIT: {
|
|
@@ -2748,7 +3138,9 @@ var DEFAULT_DESCRIPTIONS = {
|
|
|
2748
3138
|
confirm_3ds_challenge: "After the buyer completes a 3DS challenge (redirected back from challengeUrl), call this to poll MP and confirm whether the payment is now resolved. Polls get_payment up to N times with exponential backoff. Returns { payment, threeDs, resolved, attempts }. USE THIS as the FINAL step in the 3DS flow (after analyze_payment_3ds detected a challenge_required). Without confirming, the payment stays in 'pending' indefinitely from the buyer's perspective.",
|
|
2749
3139
|
// ── v0.10 — Auto-paginate variants ──────────────────────────────────────
|
|
2750
3140
|
search_payments_all: "Collect ALL payments matching a filter \u2014 auto-paginates under the hood. Returns an array (NOT paginated) so the agent doesn't have to manage offset/limit loops manually. SAFETY: pass `max_items` to cap; without it, MP traversal is bounded by the toolkit's internal max (10,000 items) to prevent runaway iterations. USE WHEN the agent needs to enumerate everything (e.g., monthly reconciliation 'all approved payments in March'). For agent flows that only need 'first N matches', pass `max_items` directly.",
|
|
2751
|
-
list_settlements_all: "Collect ALL settlements matching a filter \u2014 auto-paginates. Pass `max_items` to cap. Use for monthly bank-conciliation reports."
|
|
3141
|
+
list_settlements_all: "Collect ALL settlements matching a filter \u2014 auto-paginates. Pass `max_items` to cap. Use for monthly bank-conciliation reports.",
|
|
3142
|
+
// ── v0.11 — TaxID validation cross-LATAM (pure) ──────────────────────────
|
|
3143
|
+
validate_tax_id: "PURE HELPER (no network, sub-ms) \u2014 validates a tax ID against the appropriate country algorithm. Supports AR (DNI/CUIT/CUIL with modulo-11), BR (CPF/CNPJ with two-step weighted modulo), MX (RFC structure), CL (RUT with K digit), CO (NIT modulo-11), UY (RUT 12-digit checksum), PE (RUC 11-digit + prefix validation). Returns { valid, normalized, formatted, type, country, error }. USE THIS BEFORE submitting buyer identification to MP \u2014 invalid tax IDs cause 4xx rejections. Surface the Spanish error verbatim."
|
|
2752
3144
|
};
|
|
2753
3145
|
function mercadoPagoTools(client, options) {
|
|
2754
3146
|
const desc = (name) => options.descriptions?.[name] ?? DEFAULT_DESCRIPTIONS[name];
|
|
@@ -2876,7 +3268,45 @@ function mercadoPagoTools(client, options) {
|
|
|
2876
3268
|
type: zod.z.enum(["DNI", "CUIT", "CUIL"]),
|
|
2877
3269
|
number: zod.z.string()
|
|
2878
3270
|
}).optional().describe("Payer identification \u2014 required for some payment types in AR"),
|
|
2879
|
-
statement_descriptor: zod.z.string().max(13).optional().describe("Shows on buyer's card statement (max 13 chars)")
|
|
3271
|
+
statement_descriptor: zod.z.string().max(13).optional().describe("Shows on buyer's card statement (max 13 chars)"),
|
|
3272
|
+
// v0.11 — fraud scoring enrichment fields
|
|
3273
|
+
additional_info: zod.z.object({
|
|
3274
|
+
ip_address: zod.z.string().optional().describe(
|
|
3275
|
+
"Buyer's IP address (from req.headers X-Forwarded-For). STRONGLY RECOMMENDED for card payments \u2014 improves MP fraud scoring confidence and reduces false-positive rejections (3-5x lower per RG 5286/2023)."
|
|
3276
|
+
),
|
|
3277
|
+
referral_url: zod.z.string().url().optional().describe("Page the buyer came from"),
|
|
3278
|
+
payer: zod.z.object({
|
|
3279
|
+
first_name: zod.z.string().optional(),
|
|
3280
|
+
last_name: zod.z.string().optional(),
|
|
3281
|
+
phone: zod.z.object({ area_code: zod.z.string().optional(), number: zod.z.string().optional() }).optional(),
|
|
3282
|
+
address: zod.z.object({
|
|
3283
|
+
zip_code: zod.z.string().optional(),
|
|
3284
|
+
street_name: zod.z.string().optional(),
|
|
3285
|
+
street_number: zod.z.number().optional()
|
|
3286
|
+
}).optional(),
|
|
3287
|
+
registration_date: zod.z.string().optional().describe("ISO 8601 \u2014 when the buyer registered on YOUR platform"),
|
|
3288
|
+
authentication_type: zod.z.string().optional(),
|
|
3289
|
+
is_prime_user: zod.z.boolean().optional(),
|
|
3290
|
+
is_first_purchase_online: zod.z.boolean().optional(),
|
|
3291
|
+
last_purchase: zod.z.string().optional()
|
|
3292
|
+
}).optional(),
|
|
3293
|
+
shipments: zod.z.object({
|
|
3294
|
+
receiver_address: zod.z.object({
|
|
3295
|
+
zip_code: zod.z.string().optional(),
|
|
3296
|
+
street_name: zod.z.string().optional(),
|
|
3297
|
+
street_number: zod.z.number().optional(),
|
|
3298
|
+
floor: zod.z.string().optional(),
|
|
3299
|
+
apartment: zod.z.string().optional(),
|
|
3300
|
+
city_name: zod.z.string().optional(),
|
|
3301
|
+
state_name: zod.z.string().optional(),
|
|
3302
|
+
country_name: zod.z.string().optional()
|
|
3303
|
+
}).optional(),
|
|
3304
|
+
express_shipment: zod.z.boolean().optional(),
|
|
3305
|
+
local_pickup: zod.z.boolean().optional()
|
|
3306
|
+
}).optional()
|
|
3307
|
+
}).optional().describe(
|
|
3308
|
+
"Fraud scoring enrichment. Pass IP address + payer profile + shipping address for materially better approval rates on card payments."
|
|
3309
|
+
)
|
|
2880
3310
|
}),
|
|
2881
3311
|
execute: async (input) => {
|
|
2882
3312
|
const payment = await client.createPayment({
|
|
@@ -2889,6 +3319,7 @@ function mercadoPagoTools(client, options) {
|
|
|
2889
3319
|
...input.external_reference !== void 0 ? { externalReference: input.external_reference } : {},
|
|
2890
3320
|
...input.identification !== void 0 ? { identification: input.identification } : {},
|
|
2891
3321
|
...input.statement_descriptor !== void 0 ? { statementDescriptor: input.statement_descriptor } : {},
|
|
3322
|
+
...input.additional_info !== void 0 ? { additionalInfo: input.additional_info } : {},
|
|
2892
3323
|
...options.notificationUrl !== void 0 ? { notificationUrl: options.notificationUrl } : {},
|
|
2893
3324
|
// Deterministic idempotency key — safe to retry, same inputs always
|
|
2894
3325
|
// produce the same key (MP dedupes on its side).
|
|
@@ -4642,6 +5073,34 @@ function mercadoPagoTools(client, options) {
|
|
|
4642
5073
|
const all = await collect(paginateSettlements(client, filterClean, opts));
|
|
4643
5074
|
return { ok: true, count: all.length, settlements: all };
|
|
4644
5075
|
}
|
|
5076
|
+
}),
|
|
5077
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
5078
|
+
// v0.11 — TaxID validation cross-LATAM (pure)
|
|
5079
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
5080
|
+
validate_tax_id: ai.tool({
|
|
5081
|
+
description: desc("validate_tax_id"),
|
|
5082
|
+
inputSchema: zod.z.object({
|
|
5083
|
+
tax_id: zod.z.string().min(1).describe(
|
|
5084
|
+
"The tax ID to validate. Accepts any format with or without separators (20-41758101-5, 20.41758101.5, 20417581015 all work for AR CUIT)."
|
|
5085
|
+
),
|
|
5086
|
+
type: zod.z.enum([
|
|
5087
|
+
"DNI",
|
|
5088
|
+
"CUIT",
|
|
5089
|
+
"CUIL",
|
|
5090
|
+
"CPF",
|
|
5091
|
+
"CNPJ",
|
|
5092
|
+
"RFC",
|
|
5093
|
+
"RUT_CL",
|
|
5094
|
+
"NIT",
|
|
5095
|
+
"RUT_UY",
|
|
5096
|
+
"RUC"
|
|
5097
|
+
]).describe(
|
|
5098
|
+
"TaxID type. AR: DNI/CUIT/CUIL. BR: CPF (persona f\xEDsica) / CNPJ (persona jur\xEDdica). MX: RFC. CL: RUT_CL. CO: NIT. UY: RUT_UY. PE: RUC."
|
|
5099
|
+
)
|
|
5100
|
+
}),
|
|
5101
|
+
execute: async ({ tax_id, type }) => {
|
|
5102
|
+
return validateTaxId(tax_id, type);
|
|
5103
|
+
}
|
|
4645
5104
|
})
|
|
4646
5105
|
};
|
|
4647
5106
|
}
|
|
@@ -5152,6 +5611,123 @@ function sleep2(ms) {
|
|
|
5152
5611
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5153
5612
|
}
|
|
5154
5613
|
|
|
5614
|
+
// src/middleware.ts
|
|
5615
|
+
function compose(...middlewares) {
|
|
5616
|
+
return (tool2) => {
|
|
5617
|
+
return middlewares.reduceRight((wrapped, mw) => mw(wrapped), tool2);
|
|
5618
|
+
};
|
|
5619
|
+
}
|
|
5620
|
+
function withAuditLog(logger, operation, actor) {
|
|
5621
|
+
return (tool2) => {
|
|
5622
|
+
const original = tool2.execute;
|
|
5623
|
+
if (!original) return tool2;
|
|
5624
|
+
return {
|
|
5625
|
+
...tool2,
|
|
5626
|
+
execute: (async (input, opts) => {
|
|
5627
|
+
return logger.record({
|
|
5628
|
+
operation,
|
|
5629
|
+
input,
|
|
5630
|
+
...actor !== void 0 ? { actor } : {},
|
|
5631
|
+
fn: () => original(input, opts)
|
|
5632
|
+
});
|
|
5633
|
+
})
|
|
5634
|
+
};
|
|
5635
|
+
};
|
|
5636
|
+
}
|
|
5637
|
+
function withRateLimit(limiter) {
|
|
5638
|
+
return (tool2) => {
|
|
5639
|
+
const original = tool2.execute;
|
|
5640
|
+
if (!original) return tool2;
|
|
5641
|
+
return {
|
|
5642
|
+
...tool2,
|
|
5643
|
+
execute: (async (input, opts) => {
|
|
5644
|
+
await limiter.acquire();
|
|
5645
|
+
return original(input, opts);
|
|
5646
|
+
})
|
|
5647
|
+
};
|
|
5648
|
+
};
|
|
5649
|
+
}
|
|
5650
|
+
function withMetrics(toolName, hook) {
|
|
5651
|
+
return (tool2) => {
|
|
5652
|
+
const original = tool2.execute;
|
|
5653
|
+
if (!original) return tool2;
|
|
5654
|
+
return {
|
|
5655
|
+
...tool2,
|
|
5656
|
+
execute: (async (input, opts) => {
|
|
5657
|
+
const t0 = Date.now();
|
|
5658
|
+
try {
|
|
5659
|
+
const result = await original(input, opts);
|
|
5660
|
+
hook.onMetric({
|
|
5661
|
+
toolName,
|
|
5662
|
+
durationMs: Date.now() - t0,
|
|
5663
|
+
success: true
|
|
5664
|
+
});
|
|
5665
|
+
return result;
|
|
5666
|
+
} catch (err) {
|
|
5667
|
+
hook.onMetric({
|
|
5668
|
+
toolName,
|
|
5669
|
+
durationMs: Date.now() - t0,
|
|
5670
|
+
success: false,
|
|
5671
|
+
errorCode: extractErrorCode2(err)
|
|
5672
|
+
});
|
|
5673
|
+
throw err;
|
|
5674
|
+
}
|
|
5675
|
+
})
|
|
5676
|
+
};
|
|
5677
|
+
};
|
|
5678
|
+
}
|
|
5679
|
+
var defaultShouldRetry = (err) => {
|
|
5680
|
+
if (err && typeof err === "object" && "status" in err) {
|
|
5681
|
+
const status = err.status;
|
|
5682
|
+
if (typeof status === "number" && status >= 400 && status < 500) {
|
|
5683
|
+
return false;
|
|
5684
|
+
}
|
|
5685
|
+
}
|
|
5686
|
+
return true;
|
|
5687
|
+
};
|
|
5688
|
+
function withRetry(opts = {}) {
|
|
5689
|
+
const maxAttempts = opts.maxAttempts ?? 3;
|
|
5690
|
+
const baseBackoff = opts.baseBackoffMs ?? 250;
|
|
5691
|
+
const shouldRetry = opts.shouldRetry ?? defaultShouldRetry;
|
|
5692
|
+
return (tool2) => {
|
|
5693
|
+
const original = tool2.execute;
|
|
5694
|
+
if (!original) return tool2;
|
|
5695
|
+
return {
|
|
5696
|
+
...tool2,
|
|
5697
|
+
execute: (async (input, opts2) => {
|
|
5698
|
+
let attempt = 0;
|
|
5699
|
+
while (true) {
|
|
5700
|
+
try {
|
|
5701
|
+
return await original(input, opts2);
|
|
5702
|
+
} catch (err) {
|
|
5703
|
+
attempt++;
|
|
5704
|
+
if (attempt >= maxAttempts || !shouldRetry(err, attempt)) {
|
|
5705
|
+
throw err;
|
|
5706
|
+
}
|
|
5707
|
+
const delayMs = baseBackoff * Math.pow(2, attempt - 1);
|
|
5708
|
+
opts.onRetry?.({ attempt, error: err, delayMs });
|
|
5709
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
5710
|
+
}
|
|
5711
|
+
}
|
|
5712
|
+
})
|
|
5713
|
+
};
|
|
5714
|
+
};
|
|
5715
|
+
}
|
|
5716
|
+
function applyToAllTools(tools, middleware) {
|
|
5717
|
+
const out = {};
|
|
5718
|
+
for (const [name, tool2] of Object.entries(tools)) {
|
|
5719
|
+
out[name] = middleware(tool2);
|
|
5720
|
+
}
|
|
5721
|
+
return out;
|
|
5722
|
+
}
|
|
5723
|
+
function extractErrorCode2(err) {
|
|
5724
|
+
if (err && typeof err === "object") {
|
|
5725
|
+
const e = err;
|
|
5726
|
+
return e.code ?? e.name ?? "unknown_error";
|
|
5727
|
+
}
|
|
5728
|
+
return "unknown_error";
|
|
5729
|
+
}
|
|
5730
|
+
|
|
5155
5731
|
exports.AHORA_PROGRAM_PROMOS = AHORA_PROGRAM_PROMOS;
|
|
5156
5732
|
exports.AR_ISSUER_PROMOS = AR_ISSUER_PROMOS;
|
|
5157
5733
|
exports.AuditLogger = AuditLogger;
|
|
@@ -5178,12 +5754,15 @@ exports.TEST_PAYERS_AR = TEST_PAYERS_AR;
|
|
|
5178
5754
|
exports.TokenBucketRateLimiter = TokenBucketRateLimiter;
|
|
5179
5755
|
exports.WebhookDedup = WebhookDedup;
|
|
5180
5756
|
exports.analyze3DS = analyze3DS;
|
|
5757
|
+
exports.applyToAllTools = applyToAllTools;
|
|
5181
5758
|
exports.buildAuthorizeUrl = buildAuthorizeUrl;
|
|
5182
5759
|
exports.buildTestCardScenario = buildTestCardScenario;
|
|
5183
5760
|
exports.classifyError = classifyError;
|
|
5184
5761
|
exports.collect = collect;
|
|
5762
|
+
exports.compose = compose;
|
|
5185
5763
|
exports.computeMarketplaceFee = computeMarketplaceFee;
|
|
5186
5764
|
exports.confirmChallengeAndPoll = confirmChallengeAndPoll;
|
|
5765
|
+
exports.detectAndValidate = detectAndValidate;
|
|
5187
5766
|
exports.exchangeCodeForToken = exchangeCodeForToken;
|
|
5188
5767
|
exports.expirationTimeMs = expirationTimeMs;
|
|
5189
5768
|
exports.explainPaymentStatus = explainPaymentStatus;
|
|
@@ -5200,6 +5779,11 @@ exports.paginateSubscriptionPlans = paginateSubscriptionPlans;
|
|
|
5200
5779
|
exports.paginateSubscriptions = paginateSubscriptions;
|
|
5201
5780
|
exports.parseWebhookEvent = parseWebhookEvent;
|
|
5202
5781
|
exports.refreshAccessToken = refreshAccessToken;
|
|
5782
|
+
exports.validateTaxId = validateTaxId;
|
|
5203
5783
|
exports.verifyWebhookSignature = verifyWebhookSignature;
|
|
5784
|
+
exports.withAuditLog = withAuditLog;
|
|
5785
|
+
exports.withMetrics = withMetrics;
|
|
5786
|
+
exports.withRateLimit = withRateLimit;
|
|
5787
|
+
exports.withRetry = withRetry;
|
|
5204
5788
|
//# sourceMappingURL=index.cjs.map
|
|
5205
5789
|
//# sourceMappingURL=index.cjs.map
|