@flopay/react 0.3.14 → 0.3.17
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 +6 -4
- package/dist/index.cjs +142 -123
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.mjs +143 -124
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -131,14 +131,16 @@ Use `onButtonClick` to track button interactions, `onDecline` to track declines/
|
|
|
131
131
|
createSession={{
|
|
132
132
|
clientId: 'your-client-id',
|
|
133
133
|
items: [{ providerItemId: 'product-1', providerItemName: 'Widget', totalAmount: 29.99, currency: 'EUR' }],
|
|
134
|
-
account: { userId: 'user_1' },
|
|
134
|
+
account: { userId: 'user_1', email: 'test@email.com' },
|
|
135
135
|
successUrl: '/success',
|
|
136
136
|
cancelUrl: '/cancel',
|
|
137
137
|
}}
|
|
138
|
-
onBeforeButtonClick={async ({ method }) => {
|
|
138
|
+
onBeforeButtonClick={async ({ method, createSession }) => {
|
|
139
139
|
if (method !== 'card') return;
|
|
140
140
|
|
|
141
|
-
const email = await openEmailCaptureModal(
|
|
141
|
+
const email = await openEmailCaptureModal({
|
|
142
|
+
initialEmail: createSession?.account.email ?? '',
|
|
143
|
+
});
|
|
142
144
|
if (!email) return false;
|
|
143
145
|
|
|
144
146
|
return {
|
|
@@ -178,7 +180,7 @@ Skip the backend API route — create the session directly in the component:
|
|
|
178
180
|
|
|
179
181
|
The component POSTs to the billing API, gets the full session back, and renders the form — zero backend code needed.
|
|
180
182
|
|
|
181
|
-
When you use `onBeforeButtonClick`, `createSession.account.email`
|
|
183
|
+
When you use `onBeforeButtonClick`, `createSession.account.email` should still be present when checkout renders. If you only have a temporary address such as `test@email.com`, pass it first and replace it in `onBeforeButtonClick` before the card flow continues. PayPal and wallet buttons still bootstrap normally, but this hook does not run for them, so collect any data those methods require before the user uses them.
|
|
182
184
|
|
|
183
185
|
### Advanced: Manual Provider Setup
|
|
184
186
|
|
package/dist/index.cjs
CHANGED
|
@@ -351,15 +351,6 @@ function buildSyntheticSession(params, checkoutModeOverride) {
|
|
|
351
351
|
}))
|
|
352
352
|
};
|
|
353
353
|
}
|
|
354
|
-
function ensureInlineSessionReady(params) {
|
|
355
|
-
if (!params.account.email?.trim()) {
|
|
356
|
-
throw new import_shared3.FloPayError(
|
|
357
|
-
"Email is required before continuing with card checkout.",
|
|
358
|
-
"validation_error",
|
|
359
|
-
{ param: "createSession.account.email" }
|
|
360
|
-
);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
354
|
function mergeAccountPatch(base, patch) {
|
|
364
355
|
if (!patch) return base;
|
|
365
356
|
return {
|
|
@@ -414,6 +405,52 @@ function toCssWeight(value) {
|
|
|
414
405
|
if (typeof value === "number" || typeof value === "string") return value;
|
|
415
406
|
return void 0;
|
|
416
407
|
}
|
|
408
|
+
function resolveExpressCheckoutLoadState(event, methods) {
|
|
409
|
+
const available = event.availablePaymentMethods;
|
|
410
|
+
if (!available) return "unavailable";
|
|
411
|
+
return methods.some((method) => available[method]) ? "ready" : "unavailable";
|
|
412
|
+
}
|
|
413
|
+
function ExpressCheckoutReadySwap({
|
|
414
|
+
state,
|
|
415
|
+
placeholderTestId,
|
|
416
|
+
children
|
|
417
|
+
}) {
|
|
418
|
+
if (state === "unavailable") return null;
|
|
419
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { position: "relative", minHeight: 44 }, children: [
|
|
420
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
421
|
+
"div",
|
|
422
|
+
{
|
|
423
|
+
"data-testid": placeholderTestId,
|
|
424
|
+
"aria-hidden": state === "ready",
|
|
425
|
+
style: {
|
|
426
|
+
position: "absolute",
|
|
427
|
+
inset: 0,
|
|
428
|
+
height: 44,
|
|
429
|
+
borderRadius: 8,
|
|
430
|
+
background: "#e5e7eb",
|
|
431
|
+
animation: state === "ready" ? void 0 : "flopay-pulse 1.5s ease-in-out infinite",
|
|
432
|
+
opacity: state === "ready" ? 0 : 1,
|
|
433
|
+
transform: state === "ready" ? "scale(0.985)" : "scale(1)",
|
|
434
|
+
transition: "opacity 140ms ease-out, transform 140ms ease-out",
|
|
435
|
+
pointerEvents: "none"
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
),
|
|
439
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
440
|
+
"div",
|
|
441
|
+
{
|
|
442
|
+
style: {
|
|
443
|
+
minHeight: 44,
|
|
444
|
+
opacity: state === "ready" ? 1 : 0,
|
|
445
|
+
transform: state === "ready" ? "translateY(0)" : "translateY(2px)",
|
|
446
|
+
transition: "opacity 140ms ease-out, transform 140ms ease-out",
|
|
447
|
+
pointerEvents: state === "ready" ? "auto" : "none"
|
|
448
|
+
},
|
|
449
|
+
children
|
|
450
|
+
}
|
|
451
|
+
)
|
|
452
|
+
] });
|
|
453
|
+
}
|
|
417
454
|
function ProcessingOverlay({ status, errorMessage }) {
|
|
418
455
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: {
|
|
419
456
|
position: "fixed",
|
|
@@ -531,7 +568,7 @@ function PayPalButtonInner({
|
|
|
531
568
|
}) {
|
|
532
569
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
533
570
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
534
|
-
const [
|
|
571
|
+
const [loadState, setLoadState] = (0, import_react6.useState)("loading");
|
|
535
572
|
const [submitting, setSubmitting] = (0, import_react6.useState)(false);
|
|
536
573
|
const paypalResumeAttempted = (0, import_react6.useRef)(false);
|
|
537
574
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
@@ -643,12 +680,11 @@ function PayPalButtonInner({
|
|
|
643
680
|
}
|
|
644
681
|
}, [stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline]);
|
|
645
682
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
646
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("
|
|
683
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-paypal-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
647
684
|
import_react_stripe_js.ExpressCheckoutElement,
|
|
648
685
|
{
|
|
649
|
-
onReady: () =>
|
|
650
|
-
onLoadError: () =>
|
|
651
|
-
},
|
|
686
|
+
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
|
|
687
|
+
onLoadError: () => setLoadState("unavailable"),
|
|
652
688
|
onConfirm: handlePayPalConfirm,
|
|
653
689
|
onCancel: () => {
|
|
654
690
|
onDecline?.(buildDeclineEvent("paypal", "PayPal checkout was cancelled."));
|
|
@@ -680,7 +716,7 @@ function WalletButtonInner({
|
|
|
680
716
|
}) {
|
|
681
717
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
682
718
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
683
|
-
const [
|
|
719
|
+
const [loadState, setLoadState] = (0, import_react6.useState)("loading");
|
|
684
720
|
const [submitting, setSubmitting] = (0, import_react6.useState)(false);
|
|
685
721
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
686
722
|
const lastWalletMethodRef = (0, import_react6.useRef)("card");
|
|
@@ -746,12 +782,11 @@ function WalletButtonInner({
|
|
|
746
782
|
[stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline]
|
|
747
783
|
);
|
|
748
784
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
749
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("
|
|
785
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-wallet-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
750
786
|
import_react_stripe_js.ExpressCheckoutElement,
|
|
751
787
|
{
|
|
752
|
-
onReady: () =>
|
|
753
|
-
onLoadError: () =>
|
|
754
|
-
},
|
|
788
|
+
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["applePay", "googlePay"])),
|
|
789
|
+
onLoadError: () => setLoadState("unavailable"),
|
|
755
790
|
onClick: (event) => {
|
|
756
791
|
lastWalletMethodRef.current = event.expressPaymentType === "apple_pay" ? "apple_pay" : "google_pay";
|
|
757
792
|
event.resolve();
|
|
@@ -795,6 +830,7 @@ function SplitCardFormInner({
|
|
|
795
830
|
isProcessing: externalProcessing,
|
|
796
831
|
error: externalError,
|
|
797
832
|
onErrorChange,
|
|
833
|
+
onFullNameChange,
|
|
798
834
|
onFirstNameChange,
|
|
799
835
|
onLastNameChange,
|
|
800
836
|
showPayPal = true,
|
|
@@ -821,6 +857,7 @@ function SplitCardFormInner({
|
|
|
821
857
|
}) {
|
|
822
858
|
const flopay = useFloPay();
|
|
823
859
|
const elements = useElements();
|
|
860
|
+
const checkout = (0, import_react6.useContext)(CheckoutContext);
|
|
824
861
|
const contextBillingUrl = useBillingApiUrl();
|
|
825
862
|
const [processing, setProcessing] = (0, import_react6.useState)(false);
|
|
826
863
|
const [error, setError] = (0, import_react6.useState)(null);
|
|
@@ -866,7 +903,8 @@ function SplitCardFormInner({
|
|
|
866
903
|
title: { ...base.title, ...buttonsStylesOverride.title }
|
|
867
904
|
};
|
|
868
905
|
}, [buttonsTheme, buttonsStylesOverride]);
|
|
869
|
-
const
|
|
906
|
+
const isInlineSessionPatchProcessing = checkout.inlineSessionPatchProcessing ?? false;
|
|
907
|
+
const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
|
|
870
908
|
const isSelfContained = !onTokenizedBody;
|
|
871
909
|
const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
|
|
872
910
|
const resolvedAccount = (0, import_react6.useMemo)(() => mergeAccountPatch({
|
|
@@ -911,10 +949,11 @@ function SplitCardFormInner({
|
|
|
911
949
|
const showWallets = showApplePay || showGooglePay;
|
|
912
950
|
const handleNameChange = (0, import_react6.useCallback)((value) => {
|
|
913
951
|
setFullName(value);
|
|
952
|
+
onFullNameChange?.(value);
|
|
914
953
|
const parts = value.trim().split(/\s+/);
|
|
915
954
|
onFirstNameChange?.(parts[0] ?? "");
|
|
916
955
|
onLastNameChange?.(parts.length > 1 ? parts.slice(1).join(" ") : "");
|
|
917
|
-
}, [onFirstNameChange, onLastNameChange]);
|
|
956
|
+
}, [onFullNameChange, onFirstNameChange, onLastNameChange]);
|
|
918
957
|
const runBeforeCardButtonClick = (0, import_react6.useCallback)(async () => {
|
|
919
958
|
if (!onBeforeButtonClick) return true;
|
|
920
959
|
try {
|
|
@@ -925,8 +964,11 @@ function SplitCardFormInner({
|
|
|
925
964
|
if (result === false) {
|
|
926
965
|
return false;
|
|
927
966
|
}
|
|
928
|
-
if (result
|
|
929
|
-
|
|
967
|
+
if (result && typeof result === "object") {
|
|
968
|
+
await checkout.applyInlineSessionPatch?.(result);
|
|
969
|
+
if (result.account) {
|
|
970
|
+
setAccountPatch((prev) => ({ ...prev ?? {}, ...result.account }));
|
|
971
|
+
}
|
|
930
972
|
}
|
|
931
973
|
return true;
|
|
932
974
|
} catch (err) {
|
|
@@ -938,7 +980,7 @@ function SplitCardFormInner({
|
|
|
938
980
|
onError?.(floPayErr);
|
|
939
981
|
return false;
|
|
940
982
|
}
|
|
941
|
-
}, [onBeforeButtonClick, sessionId, updateError, onError]);
|
|
983
|
+
}, [checkout.applyInlineSessionPatch, onBeforeButtonClick, sessionId, updateError, onError]);
|
|
942
984
|
const processPaymentInternal = (0, import_react6.useCallback)(
|
|
943
985
|
async (tokenizedBody) => {
|
|
944
986
|
if (processingRef.current) return;
|
|
@@ -1547,11 +1589,13 @@ function SplitCardFormInner({
|
|
|
1547
1589
|
{
|
|
1548
1590
|
type: "button",
|
|
1549
1591
|
onClick: async () => {
|
|
1592
|
+
if (isSubmitting) return;
|
|
1550
1593
|
const shouldContinue = await runBeforeCardButtonClick();
|
|
1551
1594
|
if (!shouldContinue) return;
|
|
1552
1595
|
onButtonClick?.("card");
|
|
1553
1596
|
expandToCard();
|
|
1554
1597
|
},
|
|
1598
|
+
disabled: isSubmitting,
|
|
1555
1599
|
style: {
|
|
1556
1600
|
width: "100%",
|
|
1557
1601
|
padding: "0.9rem 1rem",
|
|
@@ -1561,7 +1605,7 @@ function SplitCardFormInner({
|
|
|
1561
1605
|
borderRadius: "8px",
|
|
1562
1606
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
1563
1607
|
fontWeight: 600,
|
|
1564
|
-
cursor: "pointer",
|
|
1608
|
+
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
1565
1609
|
display: "flex",
|
|
1566
1610
|
alignItems: "center",
|
|
1567
1611
|
justifyContent: "center",
|
|
@@ -1569,6 +1613,7 @@ function SplitCardFormInner({
|
|
|
1569
1613
|
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
1570
1614
|
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
1571
1615
|
position: "relative",
|
|
1616
|
+
opacity: isSubmitting ? 0.6 : 1,
|
|
1572
1617
|
...bStyles.cardButton
|
|
1573
1618
|
},
|
|
1574
1619
|
onMouseDown: (e) => {
|
|
@@ -1652,6 +1697,12 @@ function SplitCardFormInner({
|
|
|
1652
1697
|
|
|
1653
1698
|
// src/flopay-checkout.tsx
|
|
1654
1699
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1700
|
+
function hasInlineSessionPatchData(patch) {
|
|
1701
|
+
if (!patch) return false;
|
|
1702
|
+
return Boolean(
|
|
1703
|
+
patch.account && Object.keys(patch.account).length > 0 || patch.couponCodes !== void 0 || patch.tagsData !== void 0 || patch.utmMetadata !== void 0
|
|
1704
|
+
);
|
|
1705
|
+
}
|
|
1655
1706
|
function FloPayCheckout({
|
|
1656
1707
|
sessionId: sessionIdProp,
|
|
1657
1708
|
createSession: createSessionParams,
|
|
@@ -1664,6 +1715,9 @@ function FloPayCheckout({
|
|
|
1664
1715
|
onComplete,
|
|
1665
1716
|
onError,
|
|
1666
1717
|
onDecline,
|
|
1718
|
+
onFullNameChange,
|
|
1719
|
+
onCountryChange,
|
|
1720
|
+
onZipChange,
|
|
1667
1721
|
showPayPal = true,
|
|
1668
1722
|
showApplePay = true,
|
|
1669
1723
|
showGooglePay = true,
|
|
@@ -1699,7 +1753,6 @@ function FloPayCheckout({
|
|
|
1699
1753
|
const [createSessionPatch, setCreateSessionPatch] = (0, import_react7.useState)(void 0);
|
|
1700
1754
|
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0, import_react7.useState)("");
|
|
1701
1755
|
const [cardBootstrapPending, setCardBootstrapPending] = (0, import_react7.useState)(false);
|
|
1702
|
-
const [deferredCardOpen, setDeferredCardOpen] = (0, import_react7.useState)(false);
|
|
1703
1756
|
const autoCheckoutAttempted = (0, import_react7.useRef)(false);
|
|
1704
1757
|
const onCompleteRef = (0, import_react7.useRef)(onComplete);
|
|
1705
1758
|
onCompleteRef.current = onComplete;
|
|
@@ -1834,9 +1887,6 @@ function FloPayCheckout({
|
|
|
1834
1887
|
);
|
|
1835
1888
|
const inflightRef = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
|
|
1836
1889
|
const initializedHashRef = (0, import_react7.useRef)(null);
|
|
1837
|
-
const deferInlineSessionUntilCardClick = Boolean(
|
|
1838
|
-
effectiveCreateSession && !children && layout === "buttons" && onBeforeButtonClick && (effectiveCreateSession.checkoutMode ?? checkoutModeProp ?? "full") === "full"
|
|
1839
|
-
);
|
|
1840
1890
|
function hashCreateParams(params) {
|
|
1841
1891
|
const key = JSON.stringify({
|
|
1842
1892
|
c: params?.clientId,
|
|
@@ -1866,7 +1916,6 @@ function FloPayCheckout({
|
|
|
1866
1916
|
setResolvedSessionId(sessionIdProp ?? "");
|
|
1867
1917
|
}, [sessionIdProp]);
|
|
1868
1918
|
async function resolveInlineSession(params, cacheKey) {
|
|
1869
|
-
ensureInlineSessionReady(params);
|
|
1870
1919
|
const api = new import_js.PaymentAPI(resolvedBillingUrl);
|
|
1871
1920
|
let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
|
|
1872
1921
|
let realResult = null;
|
|
@@ -1911,104 +1960,64 @@ function FloPayCheckout({
|
|
|
1911
1960
|
} finally {
|
|
1912
1961
|
inflightRef.current.delete(cacheKey);
|
|
1913
1962
|
}
|
|
1914
|
-
if (patch) {
|
|
1915
|
-
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
1916
|
-
setCreateSessionPatch((prev) => mergeInlineSessionPatches(prev, patch));
|
|
1917
|
-
}
|
|
1918
|
-
const { sid, result: realResult } = resolved;
|
|
1919
|
-
setUnified(realResult);
|
|
1920
|
-
if (realResult.data.session) {
|
|
1921
|
-
setSession(realResult.data.session);
|
|
1922
|
-
}
|
|
1923
|
-
if (sid) {
|
|
1924
|
-
setResolvedSessionId(sid);
|
|
1925
|
-
}
|
|
1926
|
-
let publishableKey;
|
|
1927
|
-
if (realResult.provider === "stripe") {
|
|
1928
|
-
publishableKey = realResult.data.stripe?.publishableKey;
|
|
1929
|
-
}
|
|
1930
|
-
if (!publishableKey) publishableKey = fallbackPublishableKey;
|
|
1931
|
-
if (!publishableKey) {
|
|
1932
|
-
throw new import_shared6.FloPayError(
|
|
1933
|
-
"No publishable key found. Provide fallbackPublishableKey or ensure the session includes gatewayData.publishableKey.",
|
|
1934
|
-
"validation_error"
|
|
1935
|
-
);
|
|
1936
|
-
}
|
|
1937
|
-
const instance = await (0, import_js.loadFloPay)(publishableKey, {
|
|
1938
|
-
billingApiUrl: resolvedBillingUrl,
|
|
1939
|
-
locale
|
|
1940
|
-
});
|
|
1941
|
-
flopayRef.current = instance;
|
|
1942
|
-
setFloPay(instance);
|
|
1943
1963
|
initializedHashRef.current = cacheKey;
|
|
1944
|
-
|
|
1964
|
+
try {
|
|
1965
|
+
if (patch) {
|
|
1966
|
+
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
1967
|
+
setCreateSessionPatch((prev) => mergeInlineSessionPatches(prev, patch));
|
|
1968
|
+
}
|
|
1969
|
+
const { sid, result: realResult } = resolved;
|
|
1970
|
+
setUnified(realResult);
|
|
1971
|
+
if (realResult.data.session) {
|
|
1972
|
+
setSession(realResult.data.session);
|
|
1973
|
+
}
|
|
1974
|
+
if (sid) {
|
|
1975
|
+
setResolvedSessionId(sid);
|
|
1976
|
+
}
|
|
1977
|
+
let publishableKey;
|
|
1978
|
+
if (realResult.provider === "stripe") {
|
|
1979
|
+
publishableKey = realResult.data.stripe?.publishableKey;
|
|
1980
|
+
}
|
|
1981
|
+
if (!publishableKey) publishableKey = fallbackPublishableKey;
|
|
1982
|
+
if (!publishableKey) {
|
|
1983
|
+
throw new import_shared6.FloPayError(
|
|
1984
|
+
"No publishable key found. Provide fallbackPublishableKey or ensure the session includes gatewayData.publishableKey.",
|
|
1985
|
+
"validation_error"
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
const instance = await (0, import_js.loadFloPay)(publishableKey, {
|
|
1989
|
+
billingApiUrl: resolvedBillingUrl,
|
|
1990
|
+
locale
|
|
1991
|
+
});
|
|
1992
|
+
flopayRef.current = instance;
|
|
1993
|
+
setFloPay(instance);
|
|
1994
|
+
setIsLoading(false);
|
|
1995
|
+
} catch (err) {
|
|
1996
|
+
if (initializedHashRef.current === cacheKey) {
|
|
1997
|
+
initializedHashRef.current = null;
|
|
1998
|
+
}
|
|
1999
|
+
throw err;
|
|
2000
|
+
}
|
|
1945
2001
|
return resolved;
|
|
1946
2002
|
},
|
|
1947
2003
|
[fallbackPublishableKey, locale, resolvedBillingUrl]
|
|
1948
2004
|
);
|
|
1949
|
-
const
|
|
1950
|
-
if (cardBootstrapPending) return;
|
|
1951
|
-
setLoadError(null);
|
|
2005
|
+
const handleInlineSessionPatch = (0, import_react7.useCallback)(async (patch) => {
|
|
2006
|
+
if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) return;
|
|
1952
2007
|
setCardBootstrapPending(true);
|
|
1953
2008
|
try {
|
|
1954
|
-
const beforeClickResult = await onBeforeButtonClick?.({
|
|
1955
|
-
method: "card",
|
|
1956
|
-
createSession: effectiveCreateSession
|
|
1957
|
-
});
|
|
1958
|
-
if (beforeClickResult === false) {
|
|
1959
|
-
setDeferredCardOpen(false);
|
|
1960
|
-
return;
|
|
1961
|
-
}
|
|
1962
|
-
const patch = beforeClickResult && typeof beforeClickResult === "object" ? beforeClickResult : void 0;
|
|
1963
|
-
const baseParams = createSessionParamsRef.current;
|
|
1964
|
-
if (!baseParams) {
|
|
1965
|
-
throw new import_shared6.FloPayError(
|
|
1966
|
-
"createSession is required to bootstrap checkout.",
|
|
1967
|
-
"validation_error"
|
|
1968
|
-
);
|
|
1969
|
-
}
|
|
1970
|
-
ensureInlineSessionReady(mergeInlineSessionPatch(baseParams, patch));
|
|
1971
|
-
setDeferredCardOpen(true);
|
|
1972
|
-
onButtonClick?.("card");
|
|
1973
2009
|
await bootstrapInlineSession(patch);
|
|
1974
|
-
} catch (err) {
|
|
1975
|
-
setDeferredCardOpen(false);
|
|
1976
|
-
const floPayErr = err instanceof import_shared6.FloPayError ? err : new import_shared6.FloPayError(
|
|
1977
|
-
err instanceof Error ? err.message : "Failed to start card checkout.",
|
|
1978
|
-
"api_error"
|
|
1979
|
-
);
|
|
1980
|
-
setLoadError(floPayErr);
|
|
1981
|
-
onErrorRef.current?.(floPayErr);
|
|
1982
2010
|
} finally {
|
|
1983
2011
|
setCardBootstrapPending(false);
|
|
1984
2012
|
}
|
|
1985
2013
|
}, [
|
|
1986
2014
|
bootstrapInlineSession,
|
|
1987
|
-
|
|
1988
|
-
cardBootstrapPending,
|
|
1989
|
-
effectiveCreateSession,
|
|
1990
|
-
onButtonClick,
|
|
1991
|
-
onBeforeButtonClick
|
|
2015
|
+
cardBootstrapPending
|
|
1992
2016
|
]);
|
|
1993
2017
|
(0, import_react7.useEffect)(() => {
|
|
1994
2018
|
let cancelled = false;
|
|
1995
2019
|
setLoadError(null);
|
|
1996
2020
|
if (createSessionHash) {
|
|
1997
|
-
if (deferInlineSessionUntilCardClick) {
|
|
1998
|
-
if (initializedHashRef.current !== createSessionHash) {
|
|
1999
|
-
setSession(null);
|
|
2000
|
-
setUnified(null);
|
|
2001
|
-
setFloPay(null);
|
|
2002
|
-
setResolvedSessionId("");
|
|
2003
|
-
setDeferredCardOpen(false);
|
|
2004
|
-
flopayRef.current = null;
|
|
2005
|
-
}
|
|
2006
|
-
setCurrentMode(createSessionParamsRef.current?.checkoutMode ?? checkoutModeProp ?? "full");
|
|
2007
|
-
setIsLoading(false);
|
|
2008
|
-
return () => {
|
|
2009
|
-
cancelled = true;
|
|
2010
|
-
};
|
|
2011
|
-
}
|
|
2012
2021
|
if (initializedHashRef.current === createSessionHash) return;
|
|
2013
2022
|
const params = createSessionParamsRef.current;
|
|
2014
2023
|
setSession(buildSyntheticSession(params, checkoutModeProp));
|
|
@@ -2104,7 +2113,7 @@ function FloPayCheckout({
|
|
|
2104
2113
|
return () => {
|
|
2105
2114
|
cancelled = true;
|
|
2106
2115
|
};
|
|
2107
|
-
}, [resolvedSessionId, createSessionHash, checkoutModeProp,
|
|
2116
|
+
}, [resolvedSessionId, createSessionHash, checkoutModeProp, bootstrapInlineSession]);
|
|
2108
2117
|
const handleConfirmCheckout = (0, import_react7.useCallback)(async () => {
|
|
2109
2118
|
if (confirmProcessing || !session) return;
|
|
2110
2119
|
setConfirmProcessing(true);
|
|
@@ -2147,17 +2156,29 @@ function FloPayCheckout({
|
|
|
2147
2156
|
}
|
|
2148
2157
|
return opts;
|
|
2149
2158
|
}, [unified, session, appearance, resolvedBillingUrl]);
|
|
2159
|
+
const shouldHandleInlineSessionPatch = Boolean(
|
|
2160
|
+
createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && (effectiveCreateSession?.checkoutMode ?? checkoutModeProp ?? "full") === "full"
|
|
2161
|
+
);
|
|
2150
2162
|
const checkoutValue = (0, import_react7.useMemo)(
|
|
2151
2163
|
() => ({
|
|
2152
2164
|
session,
|
|
2153
2165
|
loading: isLoading,
|
|
2154
2166
|
error: loadError,
|
|
2155
|
-
checkoutMode: currentMode
|
|
2167
|
+
checkoutMode: currentMode,
|
|
2168
|
+
applyInlineSessionPatch: shouldHandleInlineSessionPatch ? handleInlineSessionPatch : void 0,
|
|
2169
|
+
inlineSessionPatchProcessing: cardBootstrapPending
|
|
2156
2170
|
}),
|
|
2157
|
-
[
|
|
2171
|
+
[
|
|
2172
|
+
session,
|
|
2173
|
+
isLoading,
|
|
2174
|
+
loadError,
|
|
2175
|
+
currentMode,
|
|
2176
|
+
shouldHandleInlineSessionPatch,
|
|
2177
|
+
handleInlineSessionPatch,
|
|
2178
|
+
cardBootstrapPending
|
|
2179
|
+
]
|
|
2158
2180
|
);
|
|
2159
2181
|
const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && (!flopay || !providerOptions);
|
|
2160
|
-
const shouldKeepDeferredInterimVisible = shouldShowInterimButtons && deferInlineSessionUntilCardClick;
|
|
2161
2182
|
if (isLoading) {
|
|
2162
2183
|
if (loadingNode) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: loadingNode });
|
|
2163
2184
|
if (layout === "buttons") {
|
|
@@ -2186,7 +2207,7 @@ function FloPayCheckout({
|
|
|
2186
2207
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
2187
2208
|
] });
|
|
2188
2209
|
}
|
|
2189
|
-
if (loadError
|
|
2210
|
+
if (loadError) {
|
|
2190
2211
|
if (errorNode) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: errorNode(loadError) });
|
|
2191
2212
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2192
2213
|
"div",
|
|
@@ -2206,13 +2227,9 @@ function FloPayCheckout({
|
|
|
2206
2227
|
InterimButtonsView,
|
|
2207
2228
|
{
|
|
2208
2229
|
onButtonClick,
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
errorMessage: shouldKeepDeferredInterimVisible ? loadError?.message ?? null : null,
|
|
2213
|
-
showPayPal: deferInlineSessionUntilCardClick ? false : showPayPal,
|
|
2214
|
-
showApplePay: deferInlineSessionUntilCardClick ? false : showApplePay,
|
|
2215
|
-
showGooglePay: deferInlineSessionUntilCardClick ? false : showGooglePay,
|
|
2230
|
+
showPayPal,
|
|
2231
|
+
showApplePay,
|
|
2232
|
+
showGooglePay,
|
|
2216
2233
|
buttonsTheme,
|
|
2217
2234
|
buttonsStyles,
|
|
2218
2235
|
cardButtonContent,
|
|
@@ -2299,6 +2316,7 @@ function FloPayCheckout({
|
|
|
2299
2316
|
onComplete,
|
|
2300
2317
|
onError,
|
|
2301
2318
|
onDecline,
|
|
2319
|
+
onFullNameChange,
|
|
2302
2320
|
showPayPal,
|
|
2303
2321
|
showApplePay,
|
|
2304
2322
|
showGooglePay,
|
|
@@ -2313,7 +2331,8 @@ function FloPayCheckout({
|
|
|
2313
2331
|
enableAVS,
|
|
2314
2332
|
avsLayout,
|
|
2315
2333
|
country: session?.customer?.country,
|
|
2316
|
-
|
|
2334
|
+
onCountryChange,
|
|
2335
|
+
onZipChange,
|
|
2317
2336
|
submitLabel,
|
|
2318
2337
|
className
|
|
2319
2338
|
}
|