@ar-agents/mercadopago 0.7.0 → 0.8.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/dist/index.d.cts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { ToolSet } from 'ai';
3
+ import { S as SubscriptionStateAdapter } from './state-C6Wzb_XX.cjs';
4
+ export { I as IdempotencyCache, a as InMemoryIdempotencyCache, b as InMemoryOAuthTokenStore, c as InMemoryStateAdapter, O as OAuthTokenRecord, d as OAuthTokenStore, e as SubscriptionStateRecord } from './state-C6Wzb_XX.cjs';
3
5
 
4
6
  /**
5
7
  * Base class for any error originating from the Mercado Pago integration. All
@@ -1625,52 +1627,6 @@ declare class MercadoPagoClient {
1625
1627
  }>;
1626
1628
  }
1627
1629
 
1628
- /**
1629
- * In-memory record of a subscription. The lib persists the MP-side fields
1630
- * needed to reason about a subscription without hitting the API every time
1631
- * (status, last webhook info, customer email, etc.) plus a free-form metadata
1632
- * bag for callers to attach business context (tenant id, plan name, etc.).
1633
- */
1634
- interface SubscriptionStateRecord {
1635
- status?: string;
1636
- payerEmail?: string;
1637
- amount?: number;
1638
- currency?: string;
1639
- frequency?: number;
1640
- frequencyType?: string;
1641
- initPoint?: string;
1642
- externalReference?: string;
1643
- createdAt?: string;
1644
- cancelledAt?: string;
1645
- lastWebhookStatus?: string;
1646
- lastWebhookAt?: string;
1647
- metadata?: Record<string, unknown>;
1648
- }
1649
- /**
1650
- * Persistence surface for subscription state. Implementations may back this
1651
- * with Upstash Redis, Vercel KV, Postgres, in-memory, or anything that
1652
- * supports the three operations. The default `InMemoryStateAdapter` is
1653
- * provided for tests and trivial single-process deployments; production
1654
- * setups should plug in a durable store.
1655
- */
1656
- interface SubscriptionStateAdapter {
1657
- set(id: string, state: Partial<SubscriptionStateRecord>): Promise<void>;
1658
- get(id: string): Promise<SubscriptionStateRecord | null>;
1659
- list?(): Promise<string[]>;
1660
- }
1661
- /**
1662
- * Volatile, single-process state adapter. Useful for tests and demos. Do not
1663
- * use in production: state is lost on restart and is not safe across tenants.
1664
- */
1665
- declare class InMemoryStateAdapter implements SubscriptionStateAdapter {
1666
- private readonly store;
1667
- set(id: string, state: Partial<SubscriptionStateRecord>): Promise<void>;
1668
- get(id: string): Promise<SubscriptionStateRecord | null>;
1669
- list(): Promise<string[]>;
1670
- /** Test helper: drop everything. Not part of the adapter interface. */
1671
- reset(): void;
1672
- }
1673
-
1674
1630
  interface MercadoPagoToolsOptions {
1675
1631
  /** State adapter for persisting subscription records. */
1676
1632
  state: SubscriptionStateAdapter;
@@ -1733,12 +1689,26 @@ type ToolName = "create_subscription" | "get_subscription_status" | "cancel_subs
1733
1689
  */
1734
1690
  declare function mercadoPagoTools(client: MercadoPagoClient, options: MercadoPagoToolsOptions): ToolSet;
1735
1691
 
1692
+ /**
1693
+ * Webhook helpers — parse incoming MP notifications and verify the
1694
+ * HMAC-SHA256 signature MP sends in the `x-signature` header.
1695
+ *
1696
+ * # Edge Runtime
1697
+ *
1698
+ * Both `verifyWebhookSignature` and `parseWebhookEvent` work in Vercel
1699
+ * Edge Runtime, Cloudflare Workers, Deno, browsers, and Node 18+. The
1700
+ * HMAC verification uses Web Crypto under the hood (see `./crypto.ts`)
1701
+ * and is **async** — make sure to `await` the call.
1702
+ */
1703
+
1736
1704
  /**
1737
1705
  * Parse a Mercado Pago webhook from the raw request body and URL search params.
1738
1706
  * MP sends the topic and resource id in EITHER the URL query string OR the
1739
1707
  * body, depending on integration version — this normalizes both shapes into a
1740
1708
  * single structure.
1741
1709
  *
1710
+ * **Pure function — synchronous, no I/O.**
1711
+ *
1742
1712
  * @example
1743
1713
  * ```ts
1744
1714
  * export async function POST(req: Request) {
@@ -1755,25 +1725,34 @@ declare function parseWebhookEvent(body: unknown, searchParams?: URLSearchParams
1755
1725
  /**
1756
1726
  * Verify the HMAC-SHA256 signature MP sends in the `x-signature` header for
1757
1727
  * webhook authenticity. Returns true if the signature matches the expected
1758
- * value derived from the integration's secret key.
1728
+ * value derived from the integration's secret key AND the timestamp is
1729
+ * within the replay-tolerance window.
1730
+ *
1731
+ * **Async** — runs on Web Crypto under the hood, works in Edge Runtime.
1759
1732
  *
1760
1733
  * @param requestId The value of the `x-request-id` request header.
1761
1734
  * @param dataId The id of the resource the webhook is about (from query or body).
1762
1735
  * @param signatureHeader The full `x-signature` header value MP sent.
1763
1736
  * @param secret Your integration's webhook secret (configured in MP dev panel).
1737
+ * @param replayToleranceSeconds Optional override. Default 300s (5 min).
1764
1738
  *
1765
1739
  * @remarks
1766
1740
  * MP's `x-signature` header has the form: `ts=NNNNNNNN,v1=HEXSIGNATURE`. We
1767
1741
  * extract the timestamp and the v1 signature, then compute
1768
1742
  * `HMAC-SHA256(secret, "id:${dataId};request-id:${requestId};ts:${ts};")`
1769
1743
  * and compare with constant-time equality.
1744
+ *
1745
+ * **Replay protection**: rejects signatures whose `ts` is older than
1746
+ * `replayToleranceSeconds` (default 5min) — prevents an attacker who
1747
+ * captured a valid webhook from replaying it later.
1770
1748
  */
1771
1749
  declare function verifyWebhookSignature(params: {
1772
1750
  requestId: string | null;
1773
1751
  dataId: string;
1774
1752
  signatureHeader: string | null;
1775
1753
  secret: string;
1776
- }): boolean;
1754
+ replayToleranceSeconds?: number;
1755
+ }): Promise<boolean>;
1777
1756
 
