platform-types 1.10.760 → 1.10.762

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/audit.d.ts CHANGED
@@ -153,6 +153,16 @@ declare global {
153
153
  | 'order_shipment_created'
154
154
  /** A shipment was voided; when the order was delivered, this un-delivered it. */
155
155
  | 'order_shipment_voided' | 'payment_linked' | 'payment_unlinked'
156
+ /**
157
+ * An operator closed the order's storefront payment attempt that sat in
158
+ * `resolution` (`POST /payments/attempts { mode: 'resolve' }`). Records a
159
+ * decision only — no money moved and the order row is untouched.
160
+ * `before`: `attemptId`, `state` (`'resolution'`), `resolutionCause`.
161
+ * `after`: `attemptId`, `state` (`'resolved'`), `outcome` (`'refunded'` |
162
+ * `'kept'`) and the operator's reason as `'[present]'` — presence only, the
163
+ * words stay on the attempt row.
164
+ */
165
+ | 'payment_attempt_resolved'
156
166
  /** HISTORICAL: written only by the removed outbound MercadoPago refund; kept so old timeline rows still parse. */
157
167
  | 'payment_refunded'
158
168
  /** At least one till tender leg was appended (an absorbed replay writes none). */
@@ -5,8 +5,8 @@ exports.NotificationTypeEnum = void 0;
5
5
  // Indexed producers resolve candidates through `getNotificationSubscribers`:
6
6
  // legacy opt-ins and explicit channel maps remain source data on USER rows.
7
7
  // Addressed ERROR / ML_FACTURADOR_COLLISION / ML_SELLER_SWITCHED /
8
- // ML_CONNECTION_BROKEN / MENTION / CUSTOMER_PENDING_APPROVAL do not select a
9
- // producer subscriber audience;
8
+ // ML_CONNECTION_BROKEN / MENTION / CUSTOMER_PENDING_APPROVAL /
9
+ // PAYMENT_ATTEMPT_RESOLUTION do not select a producer subscriber audience;
10
10
  // the consumer still reads the live USER row for each delivery channel.
11
11
  // AFIP_CERT_EXPIRY is seeded on the founding user and uses the subscriber index.
12
12
  // Exported as a real enum consumed by api and app; adding an indexed type
@@ -174,4 +174,29 @@ var NotificationTypeEnum;
174
174
  * storefront socket), and never the registrant's email address.
175
175
  */
176
176
  NotificationTypeEnum["CUSTOMER_PENDING_APPROVAL"] = "CUSTOMER_PENDING_APPROVAL";
177
+ /**
178
+ * A storefront online payment attempt entered `resolution`: Mercado Pago
179
+ * money landed that did not settle its order (a late capture after the hold
180
+ * ended or the order was cancelled, a second approval, an amount or order
181
+ * mismatch, an order already paid). Names the order (`orderId`) and the
182
+ * cause, in the title and description; the app opens the resolution queue
183
+ * (`GET /payments/attempts?state=resolution`) from it.
184
+ *
185
+ * ⚠️ ADMIN-ONLY, and its own preference key. The producer fans out to every
186
+ * non-disabled ADMIN of the store (`listActiveAdmins`) — the tier that may
187
+ * read and close the queue — and never to a plain USER, so a client offers
188
+ * the `PAYMENT_ATTEMPT_RESOLUTION` toggle to ADMINs only. No legacy opt-in
189
+ * scan, as for `CUSTOMER_PENDING_APPROVAL` (a new key is seeded nowhere): the
190
+ * consumer enforces explicit type/channel preferences
191
+ * (`notificationPreferences.PAYMENT_ATTEMPT_RESOLUTION`), default-on when
192
+ * absent. Additive — no backfill or consumer migration owed.
193
+ *
194
+ * Once per new approval: it rings on the committed move INTO the state, and
195
+ * again on each further APPROVAL recorded on an attempt already there (new
196
+ * money the operator has not seen — a pending decision is then refused
197
+ * `409 PAYMENT_ATTEMPT_CHANGED`). A replayed approval moves nothing and rings
198
+ * nothing. An attempt an operator closed (`resolved`) and a later approval
199
+ * re-opens rings again.
200
+ */
201
+ NotificationTypeEnum["PAYMENT_ATTEMPT_RESOLUTION"] = "PAYMENT_ATTEMPT_RESOLUTION";
177
202
  })(NotificationTypeEnum || (exports.NotificationTypeEnum = NotificationTypeEnum = {}));
