@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/CHANGELOG.md +47 -0
- package/README.md +63 -1
- package/cookbook/01-checkout-pro-basic.ts +99 -0
- package/cookbook/02-saas-subscription.ts +137 -0
- package/cookbook/03-webhook-handler.ts +162 -0
- package/cookbook/04-marketplace-split.ts +194 -0
- package/cookbook/05-qr-in-store.ts +142 -0
- package/cookbook/06-3ds-challenge.ts +139 -0
- package/cookbook/07-auth-only-order.ts +127 -0
- package/cookbook/08-recovery-patterns.ts +191 -0
- package/cookbook/README.md +36 -0
- package/dist/index.cjs +109 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -49
- package/dist/index.d.ts +28 -49
- package/dist/index.js +108 -13
- package/dist/index.js.map +1 -1
- package/dist/state-C6Wzb_XX.d.cts +106 -0
- package/dist/state-C6Wzb_XX.d.ts +106 -0
- package/dist/vercel-kv.cjs +92 -0
- package/dist/vercel-kv.cjs.map +1 -0
- package/dist/vercel-kv.d.cts +107 -0
- package/dist/vercel-kv.d.ts +107 -0
- package/dist/vercel-kv.js +88 -0
- package/dist/vercel-kv.js.map +1 -0
- package/package.json +25 -2
- package/tools.manifest.json +1 -1
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
2128
|
-
|
|
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
|
|
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
|