1778
1757
  /**
1779
1758
  * Mercado Pago OAuth flow — for marketplace integrations where YOUR app
@@ -2079,4 +2058,4 @@ interface PaymentStatusExplanation {
2079
2058
  */
2080
2059
  declare function explainPaymentStatus(payment: Payment): PaymentStatusExplanation;
2081
2060
 
2082
- export { type AccountBalance, type AccountInfo, type AccountMovement, type AutoRecurring, type BankAccount, type CardToken, type CreateCardTokenParams, type CreateCustomerParams, type CreateOrderParams, type CreatePaymentParams, type CreatePointPaymentIntentParams, type CreatePosParams, type CreatePreapprovalParams, type CreatePreferenceParams, type CreateQrPaymentParams, type CreateRefundParams, type CreateStoreParams, type CreateSubscriptionPlanParams, type CreateWebhookParams, type CurrencyId, type Customer, type CustomerCard, type Dispute, type FrequencyType, type IdentificationType, InMemoryStateAdapter, type InstallmentOffer, type Issuer, type MarketplaceFeeRule, type MarketplaceParams, MercadoPagoAccountTypeMismatchError, MercadoPagoAuthError, MercadoPagoAuthorizeForbiddenError, MercadoPagoBackUrlInvalidError, MercadoPagoClient, type MercadoPagoClientOptions, MercadoPagoError, MercadoPagoOverloadedError, MercadoPagoPaymentRejectedError, MercadoPagoRateLimitError, MercadoPagoSelfPaymentError, MercadoPagoTimeoutError, type MercadoPagoToolsOptions, type MerchantOrder, type OAuthToken, type Order, type OrderItem, type OrderStatus, type ParsedWebhookEvent, type Payment, type PaymentMethod, type PaymentStatus, type PaymentStatusExplanation, type PaymentsSearchResult, type PointDevice, type PointPaymentIntent, type PointPaymentIntentState, type Pos, type Preapproval, type PreapprovalStatus, type Preference, type PreferenceItem, type QrOrder, type Refund, type SearchPaymentsParams, type Settlement, type SiteId, type Store, type SubscriptionPayment, type SubscriptionPlan, type SubscriptionStateAdapter, type SubscriptionStateRecord, TEST_CARDS_AR, TEST_PAYERS_AR, type TestCard, type ThreeDSInfo, type ThreeDSStatus, type WebhookBody, type WebhookConfig, type WebhookTopic, analyze3DS, buildAuthorizeUrl, buildTestCardScenario, classifyError, computeMarketplaceFee, exchangeCodeForToken, expirationTimeMs, explainPaymentStatus, isExpiringSoon, mercadoPagoTools, parseWebhookEvent, refreshAccessToken, verifyWebhookSignature };
2061
+ export { type AccountBalance, type AccountInfo, type AccountMovement, type AutoRecurring, type BankAccount, type CardToken, type CreateCardTokenParams, type CreateCustomerParams, type CreateOrderParams, type CreatePaymentParams, type CreatePointPaymentIntentParams, type CreatePosParams, type CreatePreapprovalParams, type CreatePreferenceParams, type CreateQrPaymentParams, type CreateRefundParams, type CreateStoreParams, type CreateSubscriptionPlanParams, type CreateWebhookParams, type CurrencyId, type Customer, type CustomerCard, type Dispute, type FrequencyType, type IdentificationType, type InstallmentOffer, type Issuer, type MarketplaceFeeRule, type MarketplaceParams, MercadoPagoAccountTypeMismatchError, MercadoPagoAuthError, MercadoPagoAuthorizeForbiddenError, MercadoPagoBackUrlInvalidError, MercadoPagoClient, type MercadoPagoClientOptions, MercadoPagoError, MercadoPagoOverloadedError, MercadoPagoPaymentRejectedError, MercadoPagoRateLimitError, MercadoPagoSelfPaymentError, MercadoPagoTimeoutError, type MercadoPagoToolsOptions, type MerchantOrder, type OAuthToken, type Order, type OrderItem, type OrderStatus, type ParsedWebhookEvent, type Payment, type PaymentMethod, type PaymentStatus, type PaymentStatusExplanation, type PaymentsSearchResult, type PointDevice, type PointPaymentIntent, type PointPaymentIntentState, type Pos, type Preapproval, type PreapprovalStatus, type Preference, type PreferenceItem, type QrOrder, type Refund, type SearchPaymentsParams, type Settlement, type SiteId, type Store, type SubscriptionPayment, type SubscriptionPlan, SubscriptionStateAdapter, TEST_CARDS_AR, TEST_PAYERS_AR, type TestCard, type ThreeDSInfo, type ThreeDSStatus, type WebhookBody, type WebhookConfig, type WebhookTopic, analyze3DS, buildAuthorizeUrl, buildTestCardScenario, classifyError, computeMarketplaceFee, exchangeCodeForToken, expirationTimeMs, explainPaymentStatus, isExpiringSoon, mercadoPagoTools, parseWebhookEvent, refreshAccessToken, verifyWebhookSignature };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { ToolSet } from 'ai';
3
+ import { S as SubscriptionStateAdapter } from './state-C6Wzb_XX.js';
4
+ export { I as IdempotencyCache, a as InMemoryIdempotencyCache, b as InMemoryOAuthTokenStore, c as InMemoryStateAdapter, O as OAuthTokenRecord, d as OAuthTokenStore, e as SubscriptionStateRecord } from './state-C6Wzb_XX.js';
3
5
 
