@12-apps/payments-frontend 3.2.0 → 3.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/payments-frontend",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "type": "module",
5
5
  "description": "Browser half of the vendor-agnostic payments platform: plug-and-play MUI components for the per-provider settings page (credential form from each provider's schema, masked hints, verify/enable) and the checkout page (PIX QR + polling, card tokenization, hosted-checkout redirect), plus the headless hooks and fetch clients they build on. Talks only to the host's payments HTTP surface — never to a provider directly. Microfrontend-ready: no app coupling, host injects theme and auth.",
6
6
  "exports": {
@@ -17,7 +17,7 @@
17
17
  "storybook:build": "storybook build"
18
18
  },
19
19
  "dependencies": {
20
- "@12-apps/payments-backend": "^4.3.0",
20
+ "@12-apps/payments-backend": "^4.5.0",
21
21
  "react-qr-code": "^2.2.0"
22
22
  },
23
23
  "peerDependencies": {
@@ -54,6 +54,33 @@ function isReturnTrip(): boolean {
54
54
  return RETURN_MARKERS.some((marker) => params.has(marker));
55
55
  }
56
56
 
57
+ /**
58
+ * Whether a hand-off from THIS tab is still waiting to be resolved.
59
+ *
60
+ * Exported because a host needs it and was otherwise forced to reimplement it.
61
+ * `/menu/checkout` is a URL like any other, so a host may put a gate in front
62
+ * of it — a closed-shop curtain, a plan check — and every such gate has to
63
+ * stand aside for a buyer coming back from a payment, because that route is
64
+ * where the money is confirmed. Deciding that from the outside meant copying
65
+ * this module's marker list and its storage key into the host, which is
66
+ * precisely the drift this package exists to stop: the copy went stale the
67
+ * moment Stripe's 3-D Secure markers were added here.
68
+ *
69
+ * Read WITHOUT consuming. The gate asks on every render; only the flow may
70
+ * take the order.
71
+ */
72
+ export function hostedCheckoutReturnPending(): boolean {
73
+ if (isReturnTrip()) return true;
74
+ try {
75
+ return Boolean(
76
+ window.sessionStorage?.getItem(HOSTED_ORDER_STORAGE_KEY) ??
77
+ window.sessionStorage?.getItem(LEGACY_KEY),
78
+ );
79
+ } catch {
80
+ return false;
81
+ }
82
+ }
83
+
57
84
  /** Park the raised order before handing the buyer to the provider's page. */
58
85
  export function rememberHostedOrder(order: CheckoutOrder): void {
59
86
  try {
@@ -66,12 +93,30 @@ export function rememberHostedOrder(order: CheckoutOrder): void {
66
93
  }
67
94
 
68
95
  /**
69
- * The parked order, but ONLY on a return trip — and cleared as it is read.
96
+ * The parked order, cleared as it is read.
97
+ *
98
+ * This USED to require a marker on the URL, so that a buyer who abandoned the
99
+ * provider's page and reopened checkout got a fresh order rather than resuming
100
+ * one they never paid. That reasoning is inverted for the provider it matters
101
+ * most for, and the inversion is a money bug rather than a UX preference.
102
+ *
103
+ * Pressing the provider's "Continuar" is the ONLY thing that marks the URL.
104
+ * Closing the tab, hitting back, or retyping the store's address are all
105
+ * commoner, and all of them landed the buyer on a live payment step for an
106
+ * order that may already be paid — an invitation to pay twice. It cannot be
107
+ * decided by asking first, either: InfinitePay's `payment_check` refuses to
108
+ * answer without a `transaction_nsu` that only that same redirect carries, so
109
+ * "poll before resuming" reads PAID as PENDING and drops them on the pay
110
+ * button anyway.
111
+ *
112
+ * So a parked order is itself the signal. The cost is that a buyer who truly
113
+ * abandoned sees one confirmation screen reporting what the store actually
114
+ * knows — which is the truth — with the way back on it. The read-and-clear
115
+ * bounds it: the resume happens once per hand-off, and leaving and reopening
116
+ * checkout gives a fresh one.
70
117
  *
71
- * Gated on the URL rather than on mere presence so a buyer who abandons the
72
- * provider's page and later opens checkout again starts a fresh order instead
73
- * of resuming one they never paid. Read-and-clear for the same reason: the
74
- * resumed view belongs to exactly one return.
118
+ * `sessionStorage` already scopes this to one tab's round trip, so nothing
119
+ * here can resurface in a later, unrelated session.
75
120
  */
76
121
  /**
77
122
  * The key before the 2.0.0 rename, READ ONLY — decoded from base64 so no
@@ -128,7 +173,6 @@ function takeParkedPayload(): string | null {
128
173
  }
129
174
 
130
175
  export function takeHostedOrder(): CheckoutOrder | null {
131
- if (!isReturnTrip()) return null;
132
176
  const raw = takeParkedPayload();
133
177
  if (!raw) return null;
134
178
  try {
package/src/index.ts CHANGED
@@ -93,6 +93,17 @@ export { fetchCheckoutConfig } from './components/checkout/client';
93
93
  * literal and silently drifts when it changes.
94
94
  */
95
95
  export { HOSTED_ORDER_STORAGE_KEY } from './components/checkout/hosted-return';
96
+ /**
97
+ * Whether a hand-off from this tab is still waiting to be resolved.
98
+ *
99
+ * For a HOST GATE in front of the checkout route — a closed-shop curtain, a
100
+ * plan check. Every such gate has to stand aside for a buyer coming back from
101
+ * a payment, because that route is where the money gets confirmed, and a host
102
+ * deciding it alone had to copy this package's marker list and storage key.
103
+ * That copy goes stale: it did, the moment Stripe's 3-D Secure markers were
104
+ * added here. Reads without consuming.
105
+ */
106
+ export { hostedCheckoutReturnPending } from './components/checkout/hosted-return';
96
107
  // ---------------------------------------------------------------------------
97
108
  // Digital wallets (FUT-471/472) — the Google-branded button and the capability
98
109
  // read it is gated on. `CheckoutFlow` wires these automatically; they are