@flopay/react 1.1.6 → 1.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/README.md +42 -11
- package/dist/index.cjs +1325 -196
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -11
- package/dist/index.d.ts +75 -11
- package/dist/index.mjs +1336 -197
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -234,6 +234,7 @@ var AddressElement = createElementComponent("address", "AddressElement");
|
|
|
234
234
|
// src/split-card-form.tsx
|
|
235
235
|
import {
|
|
236
236
|
ExpressCheckoutElement,
|
|
237
|
+
PaymentElement as PaymentElement2,
|
|
237
238
|
Elements as StripeElements,
|
|
238
239
|
useElements as useStripeElements,
|
|
239
240
|
useStripe as useStripeRaw
|
|
@@ -246,10 +247,19 @@ import {
|
|
|
246
247
|
COUNTRY_OPTIONS,
|
|
247
248
|
resolveAVSConfig,
|
|
248
249
|
isAVSFieldVisible,
|
|
249
|
-
getStateFromPostalCode
|
|
250
|
+
getStateFromPostalCode,
|
|
251
|
+
filterStripeMethodsByCurrency,
|
|
252
|
+
filterStripeMethodsByCountry,
|
|
253
|
+
filterStripeMethodsByAmount,
|
|
254
|
+
getStripeMethodDisplayName,
|
|
255
|
+
hasVendoredStripeMethodLogo,
|
|
256
|
+
needsStripeMethodExplicitConfirm,
|
|
257
|
+
resolveStripeMethodBrandVariant,
|
|
258
|
+
partitionStripeMethods,
|
|
259
|
+
stripeExpressMethodToOptionKey
|
|
250
260
|
} from "@flopay/shared";
|
|
251
261
|
import { PaymentAPI as PaymentAPI2 } from "@flopay/js";
|
|
252
|
-
import { forwardRef, useCallback, useContext as useContext3, useEffect as useEffect4, useImperativeHandle, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
|
|
262
|
+
import React6, { forwardRef, useCallback, useContext as useContext3, useEffect as useEffect4, useImperativeHandle, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
|
|
253
263
|
|
|
254
264
|
// src/hooks.ts
|
|
255
265
|
import { useContext as useContext2 } from "react";
|
|
@@ -1223,9 +1233,11 @@ ${debugLines.join("\n")}`
|
|
|
1223
1233
|
// src/split-card-form.tsx
|
|
1224
1234
|
import { FloPayError as FloPayError3, resolveTheme } from "@flopay/shared";
|
|
1225
1235
|
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1226
|
-
var
|
|
1236
|
+
var STRIPE_RESUME_KEY = "flopay_stripe_resume";
|
|
1237
|
+
var LEGACY_WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
1227
1238
|
var FLOPAY_KEYFRAMES = `
|
|
1228
1239
|
.paypal-buttons { margin: 0 !important; vertical-align: top !important; }
|
|
1240
|
+
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
1229
1241
|
@keyframes flopay-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
1230
1242
|
@keyframes flopay-fade-in { 0% { opacity: 0; } 100% { opacity: 1; } }
|
|
1231
1243
|
@keyframes flopay-buttons-enter {
|
|
@@ -1246,6 +1258,25 @@ var FLOPAY_KEYFRAMES = `
|
|
|
1246
1258
|
}
|
|
1247
1259
|
`;
|
|
1248
1260
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT = 44;
|
|
1261
|
+
function derivePrimaryTileStyle(opts) {
|
|
1262
|
+
if (!opts.themeBundle) {
|
|
1263
|
+
return {
|
|
1264
|
+
backgroundColor: "white",
|
|
1265
|
+
color: "#262833",
|
|
1266
|
+
border: "1px solid #d1d5db",
|
|
1267
|
+
borderRadius: "8px",
|
|
1268
|
+
boxShadow: "0 1px 2px rgba(0,0,0,0.04)"
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1271
|
+
const submit = opts.submitButtonStyle ?? {};
|
|
1272
|
+
return {
|
|
1273
|
+
backgroundColor: submit.backgroundColor ?? opts.resolvedPrimaryColor,
|
|
1274
|
+
color: submit.color ?? "white",
|
|
1275
|
+
border: submit.border ?? "none",
|
|
1276
|
+
borderRadius: submit.borderRadius ?? opts.resolvedBorderRadius,
|
|
1277
|
+
boxShadow: submit.boxShadow
|
|
1278
|
+
};
|
|
1279
|
+
}
|
|
1249
1280
|
var BUTTONS_PANEL_HIDDEN_STYLE = {
|
|
1250
1281
|
visibility: "hidden",
|
|
1251
1282
|
position: "absolute",
|
|
@@ -1291,6 +1322,7 @@ function resolveExpressCheckoutLoadState(event, methods) {
|
|
|
1291
1322
|
function ExpressCheckoutReadySwap({
|
|
1292
1323
|
state,
|
|
1293
1324
|
placeholderTestId,
|
|
1325
|
+
borderRadius = 8,
|
|
1294
1326
|
children
|
|
1295
1327
|
}) {
|
|
1296
1328
|
if (state === "unavailable" || state === "load_error") return null;
|
|
@@ -1304,7 +1336,7 @@ function ExpressCheckoutReadySwap({
|
|
|
1304
1336
|
position: "absolute",
|
|
1305
1337
|
inset: 0,
|
|
1306
1338
|
height: 44,
|
|
1307
|
-
borderRadius
|
|
1339
|
+
borderRadius,
|
|
1308
1340
|
background: "#e5e7eb",
|
|
1309
1341
|
animation: state === "ready" ? void 0 : "flopay-pulse 1.5s ease-in-out infinite",
|
|
1310
1342
|
opacity: state === "ready" ? 0 : 1,
|
|
@@ -1347,7 +1379,8 @@ function PayPalButtonInner({
|
|
|
1347
1379
|
onButtonClick,
|
|
1348
1380
|
onDecline,
|
|
1349
1381
|
runBeforeButtonClick,
|
|
1350
|
-
onLoadStateChange
|
|
1382
|
+
onLoadStateChange,
|
|
1383
|
+
placeholderBorderRadius
|
|
1351
1384
|
}) {
|
|
1352
1385
|
const stripe = useStripeRaw();
|
|
1353
1386
|
const elements = useStripeElements();
|
|
@@ -1517,31 +1550,39 @@ function PayPalButtonInner({
|
|
|
1517
1550
|
}
|
|
1518
1551
|
}, [stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]);
|
|
1519
1552
|
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1520
|
-
/* @__PURE__ */ jsx6(
|
|
1521
|
-
|
|
1553
|
+
/* @__PURE__ */ jsx6(
|
|
1554
|
+
ExpressCheckoutReadySwap,
|
|
1522
1555
|
{
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1556
|
+
state: loadState,
|
|
1557
|
+
placeholderTestId: "flopay-paypal-placeholder",
|
|
1558
|
+
borderRadius: placeholderBorderRadius,
|
|
1559
|
+
children: /* @__PURE__ */ jsx6(
|
|
1560
|
+
ExpressCheckoutElement,
|
|
1561
|
+
{
|
|
1562
|
+
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
|
|
1563
|
+
onLoadError: () => setLoadState("load_error"),
|
|
1564
|
+
onClick: handlePayPalClick,
|
|
1565
|
+
onConfirm: handlePayPalConfirm,
|
|
1566
|
+
onCancel: () => {
|
|
1567
|
+
beforeClickRef.current = null;
|
|
1568
|
+
onDecline?.(buildDeclineEvent("paypal", "PayPal checkout was cancelled."));
|
|
1569
|
+
},
|
|
1570
|
+
options: {
|
|
1571
|
+
buttonType: { paypal: "paypal" },
|
|
1572
|
+
billingAddressRequired: false,
|
|
1573
|
+
phoneNumberRequired: false,
|
|
1574
|
+
shippingAddressRequired: false,
|
|
1575
|
+
paymentMethods: {
|
|
1576
|
+
applePay: "never",
|
|
1577
|
+
googlePay: "never",
|
|
1578
|
+
paypal: "auto",
|
|
1579
|
+
link: "never"
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1541
1582
|
}
|
|
1542
|
-
|
|
1583
|
+
)
|
|
1543
1584
|
}
|
|
1544
|
-
)
|
|
1585
|
+
),
|
|
1545
1586
|
submitting && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: "processing" })
|
|
1546
1587
|
] });
|
|
1547
1588
|
}
|
|
@@ -1549,14 +1590,14 @@ function WalletButtonInner({
|
|
|
1549
1590
|
sessionId,
|
|
1550
1591
|
email,
|
|
1551
1592
|
billingApiUrl,
|
|
1552
|
-
|
|
1553
|
-
showGooglePay = true,
|
|
1593
|
+
expressMethods,
|
|
1554
1594
|
onTokenizedBody,
|
|
1555
1595
|
onErrorChange,
|
|
1556
1596
|
onButtonClick,
|
|
1557
1597
|
onDecline,
|
|
1558
1598
|
runBeforeButtonClick,
|
|
1559
|
-
onLoadStateChange
|
|
1599
|
+
onLoadStateChange,
|
|
1600
|
+
placeholderBorderRadius
|
|
1560
1601
|
}) {
|
|
1561
1602
|
const stripe = useStripeRaw();
|
|
1562
1603
|
const elements = useStripeElements();
|
|
@@ -1574,10 +1615,9 @@ function WalletButtonInner({
|
|
|
1574
1615
|
const walletType = event.expressPaymentType;
|
|
1575
1616
|
let prepared = beforeClickRef.current;
|
|
1576
1617
|
beforeClickRef.current = null;
|
|
1618
|
+
const buttonMethod = walletType === "apple_pay" ? "apple_pay" : "google_pay";
|
|
1577
1619
|
if (!prepared && runBeforeButtonClick) {
|
|
1578
|
-
const beforeClick = await runBeforeButtonClick(
|
|
1579
|
-
walletType === "apple_pay" ? "apple_pay" : "google_pay"
|
|
1580
|
-
);
|
|
1620
|
+
const beforeClick = await runBeforeButtonClick(buttonMethod);
|
|
1581
1621
|
if (!beforeClick.proceed) {
|
|
1582
1622
|
event.paymentFailed({ reason: "fail", message: "Wallet checkout was cancelled." });
|
|
1583
1623
|
return;
|
|
@@ -1587,7 +1627,7 @@ function WalletButtonInner({
|
|
|
1587
1627
|
sessionId: beforeClick.sessionId
|
|
1588
1628
|
};
|
|
1589
1629
|
}
|
|
1590
|
-
const method =
|
|
1630
|
+
const method = buttonMethod;
|
|
1591
1631
|
const effectiveSessionId = prepared?.sessionId ?? sessionId;
|
|
1592
1632
|
const effectiveEmail = prepared?.accountPatch?.email ?? email;
|
|
1593
1633
|
try {
|
|
@@ -1657,53 +1697,655 @@ function WalletButtonInner({
|
|
|
1657
1697
|
},
|
|
1658
1698
|
[stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]
|
|
1659
1699
|
);
|
|
1700
|
+
const expressMethodMap = useMemo3(() => {
|
|
1701
|
+
const allKeys = ["applePay", "googlePay", "paypal", "link", "amazonPay", "klarna"];
|
|
1702
|
+
const alwaysCapable = /* @__PURE__ */ new Set(["applePay", "googlePay"]);
|
|
1703
|
+
const enabledKeys = new Set(expressMethods.map(stripeExpressMethodToOptionKey));
|
|
1704
|
+
const out = {};
|
|
1705
|
+
for (const key of allKeys) {
|
|
1706
|
+
if (!enabledKeys.has(key)) {
|
|
1707
|
+
out[key] = "never";
|
|
1708
|
+
} else {
|
|
1709
|
+
out[key] = alwaysCapable.has(key) ? "always" : "auto";
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
return out;
|
|
1713
|
+
}, [expressMethods]);
|
|
1714
|
+
const availableMethodKeys = useMemo3(
|
|
1715
|
+
() => expressMethods.map(stripeExpressMethodToOptionKey),
|
|
1716
|
+
[expressMethods]
|
|
1717
|
+
);
|
|
1660
1718
|
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1661
|
-
/* @__PURE__ */ jsx6(
|
|
1662
|
-
|
|
1719
|
+
/* @__PURE__ */ jsx6(
|
|
1720
|
+
ExpressCheckoutReadySwap,
|
|
1663
1721
|
{
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1722
|
+
state: loadState,
|
|
1723
|
+
placeholderTestId: "flopay-wallet-placeholder",
|
|
1724
|
+
borderRadius: placeholderBorderRadius,
|
|
1725
|
+
children: /* @__PURE__ */ jsx6(
|
|
1726
|
+
ExpressCheckoutElement,
|
|
1727
|
+
{
|
|
1728
|
+
onReady: (event) => {
|
|
1729
|
+
setLoadState(resolveExpressCheckoutLoadState(event, availableMethodKeys));
|
|
1730
|
+
},
|
|
1731
|
+
onLoadError: (_event) => {
|
|
1732
|
+
setLoadState("load_error");
|
|
1733
|
+
},
|
|
1734
|
+
onClick: async (event) => {
|
|
1735
|
+
lastWalletMethodRef.current = event.expressPaymentType === "apple_pay" ? "apple_pay" : "google_pay";
|
|
1736
|
+
const beforeClick = runBeforeButtonClick ? await runBeforeButtonClick(lastWalletMethodRef.current) : { proceed: true };
|
|
1737
|
+
if (!beforeClick.proceed) {
|
|
1738
|
+
beforeClickRef.current = null;
|
|
1739
|
+
event.reject();
|
|
1740
|
+
return;
|
|
1741
|
+
}
|
|
1742
|
+
beforeClickRef.current = {
|
|
1743
|
+
accountPatch: beforeClick.accountPatch,
|
|
1744
|
+
sessionId: beforeClick.sessionId
|
|
1745
|
+
};
|
|
1746
|
+
onButtonClick?.(lastWalletMethodRef.current);
|
|
1747
|
+
event.resolve();
|
|
1748
|
+
},
|
|
1749
|
+
onConfirm: handleWalletConfirm,
|
|
1750
|
+
onCancel: () => {
|
|
1751
|
+
beforeClickRef.current = null;
|
|
1752
|
+
onDecline?.(buildDeclineEvent(lastWalletMethodRef.current, "Wallet checkout was cancelled."));
|
|
1753
|
+
},
|
|
1754
|
+
options: {
|
|
1755
|
+
buttonType: { applePay: "plain", googlePay: "plain" },
|
|
1756
|
+
paymentMethods: expressMethodMap,
|
|
1757
|
+
layout: { maxColumns: 1, overflow: "never" }
|
|
1758
|
+
}
|
|
1677
1759
|
}
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1760
|
+
)
|
|
1761
|
+
}
|
|
1762
|
+
),
|
|
1763
|
+
submitting && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: "processing" })
|
|
1764
|
+
] });
|
|
1765
|
+
}
|
|
1766
|
+
function StripeMethodButton({
|
|
1767
|
+
method,
|
|
1768
|
+
themeId,
|
|
1769
|
+
submitting = false,
|
|
1770
|
+
disabled = false,
|
|
1771
|
+
highlighted = false,
|
|
1772
|
+
hasNextStep = false,
|
|
1773
|
+
onClick,
|
|
1774
|
+
backgroundColor,
|
|
1775
|
+
borderColor,
|
|
1776
|
+
textColor,
|
|
1777
|
+
borderRadius,
|
|
1778
|
+
fontFamily
|
|
1779
|
+
}) {
|
|
1780
|
+
const brand = resolveStripeMethodBrandVariant(method, themeId);
|
|
1781
|
+
const resolvedBackground = brand?.backgroundColor ?? backgroundColor ?? "#ffffff";
|
|
1782
|
+
const resolvedBorder = brand?.borderColor ?? borderColor ?? "#d1d5db";
|
|
1783
|
+
const resolvedTextColor = brand?.textColor ?? textColor ?? "#262833";
|
|
1784
|
+
return /* @__PURE__ */ jsx6(
|
|
1785
|
+
"button",
|
|
1786
|
+
{
|
|
1787
|
+
type: "button",
|
|
1788
|
+
"data-testid": `flopay-stripe-method-button-${method}`,
|
|
1789
|
+
"data-method": method,
|
|
1790
|
+
onClick: () => {
|
|
1791
|
+
if (!submitting && !disabled) onClick();
|
|
1792
|
+
},
|
|
1793
|
+
disabled: submitting || disabled,
|
|
1794
|
+
"aria-busy": submitting || void 0,
|
|
1795
|
+
style: {
|
|
1796
|
+
position: "relative",
|
|
1797
|
+
width: "100%",
|
|
1798
|
+
boxSizing: "border-box",
|
|
1799
|
+
height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT,
|
|
1800
|
+
padding: "0 1rem",
|
|
1801
|
+
backgroundColor: resolvedBackground,
|
|
1802
|
+
color: resolvedTextColor,
|
|
1803
|
+
border: `1px solid ${resolvedBorder}`,
|
|
1804
|
+
borderRadius: borderRadius ?? 8,
|
|
1805
|
+
fontSize: "0.95rem",
|
|
1806
|
+
fontWeight: 600,
|
|
1807
|
+
fontFamily,
|
|
1808
|
+
cursor: submitting || disabled ? "not-allowed" : "pointer",
|
|
1809
|
+
opacity: disabled && !submitting ? 0.55 : 1,
|
|
1810
|
+
// Submitting state pulses the whole button background, mirroring
|
|
1811
|
+
// the wallet ECE's `flopay-pulse` skeleton. This keeps the loading
|
|
1812
|
+
// affordance consistent between embedded wallets (Apple Pay,
|
|
1813
|
+
// Google Pay) and these custom APM tile buttons — same animation
|
|
1814
|
+
// curve, same duration, only the surface colour changes (grey for
|
|
1815
|
+
// the wallet skeleton vs. brand colour for an in-flight tile).
|
|
1816
|
+
animation: submitting ? "flopay-pulse 1.5s ease-in-out infinite" : void 0,
|
|
1817
|
+
display: "flex",
|
|
1818
|
+
alignItems: "center",
|
|
1819
|
+
// Always center the logo+name group. The drill-in chevron (input
|
|
1820
|
+
// methods) is absolutely positioned at the right edge below so it
|
|
1821
|
+
// doesn't pull the label off-center.
|
|
1822
|
+
justifyContent: "center",
|
|
1823
|
+
gap: 8,
|
|
1824
|
+
transition: "transform 0.1s, opacity 140ms ease-out, border-color 140ms ease-out",
|
|
1825
|
+
boxShadow: highlighted ? "0 0 0 2px rgba(74, 73, 255, 0.15)" : void 0
|
|
1826
|
+
},
|
|
1827
|
+
children: submitting ? (
|
|
1828
|
+
// Pulse-skeleton parity with the wallet ECE: no spinner, just the
|
|
1829
|
+
// status text on top of the pulsing background. Keeps the loading
|
|
1830
|
+
// affordance shape-equivalent across both kinds of tile.
|
|
1831
|
+
/* @__PURE__ */ jsx6("span", { style: { margin: "0 auto" }, children: `Connecting to ${getStripeMethodDisplayName(method)}\u2026` })
|
|
1832
|
+
) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1833
|
+
/* @__PURE__ */ jsxs4(
|
|
1834
|
+
"span",
|
|
1835
|
+
{
|
|
1836
|
+
style: {
|
|
1837
|
+
display: "inline-flex",
|
|
1838
|
+
alignItems: "center",
|
|
1839
|
+
// Real vendored logos are self-contained brand cards, so they
|
|
1840
|
+
// get an 8px gap from the label. The generated placeholder
|
|
1841
|
+
// monogram reads as part of the label (the tile's first letter),
|
|
1842
|
+
// so it sits flush (0px) against the name.
|
|
1843
|
+
gap: hasVendoredStripeMethodLogo(method) ? 8 : 0
|
|
1844
|
+
},
|
|
1845
|
+
children: [
|
|
1846
|
+
brand?.logoSvg && /* @__PURE__ */ jsx6(
|
|
1847
|
+
"span",
|
|
1848
|
+
{
|
|
1849
|
+
"aria-hidden": "true",
|
|
1850
|
+
style: {
|
|
1851
|
+
// 3:2 box matching the vendored datatrans logos' 120×80
|
|
1852
|
+
// viewBox. Each logo ships with its own white rounded-rect
|
|
1853
|
+
// background baked in, so the mark stays legible on any
|
|
1854
|
+
// brand-coloured tile without an extra chip wrapper here.
|
|
1855
|
+
width: 30,
|
|
1856
|
+
height: 20,
|
|
1857
|
+
flexShrink: 0,
|
|
1858
|
+
display: "inline-flex",
|
|
1859
|
+
borderRadius: 3,
|
|
1860
|
+
overflow: "hidden"
|
|
1861
|
+
},
|
|
1862
|
+
dangerouslySetInnerHTML: { __html: brand.logoSvg }
|
|
1863
|
+
}
|
|
1864
|
+
),
|
|
1865
|
+
/* @__PURE__ */ jsx6("span", { children: getStripeMethodDisplayName(method) })
|
|
1866
|
+
]
|
|
1867
|
+
}
|
|
1868
|
+
),
|
|
1869
|
+
hasNextStep && /* @__PURE__ */ jsx6(
|
|
1870
|
+
"svg",
|
|
1871
|
+
{
|
|
1872
|
+
width: "14",
|
|
1873
|
+
height: "14",
|
|
1874
|
+
viewBox: "0 0 24 24",
|
|
1875
|
+
fill: "none",
|
|
1876
|
+
stroke: resolvedTextColor,
|
|
1877
|
+
strokeWidth: "2.5",
|
|
1878
|
+
strokeLinecap: "round",
|
|
1879
|
+
strokeLinejoin: "round",
|
|
1880
|
+
style: {
|
|
1881
|
+
position: "absolute",
|
|
1882
|
+
right: "1rem",
|
|
1883
|
+
top: "50%",
|
|
1884
|
+
transform: "translateY(-50%)",
|
|
1885
|
+
flexShrink: 0,
|
|
1886
|
+
opacity: 0.7
|
|
1887
|
+
},
|
|
1888
|
+
"aria-hidden": "true",
|
|
1889
|
+
children: /* @__PURE__ */ jsx6("path", { d: "M9 18l6-6-6-6" })
|
|
1890
|
+
}
|
|
1891
|
+
)
|
|
1892
|
+
] })
|
|
1893
|
+
}
|
|
1894
|
+
);
|
|
1895
|
+
}
|
|
1896
|
+
function StripeMethodInlineForm({
|
|
1897
|
+
method,
|
|
1898
|
+
sessionId,
|
|
1899
|
+
email,
|
|
1900
|
+
billingName,
|
|
1901
|
+
billingApiUrl,
|
|
1902
|
+
onTokenizedBody,
|
|
1903
|
+
onErrorChange,
|
|
1904
|
+
onDecline,
|
|
1905
|
+
onCancel,
|
|
1906
|
+
runBeforeButtonClick,
|
|
1907
|
+
onButtonClick,
|
|
1908
|
+
isProcessing,
|
|
1909
|
+
submitButtonColor,
|
|
1910
|
+
submitButtonBorderRadius,
|
|
1911
|
+
submitButtonStyle
|
|
1912
|
+
}) {
|
|
1913
|
+
const stripe = useStripeRaw();
|
|
1914
|
+
const elements = useStripeElements();
|
|
1915
|
+
const [submitting, setSubmitting] = useState3(false);
|
|
1916
|
+
const submittingRef = useRef3(false);
|
|
1917
|
+
const [isMethodComplete, setIsMethodComplete] = useState3(false);
|
|
1918
|
+
const [loadState, setLoadState] = useState3("loading");
|
|
1919
|
+
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
1920
|
+
const handlePay = useCallback(async () => {
|
|
1921
|
+
if (!stripe || !elements || isProcessing || submittingRef.current || !isMethodComplete) return;
|
|
1922
|
+
submittingRef.current = true;
|
|
1923
|
+
setSubmitting(true);
|
|
1924
|
+
const beforeClick = runBeforeButtonClick ? await runBeforeButtonClick("card") : { proceed: true };
|
|
1925
|
+
if (!beforeClick.proceed) {
|
|
1926
|
+
submittingRef.current = false;
|
|
1927
|
+
setSubmitting(false);
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
1930
|
+
onButtonClick?.("card");
|
|
1931
|
+
const effectiveSessionId = beforeClick.sessionId ?? sessionId;
|
|
1932
|
+
const effectiveEmail = beforeClick.accountPatch?.email ?? email;
|
|
1933
|
+
try {
|
|
1934
|
+
onErrorChange?.(null);
|
|
1935
|
+
const submitRes = await elements.submit();
|
|
1936
|
+
if (submitRes.error) {
|
|
1937
|
+
onErrorChange?.(submitRes.error.message ?? "Payment failed.");
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
const pmRes = await stripe.createPaymentMethod({ elements });
|
|
1941
|
+
if (pmRes.error || !pmRes.paymentMethod) {
|
|
1942
|
+
onErrorChange?.(pmRes.error?.message ?? "Failed to create payment method.");
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
const paymentMethod = pmRes.paymentMethod;
|
|
1946
|
+
if (!effectiveSessionId || !effectiveEmail) {
|
|
1947
|
+
throw new Error("Missing sessionId or email for payment.");
|
|
1948
|
+
}
|
|
1949
|
+
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
1950
|
+
method: "POST",
|
|
1951
|
+
headers: { "Content-Type": "application/json" },
|
|
1952
|
+
body: JSON.stringify({
|
|
1953
|
+
sessionId: effectiveSessionId,
|
|
1954
|
+
email: effectiveEmail,
|
|
1955
|
+
paymentMethodType: paymentMethod.type || method,
|
|
1956
|
+
isPaypal: false
|
|
1957
|
+
})
|
|
1958
|
+
});
|
|
1959
|
+
if (!intentResponse.ok) {
|
|
1960
|
+
const intentError = await buildFloPayApiErrorFromResponse(intentResponse, "Failed to create payment intent");
|
|
1961
|
+
onErrorChange?.(intentError.message);
|
|
1962
|
+
onDecline?.(buildDeclineEvent("card", intentError));
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1965
|
+
const intentJson = await intentResponse.json();
|
|
1966
|
+
const intentClientSecret = intentJson.data?.id;
|
|
1967
|
+
if (!intentClientSecret) throw new Error("No client_secret in payment intent response");
|
|
1968
|
+
if (typeof window !== "undefined") {
|
|
1969
|
+
try {
|
|
1970
|
+
localStorage.setItem(STRIPE_RESUME_KEY, JSON.stringify({
|
|
1971
|
+
sessionId: effectiveSessionId,
|
|
1972
|
+
paymentMethodId: paymentMethod.id,
|
|
1973
|
+
paymentMethodType: paymentMethod.type ?? method,
|
|
1974
|
+
gateway: "stripe"
|
|
1975
|
+
}));
|
|
1976
|
+
} catch {
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
const { error: confirmError, paymentIntent } = await stripe.confirmPayment({
|
|
1980
|
+
clientSecret: intentClientSecret,
|
|
1981
|
+
confirmParams: {
|
|
1982
|
+
return_url: window.location.href,
|
|
1983
|
+
payment_method: paymentMethod.id
|
|
1684
1984
|
},
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1985
|
+
redirect: "if_required"
|
|
1986
|
+
});
|
|
1987
|
+
if (confirmError) {
|
|
1988
|
+
if (typeof window !== "undefined") {
|
|
1989
|
+
try {
|
|
1990
|
+
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
1991
|
+
} catch {
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
const message = confirmError.message ?? "Payment failed.";
|
|
1995
|
+
onErrorChange?.(message);
|
|
1996
|
+
onDecline?.(buildDeclineEvent("card", message, { code: confirmError.code }));
|
|
1997
|
+
return;
|
|
1998
|
+
}
|
|
1999
|
+
const SUCCESSFUL_PI_STATUSES = /* @__PURE__ */ new Set(["succeeded", "requires_capture", "processing"]);
|
|
2000
|
+
const piStatus = paymentIntent?.status;
|
|
2001
|
+
if (!piStatus || !SUCCESSFUL_PI_STATUSES.has(piStatus)) {
|
|
2002
|
+
if (typeof window !== "undefined") {
|
|
2003
|
+
try {
|
|
2004
|
+
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
2005
|
+
} catch {
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
const message = piStatus === "canceled" ? "Payment was canceled." : "Payment was not completed. Please try again.";
|
|
2009
|
+
onErrorChange?.(message);
|
|
2010
|
+
onDecline?.(buildDeclineEvent("card", message, { code: piStatus ?? "missing_payment_intent" }));
|
|
2011
|
+
return;
|
|
2012
|
+
}
|
|
2013
|
+
if (typeof window !== "undefined") {
|
|
2014
|
+
try {
|
|
2015
|
+
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
2016
|
+
} catch {
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
const confirmedPmId = typeof paymentIntent?.payment_method === "string" ? paymentIntent.payment_method : paymentIntent?.payment_method?.id;
|
|
2020
|
+
onTokenizedBody({
|
|
2021
|
+
id: confirmedPmId ?? paymentMethod.id,
|
|
2022
|
+
type: "card",
|
|
2023
|
+
threeDSecureActionResultTokenId: paymentIntent?.id,
|
|
2024
|
+
gateway: "stripe",
|
|
2025
|
+
paymentMethodType: paymentMethod.type ?? method
|
|
2026
|
+
}, {
|
|
2027
|
+
accountPatch: beforeClick.accountPatch,
|
|
2028
|
+
sessionId: effectiveSessionId
|
|
2029
|
+
});
|
|
2030
|
+
} catch (err) {
|
|
2031
|
+
onErrorChange?.(err instanceof Error ? err.message : "Payment failed. Please try again.");
|
|
2032
|
+
} finally {
|
|
2033
|
+
submittingRef.current = false;
|
|
2034
|
+
setSubmitting(false);
|
|
2035
|
+
}
|
|
2036
|
+
}, [
|
|
2037
|
+
stripe,
|
|
2038
|
+
elements,
|
|
2039
|
+
isProcessing,
|
|
2040
|
+
isMethodComplete,
|
|
2041
|
+
runBeforeButtonClick,
|
|
2042
|
+
onButtonClick,
|
|
2043
|
+
sessionId,
|
|
2044
|
+
email,
|
|
2045
|
+
baseUrl,
|
|
2046
|
+
method,
|
|
2047
|
+
onTokenizedBody,
|
|
2048
|
+
onErrorChange,
|
|
2049
|
+
onDecline
|
|
2050
|
+
]);
|
|
2051
|
+
void onCancel;
|
|
2052
|
+
return /* @__PURE__ */ jsxs4("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
|
|
2053
|
+
/* @__PURE__ */ jsx6(
|
|
2054
|
+
PaymentElement2,
|
|
2055
|
+
{
|
|
2056
|
+
onReady: () => setLoadState("ready"),
|
|
2057
|
+
onLoadError: () => setLoadState("load_error"),
|
|
2058
|
+
onChange: (event) => {
|
|
2059
|
+
const evRecord = event;
|
|
2060
|
+
setIsMethodComplete(!!evRecord.complete);
|
|
1689
2061
|
},
|
|
1690
2062
|
options: {
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
klarna: "never"
|
|
1699
|
-
},
|
|
1700
|
-
layout: { maxColumns: 1, overflow: "never" }
|
|
2063
|
+
layout: { type: "accordion", defaultCollapsed: false, radios: "never" },
|
|
2064
|
+
defaultValues: {
|
|
2065
|
+
billingDetails: {
|
|
2066
|
+
name: billingName && billingName.trim().length >= 3 ? billingName.trim() : "FloPay Customer",
|
|
2067
|
+
...email ? { email } : {}
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
1701
2070
|
}
|
|
1702
2071
|
}
|
|
1703
|
-
)
|
|
1704
|
-
|
|
2072
|
+
),
|
|
2073
|
+
/* @__PURE__ */ jsx6(
|
|
2074
|
+
"button",
|
|
2075
|
+
{
|
|
2076
|
+
type: "button",
|
|
2077
|
+
"data-testid": `flopay-stripe-method-pay-${method}`,
|
|
2078
|
+
onClick: () => {
|
|
2079
|
+
void handlePay();
|
|
2080
|
+
},
|
|
2081
|
+
disabled: !isMethodComplete || submitting || isProcessing || loadState !== "ready",
|
|
2082
|
+
style: {
|
|
2083
|
+
width: "100%",
|
|
2084
|
+
marginTop: "0.75rem",
|
|
2085
|
+
padding: "0.875rem",
|
|
2086
|
+
backgroundColor: submitButtonColor,
|
|
2087
|
+
color: "white",
|
|
2088
|
+
border: "none",
|
|
2089
|
+
borderRadius: submitButtonBorderRadius,
|
|
2090
|
+
fontSize: "1rem",
|
|
2091
|
+
fontWeight: 600,
|
|
2092
|
+
cursor: !isMethodComplete || submitting || isProcessing || loadState !== "ready" ? "not-allowed" : "pointer",
|
|
2093
|
+
opacity: !isMethodComplete || submitting || isProcessing || loadState !== "ready" ? 0.5 : 1,
|
|
2094
|
+
transition: "opacity 120ms ease-out",
|
|
2095
|
+
...submitButtonStyle ?? {}
|
|
2096
|
+
},
|
|
2097
|
+
children: submitting ? "Processing\u2026" : `Pay with ${getStripeMethodDisplayName(method)}`
|
|
2098
|
+
}
|
|
2099
|
+
)
|
|
1705
2100
|
] });
|
|
1706
2101
|
}
|
|
2102
|
+
function StripePaymentElementInner({
|
|
2103
|
+
sessionId,
|
|
2104
|
+
email,
|
|
2105
|
+
billingName,
|
|
2106
|
+
billingApiUrl,
|
|
2107
|
+
paymentElementMethods,
|
|
2108
|
+
stripeInstance,
|
|
2109
|
+
paymentElementBaseOptions,
|
|
2110
|
+
onTokenizedBody,
|
|
2111
|
+
onErrorChange,
|
|
2112
|
+
onButtonClick,
|
|
2113
|
+
onDecline,
|
|
2114
|
+
runBeforeButtonClick,
|
|
2115
|
+
onLoadStateChange,
|
|
2116
|
+
isProcessing = false,
|
|
2117
|
+
submitButtonColor = "#4A49FF",
|
|
2118
|
+
submitButtonBorderRadius = 8,
|
|
2119
|
+
submitButtonStyle,
|
|
2120
|
+
buttonAppearance,
|
|
2121
|
+
themeId,
|
|
2122
|
+
onExpandApm,
|
|
2123
|
+
expandedApmMethod
|
|
2124
|
+
}) {
|
|
2125
|
+
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2126
|
+
const [expandedMethod, setExpandedMethod] = useState3(null);
|
|
2127
|
+
const [submittingMethod, setSubmittingMethod] = useState3(null);
|
|
2128
|
+
const submittingRef = useRef3(false);
|
|
2129
|
+
useEffect4(() => {
|
|
2130
|
+
if (paymentElementMethods.length > 0 && stripeInstance) {
|
|
2131
|
+
onLoadStateChange?.("ready");
|
|
2132
|
+
} else if (!stripeInstance) {
|
|
2133
|
+
onLoadStateChange?.("loading");
|
|
2134
|
+
}
|
|
2135
|
+
}, [paymentElementMethods.length, stripeInstance, onLoadStateChange]);
|
|
2136
|
+
const handleAutoConfirm = useCallback(async (method) => {
|
|
2137
|
+
if (!stripeInstance) return;
|
|
2138
|
+
if (submittingRef.current || isProcessing) return;
|
|
2139
|
+
submittingRef.current = true;
|
|
2140
|
+
setSubmittingMethod(method);
|
|
2141
|
+
const beforeClick = runBeforeButtonClick ? await runBeforeButtonClick("card") : { proceed: true };
|
|
2142
|
+
if (!beforeClick.proceed) {
|
|
2143
|
+
submittingRef.current = false;
|
|
2144
|
+
setSubmittingMethod(null);
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
onButtonClick?.("card");
|
|
2148
|
+
const effectiveSessionId = beforeClick.sessionId ?? sessionId;
|
|
2149
|
+
const effectiveEmail = beforeClick.accountPatch?.email ?? email;
|
|
2150
|
+
try {
|
|
2151
|
+
onErrorChange?.(null);
|
|
2152
|
+
if (!effectiveSessionId || !effectiveEmail) {
|
|
2153
|
+
throw new Error("Missing sessionId or email for payment.");
|
|
2154
|
+
}
|
|
2155
|
+
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
2156
|
+
method: "POST",
|
|
2157
|
+
headers: { "Content-Type": "application/json" },
|
|
2158
|
+
body: JSON.stringify({
|
|
2159
|
+
sessionId: effectiveSessionId,
|
|
2160
|
+
email: effectiveEmail,
|
|
2161
|
+
// Wire type, not pm_xxx — backend scopes `payment_method_types`
|
|
2162
|
+
// to this single method so unrelated account-wide methods
|
|
2163
|
+
// (apple_pay without domain verification, …) don't poison PI
|
|
2164
|
+
// creation.
|
|
2165
|
+
paymentMethodType: method,
|
|
2166
|
+
isPaypal: false
|
|
2167
|
+
})
|
|
2168
|
+
});
|
|
2169
|
+
if (!intentResponse.ok) {
|
|
2170
|
+
const intentError = await buildFloPayApiErrorFromResponse(intentResponse, "Failed to create payment intent");
|
|
2171
|
+
onErrorChange?.(intentError.message);
|
|
2172
|
+
onDecline?.(buildDeclineEvent("card", intentError));
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
const intentJson = await intentResponse.json();
|
|
2176
|
+
const intentClientSecret = intentJson.data?.id;
|
|
2177
|
+
if (!intentClientSecret) throw new Error("No client_secret in payment intent response");
|
|
2178
|
+
if (typeof window !== "undefined") {
|
|
2179
|
+
try {
|
|
2180
|
+
localStorage.setItem(STRIPE_RESUME_KEY, JSON.stringify({
|
|
2181
|
+
sessionId: effectiveSessionId,
|
|
2182
|
+
paymentMethodType: method,
|
|
2183
|
+
gateway: "stripe"
|
|
2184
|
+
}));
|
|
2185
|
+
} catch {
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
const { error: confirmError, paymentIntent } = await stripeInstance.confirmPayment({
|
|
2189
|
+
clientSecret: intentClientSecret,
|
|
2190
|
+
confirmParams: {
|
|
2191
|
+
return_url: window.location.href,
|
|
2192
|
+
// Inline the method data — no Elements / PaymentElement
|
|
2193
|
+
// required. Stripe creates the PaymentMethod during confirm
|
|
2194
|
+
// and proceeds to its popup/redirect UI.
|
|
2195
|
+
payment_method_data: {
|
|
2196
|
+
type: method,
|
|
2197
|
+
billing_details: {
|
|
2198
|
+
name: billingName && billingName.trim().length >= 3 ? billingName.trim() : "FloPay Customer",
|
|
2199
|
+
...effectiveEmail ? { email: effectiveEmail } : {}
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
},
|
|
2203
|
+
redirect: "if_required"
|
|
2204
|
+
});
|
|
2205
|
+
if (confirmError) {
|
|
2206
|
+
if (typeof window !== "undefined") {
|
|
2207
|
+
try {
|
|
2208
|
+
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
2209
|
+
} catch {
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
const message = confirmError.message ?? "Payment failed.";
|
|
2213
|
+
onErrorChange?.(message);
|
|
2214
|
+
onDecline?.(buildDeclineEvent("card", message, { code: confirmError.code }));
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
const SUCCESSFUL_PI_STATUSES = /* @__PURE__ */ new Set(["succeeded", "requires_capture", "processing"]);
|
|
2218
|
+
const piStatus = paymentIntent?.status;
|
|
2219
|
+
if (!piStatus || !SUCCESSFUL_PI_STATUSES.has(piStatus)) {
|
|
2220
|
+
if (typeof window !== "undefined") {
|
|
2221
|
+
try {
|
|
2222
|
+
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
2223
|
+
} catch {
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
const message = piStatus === "canceled" ? "Payment was canceled." : "Payment was not completed. Please try again.";
|
|
2227
|
+
onErrorChange?.(message);
|
|
2228
|
+
onDecline?.(buildDeclineEvent("card", message, { code: piStatus ?? "missing_payment_intent" }));
|
|
2229
|
+
return;
|
|
2230
|
+
}
|
|
2231
|
+
if (typeof window !== "undefined") {
|
|
2232
|
+
try {
|
|
2233
|
+
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
2234
|
+
} catch {
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
const confirmedPmId = typeof paymentIntent?.payment_method === "string" ? paymentIntent.payment_method : paymentIntent?.payment_method?.id;
|
|
2238
|
+
onTokenizedBody({
|
|
2239
|
+
id: confirmedPmId ?? paymentIntent?.id,
|
|
2240
|
+
type: "card",
|
|
2241
|
+
threeDSecureActionResultTokenId: paymentIntent?.id,
|
|
2242
|
+
gateway: "stripe",
|
|
2243
|
+
paymentMethodType: method
|
|
2244
|
+
}, {
|
|
2245
|
+
accountPatch: beforeClick.accountPatch,
|
|
2246
|
+
sessionId: effectiveSessionId
|
|
2247
|
+
});
|
|
2248
|
+
} catch (err) {
|
|
2249
|
+
onErrorChange?.(err instanceof Error ? err.message : "Payment failed. Please try again.");
|
|
2250
|
+
} finally {
|
|
2251
|
+
submittingRef.current = false;
|
|
2252
|
+
setSubmittingMethod(null);
|
|
2253
|
+
}
|
|
2254
|
+
}, [
|
|
2255
|
+
stripeInstance,
|
|
2256
|
+
isProcessing,
|
|
2257
|
+
runBeforeButtonClick,
|
|
2258
|
+
onButtonClick,
|
|
2259
|
+
sessionId,
|
|
2260
|
+
email,
|
|
2261
|
+
baseUrl,
|
|
2262
|
+
billingName,
|
|
2263
|
+
onTokenizedBody,
|
|
2264
|
+
onErrorChange,
|
|
2265
|
+
onDecline
|
|
2266
|
+
]);
|
|
2267
|
+
const [localExpandedMethod, setLocalExpandedMethod] = useState3(null);
|
|
2268
|
+
const activeExpandedMethod = onExpandApm ? expandedApmMethod ?? null : localExpandedMethod;
|
|
2269
|
+
const handleMethodClick = useCallback((method) => {
|
|
2270
|
+
if (submittingRef.current || isProcessing) return;
|
|
2271
|
+
if (activeExpandedMethod && activeExpandedMethod !== method) return;
|
|
2272
|
+
if (needsStripeMethodExplicitConfirm(method)) {
|
|
2273
|
+
if (onExpandApm) {
|
|
2274
|
+
onExpandApm(method);
|
|
2275
|
+
} else {
|
|
2276
|
+
setLocalExpandedMethod(method);
|
|
2277
|
+
}
|
|
2278
|
+
} else {
|
|
2279
|
+
void handleAutoConfirm(method);
|
|
2280
|
+
}
|
|
2281
|
+
}, [activeExpandedMethod, isProcessing, handleAutoConfirm, onExpandApm]);
|
|
2282
|
+
const localInlineElementsOptions = useMemo3(() => {
|
|
2283
|
+
if (!localExpandedMethod) return null;
|
|
2284
|
+
return {
|
|
2285
|
+
...paymentElementBaseOptions,
|
|
2286
|
+
paymentMethodTypes: [localExpandedMethod]
|
|
2287
|
+
};
|
|
2288
|
+
}, [localExpandedMethod, paymentElementBaseOptions]);
|
|
2289
|
+
return /* @__PURE__ */ jsx6(
|
|
2290
|
+
"div",
|
|
2291
|
+
{
|
|
2292
|
+
"data-testid": "flopay-stripe-payment-element-region",
|
|
2293
|
+
style: { display: "flex", flexDirection: "column", gap: "0.5rem" },
|
|
2294
|
+
children: paymentElementMethods.map((method) => {
|
|
2295
|
+
const isExpanded = expandedApmMethod === method;
|
|
2296
|
+
const isSubmittingThis = submittingMethod === method;
|
|
2297
|
+
const otherInProgress = submittingMethod !== null && submittingMethod !== method || expandedApmMethod !== null && expandedApmMethod !== void 0 && expandedApmMethod !== method;
|
|
2298
|
+
return /* @__PURE__ */ jsxs4(React6.Fragment, { children: [
|
|
2299
|
+
/* @__PURE__ */ jsx6(
|
|
2300
|
+
StripeMethodButton,
|
|
2301
|
+
{
|
|
2302
|
+
method,
|
|
2303
|
+
themeId,
|
|
2304
|
+
submitting: isSubmittingThis,
|
|
2305
|
+
disabled: otherInProgress,
|
|
2306
|
+
highlighted: isExpanded,
|
|
2307
|
+
hasNextStep: needsStripeMethodExplicitConfirm(method),
|
|
2308
|
+
onClick: () => handleMethodClick(method),
|
|
2309
|
+
backgroundColor: buttonAppearance?.backgroundColor,
|
|
2310
|
+
borderColor: buttonAppearance?.borderColor,
|
|
2311
|
+
textColor: buttonAppearance?.textColor,
|
|
2312
|
+
borderRadius: buttonAppearance?.borderRadius,
|
|
2313
|
+
fontFamily: buttonAppearance?.fontFamily
|
|
2314
|
+
}
|
|
2315
|
+
),
|
|
2316
|
+
!onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ jsx6(
|
|
2317
|
+
StripeElements,
|
|
2318
|
+
{
|
|
2319
|
+
stripe: stripeInstance,
|
|
2320
|
+
options: localInlineElementsOptions,
|
|
2321
|
+
children: /* @__PURE__ */ jsx6(
|
|
2322
|
+
StripeMethodInlineForm,
|
|
2323
|
+
{
|
|
2324
|
+
method,
|
|
2325
|
+
sessionId,
|
|
2326
|
+
email,
|
|
2327
|
+
billingName,
|
|
2328
|
+
billingApiUrl,
|
|
2329
|
+
onTokenizedBody,
|
|
2330
|
+
onErrorChange,
|
|
2331
|
+
onDecline,
|
|
2332
|
+
onCancel: () => setLocalExpandedMethod(null),
|
|
2333
|
+
runBeforeButtonClick,
|
|
2334
|
+
onButtonClick,
|
|
2335
|
+
isProcessing,
|
|
2336
|
+
submitButtonColor,
|
|
2337
|
+
submitButtonBorderRadius,
|
|
2338
|
+
submitButtonStyle
|
|
2339
|
+
}
|
|
2340
|
+
)
|
|
2341
|
+
},
|
|
2342
|
+
method
|
|
2343
|
+
)
|
|
2344
|
+
] }, method);
|
|
2345
|
+
})
|
|
2346
|
+
}
|
|
2347
|
+
);
|
|
2348
|
+
}
|
|
1707
2349
|
function SplitCardFormInner({
|
|
1708
2350
|
sessionId,
|
|
1709
2351
|
billingApiUrl,
|
|
@@ -1726,6 +2368,8 @@ function SplitCardFormInner({
|
|
|
1726
2368
|
onFirstNameChange,
|
|
1727
2369
|
onLastNameChange,
|
|
1728
2370
|
showPayPal = true,
|
|
2371
|
+
showStripe = true,
|
|
2372
|
+
enabledPaymentMethods,
|
|
1729
2373
|
showApplePay = true,
|
|
1730
2374
|
showGooglePay = true,
|
|
1731
2375
|
layout = "default",
|
|
@@ -1785,6 +2429,7 @@ function SplitCardFormInner({
|
|
|
1785
2429
|
const avsConfig = useMemo3(() => resolveAVSConfig(enableAVSProp), [enableAVSProp]);
|
|
1786
2430
|
const enableAVS = avsConfig !== null;
|
|
1787
2431
|
const [viewState, setViewState] = useState3(initialCardOpen ? "card" : "buttons");
|
|
2432
|
+
const [expandedApmMethod, setExpandedApmMethod] = useState3(null);
|
|
1788
2433
|
const showCardForm = viewState === "expanding" || viewState === "card";
|
|
1789
2434
|
const TRANSITION_MS = 280;
|
|
1790
2435
|
const expandToCard = useCallback(() => {
|
|
@@ -1795,6 +2440,18 @@ function SplitCardFormInner({
|
|
|
1795
2440
|
setViewState("collapsing");
|
|
1796
2441
|
setTimeout(() => setViewState("buttons"), TRANSITION_MS);
|
|
1797
2442
|
}, []);
|
|
2443
|
+
const expandToApm = useCallback((method) => {
|
|
2444
|
+
setExpandedApmMethod(method);
|
|
2445
|
+
setViewState("apm-expanding");
|
|
2446
|
+
setTimeout(() => setViewState("apm-form"), TRANSITION_MS);
|
|
2447
|
+
}, []);
|
|
2448
|
+
const collapseFromApm = useCallback(() => {
|
|
2449
|
+
setViewState("apm-collapsing");
|
|
2450
|
+
setTimeout(() => {
|
|
2451
|
+
setViewState("buttons");
|
|
2452
|
+
setExpandedApmMethod(null);
|
|
2453
|
+
}, TRANSITION_MS);
|
|
2454
|
+
}, []);
|
|
1798
2455
|
useEffect4(() => {
|
|
1799
2456
|
if (layout === "buttons" && initialCardOpen) {
|
|
1800
2457
|
setViewState("card");
|
|
@@ -1848,20 +2505,43 @@ function SplitCardFormInner({
|
|
|
1848
2505
|
return paypalFlopay.getRawProvider();
|
|
1849
2506
|
}, [paypalFlopay]);
|
|
1850
2507
|
const amountInCents = totalAmount || 100;
|
|
2508
|
+
const stripeAppearanceProp = appearance ? { appearance } : null;
|
|
2509
|
+
const paymentElementAppearance = useMemo3(() => {
|
|
2510
|
+
const base = appearance ?? {};
|
|
2511
|
+
const baseRules = base.rules ?? {};
|
|
2512
|
+
return {
|
|
2513
|
+
...base,
|
|
2514
|
+
rules: {
|
|
2515
|
+
...baseRules,
|
|
2516
|
+
".AccordionItem": {
|
|
2517
|
+
padding: "10px 14px",
|
|
2518
|
+
boxShadow: "none",
|
|
2519
|
+
...baseRules[".AccordionItem"] ?? {}
|
|
2520
|
+
},
|
|
2521
|
+
".AccordionItemContents": {
|
|
2522
|
+
padding: "6px 14px 12px",
|
|
2523
|
+
boxShadow: "none",
|
|
2524
|
+
...baseRules[".AccordionItemContents"] ?? {}
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
};
|
|
2528
|
+
}, [appearance]);
|
|
1851
2529
|
const walletOptions = useMemo3(() => ({
|
|
1852
2530
|
mode: "payment",
|
|
1853
2531
|
amount: amountInCents,
|
|
1854
2532
|
currency: currency.toLowerCase(),
|
|
1855
2533
|
paymentMethodCreation: "manual",
|
|
1856
|
-
captureMethod: "manual"
|
|
1857
|
-
|
|
2534
|
+
captureMethod: "manual",
|
|
2535
|
+
...stripeAppearanceProp
|
|
2536
|
+
}), [amountInCents, currency, stripeAppearanceProp]);
|
|
1858
2537
|
const paypalOptions = useMemo3(() => ({
|
|
1859
2538
|
mode: "payment",
|
|
1860
2539
|
amount: amountInCents,
|
|
1861
2540
|
currency: currency.toLowerCase(),
|
|
1862
2541
|
captureMethod: "manual",
|
|
1863
|
-
setupFutureUsage: "off_session"
|
|
1864
|
-
|
|
2542
|
+
setupFutureUsage: "off_session",
|
|
2543
|
+
...stripeAppearanceProp
|
|
2544
|
+
}), [amountInCents, currency, stripeAppearanceProp]);
|
|
1865
2545
|
const updateError = useCallback(
|
|
1866
2546
|
(err) => {
|
|
1867
2547
|
setError(err);
|
|
@@ -1875,22 +2555,98 @@ function SplitCardFormInner({
|
|
|
1875
2555
|
},
|
|
1876
2556
|
[onDecline]
|
|
1877
2557
|
);
|
|
1878
|
-
const
|
|
2558
|
+
const directPaypalConfigured = !!directPaypal?.clientId;
|
|
2559
|
+
const hasEnabledMethodsPayload = Array.isArray(enabledPaymentMethods);
|
|
2560
|
+
const hasEnabledMethods = hasEnabledMethodsPayload && enabledPaymentMethods.length > 0;
|
|
2561
|
+
const paypalEnabled = hasEnabledMethodsPayload && enabledPaymentMethods.includes("paypal");
|
|
2562
|
+
const { expressMethods, paymentElementMethods } = useMemo3(
|
|
2563
|
+
() => partitionStripeMethods(enabledPaymentMethods, {
|
|
2564
|
+
excludePaypal: directPaypalConfigured
|
|
2565
|
+
}),
|
|
2566
|
+
[enabledPaymentMethods, directPaypalConfigured]
|
|
2567
|
+
);
|
|
2568
|
+
const paypalRenderedSeparately = directPaypalConfigured || !!paypalFlopay;
|
|
2569
|
+
const expressMethodsForWalletRow = useMemo3(
|
|
2570
|
+
() => paypalRenderedSeparately ? expressMethods.filter((m) => m !== "paypal") : expressMethods,
|
|
2571
|
+
[expressMethods, paypalRenderedSeparately]
|
|
2572
|
+
);
|
|
2573
|
+
const legacyExpressMethods = useMemo3(() => {
|
|
2574
|
+
const out = [];
|
|
2575
|
+
if (showApplePay) out.push("apple_pay");
|
|
2576
|
+
if (showGooglePay) out.push("google_pay");
|
|
2577
|
+
return out;
|
|
2578
|
+
}, [showApplePay, showGooglePay]);
|
|
2579
|
+
const walletExpressMethods = hasEnabledMethodsPayload ? expressMethodsForWalletRow : legacyExpressMethods;
|
|
2580
|
+
const showWallets = showStripe && walletExpressMethods.length > 0;
|
|
2581
|
+
const paymentElementMethodsForCurrency = useMemo3(
|
|
2582
|
+
() => filterStripeMethodsByAmount(
|
|
2583
|
+
filterStripeMethodsByCountry(
|
|
2584
|
+
filterStripeMethodsByCurrency(paymentElementMethods, currency),
|
|
2585
|
+
countryProp
|
|
2586
|
+
),
|
|
2587
|
+
currency,
|
|
2588
|
+
amountInCents
|
|
2589
|
+
),
|
|
2590
|
+
[paymentElementMethods, currency, countryProp, amountInCents]
|
|
2591
|
+
);
|
|
2592
|
+
const paymentElementBaseOptions = useMemo3(() => ({
|
|
2593
|
+
mode: "payment",
|
|
2594
|
+
amount: amountInCents,
|
|
2595
|
+
currency: currency.toLowerCase(),
|
|
2596
|
+
paymentMethodCreation: "manual",
|
|
2597
|
+
appearance: paymentElementAppearance
|
|
2598
|
+
}), [amountInCents, currency, paymentElementAppearance]);
|
|
1879
2599
|
const [paypalLoadState, setPaypalLoadState] = useState3("loading");
|
|
1880
2600
|
const [walletLoadState, setWalletLoadState] = useState3("loading");
|
|
2601
|
+
const [paymentElementLoadState, setPaymentElementLoadState] = useState3("loading");
|
|
1881
2602
|
const [directPaypalReady, setDirectPaypalReady] = useState3(false);
|
|
1882
2603
|
const [inAppBrowserDetected, setInAppBrowserDetected] = useState3();
|
|
1883
2604
|
useEffect4(() => {
|
|
1884
2605
|
setInAppBrowserDetected(isInAppBrowser());
|
|
1885
2606
|
}, []);
|
|
1886
|
-
const
|
|
1887
|
-
const
|
|
1888
|
-
const shouldShowWallets = showWallets;
|
|
2607
|
+
const shouldShowPayPal = showPayPal && (directPaypalConfigured || (hasEnabledMethodsPayload ? paypalEnabled : inAppBrowserDetected === false));
|
|
2608
|
+
const shouldShowWallets = showStripe && showWallets;
|
|
1889
2609
|
const shouldRenderDirectPayPal = shouldShowPayPal && directPaypalConfigured;
|
|
1890
2610
|
const shouldRenderStripePayPal = shouldShowPayPal && !directPaypalConfigured && !!paypalStripeInstance;
|
|
1891
2611
|
const shouldRenderWallets = shouldShowWallets && !!stripeInstance;
|
|
2612
|
+
const shouldRenderPaymentElement = showStripe && hasEnabledMethods && paymentElementMethodsForCurrency.length > 0 && !!stripeInstance;
|
|
1892
2613
|
const shouldDisplayPayPalRow = shouldRenderDirectPayPal ? directPaypalReady : shouldRenderStripePayPal && isExpressCheckoutRowVisible(paypalLoadState);
|
|
1893
2614
|
const shouldDisplayWalletRow = shouldRenderWallets && isExpressCheckoutRowVisible(walletLoadState);
|
|
2615
|
+
const shouldDisplayPaymentElementRow = shouldRenderPaymentElement && paymentElementLoadState !== "load_error";
|
|
2616
|
+
const validationFiredRef = useRef3(false);
|
|
2617
|
+
useEffect4(() => {
|
|
2618
|
+
if (validationFiredRef.current) return;
|
|
2619
|
+
if (!showStripe && !showPayPal) {
|
|
2620
|
+
validationFiredRef.current = true;
|
|
2621
|
+
const err = new FloPayError3(
|
|
2622
|
+
"FloPay: both `showStripe` and `showPayPal` are false \u2014 nothing to render.",
|
|
2623
|
+
"validation_error"
|
|
2624
|
+
);
|
|
2625
|
+
onError?.(err);
|
|
2626
|
+
updateError(err.message);
|
|
2627
|
+
} else if (!showStripe && showPayPal && !directPaypalConfigured && !paypalStripeInstance) {
|
|
2628
|
+
validationFiredRef.current = true;
|
|
2629
|
+
const err = new FloPayError3(
|
|
2630
|
+
"FloPay: `showStripe` is false and no PayPal gateway is configured for this session \u2014 nothing to render.",
|
|
2631
|
+
"validation_error"
|
|
2632
|
+
);
|
|
2633
|
+
onError?.(err);
|
|
2634
|
+
updateError(err.message);
|
|
2635
|
+
}
|
|
2636
|
+
}, [showStripe, showPayPal, directPaypalConfigured, paypalStripeInstance, onError, updateError]);
|
|
2637
|
+
const deprecationLoggedRef = useRef3(false);
|
|
2638
|
+
useEffect4(() => {
|
|
2639
|
+
if (deprecationLoggedRef.current) return;
|
|
2640
|
+
if (!hasEnabledMethods) return;
|
|
2641
|
+
const stale = [];
|
|
2642
|
+
if (showApplePay !== true) stale.push("showApplePay");
|
|
2643
|
+
if (showGooglePay !== true) stale.push("showGooglePay");
|
|
2644
|
+
if (stale.length === 0) return;
|
|
2645
|
+
deprecationLoggedRef.current = true;
|
|
2646
|
+
console.warn(
|
|
2647
|
+
`[FloPay] ${stale.join(" / ")} ${stale.length === 1 ? "is" : "are"} deprecated: the Apple Pay / Google Pay surface is now driven by \`gateways.stripe.enabledPaymentMethods\` on the session response. Remove the legacy prop(s) to silence this warning.`
|
|
2648
|
+
);
|
|
2649
|
+
}, [hasEnabledMethods, showApplePay, showGooglePay]);
|
|
1894
2650
|
const handleNameChange = useCallback((value) => {
|
|
1895
2651
|
setFullName(value);
|
|
1896
2652
|
onFullNameChange?.(value);
|
|
@@ -2191,24 +2947,75 @@ function SplitCardFormInner({
|
|
|
2191
2947
|
}
|
|
2192
2948
|
}
|
|
2193
2949
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
2950
|
+
const stripeResumeAttemptedRef = useRef3(false);
|
|
2194
2951
|
useEffect4(() => {
|
|
2195
|
-
if (typeof window === "undefined") return;
|
|
2196
|
-
const
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2952
|
+
if (typeof window === "undefined" || stripeResumeAttemptedRef.current) return;
|
|
2953
|
+
const params = new URLSearchParams(window.location.search);
|
|
2954
|
+
const paymentIntentId = params.get("payment_intent");
|
|
2955
|
+
const clientSecret = params.get("payment_intent_client_secret");
|
|
2956
|
+
const redirectStatus = params.get("redirect_status");
|
|
2957
|
+
if (!paymentIntentId || !clientSecret) return;
|
|
2958
|
+
const readPayload = (key) => {
|
|
2959
|
+
const raw = localStorage.getItem(key);
|
|
2960
|
+
if (!raw) return null;
|
|
2961
|
+
try {
|
|
2962
|
+
return JSON.parse(raw);
|
|
2963
|
+
} catch {
|
|
2964
|
+
localStorage.removeItem(key);
|
|
2965
|
+
return null;
|
|
2207
2966
|
}
|
|
2208
|
-
}
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2967
|
+
};
|
|
2968
|
+
const payload = readPayload(STRIPE_RESUME_KEY) ?? readPayload(LEGACY_WALLET_RESUME_KEY);
|
|
2969
|
+
if (payload?.sessionId && payload.sessionId !== sessionId) return;
|
|
2970
|
+
stripeResumeAttemptedRef.current = true;
|
|
2971
|
+
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
2972
|
+
localStorage.removeItem(LEGACY_WALLET_RESUME_KEY);
|
|
2973
|
+
const cleanedUrl = new URL(window.location.href);
|
|
2974
|
+
cleanedUrl.searchParams.delete("payment_intent");
|
|
2975
|
+
cleanedUrl.searchParams.delete("payment_intent_client_secret");
|
|
2976
|
+
cleanedUrl.searchParams.delete("redirect_status");
|
|
2977
|
+
window.history.replaceState({}, "", cleanedUrl.toString());
|
|
2978
|
+
const paymentMethodType = payload?.paymentMethodType ?? payload?.tokenType ?? "card";
|
|
2979
|
+
const declineMethod = "card";
|
|
2980
|
+
(async () => {
|
|
2981
|
+
const rawProvider = flopay?.getRawProvider();
|
|
2982
|
+
if (!rawProvider) {
|
|
2983
|
+
const message = "Payment is not available \u2014 please refresh and try again.";
|
|
2984
|
+
updateError(message);
|
|
2985
|
+
emitDecline(declineMethod, message);
|
|
2986
|
+
return;
|
|
2987
|
+
}
|
|
2988
|
+
if (redirectStatus === "failed") {
|
|
2989
|
+
const message = "Payment was declined. Please try again.";
|
|
2990
|
+
updateError(message);
|
|
2991
|
+
emitDecline(declineMethod, message);
|
|
2992
|
+
return;
|
|
2993
|
+
}
|
|
2994
|
+
const { paymentIntent, error: error2 } = await rawProvider.retrievePaymentIntent(clientSecret);
|
|
2995
|
+
if (error2) {
|
|
2996
|
+
const message = error2.message ?? "Failed to retrieve payment status.";
|
|
2997
|
+
updateError(message);
|
|
2998
|
+
emitDecline(declineMethod, message, { code: error2.code });
|
|
2999
|
+
return;
|
|
3000
|
+
}
|
|
3001
|
+
const piStatus = paymentIntent?.status;
|
|
3002
|
+
const successful = piStatus === "succeeded" || piStatus === "requires_capture" || piStatus === "processing";
|
|
3003
|
+
if (!paymentIntent || !successful) {
|
|
3004
|
+
const message = piStatus === "canceled" ? "Payment was canceled." : "Payment was not completed. Please try again.";
|
|
3005
|
+
updateError(message);
|
|
3006
|
+
emitDecline(declineMethod, message, { code: piStatus ?? "missing_payment_intent" });
|
|
3007
|
+
return;
|
|
3008
|
+
}
|
|
3009
|
+
const resolvedPmId = typeof paymentIntent.payment_method === "string" ? paymentIntent.payment_method : paymentIntent.payment_method?.id;
|
|
3010
|
+
dispatchTokenizedBody({
|
|
3011
|
+
id: resolvedPmId ?? payload?.paymentMethodId ?? payload?.tokenId ?? paymentIntent.id,
|
|
3012
|
+
type: "card",
|
|
3013
|
+
threeDSecureActionResultTokenId: paymentIntent.id,
|
|
3014
|
+
gateway: payload?.gateway ?? "stripe",
|
|
3015
|
+
paymentMethodType
|
|
3016
|
+
});
|
|
3017
|
+
})();
|
|
3018
|
+
}, [sessionId, dispatchTokenizedBody, flopay, updateError, emitDecline]);
|
|
2212
3019
|
const handleSubmit = useCallback(
|
|
2213
3020
|
async (e) => {
|
|
2214
3021
|
e.preventDefault();
|
|
@@ -2491,17 +3298,23 @@ function SplitCardFormInner({
|
|
|
2491
3298
|
/* @__PURE__ */ jsx6("div", { style: {
|
|
2492
3299
|
flex: 1,
|
|
2493
3300
|
backgroundColor: cardInputBg,
|
|
2494
|
-
|
|
3301
|
+
// Longhand only — mixing `border` shorthand with per-side
|
|
3302
|
+
// overrides triggers React's "shorthand vs longhand" warning
|
|
3303
|
+
// because render order isn't deterministic.
|
|
2495
3304
|
borderTop: "none",
|
|
2496
3305
|
borderRight: "none",
|
|
3306
|
+
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3307
|
+
borderLeft: `1px solid ${resolvedBorder}`,
|
|
2497
3308
|
borderBottomLeftRadius: "8px",
|
|
2498
3309
|
padding: "10px"
|
|
2499
3310
|
}, children: /* @__PURE__ */ jsx6(CardExpiryElement, { options: stripeElementStyle }) }),
|
|
2500
3311
|
/* @__PURE__ */ jsx6("div", { style: {
|
|
2501
3312
|
flex: 1,
|
|
2502
3313
|
backgroundColor: cardInputBg,
|
|
2503
|
-
border: `1px solid ${resolvedBorder}`,
|
|
2504
3314
|
borderTop: "none",
|
|
3315
|
+
borderRight: `1px solid ${resolvedBorder}`,
|
|
3316
|
+
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3317
|
+
borderLeft: `1px solid ${resolvedBorder}`,
|
|
2505
3318
|
borderBottomRightRadius: "8px",
|
|
2506
3319
|
padding: "10px"
|
|
2507
3320
|
}, children: /* @__PURE__ */ jsx6(CardCvcElement, { options: stripeElementStyle }) })
|
|
@@ -2593,7 +3406,10 @@ function SplitCardFormInner({
|
|
|
2593
3406
|
isAVSFieldVisible(avsConfig.city, cc) && /* @__PURE__ */ jsx6("div", { style: {
|
|
2594
3407
|
flex: 1,
|
|
2595
3408
|
backgroundColor: cardInputBg,
|
|
2596
|
-
|
|
3409
|
+
borderTop: `1px solid ${resolvedBorder}`,
|
|
3410
|
+
borderRight: `1px solid ${resolvedBorder}`,
|
|
3411
|
+
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3412
|
+
borderLeft: `1px solid ${resolvedBorder}`,
|
|
2597
3413
|
padding: "10px",
|
|
2598
3414
|
borderTopLeftRadius: "8px",
|
|
2599
3415
|
borderBottomLeftRadius: "8px",
|
|
@@ -2670,7 +3486,10 @@ function SplitCardFormInner({
|
|
|
2670
3486
|
isAVSFieldVisible(avsConfig.country, cc) && /* @__PURE__ */ jsx6("div", { style: {
|
|
2671
3487
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
2672
3488
|
backgroundColor: cardInputBg,
|
|
2673
|
-
|
|
3489
|
+
borderTop: `1px solid ${resolvedBorder}`,
|
|
3490
|
+
borderRight: `1px solid ${resolvedBorder}`,
|
|
3491
|
+
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3492
|
+
borderLeft: `1px solid ${resolvedBorder}`,
|
|
2674
3493
|
padding: "10px",
|
|
2675
3494
|
...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: "8px", borderBottomLeftRadius: "8px", borderRight: "none" } : { borderRadius: "8px" },
|
|
2676
3495
|
...isButtons && bStyles.countrySelect ? bStyles.countrySelect : {}
|
|
@@ -2765,11 +3584,65 @@ function SplitCardFormInner({
|
|
|
2765
3584
|
}
|
|
2766
3585
|
)
|
|
2767
3586
|
] });
|
|
3587
|
+
const gateDebugStyle = {
|
|
3588
|
+
margin: 0,
|
|
3589
|
+
padding: "6px 8px",
|
|
3590
|
+
background: "#eef2ff",
|
|
3591
|
+
border: "1px solid #c7d2fe",
|
|
3592
|
+
borderRadius: 6,
|
|
3593
|
+
color: "#111827",
|
|
3594
|
+
font: "11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
3595
|
+
whiteSpace: "pre-wrap",
|
|
3596
|
+
wordBreak: "break-word"
|
|
3597
|
+
};
|
|
3598
|
+
const renderDirectPaypalGateDebug = (testId) => {
|
|
3599
|
+
if (!debug) return null;
|
|
3600
|
+
if (!showPayPal || !directPaypalConfigured) {
|
|
3601
|
+
return /* @__PURE__ */ jsx6("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
|
|
3602
|
+
}
|
|
3603
|
+
return /* @__PURE__ */ jsx6("pre", { "data-testid": testId, style: gateDebugStyle, children: [
|
|
3604
|
+
"FloPay/DirectPayPal-debug (parent gate)",
|
|
3605
|
+
` showPayPal=${showPayPal}`,
|
|
3606
|
+
` directPaypalConfigured=${directPaypalConfigured}`,
|
|
3607
|
+
` inAppBrowserDetected=${String(inAppBrowserDetected)}`,
|
|
3608
|
+
` shouldRenderDirectPayPal=${shouldRenderDirectPayPal}`,
|
|
3609
|
+
` shouldRenderStripePayPal=${shouldRenderStripePayPal}`,
|
|
3610
|
+
` hasPaypalStripeInstance=${!!paypalStripeInstance}`
|
|
3611
|
+
].join("\n") });
|
|
3612
|
+
};
|
|
3613
|
+
const renderStripeGateDebug = (testId) => {
|
|
3614
|
+
if (!debug) return null;
|
|
3615
|
+
if (!showStripe || !stripeInstance) {
|
|
3616
|
+
return /* @__PURE__ */ jsx6("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
|
|
3617
|
+
}
|
|
3618
|
+
return /* @__PURE__ */ jsx6("pre", { "data-testid": testId, style: gateDebugStyle, children: [
|
|
3619
|
+
"FloPay/Stripe-debug (parent gate)",
|
|
3620
|
+
` showStripe=${showStripe}`,
|
|
3621
|
+
` currency=${currency}`,
|
|
3622
|
+
` amountInCents=${amountInCents}`,
|
|
3623
|
+
` enabledPaymentMethods: ${JSON.stringify(enabledPaymentMethods ?? [])}`,
|
|
3624
|
+
` enabledPaymentMethodsProvided=${hasEnabledMethodsPayload}`,
|
|
3625
|
+
` hasEnabledMethods=${hasEnabledMethods}`,
|
|
3626
|
+
` expressMethods: ${JSON.stringify(expressMethods)}`,
|
|
3627
|
+
` walletExpressMethods: ${JSON.stringify(walletExpressMethods)}`,
|
|
3628
|
+
` paymentElementMethods: ${JSON.stringify(paymentElementMethods)}`,
|
|
3629
|
+
` paymentElementMethodsForCurrency: ${JSON.stringify(paymentElementMethodsForCurrency)}`,
|
|
3630
|
+
` hasStripeInstance=${!!stripeInstance}`,
|
|
3631
|
+
` shouldRenderWallets=${shouldRenderWallets}`,
|
|
3632
|
+
` shouldRenderPaymentElement=${shouldRenderPaymentElement}`
|
|
3633
|
+
].join("\n") });
|
|
3634
|
+
};
|
|
3635
|
+
const isApmView = viewState === "apm-expanding" || viewState === "apm-form" || viewState === "apm-collapsing";
|
|
3636
|
+
const apmAnim = viewState === "apm-expanding" ? `flopay-card-enter ${TRANSITION_MS}ms cubic-bezier(0, 0, 0.2, 1) both` : viewState === "apm-collapsing" ? `flopay-card-exit ${TRANSITION_MS}ms cubic-bezier(0.4, 0, 0.2, 1) both` : void 0;
|
|
3637
|
+
const apmInlineOptions = expandedApmMethod ? {
|
|
3638
|
+
...paymentElementBaseOptions,
|
|
3639
|
+
paymentMethodTypes: [expandedApmMethod]
|
|
3640
|
+
} : null;
|
|
2768
3641
|
if (layout === "buttons") {
|
|
2769
|
-
const isButtonsView = viewState === "buttons" || viewState === "expanding";
|
|
3642
|
+
const isButtonsView = viewState === "buttons" || viewState === "expanding" || viewState === "apm-expanding";
|
|
2770
3643
|
const isCardView = viewState === "expanding" || viewState === "card" || viewState === "collapsing";
|
|
2771
3644
|
const cardButtonSizing = cardButtonContent === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
2772
|
-
const buttonsAnim = viewState === "expanding" ? `flopay-buttons-exit ${TRANSITION_MS}ms cubic-bezier(0.4, 0, 0.2, 1) both` : viewState === "collapsing" ? `flopay-buttons-enter ${TRANSITION_MS}ms cubic-bezier(0, 0, 0.2, 1) both` : void 0;
|
|
3645
|
+
const buttonsAnim = viewState === "expanding" || viewState === "apm-expanding" ? `flopay-buttons-exit ${TRANSITION_MS}ms cubic-bezier(0.4, 0, 0.2, 1) both` : viewState === "collapsing" || viewState === "apm-collapsing" ? `flopay-buttons-enter ${TRANSITION_MS}ms cubic-bezier(0, 0, 0.2, 1) both` : void 0;
|
|
2773
3646
|
const cardAnim = viewState === "expanding" ? `flopay-card-enter ${TRANSITION_MS}ms cubic-bezier(0, 0, 0.2, 1) both` : viewState === "collapsing" ? `flopay-card-exit ${TRANSITION_MS}ms cubic-bezier(0.4, 0, 0.2, 1) both` : void 0;
|
|
2774
3647
|
return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
2775
3648
|
/* @__PURE__ */ jsx6(FloPayKeyframes, {}),
|
|
@@ -2790,32 +3663,8 @@ function SplitCardFormInner({
|
|
|
2790
3663
|
...buttonsAnim ? { animation: buttonsAnim, pointerEvents: "none" } : {}
|
|
2791
3664
|
},
|
|
2792
3665
|
children: [
|
|
2793
|
-
debug
|
|
2794
|
-
|
|
2795
|
-
{
|
|
2796
|
-
"data-testid": "flopay-direct-paypal-gate-debug",
|
|
2797
|
-
style: {
|
|
2798
|
-
margin: 0,
|
|
2799
|
-
padding: "6px 8px",
|
|
2800
|
-
background: "#eef2ff",
|
|
2801
|
-
border: "1px solid #c7d2fe",
|
|
2802
|
-
borderRadius: 6,
|
|
2803
|
-
color: "#111827",
|
|
2804
|
-
font: "11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
2805
|
-
whiteSpace: "pre-wrap",
|
|
2806
|
-
wordBreak: "break-word"
|
|
2807
|
-
},
|
|
2808
|
-
children: [
|
|
2809
|
-
"FloPay/DirectPayPal-debug (parent gate)",
|
|
2810
|
-
` showPayPal=${showPayPal}`,
|
|
2811
|
-
` directPaypalConfigured=${directPaypalConfigured}`,
|
|
2812
|
-
` inAppBrowserDetected=${String(inAppBrowserDetected)}`,
|
|
2813
|
-
` shouldRenderDirectPayPal=${shouldRenderDirectPayPal}`,
|
|
2814
|
-
` shouldRenderStripePayPal=${shouldRenderStripePayPal}`,
|
|
2815
|
-
` hasPaypalStripeInstance=${!!paypalStripeInstance}`
|
|
2816
|
-
].join("\n")
|
|
2817
|
-
}
|
|
2818
|
-
),
|
|
3666
|
+
renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug"),
|
|
3667
|
+
renderStripeGateDebug("flopay-stripe-gate-debug"),
|
|
2819
3668
|
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
2820
3669
|
paypalDirectRetry && /* @__PURE__ */ jsx6(
|
|
2821
3670
|
"div",
|
|
@@ -2870,7 +3719,8 @@ function SplitCardFormInner({
|
|
|
2870
3719
|
onButtonClick,
|
|
2871
3720
|
onDecline,
|
|
2872
3721
|
runBeforeButtonClick,
|
|
2873
|
-
onLoadStateChange: setPaypalLoadState
|
|
3722
|
+
onLoadStateChange: setPaypalLoadState,
|
|
3723
|
+
placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
|
|
2874
3724
|
}
|
|
2875
3725
|
) }),
|
|
2876
3726
|
shouldRenderWallets ? /* @__PURE__ */ jsx6(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx6(
|
|
@@ -2879,17 +3729,48 @@ function SplitCardFormInner({
|
|
|
2879
3729
|
sessionId,
|
|
2880
3730
|
email: resolvedAccount.email,
|
|
2881
3731
|
billingApiUrl: resolvedBillingApiUrl,
|
|
2882
|
-
|
|
2883
|
-
|
|
3732
|
+
expressMethods: walletExpressMethods,
|
|
3733
|
+
onTokenizedBody: dispatchTokenizedBody,
|
|
3734
|
+
onErrorChange: updateError,
|
|
3735
|
+
onButtonClick,
|
|
3736
|
+
onDecline,
|
|
3737
|
+
runBeforeButtonClick,
|
|
3738
|
+
onLoadStateChange: setWalletLoadState,
|
|
3739
|
+
placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
|
|
3740
|
+
}
|
|
3741
|
+
) }) : shouldShowWallets ? /* @__PURE__ */ jsx6("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
|
|
3742
|
+
shouldRenderPaymentElement && /* @__PURE__ */ jsx6(
|
|
3743
|
+
StripePaymentElementInner,
|
|
3744
|
+
{
|
|
3745
|
+
sessionId,
|
|
3746
|
+
email: resolvedAccount.email,
|
|
3747
|
+
billingName: [resolvedAccount.firstName, resolvedAccount.lastName].filter(Boolean).join(" ").trim() || void 0,
|
|
3748
|
+
billingApiUrl: resolvedBillingApiUrl,
|
|
3749
|
+
paymentElementMethods: paymentElementMethodsForCurrency,
|
|
3750
|
+
stripeInstance,
|
|
3751
|
+
paymentElementBaseOptions,
|
|
2884
3752
|
onTokenizedBody: dispatchTokenizedBody,
|
|
2885
3753
|
onErrorChange: updateError,
|
|
2886
3754
|
onButtonClick,
|
|
2887
3755
|
onDecline,
|
|
2888
3756
|
runBeforeButtonClick,
|
|
2889
|
-
onLoadStateChange:
|
|
3757
|
+
onLoadStateChange: setPaymentElementLoadState,
|
|
3758
|
+
isProcessing: isSubmitting,
|
|
3759
|
+
submitButtonColor: resolvedPrimaryColor,
|
|
3760
|
+
submitButtonBorderRadius: resolvedBorderRadius,
|
|
3761
|
+
submitButtonStyle: bStyles.submitButton,
|
|
3762
|
+
onExpandApm: expandToApm,
|
|
3763
|
+
expandedApmMethod,
|
|
3764
|
+
themeId: theme,
|
|
3765
|
+
buttonAppearance: {
|
|
3766
|
+
backgroundColor: bStyles.cardButton?.backgroundColor,
|
|
3767
|
+
borderColor: bStyles.cardInputBorder,
|
|
3768
|
+
textColor: bStyles.cardButton?.color,
|
|
3769
|
+
borderRadius: bStyles.cardButton?.borderRadius
|
|
3770
|
+
}
|
|
2890
3771
|
}
|
|
2891
|
-
)
|
|
2892
|
-
/* @__PURE__ */ jsx6(
|
|
3772
|
+
),
|
|
3773
|
+
showStripe && /* @__PURE__ */ jsx6(
|
|
2893
3774
|
"button",
|
|
2894
3775
|
{
|
|
2895
3776
|
type: "button",
|
|
@@ -2904,10 +3785,21 @@ function SplitCardFormInner({
|
|
|
2904
3785
|
style: {
|
|
2905
3786
|
width: "100%",
|
|
2906
3787
|
...cardButtonSizing,
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
3788
|
+
// `bStyles.cardButton` first — supplies the bundle's
|
|
3789
|
+
// padding / typography / border-radius — then the
|
|
3790
|
+
// primary surface overrides on top, so the card button
|
|
3791
|
+
// ends up wearing the *submit* button's colours rather
|
|
3792
|
+
// than the bundle's neutral white-tile `cardButton`
|
|
3793
|
+
// colours. Without this order flip, every non-classic
|
|
3794
|
+
// bundle's `cardButton.backgroundColor` was winning
|
|
3795
|
+
// over the primary fill we just derived above it.
|
|
3796
|
+
...bStyles.cardButton,
|
|
3797
|
+
...derivePrimaryTileStyle({
|
|
3798
|
+
themeBundle,
|
|
3799
|
+
resolvedPrimaryColor,
|
|
3800
|
+
resolvedBorderRadius,
|
|
3801
|
+
submitButtonStyle: bStyles.submitButton
|
|
3802
|
+
}),
|
|
2911
3803
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
2912
3804
|
fontWeight: 600,
|
|
2913
3805
|
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
@@ -2916,10 +3808,8 @@ function SplitCardFormInner({
|
|
|
2916
3808
|
justifyContent: "center",
|
|
2917
3809
|
gap: "0.625rem",
|
|
2918
3810
|
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
2919
|
-
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
2920
3811
|
position: "relative",
|
|
2921
|
-
opacity: isSubmitting ? 0.6 : 1
|
|
2922
|
-
...bStyles.cardButton
|
|
3812
|
+
opacity: isSubmitting ? 0.6 : 1
|
|
2923
3813
|
},
|
|
2924
3814
|
onMouseDown: (e) => {
|
|
2925
3815
|
e.currentTarget.style.transform = "scale(0.985)";
|
|
@@ -2950,44 +3840,209 @@ function SplitCardFormInner({
|
|
|
2950
3840
|
]
|
|
2951
3841
|
}
|
|
2952
3842
|
),
|
|
2953
|
-
isCardView && /* @__PURE__ */ jsx6("div", { style: {
|
|
3843
|
+
showStripe && isCardView && /* @__PURE__ */ jsx6("div", { style: {
|
|
2954
3844
|
gridArea: "1 / 1",
|
|
2955
3845
|
...cardAnim ? { animation: cardAnim } : {},
|
|
2956
3846
|
...viewState === "collapsing" ? { pointerEvents: "none" } : {}
|
|
2957
|
-
}, children: cardFormBlock })
|
|
3847
|
+
}, children: cardFormBlock }),
|
|
3848
|
+
showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ jsx6("div", { style: {
|
|
3849
|
+
gridArea: "1 / 1",
|
|
3850
|
+
...apmAnim ? { animation: apmAnim } : {},
|
|
3851
|
+
...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
|
|
3852
|
+
}, children: /* @__PURE__ */ jsxs4("div", { style: {
|
|
3853
|
+
backgroundColor: cardBg,
|
|
3854
|
+
borderRadius: containerRadius,
|
|
3855
|
+
...containerOverrides,
|
|
3856
|
+
padding: containerPadding
|
|
3857
|
+
}, children: [
|
|
3858
|
+
/* @__PURE__ */ jsxs4("div", { style: {
|
|
3859
|
+
display: "flex",
|
|
3860
|
+
alignItems: "center",
|
|
3861
|
+
padding: "0.75rem 0 0.625rem"
|
|
3862
|
+
}, children: [
|
|
3863
|
+
/* @__PURE__ */ jsxs4(
|
|
3864
|
+
"button",
|
|
3865
|
+
{
|
|
3866
|
+
type: "button",
|
|
3867
|
+
"data-testid": "flopay-apm-back-button",
|
|
3868
|
+
onClick: collapseFromApm,
|
|
3869
|
+
style: {
|
|
3870
|
+
display: "inline-flex",
|
|
3871
|
+
alignItems: "center",
|
|
3872
|
+
gap: hideBackButtonLabel ? 0 : "0.5rem",
|
|
3873
|
+
background: "none",
|
|
3874
|
+
border: "none",
|
|
3875
|
+
cursor: "pointer",
|
|
3876
|
+
color: "#4b5563",
|
|
3877
|
+
fontSize: bStyles.backButtonFontSize ?? "0.85rem",
|
|
3878
|
+
fontWeight: 500,
|
|
3879
|
+
padding: 0,
|
|
3880
|
+
transition: "color 0.15s",
|
|
3881
|
+
flexShrink: 0,
|
|
3882
|
+
...bStyles.backButton
|
|
3883
|
+
},
|
|
3884
|
+
"aria-label": "Back to payment methods",
|
|
3885
|
+
children: [
|
|
3886
|
+
/* @__PURE__ */ jsx6("span", { style: {
|
|
3887
|
+
display: "inline-flex",
|
|
3888
|
+
alignItems: "center",
|
|
3889
|
+
justifyContent: "center",
|
|
3890
|
+
width: 28,
|
|
3891
|
+
height: 28,
|
|
3892
|
+
borderRadius: "50%",
|
|
3893
|
+
backgroundColor: "#f3f4f6",
|
|
3894
|
+
transition: "background-color 0.15s",
|
|
3895
|
+
...bStyles.backButtonIcon
|
|
3896
|
+
}, children: /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
3897
|
+
/* @__PURE__ */ jsx6(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
3898
|
+
]
|
|
3899
|
+
}
|
|
3900
|
+
),
|
|
3901
|
+
/* @__PURE__ */ jsx6("div", { style: {
|
|
3902
|
+
flex: 1,
|
|
3903
|
+
textAlign: "center",
|
|
3904
|
+
fontWeight: 600,
|
|
3905
|
+
fontSize: bStyles.titleFontSize ?? "1.05rem",
|
|
3906
|
+
color: resolvedTitleColor,
|
|
3907
|
+
paddingRight: 80,
|
|
3908
|
+
...bStyles.title
|
|
3909
|
+
}, children: `Pay with ${getStripeMethodDisplayName(expandedApmMethod)}` })
|
|
3910
|
+
] }),
|
|
3911
|
+
/* @__PURE__ */ jsx6(
|
|
3912
|
+
StripeElements,
|
|
3913
|
+
{
|
|
3914
|
+
stripe: stripeInstance,
|
|
3915
|
+
options: apmInlineOptions,
|
|
3916
|
+
children: /* @__PURE__ */ jsx6(
|
|
3917
|
+
StripeMethodInlineForm,
|
|
3918
|
+
{
|
|
3919
|
+
method: expandedApmMethod,
|
|
3920
|
+
sessionId,
|
|
3921
|
+
email: resolvedAccount.email,
|
|
3922
|
+
billingName: [resolvedAccount.firstName, resolvedAccount.lastName].filter(Boolean).join(" ").trim() || void 0,
|
|
3923
|
+
billingApiUrl: resolvedBillingApiUrl,
|
|
3924
|
+
onTokenizedBody: dispatchTokenizedBody,
|
|
3925
|
+
onErrorChange: updateError,
|
|
3926
|
+
onDecline,
|
|
3927
|
+
onCancel: collapseFromApm,
|
|
3928
|
+
runBeforeButtonClick,
|
|
3929
|
+
onButtonClick,
|
|
3930
|
+
isProcessing: isSubmitting,
|
|
3931
|
+
submitButtonColor: resolvedPrimaryColor,
|
|
3932
|
+
submitButtonBorderRadius: resolvedBorderRadius,
|
|
3933
|
+
submitButtonStyle: bStyles.submitButton
|
|
3934
|
+
}
|
|
3935
|
+
)
|
|
3936
|
+
},
|
|
3937
|
+
expandedApmMethod
|
|
3938
|
+
)
|
|
3939
|
+
] }) })
|
|
2958
3940
|
] })
|
|
2959
3941
|
] });
|
|
2960
3942
|
}
|
|
3943
|
+
if (isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && showStripe) {
|
|
3944
|
+
return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
3945
|
+
/* @__PURE__ */ jsx6(FloPayKeyframes, {}),
|
|
3946
|
+
overlayStatus && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
3947
|
+
/* @__PURE__ */ jsx6("div", { style: {
|
|
3948
|
+
...apmAnim ? { animation: apmAnim } : {},
|
|
3949
|
+
...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
|
|
3950
|
+
}, children: /* @__PURE__ */ jsxs4("div", { style: {
|
|
3951
|
+
backgroundColor: cardBg,
|
|
3952
|
+
borderRadius: containerRadius,
|
|
3953
|
+
...containerOverrides,
|
|
3954
|
+
padding: containerPadding
|
|
3955
|
+
}, children: [
|
|
3956
|
+
/* @__PURE__ */ jsxs4("div", { style: {
|
|
3957
|
+
display: "flex",
|
|
3958
|
+
alignItems: "center",
|
|
3959
|
+
padding: "0.75rem 0 0.625rem"
|
|
3960
|
+
}, children: [
|
|
3961
|
+
/* @__PURE__ */ jsxs4(
|
|
3962
|
+
"button",
|
|
3963
|
+
{
|
|
3964
|
+
type: "button",
|
|
3965
|
+
"data-testid": "flopay-apm-back-button-default",
|
|
3966
|
+
onClick: collapseFromApm,
|
|
3967
|
+
style: {
|
|
3968
|
+
display: "inline-flex",
|
|
3969
|
+
alignItems: "center",
|
|
3970
|
+
gap: hideBackButtonLabel ? 0 : "0.5rem",
|
|
3971
|
+
background: "none",
|
|
3972
|
+
border: "none",
|
|
3973
|
+
cursor: "pointer",
|
|
3974
|
+
color: "#4b5563",
|
|
3975
|
+
fontSize: bStyles.backButtonFontSize ?? "0.85rem",
|
|
3976
|
+
fontWeight: 500,
|
|
3977
|
+
padding: 0,
|
|
3978
|
+
transition: "color 0.15s",
|
|
3979
|
+
flexShrink: 0,
|
|
3980
|
+
...bStyles.backButton
|
|
3981
|
+
},
|
|
3982
|
+
"aria-label": "Back to payment methods",
|
|
3983
|
+
children: [
|
|
3984
|
+
/* @__PURE__ */ jsx6("span", { style: {
|
|
3985
|
+
display: "inline-flex",
|
|
3986
|
+
alignItems: "center",
|
|
3987
|
+
justifyContent: "center",
|
|
3988
|
+
width: 28,
|
|
3989
|
+
height: 28,
|
|
3990
|
+
borderRadius: "50%",
|
|
3991
|
+
backgroundColor: "#f3f4f6",
|
|
3992
|
+
transition: "background-color 0.15s",
|
|
3993
|
+
...bStyles.backButtonIcon
|
|
3994
|
+
}, children: /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
3995
|
+
/* @__PURE__ */ jsx6(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
3996
|
+
]
|
|
3997
|
+
}
|
|
3998
|
+
),
|
|
3999
|
+
/* @__PURE__ */ jsx6("div", { style: {
|
|
4000
|
+
flex: 1,
|
|
4001
|
+
textAlign: "center",
|
|
4002
|
+
fontWeight: 600,
|
|
4003
|
+
fontSize: bStyles.titleFontSize ?? "1.05rem",
|
|
4004
|
+
color: resolvedTitleColor,
|
|
4005
|
+
paddingRight: 80,
|
|
4006
|
+
...bStyles.title
|
|
4007
|
+
}, children: `Pay with ${getStripeMethodDisplayName(expandedApmMethod)}` })
|
|
4008
|
+
] }),
|
|
4009
|
+
/* @__PURE__ */ jsx6(
|
|
4010
|
+
StripeElements,
|
|
4011
|
+
{
|
|
4012
|
+
stripe: stripeInstance,
|
|
4013
|
+
options: apmInlineOptions,
|
|
4014
|
+
children: /* @__PURE__ */ jsx6(
|
|
4015
|
+
StripeMethodInlineForm,
|
|
4016
|
+
{
|
|
4017
|
+
method: expandedApmMethod,
|
|
4018
|
+
sessionId,
|
|
4019
|
+
email: resolvedAccount.email,
|
|
4020
|
+
billingName: [resolvedAccount.firstName, resolvedAccount.lastName].filter(Boolean).join(" ").trim() || void 0,
|
|
4021
|
+
billingApiUrl: resolvedBillingApiUrl,
|
|
4022
|
+
onTokenizedBody: dispatchTokenizedBody,
|
|
4023
|
+
onErrorChange: updateError,
|
|
4024
|
+
onDecline,
|
|
4025
|
+
onCancel: collapseFromApm,
|
|
4026
|
+
runBeforeButtonClick,
|
|
4027
|
+
onButtonClick,
|
|
4028
|
+
isProcessing: isSubmitting,
|
|
4029
|
+
submitButtonColor: resolvedPrimaryColor,
|
|
4030
|
+
submitButtonBorderRadius: resolvedBorderRadius,
|
|
4031
|
+
submitButtonStyle: bStyles.submitButton
|
|
4032
|
+
}
|
|
4033
|
+
)
|
|
4034
|
+
},
|
|
4035
|
+
expandedApmMethod
|
|
4036
|
+
)
|
|
4037
|
+
] }) })
|
|
4038
|
+
] });
|
|
4039
|
+
}
|
|
2961
4040
|
return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
2962
4041
|
/* @__PURE__ */ jsx6(FloPayKeyframes, {}),
|
|
2963
4042
|
overlayStatus && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
2964
4043
|
/* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
2965
|
-
debug
|
|
2966
|
-
|
|
2967
|
-
{
|
|
2968
|
-
"data-testid": "flopay-direct-paypal-gate-debug-default",
|
|
2969
|
-
style: {
|
|
2970
|
-
margin: 0,
|
|
2971
|
-
padding: "6px 8px",
|
|
2972
|
-
background: "#eef2ff",
|
|
2973
|
-
border: "1px solid #c7d2fe",
|
|
2974
|
-
borderRadius: 6,
|
|
2975
|
-
color: "#111827",
|
|
2976
|
-
font: "11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
2977
|
-
whiteSpace: "pre-wrap",
|
|
2978
|
-
wordBreak: "break-word"
|
|
2979
|
-
},
|
|
2980
|
-
children: [
|
|
2981
|
-
"FloPay/DirectPayPal-debug (parent gate)",
|
|
2982
|
-
` showPayPal=${showPayPal}`,
|
|
2983
|
-
` directPaypalConfigured=${directPaypalConfigured}`,
|
|
2984
|
-
` inAppBrowserDetected=${String(inAppBrowserDetected)}`,
|
|
2985
|
-
` shouldRenderDirectPayPal=${shouldRenderDirectPayPal}`,
|
|
2986
|
-
` shouldRenderStripePayPal=${shouldRenderStripePayPal}`,
|
|
2987
|
-
` hasPaypalStripeInstance=${!!paypalStripeInstance}`
|
|
2988
|
-
].join("\n")
|
|
2989
|
-
}
|
|
2990
|
-
),
|
|
4044
|
+
renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug-default"),
|
|
4045
|
+
renderStripeGateDebug("flopay-stripe-gate-debug-default"),
|
|
2991
4046
|
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
2992
4047
|
paypalDirectRetry && /* @__PURE__ */ jsx6(
|
|
2993
4048
|
"div",
|
|
@@ -3042,7 +4097,8 @@ function SplitCardFormInner({
|
|
|
3042
4097
|
onButtonClick,
|
|
3043
4098
|
onDecline,
|
|
3044
4099
|
runBeforeButtonClick,
|
|
3045
|
-
onLoadStateChange: setPaypalLoadState
|
|
4100
|
+
onLoadStateChange: setPaypalLoadState,
|
|
4101
|
+
placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
|
|
3046
4102
|
}
|
|
3047
4103
|
) }),
|
|
3048
4104
|
shouldRenderWallets && /* @__PURE__ */ jsx6(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx6(
|
|
@@ -3051,18 +4107,49 @@ function SplitCardFormInner({
|
|
|
3051
4107
|
sessionId,
|
|
3052
4108
|
email: resolvedAccount.email,
|
|
3053
4109
|
billingApiUrl: resolvedBillingApiUrl,
|
|
3054
|
-
|
|
3055
|
-
|
|
4110
|
+
expressMethods: walletExpressMethods,
|
|
4111
|
+
onTokenizedBody: dispatchTokenizedBody,
|
|
4112
|
+
onErrorChange: updateError,
|
|
4113
|
+
onButtonClick,
|
|
4114
|
+
onDecline,
|
|
4115
|
+
runBeforeButtonClick,
|
|
4116
|
+
onLoadStateChange: setWalletLoadState,
|
|
4117
|
+
placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
|
|
4118
|
+
}
|
|
4119
|
+
) }),
|
|
4120
|
+
shouldRenderPaymentElement && /* @__PURE__ */ jsx6(
|
|
4121
|
+
StripePaymentElementInner,
|
|
4122
|
+
{
|
|
4123
|
+
sessionId,
|
|
4124
|
+
email: resolvedAccount.email,
|
|
4125
|
+
billingName: [resolvedAccount.firstName, resolvedAccount.lastName].filter(Boolean).join(" ").trim() || void 0,
|
|
4126
|
+
billingApiUrl: resolvedBillingApiUrl,
|
|
4127
|
+
paymentElementMethods: paymentElementMethodsForCurrency,
|
|
4128
|
+
stripeInstance,
|
|
4129
|
+
paymentElementBaseOptions,
|
|
3056
4130
|
onTokenizedBody: dispatchTokenizedBody,
|
|
3057
4131
|
onErrorChange: updateError,
|
|
3058
4132
|
onButtonClick,
|
|
3059
4133
|
onDecline,
|
|
3060
4134
|
runBeforeButtonClick,
|
|
3061
|
-
onLoadStateChange:
|
|
4135
|
+
onLoadStateChange: setPaymentElementLoadState,
|
|
4136
|
+
isProcessing: isSubmitting,
|
|
4137
|
+
submitButtonColor: resolvedPrimaryColor,
|
|
4138
|
+
submitButtonBorderRadius: resolvedBorderRadius,
|
|
4139
|
+
submitButtonStyle: bStyles.submitButton,
|
|
4140
|
+
themeId: theme,
|
|
4141
|
+
onExpandApm: expandToApm,
|
|
4142
|
+
expandedApmMethod,
|
|
4143
|
+
buttonAppearance: {
|
|
4144
|
+
backgroundColor: bStyles.cardButton?.backgroundColor,
|
|
4145
|
+
borderColor: bStyles.cardInputBorder,
|
|
4146
|
+
textColor: bStyles.cardButton?.color,
|
|
4147
|
+
borderRadius: bStyles.cardButton?.borderRadius
|
|
4148
|
+
}
|
|
3062
4149
|
}
|
|
3063
|
-
)
|
|
4150
|
+
)
|
|
3064
4151
|
] }),
|
|
3065
|
-
(shouldDisplayWalletRow || shouldDisplayPayPalRow) && /* @__PURE__ */ jsxs4("div", { style: {
|
|
4152
|
+
showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ jsxs4("div", { style: {
|
|
3066
4153
|
display: "flex",
|
|
3067
4154
|
alignItems: "center",
|
|
3068
4155
|
gap: "0.75rem",
|
|
@@ -3074,7 +4161,7 @@ function SplitCardFormInner({
|
|
|
3074
4161
|
/* @__PURE__ */ jsx6("span", { children: "or pay with card" }),
|
|
3075
4162
|
/* @__PURE__ */ jsx6("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
|
|
3076
4163
|
] }),
|
|
3077
|
-
cardFormBlock
|
|
4164
|
+
showStripe && cardFormBlock
|
|
3078
4165
|
] });
|
|
3079
4166
|
}
|
|
3080
4167
|
|
|
@@ -3607,6 +4694,7 @@ function hasInlineSessionPatchData(patch) {
|
|
|
3607
4694
|
}
|
|
3608
4695
|
function FloPayCheckout({
|
|
3609
4696
|
sessionId: sessionIdProp,
|
|
4697
|
+
nonce: nonceProp,
|
|
3610
4698
|
createSession: createSessionParams,
|
|
3611
4699
|
billingApiUrl,
|
|
3612
4700
|
appearance: appearanceOverride,
|
|
@@ -3620,6 +4708,7 @@ function FloPayCheckout({
|
|
|
3620
4708
|
onCountryChange,
|
|
3621
4709
|
onZipChange,
|
|
3622
4710
|
showPayPal = true,
|
|
4711
|
+
showStripe = true,
|
|
3623
4712
|
showApplePay = true,
|
|
3624
4713
|
showGooglePay = true,
|
|
3625
4714
|
debug = false,
|
|
@@ -3966,6 +5055,14 @@ function FloPayCheckout({
|
|
|
3966
5055
|
},
|
|
3967
5056
|
successUrl: params?.successUrl,
|
|
3968
5057
|
cancelUrl: params?.cancelUrl,
|
|
5058
|
+
// Unified products[] is the post-#760 wire shape. Must be included or
|
|
5059
|
+
// carts that only set `products` (no legacy items/subscriptions) all
|
|
5060
|
+
// hash to the same key — the bootstrap effect's `createSessionHash`
|
|
5061
|
+
// dep then never changes when products change, the session-id cache
|
|
5062
|
+
// hits the wrong session, and the backend's enabledPaymentMethods
|
|
5063
|
+
// result for the *previous* cart sticks until a fresh page-load with
|
|
5064
|
+
// the session cache cleared.
|
|
5065
|
+
p: params?.products?.map((x) => `${x.type ?? ""}:${x.code ?? x.providerItemId ?? x.providerPlanId ?? ""}:${x.totalAmount ?? ""}:${x.overrideAmount ?? ""}:${x.quantity ?? 1}`).sort(),
|
|
3969
5066
|
i: params?.items?.map((x) => `${x.code ?? x.providerItemId ?? ""}:${x.totalAmount ?? ""}:${x.overrideAmount ?? ""}:${x.quantity ?? 1}`).sort(),
|
|
3970
5067
|
s: params?.subscriptions?.map((x) => `${x.code ?? x.providerPlanId ?? ""}:${x.totalAmount ?? ""}:${x.overrideAmount ?? ""}:${x.quantity ?? 1}`).sort(),
|
|
3971
5068
|
couponCodes: params?.couponCodes,
|
|
@@ -4192,7 +5289,7 @@ function FloPayCheckout({
|
|
|
4192
5289
|
async function init() {
|
|
4193
5290
|
try {
|
|
4194
5291
|
const api = new PaymentAPI4(resolvedBillingUrl);
|
|
4195
|
-
const result = await api.getUnifiedCheckoutSession(activeSessionId);
|
|
5292
|
+
const result = await api.getUnifiedCheckoutSession(activeSessionId, nonceProp);
|
|
4196
5293
|
if (cancelled) return;
|
|
4197
5294
|
setUnified(result);
|
|
4198
5295
|
const sess = result.data.session ?? null;
|
|
@@ -4279,6 +5376,7 @@ function FloPayCheckout({
|
|
|
4279
5376
|
createSessionHash,
|
|
4280
5377
|
effectiveCreateSessionMode,
|
|
4281
5378
|
initSessionDependency,
|
|
5379
|
+
nonceProp,
|
|
4282
5380
|
runSavedPaymentFlow
|
|
4283
5381
|
]);
|
|
4284
5382
|
const handleConfirmCheckout = useCallback2(async () => {
|
|
@@ -4352,17 +5450,18 @@ function FloPayCheckout({
|
|
|
4352
5450
|
] });
|
|
4353
5451
|
}
|
|
4354
5452
|
if (layout === "buttons") {
|
|
5453
|
+
const bundleRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
4355
5454
|
const skeletonBar = (h) => /* @__PURE__ */ jsx7("div", { style: {
|
|
4356
5455
|
height: h,
|
|
4357
|
-
borderRadius:
|
|
5456
|
+
borderRadius: bundleRadius,
|
|
4358
5457
|
background: "#e5e7eb",
|
|
4359
5458
|
animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
|
|
4360
5459
|
} });
|
|
4361
5460
|
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4362
5461
|
/* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
4363
5462
|
showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
4364
|
-
(showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
4365
|
-
skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
5463
|
+
showStripe && (showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
5464
|
+
showStripe && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
4366
5465
|
/* @__PURE__ */ jsx7("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
4367
5466
|
] }),
|
|
4368
5467
|
modeOverlay
|
|
@@ -4390,6 +5489,8 @@ function FloPayCheckout({
|
|
|
4390
5489
|
return /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx7(
|
|
4391
5490
|
"div",
|
|
4392
5491
|
{
|
|
5492
|
+
role: "alert",
|
|
5493
|
+
"data-testid": "flopay-load-error",
|
|
4393
5494
|
style: {
|
|
4394
5495
|
padding: 24,
|
|
4395
5496
|
textAlign: "center",
|
|
@@ -4407,6 +5508,7 @@ function FloPayCheckout({
|
|
|
4407
5508
|
{
|
|
4408
5509
|
onButtonClick,
|
|
4409
5510
|
showPayPal,
|
|
5511
|
+
showStripe,
|
|
4410
5512
|
showApplePay,
|
|
4411
5513
|
showGooglePay,
|
|
4412
5514
|
theme,
|
|
@@ -4551,6 +5653,8 @@ function FloPayCheckout({
|
|
|
4551
5653
|
onErrorChange: setModeError,
|
|
4552
5654
|
onFullNameChange,
|
|
4553
5655
|
showPayPal,
|
|
5656
|
+
showStripe,
|
|
5657
|
+
enabledPaymentMethods: unified?.data.stripe?.enabledPaymentMethods,
|
|
4554
5658
|
showApplePay,
|
|
4555
5659
|
showGooglePay,
|
|
4556
5660
|
layout,
|
|
@@ -4615,6 +5719,7 @@ function InterimButtonsView({
|
|
|
4615
5719
|
cardOpen,
|
|
4616
5720
|
errorMessage,
|
|
4617
5721
|
showPayPal,
|
|
5722
|
+
showStripe = true,
|
|
4618
5723
|
showApplePay,
|
|
4619
5724
|
showGooglePay,
|
|
4620
5725
|
theme,
|
|
@@ -4646,9 +5751,10 @@ function InterimButtonsView({
|
|
|
4646
5751
|
title: { ...base.title, ...stylesOverride.title }
|
|
4647
5752
|
};
|
|
4648
5753
|
}, [themeBundle, buttonsTheme, stylesOverride]);
|
|
5754
|
+
const skeletonRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
4649
5755
|
const skeleton = (h) => /* @__PURE__ */ jsx7("div", { style: {
|
|
4650
5756
|
height: h,
|
|
4651
|
-
borderRadius:
|
|
5757
|
+
borderRadius: skeletonRadius,
|
|
4652
5758
|
background: "#e5e7eb",
|
|
4653
5759
|
animation: "flopay-interim-pulse 1.5s ease-in-out infinite"
|
|
4654
5760
|
} });
|
|
@@ -4719,8 +5825,28 @@ function InterimButtonsView({
|
|
|
4719
5825
|
] }),
|
|
4720
5826
|
/* @__PURE__ */ jsx7("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx7("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
4721
5827
|
/* @__PURE__ */ jsxs5("div", { style: { display: "flex" }, children: [
|
|
4722
|
-
/* @__PURE__ */ jsx7("div", { style: {
|
|
4723
|
-
|
|
5828
|
+
/* @__PURE__ */ jsx7("div", { style: {
|
|
5829
|
+
flex: 1,
|
|
5830
|
+
backgroundColor: inputBg,
|
|
5831
|
+
borderTop: "none",
|
|
5832
|
+
borderRight: "none",
|
|
5833
|
+
borderBottom: `1px solid ${inputBorder}`,
|
|
5834
|
+
borderLeft: `1px solid ${inputBorder}`,
|
|
5835
|
+
borderBottomLeftRadius: 8,
|
|
5836
|
+
padding: 12,
|
|
5837
|
+
height: 45
|
|
5838
|
+
}, children: /* @__PURE__ */ jsx7("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
5839
|
+
/* @__PURE__ */ jsx7("div", { style: {
|
|
5840
|
+
flex: 1,
|
|
5841
|
+
backgroundColor: inputBg,
|
|
5842
|
+
borderTop: "none",
|
|
5843
|
+
borderRight: `1px solid ${inputBorder}`,
|
|
5844
|
+
borderBottom: `1px solid ${inputBorder}`,
|
|
5845
|
+
borderLeft: `1px solid ${inputBorder}`,
|
|
5846
|
+
borderBottomRightRadius: 8,
|
|
5847
|
+
padding: 12,
|
|
5848
|
+
height: 45
|
|
5849
|
+
}, children: /* @__PURE__ */ jsx7("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
|
|
4724
5850
|
] }),
|
|
4725
5851
|
/* @__PURE__ */ jsx7("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx7("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
4726
5852
|
/* @__PURE__ */ jsx7("div", { style: {
|
|
@@ -4744,8 +5870,8 @@ function InterimButtonsView({
|
|
|
4744
5870
|
}
|
|
4745
5871
|
return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
4746
5872
|
showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
4747
|
-
(showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
4748
|
-
/* @__PURE__ */ jsx7(
|
|
5873
|
+
showStripe && (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
5874
|
+
showStripe && /* @__PURE__ */ jsx7(
|
|
4749
5875
|
"button",
|
|
4750
5876
|
{
|
|
4751
5877
|
type: "button",
|
|
@@ -4814,7 +5940,7 @@ import { PaymentAPI as PaymentAPI5 } from "@flopay/js";
|
|
|
4814
5940
|
import { FloPayError as FloPayError6 } from "@flopay/shared";
|
|
4815
5941
|
import { forwardRef as forwardRef2, useCallback as useCallback3, useEffect as useEffect6, useImperativeHandle as useImperativeHandle2, useState as useState5 } from "react";
|
|
4816
5942
|
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
4817
|
-
var
|
|
5943
|
+
var WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
4818
5944
|
var CheckoutForm = forwardRef2(
|
|
4819
5945
|
function CheckoutForm2(props, ref) {
|
|
4820
5946
|
return /* @__PURE__ */ jsx8(CheckoutFormInner, { ...props, innerRef: ref });
|
|
@@ -4940,7 +6066,7 @@ function CheckoutFormInner({
|
|
|
4940
6066
|
onDecline?.(buildDeclineEvent("paypal", message));
|
|
4941
6067
|
return;
|
|
4942
6068
|
}
|
|
4943
|
-
localStorage.setItem(
|
|
6069
|
+
localStorage.setItem(WALLET_RESUME_KEY, JSON.stringify({
|
|
4944
6070
|
sessionId,
|
|
4945
6071
|
paymentIntentId: "",
|
|
4946
6072
|
tokenType: "card",
|
|
@@ -5016,12 +6142,12 @@ function CheckoutFormInner({
|
|
|
5016
6142
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
5017
6143
|
useEffect6(() => {
|
|
5018
6144
|
if (typeof window === "undefined") return;
|
|
5019
|
-
const stored = localStorage.getItem(
|
|
6145
|
+
const stored = localStorage.getItem(WALLET_RESUME_KEY);
|
|
5020
6146
|
if (!stored) return;
|
|
5021
6147
|
try {
|
|
5022
6148
|
const payload = JSON.parse(stored);
|
|
5023
6149
|
if (payload.sessionId === sessionId) {
|
|
5024
|
-
localStorage.removeItem(
|
|
6150
|
+
localStorage.removeItem(WALLET_RESUME_KEY);
|
|
5025
6151
|
dispatchTokenizedBody({
|
|
5026
6152
|
id: payload.tokenId,
|
|
5027
6153
|
type: payload.tokenType,
|
|
@@ -5029,7 +6155,7 @@ function CheckoutFormInner({
|
|
|
5029
6155
|
});
|
|
5030
6156
|
}
|
|
5031
6157
|
} catch {
|
|
5032
|
-
localStorage.removeItem(
|
|
6158
|
+
localStorage.removeItem(WALLET_RESUME_KEY);
|
|
5033
6159
|
}
|
|
5034
6160
|
}, [sessionId, dispatchTokenizedBody]);
|
|
5035
6161
|
const handleSubmit = useCallback3(
|
|
@@ -5374,10 +6500,12 @@ function resolveCreateSessionDraft(props) {
|
|
|
5374
6500
|
if (!props.clientId || !props.account || !props.successUrl || !props.cancelUrl) {
|
|
5375
6501
|
return null;
|
|
5376
6502
|
}
|
|
6503
|
+
const hasProducts = props.products != null;
|
|
5377
6504
|
return {
|
|
5378
6505
|
clientId: props.clientId,
|
|
5379
|
-
|
|
5380
|
-
|
|
6506
|
+
products: props.products,
|
|
6507
|
+
items: hasProducts ? void 0 : props.items,
|
|
6508
|
+
subscriptions: hasProducts ? void 0 : props.subscriptions,
|
|
5381
6509
|
account: props.account,
|
|
5382
6510
|
successUrl: props.successUrl,
|
|
5383
6511
|
cancelUrl: props.cancelUrl,
|
|
@@ -5395,6 +6523,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
5395
6523
|
paymentMethodId: _deprecatedPaymentMethodId,
|
|
5396
6524
|
checkoutMethod: _deprecatedCheckoutMethod,
|
|
5397
6525
|
clientId,
|
|
6526
|
+
products,
|
|
5398
6527
|
items,
|
|
5399
6528
|
subscriptions,
|
|
5400
6529
|
account,
|
|
@@ -5425,6 +6554,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
5425
6554
|
() => resolveCreateSessionDraft({
|
|
5426
6555
|
createSession,
|
|
5427
6556
|
clientId,
|
|
6557
|
+
products,
|
|
5428
6558
|
items,
|
|
5429
6559
|
subscriptions,
|
|
5430
6560
|
account,
|
|
@@ -5440,6 +6570,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
5440
6570
|
clientId,
|
|
5441
6571
|
couponCodes,
|
|
5442
6572
|
createSession,
|
|
6573
|
+
products,
|
|
5443
6574
|
items,
|
|
5444
6575
|
subscriptions,
|
|
5445
6576
|
successUrl,
|
|
@@ -5728,10 +6859,20 @@ function FloPayAutomaticPaymentButton({
|
|
|
5728
6859
|
style: {
|
|
5729
6860
|
width: "100%",
|
|
5730
6861
|
...cardButtonSizing,
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
6862
|
+
// `bStyles.cardButton` first so the bundle's padding / typography
|
|
6863
|
+
// / radius / shadow come through, then `derivePrimaryTileStyle`
|
|
6864
|
+
// on top so the auto-pay button carries the *submit* button's
|
|
6865
|
+
// background and text colours — making it visually identical to
|
|
6866
|
+
// the "Confirm Payment" / "Pay with X" actions it stands in for.
|
|
6867
|
+
// Inline `style` consumer override stays at the end so explicit
|
|
6868
|
+
// per-button overrides still win.
|
|
6869
|
+
...bStyles.cardButton,
|
|
6870
|
+
...derivePrimaryTileStyle({
|
|
6871
|
+
themeBundle,
|
|
6872
|
+
resolvedPrimaryColor: themeBundle?.appearance.variables?.colorPrimary ?? "#4A49FF",
|
|
6873
|
+
resolvedBorderRadius: themeBundle?.appearance.variables?.borderRadius ?? "8px",
|
|
6874
|
+
submitButtonStyle: bStyles.submitButton
|
|
6875
|
+
}),
|
|
5735
6876
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
5736
6877
|
fontWeight: 600,
|
|
5737
6878
|
cursor: disabled || isProcessing ? "not-allowed" : "pointer",
|
|
@@ -5739,11 +6880,9 @@ function FloPayAutomaticPaymentButton({
|
|
|
5739
6880
|
alignItems: "center",
|
|
5740
6881
|
justifyContent: "center",
|
|
5741
6882
|
gap: "0.625rem",
|
|
5742
|
-
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
5743
6883
|
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
5744
6884
|
position: "relative",
|
|
5745
6885
|
opacity: disabled || isProcessing ? 0.6 : 1,
|
|
5746
|
-
...bStyles.cardButton,
|
|
5747
6886
|
...style
|
|
5748
6887
|
},
|
|
5749
6888
|
onMouseDown: (e) => {
|