4
6
  /**
5
7
  * Base class for any error originating from the Mercado Pago integration. All
@@ -1625,52 +1627,6 @@ declare class MercadoPagoClient {
1625
1627
  }>;
1626
1628
  }
1627
1629
 
1628
- /**
1629
- * In-memory record of a subscription. The lib persists the MP-side fields
1630
- * needed to reason about a subscription without hitting the API every time
1631
- * (status, last webhook info, customer email, etc.) plus a free-form metadata
1632
- * bag for callers to attach business context (tenant id, plan name, etc.).
1633
- */
1634
- interface SubscriptionStateRecord {
1635
- status?: string;
1636
- payerEmail?: string;
1637
- amount?: number;
1638
- currency?: string;
1639
- frequency?: number;
1640
- frequencyType?: string;
1641
- initPoint?: string;
1642
- externalReference?: string;
1643
- createdAt?: string;
1644
- cancelledAt?: string;
1645
- lastWebhookStatus?: string;
1646
- lastWebhookAt?: string;
1647
- metadata?: Record<string, unknown>;
1648
- }
1649
- /**
1650
- * Persistence surface for subscription state. Implementations may back this
1651
- * with Upstash Redis, Vercel KV, Postgres, in-memory, or anything that
1652
- * supports the three operations. The default `InMemoryStateAdapter` is
1653
- * provided for tests and trivial single-process deployments; production
1654
- * setups should plug in a durable store.
1655
- */
1656
- interface SubscriptionStateAdapter {
1657
- set(id: string, state: Partial<SubscriptionStateRecord>): Promise<void>;
1658
- get(id: string): Promise<SubscriptionStateRecord | null>;
1659
- list?(): Promise<string[]>;
1660
- }
1661
- /**
1662
- * Volatile, single-process state adapter. Useful for tests and demos. Do not
1663
- * use in production: state is lost on restart and is not safe across tenants.
1664
- */
1665
- declare class InMemoryStateAdapter implements SubscriptionStateAdapter {
1666
- private readonly store;
1667
- set(id: string, state: Partial<SubscriptionStateRecord>): Promise<void>;
1668
- get(id: string): Promise<SubscriptionStateRecord | null>;
1669
- list(): Promise<string[]>;
1670
- /** Test helper: drop everything. Not part of the adapter interface. */
1671
- reset(): void;
1672
- }
1673
-
1674
1630
  interface MercadoPagoToolsOptions {
1675
1631
  /** State adapter for persisting subscription records. */
1676
1632
  state: SubscriptionStateAdapter;
@@ -1733,12 +1689,26 @@ type ToolName = "create_subscription" | "get_subscription_status" | "cancel_subs
1733
1689
  */
1734
1690
  declare function mercadoPagoTools(client: MercadoPagoClient, options: MercadoPagoToolsOptions): ToolSet;
1735
1691
 
1692
+ /**
1693
+ * Webhook helpers — parse incoming MP notifications and verify the
1694
+ * HMAC-SHA256 signature MP sends in the `x-signature` header.
1695
+ *
1696
+ * # Edge Runtime
1697
+ *
1698
+ * Both `verifyWebhookSignature` and `parseWebhookEvent` work in Vercel
1699
+ * Edge Runtime, Cloudflare Workers, Deno, browsers, and Node 18+. The
1700
+ * HMAC verification uses Web Crypto under the hood (see `./crypto.ts`)
1701
+ * and is **async** — make sure to `await` the call.
1702
+ */
1703
+
1736
1704
  /**
1737
1705
  * Parse a Mercado Pago webhook from the raw request body and URL search params.
1738
1706
  * MP sends the topic and resource id in EITHER the URL query string OR the
1739
1707
  * body, depending on integration version — this normalizes both shapes into a
1740
1708
  * single structure.
1741
1709
  *
1710
+ * **Pure function — synchronous, no I/O.**
1711
+ *
1742
1712
  * @example
1743
1713
  * ```ts
1744
1714
  * export async function POST(req: Request) {
@@ -1755,25 +1725,34 @@ declare function parseWebhookEvent(body: unknown, searchParams?: URLSearchParams
1755
1725
  /**
1756
1726
  * Verify the HMAC-SHA256 signature MP sends in the `x-signature` header for
1757
1727
  * webhook authenticity. Returns true if the signature matches the expected
1758
- * value derived from the integration's secret key.
1728
+ * value derived from the integration's secret key AND the timestamp is
1729
+ * within the replay-tolerance window.
1730
+ *
1731
+ * **Async** — runs on Web Crypto under the hood, works in Edge Runtime.
1759
1732
  *
1760
1733
  * @param requestId The value of the `x-request-id` request header.
1761
1734
  * @param dataId The id of the resource the webhook is about (from query or body).
1762
1735
  * @param signatureHeader The full `x-signature` header value MP sent.
1763
1736
  * @param secret Your integration's webhook secret (configured in MP dev panel).
1737
+ * @param replayToleranceSeconds Optional override. Default 300s (5 min).
1764
1738
  *
1765
1739
  * @remarks
1766
1740
  * MP's `x-signature` header has the form: `ts=NNNNNNNN,v1=HEXSIGNATURE`. We
1767
1741
  * extract the timestamp and the v1 signature, then compute
1768
1742
  * `HMAC-SHA256(secret, "id:${dataId};request-id:${requestId};ts:${ts};")`
1769
1743
  * and compare with constant-time equality.
1744
+ *
1745
+ * **Replay protection**: rejects signatures whose `ts` is older than
1746
+ * `replayToleranceSeconds` (default 5min) — prevents an attacker who
1747
+ * captured a valid webhook from replaying it later.
1770
1748
  */
1771
1749
  declare function verifyWebhookSignature(params: {
1772
1750
  requestId: string | null;
1773
1751
  dataId: string;
1774
1752
  signatureHeader: string | null;
1775
1753
  secret: string;
1776
- }): boolean;
1754
+ replayToleranceSeconds?: number;
1755
+ }): Promise<boolean>;
1777
1756
 