package/dist/cjs/order.js CHANGED
@@ -628,6 +628,13 @@ exports.ORDER_ERROR_CODES = [
628
628
  'ORDER_CURRENCY_NOT_SUBSCRIBED',
629
629
  'PAYMENT_METHODS_NOT_CONFIGURED',
630
630
  'PAYMENT_METHOD_NOT_FOUND',
631
+ // An online method (`Method.storefront: 'mp-checkout-pro'`) the store cannot
632
+ // take for this cart: Mercado Pago not connected, or a cart not in pesos.
633
+ 'PAYMENT_METHOD_UNAVAILABLE',
634
+ // Storefront checkout: the cart re-priced since the shopper saw it (re-read and
635
+ // confirm), and an allocated order id already taken (retry).
636
+ 'CART_PRICES_CHANGED',
637
+ 'ORDER_ID_COLLISION',
631
638
  'DELIVERY_METHOD_NOT_FOUND',
632
639
  'ORDER_BELOW_MINIMUM_PURCHASE',
633
640
  'ORDER_INVALID_CART',
@@ -19,7 +19,7 @@
19
19
  * no operator write can carry it back onto the order.
20
20
  */
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.PAYMENT_ATTEMPT_RESOLUTION_CAUSES = exports.ORDER_NOT_PAYABLE_REASONS = exports.PAYMENT_ATTEMPT_ERROR_CODES = exports.PAYMENT_ATTEMPT_STATES = void 0;
22
+ exports.PAYMENT_HOLD_MINUTES_DEFAULT = exports.PAYMENT_HOLD_MINUTES_MAX = exports.PAYMENT_HOLD_MINUTES_MIN = exports.PAYMENT_ATTEMPT_RESOLUTION_CAUSES = exports.ORDER_NOT_PAYABLE_REASONS = exports.PAYMENT_ATTEMPT_RESOLUTION_REASON_MAX = exports.PAYMENT_ATTEMPT_RESOLUTION_OUTCOMES = exports.PAYMENT_ATTEMPT_ERROR_CODES = exports.PAYMENT_ATTEMPT_STATES = void 0;
23
23
  /** Every {@link PaymentAttemptState}, in lifecycle order. */
24
24
  exports.PAYMENT_ATTEMPT_STATES = [
25
25
  'created',
@@ -31,10 +31,11 @@ exports.PAYMENT_ATTEMPT_STATES = [
31
31
  'refunded',
32
32
  'charged_back',
33
33
  'resolution',
34
+ 'resolved',
34
35
  ];
35
36
  /**
36
- * Every refusal code a payment-attempt start, or a checkout choosing an online
37
- * method, answers:
37
+ * Every refusal code a payment-attempt start, a checkout choosing an online
38
+ * method, or an operator closing a resolution answers:
38
39
  *
39
40
  * - `PAYMENT_PROVIDER_NOT_CONNECTED` · 412 — the store has no Mercado Pago
40
41
  * account connected.
@@ -44,9 +45,20 @@ exports.PAYMENT_ATTEMPT_STATES = [
44
45
  * {@link OrderNotPayableData}.
45
46
  * - `PAYMENT_ATTEMPT_EXPIRED` · 410 — the attempt's `expiresAt` passed.
46
47
  * - `PAYMENT_METHOD_UNAVAILABLE` · 409 — the checkout chose an online payment
47
- * method the store cannot take right now (its provider is not connected).
48
+ * method the store cannot take for this cart: its provider is not connected,
49
+ * or the cart is not in pesos (Checkout Pro here charges ARS only). `data` is
50
+ * `{}`. Also published in `ORDER_ERROR_CODES` — web `POST /orders` answers it.
48
51
  * - `MP_PREFERENCE_CREATE_FAILED` · 502 — Mercado Pago refused the checkout or
49
52
  * did not answer in time. No attempt was written, so starting again is safe.
53
+ * - `PAYMENT_ATTEMPT_NOT_FOUND` · 404 — the resolve named an attempt the store
54
+ * does not have, or an `orderId` that is not the attempt's.
55
+ * - `PAYMENT_ATTEMPT_NOT_IN_RESOLUTION` · 409 — the resolve's attempt is not in
56
+ * `resolution` (never was, or another operator closed it first). Nothing
57
+ * written; `data.state` is the state it is in.
58
+ * - `PAYMENT_ATTEMPT_CHANGED` · 409 — the attempt is still in `resolution` but
59
+ * is not the one the operator decided on: its `updatedAt` is not the request's
60
+ * `expectedUpdatedAt` (a further payment was recorded on it, for one). Nothing
61
+ * written; `data` is {@link PaymentAttemptChangedData}.
50
62
  */
51
63
  exports.PAYMENT_ATTEMPT_ERROR_CODES = [
52
64
  'PAYMENT_PROVIDER_NOT_CONNECTED',
@@ -55,7 +67,20 @@ exports.PAYMENT_ATTEMPT_ERROR_CODES = [
55
67
  'PAYMENT_ATTEMPT_EXPIRED',
56
68
  'PAYMENT_METHOD_UNAVAILABLE',
57
69
  'MP_PREFERENCE_CREATE_FAILED',
70
+ 'PAYMENT_ATTEMPT_NOT_FOUND',
71
+ 'PAYMENT_ATTEMPT_NOT_IN_RESOLUTION',
72
+ 'PAYMENT_ATTEMPT_CHANGED',
58
73
  ];
74
+ /**
75
+ * Every `outcome` of {@link ResolvePaymentAttemptRequest}:
76
+ *
77
+ * - `refunded` — staff refunded the payment in Mercado Pago's panel.
78
+ * - `kept` — the money stays with the store (for instance, the order is
79
+ * fulfilled by hand on it).
80
+ */
81
+ exports.PAYMENT_ATTEMPT_RESOLUTION_OUTCOMES = ['refunded', 'kept'];
82
+ /** The longest `reason` a resolve may record, in characters after trimming. */
83
+ exports.PAYMENT_ATTEMPT_RESOLUTION_REASON_MAX = 500;
59
84
  /**
60
85
  * Every `data.reason` of `409 ORDER_NOT_PAYABLE`:
61
86
  *
@@ -86,3 +111,12 @@ exports.PAYMENT_ATTEMPT_RESOLUTION_CAUSES = [
86
111
  'not-settled',
87
112
  'late-capture',
88
113
  ];
114
+ /**
115
+ * The bounds of the store's payment hold, `ecommerce.config.paymentHoldMinutes`
116
+ * — how long a new attempt stays payable, in whole minutes. Both writers refuse
117
+ * a value outside `[MIN, MAX]` (`400 VALIDATION_FAILED`); the start reads an
118
+ * absent or out-of-range stored value as `DEFAULT`.
119
+ */
120
+ exports.PAYMENT_HOLD_MINUTES_MIN = 15;
121
+ exports.PAYMENT_HOLD_MINUTES_MAX = 1440;
122
+ exports.PAYMENT_HOLD_MINUTES_DEFAULT = 60;
@@ -528,6 +528,18 @@ exports.SOCKET_ACTIONS = [
528
528
  * customer broadcast. Sent once per committed state move of the attempt.
529
529
  */
530
530
  'orderPaymentAttempt',
531
+ /**
532
+ * A storefront payment attempt an operator acts on changed: it entered
533
+ * `resolution`, took a further NEW approval while in it, or an operator
534
+ * closed it (`resolved`). `data` is
535
+ * `PaymentAttemptOperatorView` (`paymentAttempt.ts`) — never the checkout
536
+ * URL or the Preference id.
537
+ *
538
+ * ⚠️ OPERATOR sockets of the store only, and ADMIN tier only (`wsPostStore`
539
+ * with `lowTierData: null` — the tier `GET /payments/attempts` admits). Never
540
+ * a customer socket: the shopper's own frame is `orderPaymentAttempt`.
541
+ */
542
+ 'paymentAttemptChanged',
531
543
  'stripe',
532
544
  'subscription',
533
545
  // Fiscal.
@@ -1593,10 +1593,19 @@ declare global {
1593
1593
  * `register`, `mode: 'social'` with the same provider on `register-social`
1594
1594
  * (that account has no password) — never to register again, which the email
1595
1595
  * uniqueness constraint would now refuse.
1596
+ *
1597
+ * In a store that approves registrations first, the answer is the created
1598
+ * customer with `accessState: 'pending'` and NO session: no token and no
1599
+ * `sessionIssued`. The client tells the shopper the account awaits approval;
1600
+ * signing in is refused until the store approves it.
1596
1601
  */
1597
1602
  type CustomerRegisterResult = AuthCustomer | (Customer & {
1598
1603
  accessToken?: never;
1599
1604
  sessionIssued: false;
1605
+ }) | (Customer & {
1606
+ accessState: 'pending';
1607
+ accessToken?: never;
1608
+ sessionIssued?: never;
1600
1609
  });
1601
1610
  }
1602
1611
  export {};
@@ -152,7 +152,32 @@ export declare enum NotificationTypeEnum {
152
152
  * audience — the operator bell would reach the pending registrant's own
153
153
  * storefront socket), and never the registrant's email address.
154
154
  */
155
- CUSTOMER_PENDING_APPROVAL = "CUSTOMER_PENDING_APPROVAL"
155
+ CUSTOMER_PENDING_APPROVAL = "CUSTOMER_PENDING_APPROVAL",
156
+ /**
157
+ * A storefront online payment attempt entered `resolution`: Mercado Pago
158
+ * money landed that did not settle its order (a late capture after the hold
159
+ * ended or the order was cancelled, a second approval, an amount or order
160
+ * mismatch, an order already paid). Names the order (`orderId`) and the
161
+ * cause, in the title and description; the app opens the resolution queue
162
+ * (`GET /payments/attempts?state=resolution`) from it.
163
+ *
164
+ * ⚠️ ADMIN-ONLY, and its own preference key. The producer fans out to every
165
+ * non-disabled ADMIN of the store (`listActiveAdmins`) — the tier that may
166
+ * read and close the queue — and never to a plain USER, so a client offers
167
+ * the `PAYMENT_ATTEMPT_RESOLUTION` toggle to ADMINs only. No legacy opt-in
168
+ * scan, as for `CUSTOMER_PENDING_APPROVAL` (a new key is seeded nowhere): the
169
+ * consumer enforces explicit type/channel preferences
170
+ * (`notificationPreferences.PAYMENT_ATTEMPT_RESOLUTION`), default-on when
171
+ * absent. Additive — no backfill or consumer migration owed.
172
+ *
173
+ * Once per new approval: it rings on the committed move INTO the state, and
174
+ * again on each further APPROVAL recorded on an attempt already there (new
175
+ * money the operator has not seen — a pending decision is then refused
176
+ * `409 PAYMENT_ATTEMPT_CHANGED`). A replayed approval moves nothing and rings
177
+ * nothing. An attempt an operator closed (`resolved`) and a later approval
178
+ * re-opens rings again.
179
+ */
180
+ PAYMENT_ATTEMPT_RESOLUTION = "PAYMENT_ATTEMPT_RESOLUTION"
156
181
  }
157
182
  declare global {
158
183
  type CustomerNotificationPreferences = Partial<Record<'reminder-scheduled' | 'appointment-reminder', {
@@ -2,8 +2,8 @@
2
2
  // Indexed producers resolve candidates through `getNotificationSubscribers`:
3
3
  // legacy opt-ins and explicit channel maps remain source data on USER rows.
4
4
  // Addressed ERROR / ML_FACTURADOR_COLLISION / ML_SELLER_SWITCHED /
5
- // ML_CONNECTION_BROKEN / MENTION / CUSTOMER_PENDING_APPROVAL do not select a
6
- // producer subscriber audience;
5
+ // ML_CONNECTION_BROKEN / MENTION / CUSTOMER_PENDING_APPROVAL /
6
+ // PAYMENT_ATTEMPT_RESOLUTION do not select a producer subscriber audience;
7
7
  // the consumer still reads the live USER row for each delivery channel.
8
8
  // AFIP_CERT_EXPIRY is seeded on the founding user and uses the subscriber index.
9
9
  // Exported as a real enum consumed by api and app; adding an indexed type
@@ -171,4 +171,29 @@ export var NotificationTypeEnum;
171
171
  * storefront socket), and never the registrant's email address.
172
172
  */
173
173
  NotificationTypeEnum["CUSTOMER_PENDING_APPROVAL"] = "CUSTOMER_PENDING_APPROVAL";
174
+ /**
175
+ * A storefront online payment attempt entered `resolution`: Mercado Pago
176
+ * money landed that did not settle its order (a late capture after the hold
177
+ * ended or the order was cancelled, a second approval, an amount or order
178
+ * mismatch, an order already paid). Names the order (`orderId`) and the
179
+ * cause, in the title and description; the app opens the resolution queue
180
+ * (`GET /payments/attempts?state=resolution`) from it.
181
+ *
182
+ * ⚠️ ADMIN-ONLY, and its own preference key. The producer fans out to every
183
+ * non-disabled ADMIN of the store (`listActiveAdmins`) — the tier that may
184
+ * read and close the queue — and never to a plain USER, so a client offers
185
+ * the `PAYMENT_ATTEMPT_RESOLUTION` toggle to ADMINs only. No legacy opt-in
186
+ * scan, as for `CUSTOMER_PENDING_APPROVAL` (a new key is seeded nowhere): the
187
+ * consumer enforces explicit type/channel preferences
188
+ * (`notificationPreferences.PAYMENT_ATTEMPT_RESOLUTION`), default-on when
189
+ * absent. Additive — no backfill or consumer migration owed.
190
+ *
191
+ * Once per new approval: it rings on the committed move INTO the state, and
192
+ * again on each further APPROVAL recorded on an attempt already there (new
193
+ * money the operator has not seen — a pending decision is then refused
194
+ * `409 PAYMENT_ATTEMPT_CHANGED`). A replayed approval moves nothing and rings
195
+ * nothing. An attempt an operator closed (`resolved`) and a later approval
196
+ * re-opens rings again.
197
+ */
198
+ NotificationTypeEnum["PAYMENT_ATTEMPT_RESOLUTION"] = "PAYMENT_ATTEMPT_RESOLUTION";
174
199
  })(NotificationTypeEnum || (NotificationTypeEnum = {}));
package/dist/order.d.ts CHANGED
@@ -1285,9 +1285,10 @@ declare global {
1285
1285
  * `POST /orders { mode: 'cancel' }`, by ADMIN, SUPERVISOR or MANAGER. All
1286
1286
  * are distinct from a bare `disabled`, which records no cancellation.
1287
1287
  *
1288
- * `system` is written only by the payment-hold expiry, which cancels an
1289
- * order whose online payment attempt lapsed unpaid. No writer emits it yet;
1290
- * it is published first so a client can render it before one does.
1288
+ * `system` is written only by the payment-hold expiry
1289
+ * (`services/orderSystemCancellation.ts`, run by the payment-attempt sweep),
1290
+ * which cancels an order whose online payment attempt lapsed unpaid; its
1291
+ * `cancelledBy` is `'system'`, never a user id.
1291
1292
  */
1292
1293
  type OrderCancellationSource = 'customer' | 'operator' | 'system';
1293
1294
  /**
@@ -2872,6 +2873,6 @@ export declare const orderFulfilmentProgress: (order: OrderFulfilmentProgressInp
2872
2873
  * `SUBSCRIPTION_READONLY`) sit on the order CREATE leg only: an edit is not a new
2873
2874
  * order, so `bareOrderPostHandler` routes past `requireMetered` entirely.
2874
2875
  */
2875
- export declare const ORDER_ERROR_CODES: readonly ["ORDER_COST_DENOMINATION_UNKNOWN", "SERVICE_ORDER_DELIVERY_MANAGED", "ORDER_NOT_FOUND", "ORDER_LOCKED", "ORDER_NOT_READY", "ORDER_DELIVERED_ANOTHER_DAY", "ORDER_DELIVERY_STATE_UNCHANGED", "ORDER_ILLEGAL_TRANSITION", "ORDER_VERSION_CONFLICT", "CUSTOMER_NOT_FOUND", "CUSTOMER_MERGED", "ORDER_HAS_NO_CUSTOMER", "CUSTOMER_ANONYMIZED", "FX_CONVERSION_UNAVAILABLE", "ROLE_FORBIDDEN", "ORDER_CANCELLED", "PAYMENT_SETTLED_ON_ANOTHER_ORDER", "ORDER_HAS_SHIPMENTS", "ORDER_HAS_RETURNS", "SHIPMENT_QUANTITY_EXCEEDED", "SHIPMENT_LINE_MISMATCH", "SHIPMENT_NOT_FOUND", "SHIPMENT_LIMIT_REACHED", "SHIPMENT_TOO_LARGE", "ORDER_FULFILMENT_EXTERNAL", "SHIPMENT_FAILED", "ADMIN_REQUIRED", "IDEMPOTENCY_KEY_REQUIRED", "INVALID_IDEMPOTENCY_KEY", "IDEMPOTENCY_KEY_REUSE", "IDEMPOTENCY_IN_PROGRESS", "IDEMPOTENCY_LOCK_CONTENTION", "IDEMPOTENCY_KEY_FAILED", "IDEMPOTENT_RESPONSE_NOT_CACHED", "ORDER_CANCELLATION_NOT_PROTECTED", "ORDER_CANCELLATION_COMMITTED", "ORDER_CANCELLATION_LOCKED", "ORDER_CANCELLATION_TOO_LARGE", "ORDER_CANCELLATION_FAILED", "SALE_LEDGER_RETRACTION_REFUSED", "SALE_LEDGER_ROW_NOT_OWNED", "PRODUCT_NOT_FOUND", "PRODUCT_SALE_LIMIT_EXCEEDED", "PRODUCT_SALE_LIMIT_INVALID", "DEPOSIT_SOURCE_NOT_ALLOWED", "DEPOSIT_CURRENCY_MISMATCH", "DEPOSIT_EXCEEDS_TOTAL", "DEPOSIT_FREEZE_REQUIRES_INVOICE", "DEPOSIT_FREEZE_INVOICE_PENDING", "DEPOSIT_CHARACTERIZATION_CONFLICT", "DEPOSIT_FREEZE_INVOICE_NOT_QUALIFYING", "DEPOSIT_INVOICED_ORDER_MUST_FREEZE", "DEPOSIT_FROZEN_ORDER_MUST_FREEZE", "DEPOSIT_REFERENCE_IS_LINKED_PAYMENT", "DEPOSIT_DUPLICATE_REFERENCE", "TILL_TENDER_REQUIRES_DEPOSIT", "PAYMENT_REFERENCED_BY_DEPOSIT", "ORDER_HAS_UNREFUNDED_DEPOSIT", "ORDER_PRICE_FROZEN", "DEPOSIT_NOT_FOUND", "DEPOSIT_ALREADY_REFUNDED", "UNIT_QUANTITY_NOT_WHOLE", "UNIT_REVISION_STALE", "UNIT_QUANTITY_UNREPRESENTABLE", "KIT_RECIPE_CHANGED", "CART_PROMOTION_UNAVAILABLE", "ORDER_HAS_KIT_LINES", "ORDER_TARGET_REQUIRED", "ORDER_SOURCE_CONFLICT", "ORDER_CUSTOMER_REQUIRED", "BASKET_EMPTY", "BASKET_CHANGED_DURING_CHECKOUT", "CART_VERSION_CREATE_ONLY", "CART_VERSION_REQUIRES_CART_ID", "CART_REVISION_STALE", "CART_CUSTOMER_MISMATCH", "COUNTER_SALE_CREATE_ONLY", "SOLD_AT_CREATE_ONLY", "SOLD_AT_IN_FUTURE", "ORDER_TENDER_CREATE_ONLY", "CREDIT_OVERRIDE_CREATE_ONLY", "ON_ACCOUNT_CREATE_ONLY", "ON_ACCOUNT_WITH_TENDERS", "TENDERS_REQUIRE_COUNTER_SALE", "LINES_REQUIRE_COUNTER_SALE", "PRODUCT_COST_UNKNOWN", "PRICE_CHANGE_DISABLED", "LINE_DISCOUNT_EXCEEDS_MAX", "CUSTOMER_DISABLED", "SHIFT_NOT_AVAILABLE", "SOLD_AT_OUTSIDE_SHIFT", "ORDER_CURRENCY_NOT_SUBSCRIBED", "PAYMENT_METHODS_NOT_CONFIGURED", "PAYMENT_METHOD_NOT_FOUND", "DELIVERY_METHOD_NOT_FOUND", "ORDER_BELOW_MINIMUM_PURCHASE", "ORDER_INVALID_CART", "EMAIL_VERIFICATION_REQUIRED", "ACCOUNT_DISABLED", "CUSTOMER_ACCESS_PENDING", "CUSTOMER_ACCESS_REJECTED", "CURRENCY_MISMATCH", "SHIFT_NOT_OPEN", "ORDER_DISCOUNT_AFTER_INVOICE", "ORDER_DISCOUNT_ON_SERVICE_ORDER", "ORDER_DISCOUNT_ON_MARKETPLACE_ORDER", "ORDER_INVOICE_METHOD_OUTSTANDING_FACTURA", "ORDER_SERVICE_PERIOD_AFTER_INVOICE", "ORDER_ATTEMPT_COMMITTED", "ORDER_ATTEMPT_ABANDONED", "ORDER_ATTEMPT_KEY_EXPIRED", "ORDER_ATTEMPT_KEY_SCOPE_MISMATCH", "ORDER_COMPLETION_ATTEMPT_COMMITTED", "ORDER_COMPLETION_ATTEMPT_ABANDONED"];
2876
+ export declare const ORDER_ERROR_CODES: readonly ["ORDER_COST_DENOMINATION_UNKNOWN", "SERVICE_ORDER_DELIVERY_MANAGED", "ORDER_NOT_FOUND", "ORDER_LOCKED", "ORDER_NOT_READY", "ORDER_DELIVERED_ANOTHER_DAY", "ORDER_DELIVERY_STATE_UNCHANGED", "ORDER_ILLEGAL_TRANSITION", "ORDER_VERSION_CONFLICT", "CUSTOMER_NOT_FOUND", "CUSTOMER_MERGED", "ORDER_HAS_NO_CUSTOMER", "CUSTOMER_ANONYMIZED", "FX_CONVERSION_UNAVAILABLE", "ROLE_FORBIDDEN", "ORDER_CANCELLED", "PAYMENT_SETTLED_ON_ANOTHER_ORDER", "ORDER_HAS_SHIPMENTS", "ORDER_HAS_RETURNS", "SHIPMENT_QUANTITY_EXCEEDED", "SHIPMENT_LINE_MISMATCH", "SHIPMENT_NOT_FOUND", "SHIPMENT_LIMIT_REACHED", "SHIPMENT_TOO_LARGE", "ORDER_FULFILMENT_EXTERNAL", "SHIPMENT_FAILED", "ADMIN_REQUIRED", "IDEMPOTENCY_KEY_REQUIRED", "INVALID_IDEMPOTENCY_KEY", "IDEMPOTENCY_KEY_REUSE", "IDEMPOTENCY_IN_PROGRESS", "IDEMPOTENCY_LOCK_CONTENTION", "IDEMPOTENCY_KEY_FAILED", "IDEMPOTENT_RESPONSE_NOT_CACHED", "ORDER_CANCELLATION_NOT_PROTECTED", "ORDER_CANCELLATION_COMMITTED", "ORDER_CANCELLATION_LOCKED", "ORDER_CANCELLATION_TOO_LARGE", "ORDER_CANCELLATION_FAILED", "SALE_LEDGER_RETRACTION_REFUSED", "SALE_LEDGER_ROW_NOT_OWNED", "PRODUCT_NOT_FOUND", "PRODUCT_SALE_LIMIT_EXCEEDED", "PRODUCT_SALE_LIMIT_INVALID", "DEPOSIT_SOURCE_NOT_ALLOWED", "DEPOSIT_CURRENCY_MISMATCH", "DEPOSIT_EXCEEDS_TOTAL", "DEPOSIT_FREEZE_REQUIRES_INVOICE", "DEPOSIT_FREEZE_INVOICE_PENDING", "DEPOSIT_CHARACTERIZATION_CONFLICT", "DEPOSIT_FREEZE_INVOICE_NOT_QUALIFYING", "DEPOSIT_INVOICED_ORDER_MUST_FREEZE", "DEPOSIT_FROZEN_ORDER_MUST_FREEZE", "DEPOSIT_REFERENCE_IS_LINKED_PAYMENT", "DEPOSIT_DUPLICATE_REFERENCE", "TILL_TENDER_REQUIRES_DEPOSIT", "PAYMENT_REFERENCED_BY_DEPOSIT", "ORDER_HAS_UNREFUNDED_DEPOSIT", "ORDER_PRICE_FROZEN", "DEPOSIT_NOT_FOUND", "DEPOSIT_ALREADY_REFUNDED", "UNIT_QUANTITY_NOT_WHOLE", "UNIT_REVISION_STALE", "UNIT_QUANTITY_UNREPRESENTABLE", "KIT_RECIPE_CHANGED", "CART_PROMOTION_UNAVAILABLE", "ORDER_HAS_KIT_LINES", "ORDER_TARGET_REQUIRED", "ORDER_SOURCE_CONFLICT", "ORDER_CUSTOMER_REQUIRED", "BASKET_EMPTY", "BASKET_CHANGED_DURING_CHECKOUT", "CART_VERSION_CREATE_ONLY", "CART_VERSION_REQUIRES_CART_ID", "CART_REVISION_STALE", "CART_CUSTOMER_MISMATCH", "COUNTER_SALE_CREATE_ONLY", "SOLD_AT_CREATE_ONLY", "SOLD_AT_IN_FUTURE", "ORDER_TENDER_CREATE_ONLY", "CREDIT_OVERRIDE_CREATE_ONLY", "ON_ACCOUNT_CREATE_ONLY", "ON_ACCOUNT_WITH_TENDERS", "TENDERS_REQUIRE_COUNTER_SALE", "LINES_REQUIRE_COUNTER_SALE", "PRODUCT_COST_UNKNOWN", "PRICE_CHANGE_DISABLED", "LINE_DISCOUNT_EXCEEDS_MAX", "CUSTOMER_DISABLED", "SHIFT_NOT_AVAILABLE", "SOLD_AT_OUTSIDE_SHIFT", "ORDER_CURRENCY_NOT_SUBSCRIBED", "PAYMENT_METHODS_NOT_CONFIGURED", "PAYMENT_METHOD_NOT_FOUND", "PAYMENT_METHOD_UNAVAILABLE", "CART_PRICES_CHANGED", "ORDER_ID_COLLISION", "DELIVERY_METHOD_NOT_FOUND", "ORDER_BELOW_MINIMUM_PURCHASE", "ORDER_INVALID_CART", "EMAIL_VERIFICATION_REQUIRED", "ACCOUNT_DISABLED", "CUSTOMER_ACCESS_PENDING", "CUSTOMER_ACCESS_REJECTED", "CURRENCY_MISMATCH", "SHIFT_NOT_OPEN", "ORDER_DISCOUNT_AFTER_INVOICE", "ORDER_DISCOUNT_ON_SERVICE_ORDER", "ORDER_DISCOUNT_ON_MARKETPLACE_ORDER", "ORDER_INVOICE_METHOD_OUTSTANDING_FACTURA", "ORDER_SERVICE_PERIOD_AFTER_INVOICE", "ORDER_ATTEMPT_COMMITTED", "ORDER_ATTEMPT_ABANDONED", "ORDER_ATTEMPT_KEY_EXPIRED", "ORDER_ATTEMPT_KEY_SCOPE_MISMATCH", "ORDER_COMPLETION_ATTEMPT_COMMITTED", "ORDER_COMPLETION_ATTEMPT_ABANDONED"];
2876
2877
  export type OrderErrorCode = (typeof ORDER_ERROR_CODES)[number];
2877
2878
  export {};
package/dist/order.js CHANGED
@@ -621,6 +621,13 @@ export const ORDER_ERROR_CODES = [
621
621
  'ORDER_CURRENCY_NOT_SUBSCRIBED',
622
622
  'PAYMENT_METHODS_NOT_CONFIGURED',
623
623
  'PAYMENT_METHOD_NOT_FOUND',
624
+ // An online method (`Method.storefront: 'mp-checkout-pro'`) the store cannot
625
+ // take for this cart: Mercado Pago not connected, or a cart not in pesos.
626
+ 'PAYMENT_METHOD_UNAVAILABLE',
627
+ // Storefront checkout: the cart re-priced since the shopper saw it (re-read and
628
+ // confirm), and an allocated order id already taken (retry).
629
+ 'CART_PRICES_CHANGED',
630
+ 'ORDER_ID_COLLISION',
624
631
  'DELIVERY_METHOD_NOT_FOUND',
625
632
  'ORDER_BELOW_MINIMUM_PURCHASE',
626
633
  'ORDER_INVALID_CART',
package/dist/payment.d.ts CHANGED
@@ -136,6 +136,18 @@ declare global {
136
136
  externalReference?: string;
137
137
  reconciled?: boolean;
138
138
  reconcileReason?: string;
139
+ /**
140
+ * MercadoPago's own money breakdown, in major units of `currency`: `gross` is
141
+ * `transaction_amount`, `net` is `transaction_details.net_received_amount`
142
+ * (what the store received), and `fee` is what MercadoPago kept
143
+ * (`gross − net`; the collector-paid `fee_details` when MercadoPago states no
144
+ * net). Each is present only when MercadoPago reported it, on MercadoPago
145
+ * payments recorded since these fields existed. Absent means "not recorded",
146
+ * never zero; a `fee` of `0` is a fee-free payment.
147
+ */
148
+ gross?: number;
149
+ fee?: number;
150
+ net?: number;
139
151
  }
140
152
  /**
141
153
  * Confidence tier for a link suggestion.
@@ -33,14 +33,26 @@ declare global {
33
33
  * unless money had already reached it by another route; then the order is
34
34
  * left as it is and the attempt stays `expired` — not `resolution`, since
35
35
  * that money is not this attempt's.
36
- * - `cancelled` — the order was cancelled while the attempt was live.
37
- * - `refunded` — the approved payment was refunded.
36
+ * - `cancelled` — the order was cancelled while the attempt was live: by an
37
+ * operator (`POST /orders { mode: 'cancel' }`), in the same transaction as
38
+ * the cancellation. An approval that still lands on its checkout is a late
39
+ * capture and moves it to `resolution`.
40
+ * - `refunded` — the approved payment was refunded. Only from `approved`: a
41
+ * refund on a `resolution` attempt is the operator's resolution work and
42
+ * leaves it `resolution`.
38
43
  * - `charged_back` — the approved payment was charged back.
39
44
  * - `resolution` — money landed that must NOT settle the order: an approval
40
45
  * on an order already paid, on an expired or cancelled order, or for an
41
46
  * amount other than the order total. The payment is recorded and an
42
47
  * operator decides; the order is neither settled nor re-opened. Show it to
43
48
  * the shopper as under review.
49
+ * - `resolved` — an operator closed the `resolution`
50
+ * ({@link ResolvePaymentAttemptRequest}), recording whether the money was
51
+ * refunded in Mercado Pago or kept. Moves no money and never touches the
52
+ * order. Not quite terminal: a chargeback still moves it to `charged_back`,
53
+ * and a FURTHER approval on the same checkout re-opens it to `resolution`
54
+ * — new money always needs an operator again. Show it to the shopper as
55
+ * reviewed by the store (the outcome and reason are operator-only).
44
56
  */
45
57
  type PaymentAttemptState = (typeof PAYMENT_ATTEMPT_STATES)[number];
46
58
  /** One of {@link PAYMENT_ATTEMPT_ERROR_CODES}. */
@@ -49,6 +61,8 @@ declare global {
49
61
  type OrderNotPayableReason = (typeof ORDER_NOT_PAYABLE_REASONS)[number];
50
62
  /** One of {@link PAYMENT_ATTEMPT_RESOLUTION_CAUSES}. */
51
63
  type PaymentAttemptResolutionCause = (typeof PAYMENT_ATTEMPT_RESOLUTION_CAUSES)[number];
64
+ /** One of {@link PAYMENT_ATTEMPT_RESOLUTION_OUTCOMES}. */
65
+ type PaymentAttemptResolutionOutcome = (typeof PAYMENT_ATTEMPT_RESOLUTION_OUTCOMES)[number];
52
66
  /**
53
67
  * The body that starts (or returns the live) payment attempt for an order.
54
68
  * The caller must be the order's customer; the store is the token's. The
@@ -69,6 +83,18 @@ declare global {
69
83
  interface OrderNotPayableData {
70
84
  reason: OrderNotPayableReason;
71
85
  }
86
+ /**
87
+ * `data` of `409 PAYMENT_ATTEMPT_CHANGED`: the attempt as it stands now. Show
88
+ * it to the operator — a payment they have not seen may be on it — and resend
89
+ * with its `updatedAt` once they have.
90
+ */
91
+ interface PaymentAttemptChangedData {
92
+ attempt: PaymentAttemptOperatorView;
93
+ }
94
+ /** `data` of `409 PAYMENT_ATTEMPT_NOT_IN_RESOLUTION`: the state the attempt is actually in. */
95
+ interface PaymentAttemptNotInResolutionData {
96
+ state: PaymentAttemptState;
97
+ }
72
98
  /**
73
99
  * The minimised attempt the shopper sees on their own order — never the
74
100
  * stored record.
@@ -107,6 +133,12 @@ declare global {
107
133
  state: PaymentAttemptState;
108
134
  /** Why the attempt is in `resolution` — set by the move into it. */
109
135
  resolutionCause?: PaymentAttemptResolutionCause;
136
+ /**
137
+ * How an operator closed the resolution — set by the move to `resolved`
138
+ * and kept after it (a later chargeback, or a re-opening approval, leaves
139
+ * the last closing on record).
140
+ */
141
+ resolution?: PaymentAttemptResolutionRecord;
110
142
  /** The Mercado Pago payments whose approval this attempt processed, oldest first. */
111
143
  approvedPaymentIds: string[];
112
144
  /** The Mercado Pago payment whose notification made the last move. */
@@ -121,9 +153,49 @@ declare global {
121
153
  /** Unix ms. */
122
154
  updatedAt: number;
123
155
  }
156
+ /** How an operator closed a `resolution` — see {@link ResolvePaymentAttemptRequest}. */
157
+ interface PaymentAttemptResolutionRecord {
158
+ outcome: PaymentAttemptResolutionOutcome;
159
+ /** The operator's own words, as sent (trimmed). */
160
+ reason: string;
161
+ /** The store user who closed it. */
162
+ resolvedBy: string;
163
+ /** Unix ms. */
164
+ resolvedAt: number;
165
+ }
166
+ /**
167
+ * `POST /payments/attempts { mode: 'resolve' }` (App host, admin) — an
168
+ * operator closes an attempt in `resolution`, moving it to `resolved`.
169
+ *
170
+ * Records a decision and nothing else: it moves NO money, writes no
171
+ * `PAYMENT#` row and never touches the order. A refund is made in Mercado
172
+ * Pago's own panel (the api has no outbound refund); `outcome: 'refunded'`
173
+ * records that staff did so, `'kept'` that the money stays with the store.
174
+ *
175
+ * ⚠️ The operator closes the attempt AS THEY SAW IT: `expectedUpdatedAt` is
176
+ * the `updatedAt` of the {@link PaymentAttemptOperatorView} they decided on.
177
+ * Anything that moved the attempt since — a further approval recorded on it
178
+ * included — answers `409 PAYMENT_ATTEMPT_CHANGED` with the current view and
179
+ * writes nothing, so a decision is never applied to money it did not cover.
180
+ */
181
+ interface ResolvePaymentAttemptRequest {
182
+ mode: 'resolve';
183
+ attemptId: string;
184
+ /** The attempt's order — must be the one `attemptId` names. */
185
+ orderId: string;
186
+ /** The `updatedAt` (Unix ms) of the operator view the decision was taken on. */
187
+ expectedUpdatedAt: number;
188
+ outcome: PaymentAttemptResolutionOutcome;
189
+ /** Required, 1–{@link PAYMENT_ATTEMPT_RESOLUTION_REASON_MAX} characters after trimming. */
190
+ reason: string;
191
+ }
192
+ /** `data` of a successful resolve: the attempt as it now stands. */
193
+ interface ResolvePaymentAttemptResponse {
194
+ attempt: PaymentAttemptOperatorView;
195
+ }
124
196
  /**
125
- * `data` of `GET /payments/attempts?state=resolution` (App host, admin):
126
- * the store's attempts in that state, newest activity first. Page on
197
+ * `data` of `GET /payments/attempts?state=resolution|resolved` (App host,
198
+ * admin): the store's attempts in that state, newest activity first. Page on
127
199
  * `nextCursor`'s presence, never on the page's length — the state is a
128
200
  * filter, so a page can be short, even empty, with more to come.
129
201
  */
@@ -134,10 +206,10 @@ declare global {
134
206
  }
135
207
  }
136
208
  /** Every {@link PaymentAttemptState}, in lifecycle order. */
137
- export declare const PAYMENT_ATTEMPT_STATES: readonly ["created", "pending", "approved", "rejected", "expired", "cancelled", "refunded", "charged_back", "resolution"];
209
+ export declare const PAYMENT_ATTEMPT_STATES: readonly ["created", "pending", "approved", "rejected", "expired", "cancelled", "refunded", "charged_back", "resolution", "resolved"];
138
210
  /**
139
- * Every refusal code a payment-attempt start, or a checkout choosing an online
140
- * method, answers:
211
+ * Every refusal code a payment-attempt start, a checkout choosing an online
212
+ * method, or an operator closing a resolution answers:
141
213
  *
142
214
  * - `PAYMENT_PROVIDER_NOT_CONNECTED` · 412 — the store has no Mercado Pago
143
215
  * account connected.
@@ -147,11 +219,32 @@ export declare const PAYMENT_ATTEMPT_STATES: readonly ["created", "pending", "ap
147
219
  * {@link OrderNotPayableData}.
148
220
  * - `PAYMENT_ATTEMPT_EXPIRED` · 410 — the attempt's `expiresAt` passed.
149
221
  * - `PAYMENT_METHOD_UNAVAILABLE` · 409 — the checkout chose an online payment
150
- * method the store cannot take right now (its provider is not connected).
222
+ * method the store cannot take for this cart: its provider is not connected,
223
+ * or the cart is not in pesos (Checkout Pro here charges ARS only). `data` is
224
+ * `{}`. Also published in `ORDER_ERROR_CODES` — web `POST /orders` answers it.
151
225
  * - `MP_PREFERENCE_CREATE_FAILED` · 502 — Mercado Pago refused the checkout or
152
226
  * did not answer in time. No attempt was written, so starting again is safe.
227
+ * - `PAYMENT_ATTEMPT_NOT_FOUND` · 404 — the resolve named an attempt the store
228
+ * does not have, or an `orderId` that is not the attempt's.
229
+ * - `PAYMENT_ATTEMPT_NOT_IN_RESOLUTION` · 409 — the resolve's attempt is not in
230
+ * `resolution` (never was, or another operator closed it first). Nothing
231
+ * written; `data.state` is the state it is in.
232
+ * - `PAYMENT_ATTEMPT_CHANGED` · 409 — the attempt is still in `resolution` but
233
+ * is not the one the operator decided on: its `updatedAt` is not the request's
234
+ * `expectedUpdatedAt` (a further payment was recorded on it, for one). Nothing
235
+ * written; `data` is {@link PaymentAttemptChangedData}.
153
236
  */
154
- export declare const PAYMENT_ATTEMPT_ERROR_CODES: readonly ["PAYMENT_PROVIDER_NOT_CONNECTED", "PAYMENT_PROVIDER_TOKEN_EXPIRED", "ORDER_NOT_PAYABLE", "PAYMENT_ATTEMPT_EXPIRED", "PAYMENT_METHOD_UNAVAILABLE", "MP_PREFERENCE_CREATE_FAILED"];
237
+ export declare const PAYMENT_ATTEMPT_ERROR_CODES: readonly ["PAYMENT_PROVIDER_NOT_CONNECTED", "PAYMENT_PROVIDER_TOKEN_EXPIRED", "ORDER_NOT_PAYABLE", "PAYMENT_ATTEMPT_EXPIRED", "PAYMENT_METHOD_UNAVAILABLE", "MP_PREFERENCE_CREATE_FAILED", "PAYMENT_ATTEMPT_NOT_FOUND", "PAYMENT_ATTEMPT_NOT_IN_RESOLUTION", "PAYMENT_ATTEMPT_CHANGED"];
238
+ /**
239
+ * Every `outcome` of {@link ResolvePaymentAttemptRequest}:
240
+ *
241
+ * - `refunded` — staff refunded the payment in Mercado Pago's panel.
242
+ * - `kept` — the money stays with the store (for instance, the order is
243
+ * fulfilled by hand on it).
244
+ */
245
+ export declare const PAYMENT_ATTEMPT_RESOLUTION_OUTCOMES: readonly ["refunded", "kept"];
246
+ /** The longest `reason` a resolve may record, in characters after trimming. */
247
+ export declare const PAYMENT_ATTEMPT_RESOLUTION_REASON_MAX = 500;
155
248
  /**
156
249
  * Every `data.reason` of `409 ORDER_NOT_PAYABLE`:
157
250
  *
@@ -175,4 +268,13 @@ export declare const ORDER_NOT_PAYABLE_REASONS: readonly ["cancelled", "paid", "
175
268
  * expired or been cancelled, or the order was already cancelled.
176
269
  */
177
270
  export declare const PAYMENT_ATTEMPT_RESOLUTION_CAUSES: readonly ["second-approval", "amount-mismatch", "order-mismatch", "order-already-paid", "not-settled", "late-capture"];
271
+ /**
272
+ * The bounds of the store's payment hold, `ecommerce.config.paymentHoldMinutes`
273
+ * — how long a new attempt stays payable, in whole minutes. Both writers refuse
274
+ * a value outside `[MIN, MAX]` (`400 VALIDATION_FAILED`); the start reads an
275
+ * absent or out-of-range stored value as `DEFAULT`.
276
+ */
277
+ export declare const PAYMENT_HOLD_MINUTES_MIN = 15;
278
+ export declare const PAYMENT_HOLD_MINUTES_MAX = 1440;
279
+ export declare const PAYMENT_HOLD_MINUTES_DEFAULT = 60;
178
280
  export {};
@@ -28,10 +28,11 @@ export const PAYMENT_ATTEMPT_STATES = [
28
28
  'refunded',
29
29
  'charged_back',
30
30
  'resolution',
31
+ 'resolved',
31
32
  ];
32
33
  /**
33
- * Every refusal code a payment-attempt start, or a checkout choosing an online
34
- * method, answers:
34
+ * Every refusal code a payment-attempt start, a checkout choosing an online
35
+ * method, or an operator closing a resolution answers:
35
36
  *
36
37
  * - `PAYMENT_PROVIDER_NOT_CONNECTED` · 412 — the store has no Mercado Pago
37
38
  * account connected.
@@ -41,9 +42,20 @@ export const PAYMENT_ATTEMPT_STATES = [
41
42
  * {@link OrderNotPayableData}.
42
43
  * - `PAYMENT_ATTEMPT_EXPIRED` · 410 — the attempt's `expiresAt` passed.
43
44
  * - `PAYMENT_METHOD_UNAVAILABLE` · 409 — the checkout chose an online payment
44
- * method the store cannot take right now (its provider is not connected).
45
+ * method the store cannot take for this cart: its provider is not connected,
46
+ * or the cart is not in pesos (Checkout Pro here charges ARS only). `data` is
47
+ * `{}`. Also published in `ORDER_ERROR_CODES` — web `POST /orders` answers it.
45
48
  * - `MP_PREFERENCE_CREATE_FAILED` · 502 — Mercado Pago refused the checkout or
46
49
  * did not answer in time. No attempt was written, so starting again is safe.
50
+ * - `PAYMENT_ATTEMPT_NOT_FOUND` · 404 — the resolve named an attempt the store
51
+ * does not have, or an `orderId` that is not the attempt's.
52
+ * - `PAYMENT_ATTEMPT_NOT_IN_RESOLUTION` · 409 — the resolve's attempt is not in
53
+ * `resolution` (never was, or another operator closed it first). Nothing
54
+ * written; `data.state` is the state it is in.
55
+ * - `PAYMENT_ATTEMPT_CHANGED` · 409 — the attempt is still in `resolution` but
56
+ * is not the one the operator decided on: its `updatedAt` is not the request's
57
+ * `expectedUpdatedAt` (a further payment was recorded on it, for one). Nothing
58
+ * written; `data` is {@link PaymentAttemptChangedData}.
47
59
  */
48
60
  export const PAYMENT_ATTEMPT_ERROR_CODES = [
49
61
  'PAYMENT_PROVIDER_NOT_CONNECTED',
@@ -52,7 +64,20 @@ export const PAYMENT_ATTEMPT_ERROR_CODES = [
52
64
  'PAYMENT_ATTEMPT_EXPIRED',
53
65
  'PAYMENT_METHOD_UNAVAILABLE',
54
66
  'MP_PREFERENCE_CREATE_FAILED',
67
+ 'PAYMENT_ATTEMPT_NOT_FOUND',
68
+ 'PAYMENT_ATTEMPT_NOT_IN_RESOLUTION',
69
+ 'PAYMENT_ATTEMPT_CHANGED',
55
70
  ];
71
+ /**
72
+ * Every `outcome` of {@link ResolvePaymentAttemptRequest}:
73
+ *
74
+ * - `refunded` — staff refunded the payment in Mercado Pago's panel.
75
+ * - `kept` — the money stays with the store (for instance, the order is
76
+ * fulfilled by hand on it).
77
+ */
78
+ export const PAYMENT_ATTEMPT_RESOLUTION_OUTCOMES = ['refunded', 'kept'];
79
+ /** The longest `reason` a resolve may record, in characters after trimming. */
80
+ export const PAYMENT_ATTEMPT_RESOLUTION_REASON_MAX = 500;
56
81
  /**
57
82
  * Every `data.reason` of `409 ORDER_NOT_PAYABLE`:
58
83
  *
@@ -83,3 +108,12 @@ export const PAYMENT_ATTEMPT_RESOLUTION_CAUSES = [
83
108
  'not-settled',
84
109
  'late-capture',
85
110
  ];
111
+ /**
112
+ * The bounds of the store's payment hold, `ecommerce.config.paymentHoldMinutes`
113
+ * — how long a new attempt stays payable, in whole minutes. Both writers refuse
114
+ * a value outside `[MIN, MAX]` (`400 VALIDATION_FAILED`); the start reads an
115
+ * absent or out-of-range stored value as `DEFAULT`.
116
+ */
117
+ export const PAYMENT_HOLD_MINUTES_MIN = 15;
118
+ export const PAYMENT_HOLD_MINUTES_MAX = 1440;
119
+ export const PAYMENT_HOLD_MINUTES_DEFAULT = 60;
package/dist/socket.d.ts CHANGED
@@ -26,7 +26,7 @@
26
26
  * A client must ignore actions it does not own rather than assume it
27
27
  * receives all of them.
28
28
  */
29
- export declare const SOCKET_ACTIONS: readonly ["account", "appointments", "appointmentWaitlist", "attendance", "attributes", "automation-rules", "baskets", "cart", "brands", "cash", "catalogOperation", "categories", "campaigns", "customers", "customerNote", "customerAddress", "customerContact", "deliveries", "globals", "inventory", "invoices", "literals", "loyalty", "orders", "presupuestos", "products", "promotions", "segments", "returns", "rma", "templates", "services", "service-templates", "shifts", "stores", "suppliers", "supplier-invoice", "support", "surveys", "users", "warehouses", "zones", "favorites", "webhooks", "account-delete", "baskets-delete", "cart-delete", "log-delete", "notifications", "support-message", "whatsapp-order-draft", "whatsapp-order-confirmation", "payment_received", "mp_payment_status_changed", "payment_linked", "payment_unlinked", "mercadopago", "mercadopago_dynamic_qr_created", "mercadopago_static_qr_created", "mp_hook_log_appended", "mp_ipn_log_appended", "orderPaymentAttempt", "stripe", "subscription", "caea", "print", "print-order", "print-invoice", "print-product", "print-tag", "print_job_failed", "request_printers", "printers_changed", "agent_status_changed", "print_rules_changed", "printers_active", "agent_command", "maintenance", "currency_auto_updated", "drain_progress", "integration_event_appended", "userActivityRecorded", "mercadolibre_settlement_period", "customDomain", "purchaseOrders", "cycleCounts", "stockTransfers", "workItems"];
29
+ export declare const SOCKET_ACTIONS: readonly ["account", "appointments", "appointmentWaitlist", "attendance", "attributes", "automation-rules", "baskets", "cart", "brands", "cash", "catalogOperation", "categories", "campaigns", "customers", "customerNote", "customerAddress", "customerContact", "deliveries", "globals", "inventory", "invoices", "literals", "loyalty", "orders", "presupuestos", "products", "promotions", "segments", "returns", "rma", "templates", "services", "service-templates", "shifts", "stores", "suppliers", "supplier-invoice", "support", "surveys", "users", "warehouses", "zones", "favorites", "webhooks", "account-delete", "baskets-delete", "cart-delete", "log-delete", "notifications", "support-message", "whatsapp-order-draft", "whatsapp-order-confirmation", "payment_received", "mp_payment_status_changed", "payment_linked", "payment_unlinked", "mercadopago", "mercadopago_dynamic_qr_created", "mercadopago_static_qr_created", "mp_hook_log_appended", "mp_ipn_log_appended", "orderPaymentAttempt", "paymentAttemptChanged", "stripe", "subscription", "caea", "print", "print-order", "print-invoice", "print-product", "print-tag", "print_job_failed", "request_printers", "printers_changed", "agent_status_changed", "print_rules_changed", "printers_active", "agent_command", "maintenance", "currency_auto_updated", "drain_progress", "integration_event_appended", "userActivityRecorded", "mercadolibre_settlement_period", "customDomain", "purchaseOrders", "cycleCounts", "stockTransfers", "workItems"];
30
30
  /** Union of every server→client data-frame action. */
31
31
  export type SocketAction = (typeof SOCKET_ACTIONS)[number];
32
32
  /**
package/dist/socket.js CHANGED
@@ -525,6 +525,18 @@ export const SOCKET_ACTIONS = [
525
525
  * customer broadcast. Sent once per committed state move of the attempt.
526
526
  */
527
527
  'orderPaymentAttempt',
528
+ /**
529
+ * A storefront payment attempt an operator acts on changed: it entered
530
+ * `resolution`, took a further NEW approval while in it, or an operator
531
+ * closed it (`resolved`). `data` is
532
+ * `PaymentAttemptOperatorView` (`paymentAttempt.ts`) — never the checkout
533
+ * URL or the Preference id.
534
+ *
535
+ * ⚠️ OPERATOR sockets of the store only, and ADMIN tier only (`wsPostStore`
536
+ * with `lowTierData: null` — the tier `GET /payments/attempts` admits). Never
537
+ * a customer socket: the shopper's own frame is `orderPaymentAttempt`.
538
+ */
539
+ 'paymentAttemptChanged',
528
540
  'stripe',
529
541
  'subscription',
530
542
  // Fiscal.
package/dist/store.d.ts CHANGED
@@ -146,6 +146,18 @@ declare global {
146
146
  * frame), so the storefront can say the account needs approval.
147
147
  */
148
148
  registrationMode?: 'open' | 'approval';
149
+ /**
150
+ * How long a storefront online payment holds the order, in whole
151
+ * minutes: the payment attempt's `expiresAt` and its Checkout Pro
152
+ * Preference's `expiration_date_to` are this far from the start.
153
+ * An integer from `PAYMENT_HOLD_MINUTES_MIN` (15) to
154
+ * `PAYMENT_HOLD_MINUTES_MAX` (1440); absent means
155
+ * `PAYMENT_HOLD_MINUTES_DEFAULT` (60), and so does a stored value
156
+ * outside that range. Written by `PATCH /store` (ADMIN) and
157
+ * `PUT /platform/stores/{storeId}` (MANAGER). Never sent to shoppers:
158
+ * they see the attempt's `expiresAt` instead.
159
+ */
160
+ paymentHoldMinutes?: number;
149
161
  showStocks?: boolean;
150
162
  };
151
163
  sidebar?: {
@@ -188,7 +200,7 @@ declare global {
188
200
  * data: { field: 'ecommerce.config.newCustomerPriceList', value: number }; nothing written.
189
201
  */
190
202
  interface EcommercePatchInput {
191
- config?: Pick<NonNullable<Ecommerce['config']>, 'showDefaultPriceList' | 'newCustomerPriceList' | 'registrationMode'> & StorefrontLiveSettingsPatch;
203
+ config?: Pick<NonNullable<Ecommerce['config']>, 'showDefaultPriceList' | 'newCustomerPriceList' | 'registrationMode' | 'paymentHoldMinutes'> & StorefrontLiveSettingsPatch;
192
204
  sidebar?: Ecommerce['sidebar'];
193
205
  home?: Omit<NonNullable<Ecommerce['home']>, 'displayOrders' | 'displayProfile'>;
194
206
  themeColors?: Ecommerce['themeColors'];
@@ -1742,7 +1754,11 @@ declare global {
1742
1754
  * - `'offline'` — offered, paid on delivery or pickup.
1743
1755
  * - `'mp-checkout-pro'` — offered, paid online through a payment attempt
1744
1756
  * (`StartPaymentAttemptRequest`) on the store's connected Mercado Pago
1745
- * account.
1757
+ * account. ⚠️ PESOS ONLY: Checkout Pro here charges ARS, so the storefront
1758
+ * checkout refuses this method on a cart in any other currency
1759
+ * (`409 PAYMENT_METHOD_UNAVAILABLE`, before the order is created), exactly
1760
+ * as it does when no Mercado Pago account is connected. A client should not
1761
+ * offer it on a non-ARS cart.
1746
1762
  */
1747
1763
  type StorefrontMethodKind = (typeof STOREFRONT_METHOD_KINDS)[number];
1748
1764
  interface Method {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "platform-types",
3
- "version": "1.10.760",
3
+ "version": "1.10.762",
4
4
  "description": "Shared wire and entity contracts for the platform.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",