@flopay/react 1.1.6 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -11
- package/dist/index.cjs +1323 -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 +1334 -197
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
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
|
|
@@ -4407,6 +5506,7 @@ function FloPayCheckout({
|
|
|
4407
5506
|
{
|
|
4408
5507
|
onButtonClick,
|
|
4409
5508
|
showPayPal,
|
|
5509
|
+
showStripe,
|
|
4410
5510
|
showApplePay,
|
|
4411
5511
|
showGooglePay,
|
|
4412
5512
|
theme,
|
|
@@ -4551,6 +5651,8 @@ function FloPayCheckout({
|
|
|
4551
5651
|
onErrorChange: setModeError,
|
|
4552
5652
|
onFullNameChange,
|
|
4553
5653
|
showPayPal,
|
|
5654
|
+
showStripe,
|
|
5655
|
+
enabledPaymentMethods: unified?.data.stripe?.enabledPaymentMethods,
|
|
4554
5656
|
showApplePay,
|
|
4555
5657
|
showGooglePay,
|
|
4556
5658
|
layout,
|
|
@@ -4615,6 +5717,7 @@ function InterimButtonsView({
|
|
|
4615
5717
|
cardOpen,
|
|
4616
5718
|
errorMessage,
|
|
4617
5719
|
showPayPal,
|
|
5720
|
+
showStripe = true,
|
|
4618
5721
|
showApplePay,
|
|
4619
5722
|
showGooglePay,
|
|
4620
5723
|
theme,
|
|
@@ -4646,9 +5749,10 @@ function InterimButtonsView({
|
|
|
4646
5749
|
title: { ...base.title, ...stylesOverride.title }
|
|
4647
5750
|
};
|
|
4648
5751
|
}, [themeBundle, buttonsTheme, stylesOverride]);
|
|
5752
|
+
const skeletonRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
4649
5753
|
const skeleton = (h) => /* @__PURE__ */ jsx7("div", { style: {
|
|
4650
5754
|
height: h,
|
|
4651
|
-
borderRadius:
|
|
5755
|
+
borderRadius: skeletonRadius,
|
|
4652
5756
|
background: "#e5e7eb",
|
|
4653
5757
|
animation: "flopay-interim-pulse 1.5s ease-in-out infinite"
|
|
4654
5758
|
} });
|
|
@@ -4719,8 +5823,28 @@ function InterimButtonsView({
|
|
|
4719
5823
|
] }),
|
|
4720
5824
|
/* @__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
5825
|
/* @__PURE__ */ jsxs5("div", { style: { display: "flex" }, children: [
|
|
4722
|
-
/* @__PURE__ */ jsx7("div", { style: {
|
|
4723
|
-
|
|
5826
|
+
/* @__PURE__ */ jsx7("div", { style: {
|
|
5827
|
+
flex: 1,
|
|
5828
|
+
backgroundColor: inputBg,
|
|
5829
|
+
borderTop: "none",
|
|
5830
|
+
borderRight: "none",
|
|
5831
|
+
borderBottom: `1px solid ${inputBorder}`,
|
|
5832
|
+
borderLeft: `1px solid ${inputBorder}`,
|
|
5833
|
+
borderBottomLeftRadius: 8,
|
|
5834
|
+
padding: 12,
|
|
5835
|
+
height: 45
|
|
5836
|
+
}, children: /* @__PURE__ */ jsx7("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
5837
|
+
/* @__PURE__ */ jsx7("div", { style: {
|
|
5838
|
+
flex: 1,
|
|
5839
|
+
backgroundColor: inputBg,
|
|
5840
|
+
borderTop: "none",
|
|
5841
|
+
borderRight: `1px solid ${inputBorder}`,
|
|
5842
|
+
borderBottom: `1px solid ${inputBorder}`,
|
|
5843
|
+
borderLeft: `1px solid ${inputBorder}`,
|
|
5844
|
+
borderBottomRightRadius: 8,
|
|
5845
|
+
padding: 12,
|
|
5846
|
+
height: 45
|
|
5847
|
+
}, children: /* @__PURE__ */ jsx7("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
|
|
4724
5848
|
] }),
|
|
4725
5849
|
/* @__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
5850
|
/* @__PURE__ */ jsx7("div", { style: {
|
|
@@ -4744,8 +5868,8 @@ function InterimButtonsView({
|
|
|
4744
5868
|
}
|
|
4745
5869
|
return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
4746
5870
|
showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
4747
|
-
(showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
4748
|
-
/* @__PURE__ */ jsx7(
|
|
5871
|
+
showStripe && (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
5872
|
+
showStripe && /* @__PURE__ */ jsx7(
|
|
4749
5873
|
"button",
|
|
4750
5874
|
{
|
|
4751
5875
|
type: "button",
|
|
@@ -4814,7 +5938,7 @@ import { PaymentAPI as PaymentAPI5 } from "@flopay/js";
|
|
|
4814
5938
|
import { FloPayError as FloPayError6 } from "@flopay/shared";
|
|
4815
5939
|
import { forwardRef as forwardRef2, useCallback as useCallback3, useEffect as useEffect6, useImperativeHandle as useImperativeHandle2, useState as useState5 } from "react";
|
|
4816
5940
|
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
4817
|
-
var
|
|
5941
|
+
var WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
4818
5942
|
var CheckoutForm = forwardRef2(
|
|
4819
5943
|
function CheckoutForm2(props, ref) {
|
|
4820
5944
|
return /* @__PURE__ */ jsx8(CheckoutFormInner, { ...props, innerRef: ref });
|
|
@@ -4940,7 +6064,7 @@ function CheckoutFormInner({
|
|
|
4940
6064
|
onDecline?.(buildDeclineEvent("paypal", message));
|
|
4941
6065
|
return;
|
|
4942
6066
|
}
|
|
4943
|
-
localStorage.setItem(
|
|
6067
|
+
localStorage.setItem(WALLET_RESUME_KEY, JSON.stringify({
|
|
4944
6068
|
sessionId,
|
|
4945
6069
|
paymentIntentId: "",
|
|
4946
6070
|
tokenType: "card",
|
|
@@ -5016,12 +6140,12 @@ function CheckoutFormInner({
|
|
|
5016
6140
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
5017
6141
|
useEffect6(() => {
|
|
5018
6142
|
if (typeof window === "undefined") return;
|
|
5019
|
-
const stored = localStorage.getItem(
|
|
6143
|
+
const stored = localStorage.getItem(WALLET_RESUME_KEY);
|
|
5020
6144
|
if (!stored) return;
|
|
5021
6145
|
try {
|
|
5022
6146
|
const payload = JSON.parse(stored);
|
|
5023
6147
|
if (payload.sessionId === sessionId) {
|
|
5024
|
-
localStorage.removeItem(
|
|
6148
|
+
localStorage.removeItem(WALLET_RESUME_KEY);
|
|
5025
6149
|
dispatchTokenizedBody({
|
|
5026
6150
|
id: payload.tokenId,
|
|
5027
6151
|
type: payload.tokenType,
|
|
@@ -5029,7 +6153,7 @@ function CheckoutFormInner({
|
|
|
5029
6153
|
});
|
|
5030
6154
|
}
|
|
5031
6155
|
} catch {
|
|
5032
|
-
localStorage.removeItem(
|
|
6156
|
+
localStorage.removeItem(WALLET_RESUME_KEY);
|
|
5033
6157
|
}
|
|
5034
6158
|
}, [sessionId, dispatchTokenizedBody]);
|
|
5035
6159
|
const handleSubmit = useCallback3(
|
|
@@ -5374,10 +6498,12 @@ function resolveCreateSessionDraft(props) {
|
|
|
5374
6498
|
if (!props.clientId || !props.account || !props.successUrl || !props.cancelUrl) {
|
|
5375
6499
|
return null;
|
|
5376
6500
|
}
|
|
6501
|
+
const hasProducts = props.products != null;
|
|
5377
6502
|
return {
|
|
5378
6503
|
clientId: props.clientId,
|
|
5379
|
-
|
|
5380
|
-
|
|
6504
|
+
products: props.products,
|
|
6505
|
+
items: hasProducts ? void 0 : props.items,
|
|
6506
|
+
subscriptions: hasProducts ? void 0 : props.subscriptions,
|
|
5381
6507
|
account: props.account,
|
|
5382
6508
|
successUrl: props.successUrl,
|
|
5383
6509
|
cancelUrl: props.cancelUrl,
|
|
@@ -5395,6 +6521,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
5395
6521
|
paymentMethodId: _deprecatedPaymentMethodId,
|
|
5396
6522
|
checkoutMethod: _deprecatedCheckoutMethod,
|
|
5397
6523
|
clientId,
|
|
6524
|
+
products,
|
|
5398
6525
|
items,
|
|
5399
6526
|
subscriptions,
|
|
5400
6527
|
account,
|
|
@@ -5425,6 +6552,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
5425
6552
|
() => resolveCreateSessionDraft({
|
|
5426
6553
|
createSession,
|
|
5427
6554
|
clientId,
|
|
6555
|
+
products,
|
|
5428
6556
|
items,
|
|
5429
6557
|
subscriptions,
|
|
5430
6558
|
account,
|
|
@@ -5440,6 +6568,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
5440
6568
|
clientId,
|
|
5441
6569
|
couponCodes,
|
|
5442
6570
|
createSession,
|
|
6571
|
+
products,
|
|
5443
6572
|
items,
|
|
5444
6573
|
subscriptions,
|
|
5445
6574
|
successUrl,
|
|
@@ -5728,10 +6857,20 @@ function FloPayAutomaticPaymentButton({
|
|
|
5728
6857
|
style: {
|
|
5729
6858
|
width: "100%",
|
|
5730
6859
|
...cardButtonSizing,
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
6860
|
+
// `bStyles.cardButton` first so the bundle's padding / typography
|
|
6861
|
+
// / radius / shadow come through, then `derivePrimaryTileStyle`
|
|
6862
|
+
// on top so the auto-pay button carries the *submit* button's
|
|
6863
|
+
// background and text colours — making it visually identical to
|
|
6864
|
+
// the "Confirm Payment" / "Pay with X" actions it stands in for.
|
|
6865
|
+
// Inline `style` consumer override stays at the end so explicit
|
|
6866
|
+
// per-button overrides still win.
|
|
6867
|
+
...bStyles.cardButton,
|
|
6868
|
+
...derivePrimaryTileStyle({
|
|
6869
|
+
themeBundle,
|
|
6870
|
+
resolvedPrimaryColor: themeBundle?.appearance.variables?.colorPrimary ?? "#4A49FF",
|
|
6871
|
+
resolvedBorderRadius: themeBundle?.appearance.variables?.borderRadius ?? "8px",
|
|
6872
|
+
submitButtonStyle: bStyles.submitButton
|
|
6873
|
+
}),
|
|
5735
6874
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
5736
6875
|
fontWeight: 600,
|
|
5737
6876
|
cursor: disabled || isProcessing ? "not-allowed" : "pointer",
|
|
@@ -5739,11 +6878,9 @@ function FloPayAutomaticPaymentButton({
|
|
|
5739
6878
|
alignItems: "center",
|
|
5740
6879
|
justifyContent: "center",
|
|
5741
6880
|
gap: "0.625rem",
|
|
5742
|
-
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
5743
6881
|
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
5744
6882
|
position: "relative",
|
|
5745
6883
|
opacity: disabled || isProcessing ? 0.6 : 1,
|
|
5746
|
-
...bStyles.cardButton,
|
|
5747
6884
|
...style
|
|
5748
6885
|
},
|
|
5749
6886
|
onMouseDown: (e) => {
|