1778
1757
  /**
1779
1758
  * Mercado Pago OAuth flow — for marketplace integrations where YOUR app
@@ -2079,4 +2058,4 @@ interface PaymentStatusExplanation {
2079
2058
  */
2080
2059
  declare function explainPaymentStatus(payment: Payment): PaymentStatusExplanation;
2081
2060
 
2082
- export { type AccountBalance, type AccountInfo, type AccountMovement, type AutoRecurring, type BankAccount, type CardToken, type CreateCardTokenParams, type CreateCustomerParams, type CreateOrderParams, type CreatePaymentParams, type CreatePointPaymentIntentParams, type CreatePosParams, type CreatePreapprovalParams, type CreatePreferenceParams, type CreateQrPaymentParams, type CreateRefundParams, type CreateStoreParams, type CreateSubscriptionPlanParams, type CreateWebhookParams, type CurrencyId, type Customer, type CustomerCard, type Dispute, type FrequencyType, type IdentificationType, InMemoryStateAdapter, type InstallmentOffer, type Issuer, type MarketplaceFeeRule, type MarketplaceParams, MercadoPagoAccountTypeMismatchError, MercadoPagoAuthError, MercadoPagoAuthorizeForbiddenError, MercadoPagoBackUrlInvalidError, MercadoPagoClient, type MercadoPagoClientOptions, MercadoPagoError, MercadoPagoOverloadedError, MercadoPagoPaymentRejectedError, MercadoPagoRateLimitError, MercadoPagoSelfPaymentError, MercadoPagoTimeoutError, type MercadoPagoToolsOptions, type MerchantOrder, type OAuthToken, type Order, type OrderItem, type OrderStatus, type ParsedWebhookEvent, type Payment, type PaymentMethod, type PaymentStatus, type PaymentStatusExplanation, type PaymentsSearchResult, type PointDevice, type PointPaymentIntent, type PointPaymentIntentState, type Pos, type Preapproval, type PreapprovalStatus, type Preference, type PreferenceItem, type QrOrder, type Refund, type SearchPaymentsParams, type Settlement, type SiteId, type Store, type SubscriptionPayment, type SubscriptionPlan, type SubscriptionStateAdapter, type SubscriptionStateRecord, TEST_CARDS_AR, TEST_PAYERS_AR, type TestCard, type ThreeDSInfo, type ThreeDSStatus, type WebhookBody, type WebhookConfig, type WebhookTopic, analyze3DS, buildAuthorizeUrl, buildTestCardScenario, classifyError, computeMarketplaceFee, exchangeCodeForToken, expirationTimeMs, explainPaymentStatus, isExpiringSoon, mercadoPagoTools, parseWebhookEvent, refreshAccessToken, verifyWebhookSignature };
2061
+ export { type AccountBalance, type AccountInfo, type AccountMovement, type AutoRecurring, type BankAccount, type CardToken, type CreateCardTokenParams, type CreateCustomerParams, type CreateOrderParams, type CreatePaymentParams, type CreatePointPaymentIntentParams, type CreatePosParams, type CreatePreapprovalParams, type CreatePreferenceParams, type CreateQrPaymentParams, type CreateRefundParams, type CreateStoreParams, type CreateSubscriptionPlanParams, type CreateWebhookParams, type CurrencyId, type Customer, type CustomerCard, type Dispute, type FrequencyType, type IdentificationType, type InstallmentOffer, type Issuer, type MarketplaceFeeRule, type MarketplaceParams, MercadoPagoAccountTypeMismatchError, MercadoPagoAuthError, MercadoPagoAuthorizeForbiddenError, MercadoPagoBackUrlInvalidError, MercadoPagoClient, type MercadoPagoClientOptions, MercadoPagoError, MercadoPagoOverloadedError, MercadoPagoPaymentRejectedError, MercadoPagoRateLimitError, MercadoPagoSelfPaymentError, MercadoPagoTimeoutError, type MercadoPagoToolsOptions, type MerchantOrder, type OAuthToken, type Order, type OrderItem, type OrderStatus, type ParsedWebhookEvent, type Payment, type PaymentMethod, type PaymentStatus, type PaymentStatusExplanation, type PaymentsSearchResult, type PointDevice, type PointPaymentIntent, type PointPaymentIntentState, type Pos, type Preapproval, type PreapprovalStatus, type Preference, type PreferenceItem, type QrOrder, type Refund, type SearchPaymentsParams, type Settlement, type SiteId, type Store, type SubscriptionPayment, type SubscriptionPlan, SubscriptionStateAdapter, TEST_CARDS_AR, TEST_PAYERS_AR, type TestCard, type ThreeDSInfo, type ThreeDSStatus, type WebhookBody, type WebhookConfig, type WebhookTopic, analyze3DS, buildAuthorizeUrl, buildTestCardScenario, classifyError, computeMarketplaceFee, exchangeCodeForToken, expirationTimeMs, explainPaymentStatus, isExpiringSoon, mercadoPagoTools, parseWebhookEvent, refreshAccessToken, verifyWebhookSignature };
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import { createHmac, timingSafeEqual, createHash } from 'crypto';
2
1
  import { tool } from 'ai';
3
2
  import { z } from 'zod';
4
3
 
@@ -1233,6 +1232,54 @@ var MercadoPagoClient = class {
1233
1232
  return { id: intentId, canceled: true };
1234
1233
  }
1235
1234
  };
1235
+
1236
+ // src/crypto.ts
1237
+ var subtle = (() => {
1238
+ const c = globalThis.crypto;
1239
+ if (!c?.subtle) {
1240
+ throw new Error(
1241
+ "@ar-agents/mercadopago: Web Crypto API is not available in this runtime. Use Node 18+, Vercel Edge Runtime, Cloudflare Workers, or any modern browser."
1242
+ );
1243
+ }
1244
+ return c.subtle;
1245
+ })();
1246
+ var encoder = new TextEncoder();
1247
+ async function hmacSha256Hex(secret, message) {
1248
+ const keyMaterial = await subtle.importKey(
1249
+ "raw",
1250
+ encoder.encode(secret),
1251
+ { name: "HMAC", hash: "SHA-256" },
1252
+ false,
1253
+ ["sign"]
1254
+ );
1255
+ const sigBuf = await subtle.sign(
1256
+ "HMAC",
1257
+ keyMaterial,
1258
+ encoder.encode(message)
1259
+ );
1260
+ return bufferToHex(sigBuf);
1261
+ }
1262
+ async function sha256Hex(input) {
1263
+ const digest = await subtle.digest("SHA-256", encoder.encode(input));
1264
+ return bufferToHex(digest);
1265
+ }
1266
+ function timingSafeEqualHex(a, b) {
1267
+ if (a.length !== b.length) return false;
1268
+ let diff = 0;
1269
+ for (let i = 0; i < a.length; i++) {
1270
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
1271
+ }
1272
+ return diff === 0;
1273
+ }
1274
+ function bufferToHex(buf) {
1275
+ const bytes = new Uint8Array(buf);
1276
+ let hex = "";
1277
+ for (let i = 0; i < bytes.length; i++) {
1278
+ const b = bytes[i];
1279
+ hex += (b < 16 ? "0" : "") + b.toString(16);
1280
+ }
1281
+ return hex;
1282
+ }
1236
1283
  z.enum(["MLA", "MLB", "MLM", "MCO", "MLC", "MLU"]);
1237
1284
  var CurrencyIdSchema = z.enum(["ARS", "USD", "BRL", "MXN"]);
1238
1285
  var FrequencyTypeSchema = z.enum(["months", "days"]);
@@ -2100,6 +2147,8 @@ function analyze3DS(payment) {
2100
2147
  description: "No se pudo determinar el estado 3DS \u2014 revisar payment.three_d_secure_mode + payment.status_detail manualmente."
2101
2148
  };
2102
2149
  }
2150
+
2151
+ // src/webhook.ts
2103
2152
  function parseWebhookEvent(body, searchParams) {
2104
2153
  const parseResult = WebhookBodySchema.safeParse(body ?? {});
2105
2154
  const parsedBody = parseResult.success ? parseResult.data : {};
@@ -2115,7 +2164,8 @@ function parseWebhookEvent(body, searchParams) {
2115
2164
  raw: parsedBody
2116
2165
  };
2117
2166
  }
2118
- function verifyWebhookSignature(params) {
2167
+ var DEFAULT_REPLAY_TOLERANCE_SECONDS = 300;
2168
+ async function verifyWebhookSignature(params) {
2119
2169
  if (!params.signatureHeader || !params.requestId) return false;
2120
2170
  const parts = Object.fromEntries(
2121
2171
  params.signatureHeader.split(",").map((segment) => segment.trim().split("="))
@@ -2123,16 +2173,20 @@ function verifyWebhookSignature(params) {
2123
2173
  const ts = parts.ts;
2124
2174
  const v1 = parts.v1;
2125
2175
  if (!ts || !v1) return false;
2176
+ const tolerance = params.replayToleranceSeconds ?? DEFAULT_REPLAY_TOLERANCE_SECONDS;
2177
+ const tsNumber = Number(ts);
2178
+ if (!Number.isFinite(tsNumber)) return false;
2179
+ const ageSeconds = Math.abs(Math.floor(Date.now() / 1e3) - tsNumber);
2180
+ if (ageSeconds > tolerance) return false;
2126
2181
  const manifest = `id:${params.dataId};request-id:${params.requestId};ts:${ts};`;
2127
- const expected = createHmac("sha256", params.secret).update(manifest).digest("hex");
2128
- if (expected.length !== v1.length) return false;
2129
- return timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
2182
+ const expected = await hmacSha256Hex(params.secret, manifest);
2183
+ return timingSafeEqualHex(expected, v1);
2130
2184
  }
2131
2185
 
2132
2186
  // src/tools.ts
2133
- function deterministicIdempotencyKey(...parts) {
2187
+ async function deterministicIdempotencyKey(...parts) {
2134
2188
  const payload = parts.filter((p) => p !== void 0 && p !== null).map(String).join("|");
2135
- return createHash("sha256").update(payload).digest("hex").slice(0, 32);
2189
+ return (await sha256Hex(payload)).slice(0, 32);
2136
2190
  }
2137
2191
  var DEFAULT_DESCRIPTIONS = {
2138
2192
  // ── Subscriptions ────────────────────────────────────────────────────────
@@ -2388,7 +2442,7 @@ function mercadoPagoTools(client, options) {
2388
2442
  ...options.notificationUrl !== void 0 ? { notificationUrl: options.notificationUrl } : {},
2389
2443
  // Deterministic idempotency key — safe to retry, same inputs always
2390
2444
  // produce the same key (MP dedupes on its side).
2391
- idempotencyKey: deterministicIdempotencyKey(
2445
+ idempotencyKey: await deterministicIdempotencyKey(
2392
2446
  "create_payment",
2393
2447
  input.external_reference ?? input.payer_email,
2394
2448
  input.amount_ars,
@@ -2511,7 +2565,7 @@ function mercadoPagoTools(client, options) {
2511
2565
  const refund = await client.createRefund({
2512
2566
  paymentId: payment_id,
2513
2567
  ...amount_ars !== void 0 ? { amount: amount_ars } : {},
2514
- idempotencyKey: deterministicIdempotencyKey("refund", payment_id, amount_ars ?? "full")
2568
+ idempotencyKey: await deterministicIdempotencyKey("refund", payment_id, amount_ars ?? "full")
2515
2569
  });
2516
2570
  return {
2517
2571
  refund_id: refund.id,
@@ -2777,7 +2831,7 @@ function mercadoPagoTools(client, options) {
2777
2831
  ...input.installments !== void 0 ? { installments: input.installments } : {},
2778
2832
  ...input.external_reference !== void 0 ? { externalReference: input.external_reference } : {},
2779
2833
  ...input.statement_descriptor !== void 0 ? { statementDescriptor: input.statement_descriptor } : {},
2780
- idempotencyKey: deterministicIdempotencyKey(
2834
+ idempotencyKey: await deterministicIdempotencyKey(
2781
2835
  "charge_saved_card",
2782
2836
  input.card_id,
2783
2837
  input.amount_ars,
@@ -3288,7 +3342,7 @@ function mercadoPagoTools(client, options) {
3288
3342
  resource: null
3289
3343
  };
3290
3344
  }
3291
- const verified = verifyWebhookSignature({
3345
+ const verified = await verifyWebhookSignature({
3292
3346
  requestId: request_id_header,
3293
3347
  dataId: event.dataId,
3294
3348
  signatureHeader: signature_header,
@@ -3486,7 +3540,7 @@ function mercadoPagoTools(client, options) {
3486
3540
  if (input.marketplace_fee !== void 0) params.marketplace_fee = input.marketplace_fee;
3487
3541
  if (input.collector_id !== void 0) params.collector_id = input.collector_id;
3488
3542
  const order = await client.createOrder(params, {
3489
- idempotencyKey: deterministicIdempotencyKey(
3543
+ idempotencyKey: await deterministicIdempotencyKey(
3490
3544
  "create_order",
3491
3545
  input.external_reference,
3492
3546
  input.total_amount,
@@ -4050,7 +4104,48 @@ var InMemoryStateAdapter = class {
4050
4104
  this.store.clear();
4051
4105
  }
4052
4106
  };
4107
+ var InMemoryOAuthTokenStore = class {
4108
+ store = /* @__PURE__ */ new Map();
4109
+ async set(userId, token) {
4110
+ this.store.set(userId, token);
4111
+ }
4112
+ async get(userId) {
4113
+ return this.store.get(userId) ?? null;
4114
+ }
4115
+ async delete(userId) {
4116
+ this.store.delete(userId);
4117
+ }
4118
+ async list() {
4119
+ return Array.from(this.store.keys());
4120
+ }
4121
+ /** Test helper. */
4122
+ reset() {
4123
+ this.store.clear();
4124
+ }
4125
+ };
4126
+ var InMemoryIdempotencyCache = class {
4127
+ store = /* @__PURE__ */ new Map();
4128
+ async get(key) {
4129
+ const entry = this.store.get(key);
4130
+ if (!entry) return null;
4131
+ if (Date.now() > entry.expiresAt) {
4132
+ this.store.delete(key);
4133
+ return null;
4134
+ }
4135
+ return entry.value;
4136
+ }
4137
+ async set(key, value, ttlSeconds = 86400) {
4138
+ this.store.set(key, { value, expiresAt: Date.now() + ttlSeconds * 1e3 });
4139
+ }
4140
+ async delete(key) {
4141
+ this.store.delete(key);
4142
+ }
4143
+ /** Test helper. */
4144
+ reset() {
4145
+ this.store.clear();
4146
+ }
4147
+ };
4053
4148
 
4054
- export { InMemoryStateAdapter, MercadoPagoAccountTypeMismatchError, MercadoPagoAuthError, MercadoPagoAuthorizeForbiddenError, MercadoPagoBackUrlInvalidError, MercadoPagoClient, MercadoPagoError, MercadoPagoOverloadedError, MercadoPagoPaymentRejectedError, MercadoPagoRateLimitError, MercadoPagoSelfPaymentError, MercadoPagoTimeoutError, TEST_CARDS_AR, TEST_PAYERS_AR, analyze3DS, buildAuthorizeUrl, buildTestCardScenario, classifyError, computeMarketplaceFee, exchangeCodeForToken, expirationTimeMs, explainPaymentStatus, isExpiringSoon, mercadoPagoTools, parseWebhookEvent, refreshAccessToken, verifyWebhookSignature };
4149
+ export { InMemoryIdempotencyCache, InMemoryOAuthTokenStore, InMemoryStateAdapter, MercadoPagoAccountTypeMismatchError, MercadoPagoAuthError, MercadoPagoAuthorizeForbiddenError, MercadoPagoBackUrlInvalidError, MercadoPagoClient, MercadoPagoError, MercadoPagoOverloadedError, MercadoPagoPaymentRejectedError, MercadoPagoRateLimitError, MercadoPagoSelfPaymentError, MercadoPagoTimeoutError, TEST_CARDS_AR, TEST_PAYERS_AR, analyze3DS, buildAuthorizeUrl, buildTestCardScenario, classifyError, computeMarketplaceFee, exchangeCodeForToken, expirationTimeMs, explainPaymentStatus, isExpiringSoon, mercadoPagoTools, parseWebhookEvent, refreshAccessToken, verifyWebhookSignature };
4055
4150
  //# sourceMappingURL=index.js.map
4056
4151
  //# sourceMappingURL=index.js.map