@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/dist/index.d.cts
CHANGED
|
@@ -72,6 +72,12 @@ interface FloPayCheckoutProps {
|
|
|
72
72
|
onError?: (error: FloPayError) => void;
|
|
73
73
|
/** Called when a payment is declined or the authentication step fails. */
|
|
74
74
|
onDecline?: (decline: DeclineEvent) => void;
|
|
75
|
+
/** Called when the full cardholder name input changes. */
|
|
76
|
+
onFullNameChange?: (value: string) => void;
|
|
77
|
+
/** Called when the AVS country dropdown changes. */
|
|
78
|
+
onCountryChange?: (country: string) => void;
|
|
79
|
+
/** Called when the AVS ZIP/postcode input changes. */
|
|
80
|
+
onZipChange?: (zip: string) => void;
|
|
75
81
|
/** Whether to show the PayPal button (default: true). */
|
|
76
82
|
showPayPal?: boolean;
|
|
77
83
|
/** Whether to show Apple Pay button (default: true). Only renders on supported devices. */
|
|
@@ -152,7 +158,7 @@ interface FloPayCheckoutProps {
|
|
|
152
158
|
* />
|
|
153
159
|
* ```
|
|
154
160
|
*/
|
|
155
|
-
declare function FloPayCheckout({ sessionId: sessionIdProp, createSession: createSessionParams, billingApiUrl, appearance, locale, fallbackPublishableKey, loading: loadingNode, error: errorNode, onComplete, onError, onDecline, showPayPal, showApplePay, showGooglePay, layout, buttonsTheme, buttonsStyles, cardButtonContent, cardBackButtonContent, cardTitleContent, onButtonClick, onBeforeButtonClick, enableAVS, avsLayout, submitLabel, className, children, checkoutMode: checkoutModeProp, confirmLabel, renderConfirmButton, onSessionCompleted, }: FloPayCheckoutProps): React.ReactElement;
|
|
161
|
+
declare function FloPayCheckout({ sessionId: sessionIdProp, createSession: createSessionParams, billingApiUrl, appearance, locale, fallbackPublishableKey, loading: loadingNode, error: errorNode, onComplete, onError, onDecline, onFullNameChange, onCountryChange, onZipChange, showPayPal, showApplePay, showGooglePay, layout, buttonsTheme, buttonsStyles, cardButtonContent, cardBackButtonContent, cardTitleContent, onButtonClick, onBeforeButtonClick, enableAVS, avsLayout, submitLabel, className, children, checkoutMode: checkoutModeProp, confirmLabel, renderConfirmButton, onSessionCompleted, }: FloPayCheckoutProps): React.ReactElement;
|
|
156
162
|
|
|
157
163
|
/**
|
|
158
164
|
* Returns the current `FloPay` instance, or `null` if the provider
|
|
@@ -366,6 +372,8 @@ interface SplitCardFormProps {
|
|
|
366
372
|
error?: string | null;
|
|
367
373
|
/** Called when internal error state changes. */
|
|
368
374
|
onErrorChange?: (error: string | null) => void;
|
|
375
|
+
/** Callback when the full cardholder name input changes. */
|
|
376
|
+
onFullNameChange?: (value: string) => void;
|
|
369
377
|
/** Callback when first name changes (from the name input). */
|
|
370
378
|
onFirstNameChange?: (value: string) => void;
|
|
371
379
|
/** Callback when last name changes (from the name input). */
|
package/dist/index.d.ts
CHANGED
|
@@ -72,6 +72,12 @@ interface FloPayCheckoutProps {
|
|
|
72
72
|
onError?: (error: FloPayError) => void;
|
|
73
73
|
/** Called when a payment is declined or the authentication step fails. */
|
|
74
74
|
onDecline?: (decline: DeclineEvent) => void;
|
|
75
|
+
/** Called when the full cardholder name input changes. */
|
|
76
|
+
onFullNameChange?: (value: string) => void;
|
|
77
|
+
/** Called when the AVS country dropdown changes. */
|
|
78
|
+
onCountryChange?: (country: string) => void;
|
|
79
|
+
/** Called when the AVS ZIP/postcode input changes. */
|
|
80
|
+
onZipChange?: (zip: string) => void;
|
|
75
81
|
/** Whether to show the PayPal button (default: true). */
|
|
76
82
|
showPayPal?: boolean;
|
|
77
83
|
/** Whether to show Apple Pay button (default: true). Only renders on supported devices. */
|
|
@@ -152,7 +158,7 @@ interface FloPayCheckoutProps {
|
|
|
152
158
|
* />
|
|
153
159
|
* ```
|
|
154
160
|
*/
|
|
155
|
-
declare function FloPayCheckout({ sessionId: sessionIdProp, createSession: createSessionParams, billingApiUrl, appearance, locale, fallbackPublishableKey, loading: loadingNode, error: errorNode, onComplete, onError, onDecline, showPayPal, showApplePay, showGooglePay, layout, buttonsTheme, buttonsStyles, cardButtonContent, cardBackButtonContent, cardTitleContent, onButtonClick, onBeforeButtonClick, enableAVS, avsLayout, submitLabel, className, children, checkoutMode: checkoutModeProp, confirmLabel, renderConfirmButton, onSessionCompleted, }: FloPayCheckoutProps): React.ReactElement;
|
|
161
|
+
declare function FloPayCheckout({ sessionId: sessionIdProp, createSession: createSessionParams, billingApiUrl, appearance, locale, fallbackPublishableKey, loading: loadingNode, error: errorNode, onComplete, onError, onDecline, onFullNameChange, onCountryChange, onZipChange, showPayPal, showApplePay, showGooglePay, layout, buttonsTheme, buttonsStyles, cardButtonContent, cardBackButtonContent, cardTitleContent, onButtonClick, onBeforeButtonClick, enableAVS, avsLayout, submitLabel, className, children, checkoutMode: checkoutModeProp, confirmLabel, renderConfirmButton, onSessionCompleted, }: FloPayCheckoutProps): React.ReactElement;
|
|
156
162
|
|
|
157
163
|
/**
|
|
158
164
|
* Returns the current `FloPay` instance, or `null` if the provider
|
|
@@ -366,6 +372,8 @@ interface SplitCardFormProps {
|
|
|
366
372
|
error?: string | null;
|
|
367
373
|
/** Called when internal error state changes. */
|
|
368
374
|
onErrorChange?: (error: string | null) => void;
|
|
375
|
+
/** Callback when the full cardholder name input changes. */
|
|
376
|
+
onFullNameChange?: (value: string) => void;
|
|
369
377
|
/** Callback when first name changes (from the name input). */
|
|
370
378
|
onFirstNameChange?: (value: string) => void;
|
|
371
379
|
/** Callback when last name changes (from the name input). */
|
package/dist/index.mjs
CHANGED
|
@@ -206,7 +206,7 @@ import {
|
|
|
206
206
|
useStripe as useStripeRaw
|
|
207
207
|
} from "@stripe/react-stripe-js";
|
|
208
208
|
import { resolveButtonsLayoutTheme, getPostalCodeLabel, COUNTRY_OPTIONS } from "@flopay/shared";
|
|
209
|
-
import { forwardRef, useCallback, useEffect as useEffect3, useImperativeHandle, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
209
|
+
import { forwardRef, useCallback, useContext as useContext3, useEffect as useEffect3, useImperativeHandle, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
210
210
|
|
|
211
211
|
// src/hooks.ts
|
|
212
212
|
import { useContext as useContext2 } from "react";
|
|
@@ -307,15 +307,6 @@ function buildSyntheticSession(params, checkoutModeOverride) {
|
|
|
307
307
|
}))
|
|
308
308
|
};
|
|
309
309
|
}
|
|
310
|
-
function ensureInlineSessionReady(params) {
|
|
311
|
-
if (!params.account.email?.trim()) {
|
|
312
|
-
throw new FloPayError(
|
|
313
|
-
"Email is required before continuing with card checkout.",
|
|
314
|
-
"validation_error",
|
|
315
|
-
{ param: "createSession.account.email" }
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
310
|
function mergeAccountPatch(base, patch) {
|
|
320
311
|
if (!patch) return base;
|
|
321
312
|
return {
|
|
@@ -370,6 +361,52 @@ function toCssWeight(value) {
|
|
|
370
361
|
if (typeof value === "number" || typeof value === "string") return value;
|
|
371
362
|
return void 0;
|
|
372
363
|
}
|
|
364
|
+
function resolveExpressCheckoutLoadState(event, methods) {
|
|
365
|
+
const available = event.availablePaymentMethods;
|
|
366
|
+
if (!available) return "unavailable";
|
|
367
|
+
return methods.some((method) => available[method]) ? "ready" : "unavailable";
|
|
368
|
+
}
|
|
369
|
+
function ExpressCheckoutReadySwap({
|
|
370
|
+
state,
|
|
371
|
+
placeholderTestId,
|
|
372
|
+
children
|
|
373
|
+
}) {
|
|
374
|
+
if (state === "unavailable") return null;
|
|
375
|
+
return /* @__PURE__ */ jsxs2("div", { style: { position: "relative", minHeight: 44 }, children: [
|
|
376
|
+
/* @__PURE__ */ jsx4(
|
|
377
|
+
"div",
|
|
378
|
+
{
|
|
379
|
+
"data-testid": placeholderTestId,
|
|
380
|
+
"aria-hidden": state === "ready",
|
|
381
|
+
style: {
|
|
382
|
+
position: "absolute",
|
|
383
|
+
inset: 0,
|
|
384
|
+
height: 44,
|
|
385
|
+
borderRadius: 8,
|
|
386
|
+
background: "#e5e7eb",
|
|
387
|
+
animation: state === "ready" ? void 0 : "flopay-pulse 1.5s ease-in-out infinite",
|
|
388
|
+
opacity: state === "ready" ? 0 : 1,
|
|
389
|
+
transform: state === "ready" ? "scale(0.985)" : "scale(1)",
|
|
390
|
+
transition: "opacity 140ms ease-out, transform 140ms ease-out",
|
|
391
|
+
pointerEvents: "none"
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
),
|
|
395
|
+
/* @__PURE__ */ jsx4(
|
|
396
|
+
"div",
|
|
397
|
+
{
|
|
398
|
+
style: {
|
|
399
|
+
minHeight: 44,
|
|
400
|
+
opacity: state === "ready" ? 1 : 0,
|
|
401
|
+
transform: state === "ready" ? "translateY(0)" : "translateY(2px)",
|
|
402
|
+
transition: "opacity 140ms ease-out, transform 140ms ease-out",
|
|
403
|
+
pointerEvents: state === "ready" ? "auto" : "none"
|
|
404
|
+
},
|
|
405
|
+
children
|
|
406
|
+
}
|
|
407
|
+
)
|
|
408
|
+
] });
|
|
409
|
+
}
|
|
373
410
|
function ProcessingOverlay({ status, errorMessage }) {
|
|
374
411
|
return /* @__PURE__ */ jsx4("div", { style: {
|
|
375
412
|
position: "fixed",
|
|
@@ -487,7 +524,7 @@ function PayPalButtonInner({
|
|
|
487
524
|
}) {
|
|
488
525
|
const stripe = useStripeRaw();
|
|
489
526
|
const elements = useStripeElements();
|
|
490
|
-
const [
|
|
527
|
+
const [loadState, setLoadState] = useState2("loading");
|
|
491
528
|
const [submitting, setSubmitting] = useState2(false);
|
|
492
529
|
const paypalResumeAttempted = useRef2(false);
|
|
493
530
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
@@ -599,12 +636,11 @@ function PayPalButtonInner({
|
|
|
599
636
|
}
|
|
600
637
|
}, [stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline]);
|
|
601
638
|
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
602
|
-
/* @__PURE__ */ jsx4("
|
|
639
|
+
/* @__PURE__ */ jsx4(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-paypal-placeholder", children: /* @__PURE__ */ jsx4(
|
|
603
640
|
ExpressCheckoutElement,
|
|
604
641
|
{
|
|
605
|
-
onReady: () =>
|
|
606
|
-
onLoadError: () =>
|
|
607
|
-
},
|
|
642
|
+
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
|
|
643
|
+
onLoadError: () => setLoadState("unavailable"),
|
|
608
644
|
onConfirm: handlePayPalConfirm,
|
|
609
645
|
onCancel: () => {
|
|
610
646
|
onDecline?.(buildDeclineEvent("paypal", "PayPal checkout was cancelled."));
|
|
@@ -636,7 +672,7 @@ function WalletButtonInner({
|
|
|
636
672
|
}) {
|
|
637
673
|
const stripe = useStripeRaw();
|
|
638
674
|
const elements = useStripeElements();
|
|
639
|
-
const [
|
|
675
|
+
const [loadState, setLoadState] = useState2("loading");
|
|
640
676
|
const [submitting, setSubmitting] = useState2(false);
|
|
641
677
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
642
678
|
const lastWalletMethodRef = useRef2("card");
|
|
@@ -702,12 +738,11 @@ function WalletButtonInner({
|
|
|
702
738
|
[stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline]
|
|
703
739
|
);
|
|
704
740
|
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
705
|
-
/* @__PURE__ */ jsx4("
|
|
741
|
+
/* @__PURE__ */ jsx4(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-wallet-placeholder", children: /* @__PURE__ */ jsx4(
|
|
706
742
|
ExpressCheckoutElement,
|
|
707
743
|
{
|
|
708
|
-
onReady: () =>
|
|
709
|
-
onLoadError: () =>
|
|
710
|
-
},
|
|
744
|
+
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["applePay", "googlePay"])),
|
|
745
|
+
onLoadError: () => setLoadState("unavailable"),
|
|
711
746
|
onClick: (event) => {
|
|
712
747
|
lastWalletMethodRef.current = event.expressPaymentType === "apple_pay" ? "apple_pay" : "google_pay";
|
|
713
748
|
event.resolve();
|
|
@@ -751,6 +786,7 @@ function SplitCardFormInner({
|
|
|
751
786
|
isProcessing: externalProcessing,
|
|
752
787
|
error: externalError,
|
|
753
788
|
onErrorChange,
|
|
789
|
+
onFullNameChange,
|
|
754
790
|
onFirstNameChange,
|
|
755
791
|
onLastNameChange,
|
|
756
792
|
showPayPal = true,
|
|
@@ -777,6 +813,7 @@ function SplitCardFormInner({
|
|
|
777
813
|
}) {
|
|
778
814
|
const flopay = useFloPay();
|
|
779
815
|
const elements = useElements();
|
|
816
|
+
const checkout = useContext3(CheckoutContext);
|
|
780
817
|
const contextBillingUrl = useBillingApiUrl();
|
|
781
818
|
const [processing, setProcessing] = useState2(false);
|
|
782
819
|
const [error, setError] = useState2(null);
|
|
@@ -822,7 +859,8 @@ function SplitCardFormInner({
|
|
|
822
859
|
title: { ...base.title, ...buttonsStylesOverride.title }
|
|
823
860
|
};
|
|
824
861
|
}, [buttonsTheme, buttonsStylesOverride]);
|
|
825
|
-
const
|
|
862
|
+
const isInlineSessionPatchProcessing = checkout.inlineSessionPatchProcessing ?? false;
|
|
863
|
+
const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
|
|
826
864
|
const isSelfContained = !onTokenizedBody;
|
|
827
865
|
const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
|
|
828
866
|
const resolvedAccount = useMemo2(() => mergeAccountPatch({
|
|
@@ -867,10 +905,11 @@ function SplitCardFormInner({
|
|
|
867
905
|
const showWallets = showApplePay || showGooglePay;
|
|
868
906
|
const handleNameChange = useCallback((value) => {
|
|
869
907
|
setFullName(value);
|
|
908
|
+
onFullNameChange?.(value);
|
|
870
909
|
const parts = value.trim().split(/\s+/);
|
|
871
910
|
onFirstNameChange?.(parts[0] ?? "");
|
|
872
911
|
onLastNameChange?.(parts.length > 1 ? parts.slice(1).join(" ") : "");
|
|
873
|
-
}, [onFirstNameChange, onLastNameChange]);
|
|
912
|
+
}, [onFullNameChange, onFirstNameChange, onLastNameChange]);
|
|
874
913
|
const runBeforeCardButtonClick = useCallback(async () => {
|
|
875
914
|
if (!onBeforeButtonClick) return true;
|
|
876
915
|
try {
|
|
@@ -881,8 +920,11 @@ function SplitCardFormInner({
|
|
|
881
920
|
if (result === false) {
|
|
882
921
|
return false;
|
|
883
922
|
}
|
|
884
|
-
if (result
|
|
885
|
-
|
|
923
|
+
if (result && typeof result === "object") {
|
|
924
|
+
await checkout.applyInlineSessionPatch?.(result);
|
|
925
|
+
if (result.account) {
|
|
926
|
+
setAccountPatch((prev) => ({ ...prev ?? {}, ...result.account }));
|
|
927
|
+
}
|
|
886
928
|
}
|
|
887
929
|
return true;
|
|
888
930
|
} catch (err) {
|
|
@@ -894,7 +936,7 @@ function SplitCardFormInner({
|
|
|
894
936
|
onError?.(floPayErr);
|
|
895
937
|
return false;
|
|
896
938
|
}
|
|
897
|
-
}, [onBeforeButtonClick, sessionId, updateError, onError]);
|
|
939
|
+
}, [checkout.applyInlineSessionPatch, onBeforeButtonClick, sessionId, updateError, onError]);
|
|
898
940
|
const processPaymentInternal = useCallback(
|
|
899
941
|
async (tokenizedBody) => {
|
|
900
942
|
if (processingRef.current) return;
|
|
@@ -1503,11 +1545,13 @@ function SplitCardFormInner({
|
|
|
1503
1545
|
{
|
|
1504
1546
|
type: "button",
|
|
1505
1547
|
onClick: async () => {
|
|
1548
|
+
if (isSubmitting) return;
|
|
1506
1549
|
const shouldContinue = await runBeforeCardButtonClick();
|
|
1507
1550
|
if (!shouldContinue) return;
|
|
1508
1551
|
onButtonClick?.("card");
|
|
1509
1552
|
expandToCard();
|
|
1510
1553
|
},
|
|
1554
|
+
disabled: isSubmitting,
|
|
1511
1555
|
style: {
|
|
1512
1556
|
width: "100%",
|
|
1513
1557
|
padding: "0.9rem 1rem",
|
|
@@ -1517,7 +1561,7 @@ function SplitCardFormInner({
|
|
|
1517
1561
|
borderRadius: "8px",
|
|
1518
1562
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
1519
1563
|
fontWeight: 600,
|
|
1520
|
-
cursor: "pointer",
|
|
1564
|
+
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
1521
1565
|
display: "flex",
|
|
1522
1566
|
alignItems: "center",
|
|
1523
1567
|
justifyContent: "center",
|
|
@@ -1525,6 +1569,7 @@ function SplitCardFormInner({
|
|
|
1525
1569
|
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
1526
1570
|
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
1527
1571
|
position: "relative",
|
|
1572
|
+
opacity: isSubmitting ? 0.6 : 1,
|
|
1528
1573
|
...bStyles.cardButton
|
|
1529
1574
|
},
|
|
1530
1575
|
onMouseDown: (e) => {
|
|
@@ -1608,6 +1653,12 @@ function SplitCardFormInner({
|
|
|
1608
1653
|
|
|
1609
1654
|
// src/flopay-checkout.tsx
|
|
1610
1655
|
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1656
|
+
function hasInlineSessionPatchData(patch) {
|
|
1657
|
+
if (!patch) return false;
|
|
1658
|
+
return Boolean(
|
|
1659
|
+
patch.account && Object.keys(patch.account).length > 0 || patch.couponCodes !== void 0 || patch.tagsData !== void 0 || patch.utmMetadata !== void 0
|
|
1660
|
+
);
|
|
1661
|
+
}
|
|
1611
1662
|
function FloPayCheckout({
|
|
1612
1663
|
sessionId: sessionIdProp,
|
|
1613
1664
|
createSession: createSessionParams,
|
|
@@ -1620,6 +1671,9 @@ function FloPayCheckout({
|
|
|
1620
1671
|
onComplete,
|
|
1621
1672
|
onError,
|
|
1622
1673
|
onDecline,
|
|
1674
|
+
onFullNameChange,
|
|
1675
|
+
onCountryChange,
|
|
1676
|
+
onZipChange,
|
|
1623
1677
|
showPayPal = true,
|
|
1624
1678
|
showApplePay = true,
|
|
1625
1679
|
showGooglePay = true,
|
|
@@ -1655,7 +1709,6 @@ function FloPayCheckout({
|
|
|
1655
1709
|
const [createSessionPatch, setCreateSessionPatch] = useState3(void 0);
|
|
1656
1710
|
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = useState3("");
|
|
1657
1711
|
const [cardBootstrapPending, setCardBootstrapPending] = useState3(false);
|
|
1658
|
-
const [deferredCardOpen, setDeferredCardOpen] = useState3(false);
|
|
1659
1712
|
const autoCheckoutAttempted = useRef3(false);
|
|
1660
1713
|
const onCompleteRef = useRef3(onComplete);
|
|
1661
1714
|
onCompleteRef.current = onComplete;
|
|
@@ -1790,9 +1843,6 @@ function FloPayCheckout({
|
|
|
1790
1843
|
);
|
|
1791
1844
|
const inflightRef = useRef3(/* @__PURE__ */ new Map());
|
|
1792
1845
|
const initializedHashRef = useRef3(null);
|
|
1793
|
-
const deferInlineSessionUntilCardClick = Boolean(
|
|
1794
|
-
effectiveCreateSession && !children && layout === "buttons" && onBeforeButtonClick && (effectiveCreateSession.checkoutMode ?? checkoutModeProp ?? "full") === "full"
|
|
1795
|
-
);
|
|
1796
1846
|
function hashCreateParams(params) {
|
|
1797
1847
|
const key = JSON.stringify({
|
|
1798
1848
|
c: params?.clientId,
|
|
@@ -1822,7 +1872,6 @@ function FloPayCheckout({
|
|
|
1822
1872
|
setResolvedSessionId(sessionIdProp ?? "");
|
|
1823
1873
|
}, [sessionIdProp]);
|
|
1824
1874
|
async function resolveInlineSession(params, cacheKey) {
|
|
1825
|
-
ensureInlineSessionReady(params);
|
|
1826
1875
|
const api = new PaymentAPI(resolvedBillingUrl);
|
|
1827
1876
|
let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
|
|
1828
1877
|
let realResult = null;
|
|
@@ -1867,104 +1916,64 @@ function FloPayCheckout({
|
|
|
1867
1916
|
} finally {
|
|
1868
1917
|
inflightRef.current.delete(cacheKey);
|
|
1869
1918
|
}
|
|
1870
|
-
if (patch) {
|
|
1871
|
-
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
1872
|
-
setCreateSessionPatch((prev) => mergeInlineSessionPatches(prev, patch));
|
|
1873
|
-
}
|
|
1874
|
-
const { sid, result: realResult } = resolved;
|
|
1875
|
-
setUnified(realResult);
|
|
1876
|
-
if (realResult.data.session) {
|
|
1877
|
-
setSession(realResult.data.session);
|
|
1878
|
-
}
|
|
1879
|
-
if (sid) {
|
|
1880
|
-
setResolvedSessionId(sid);
|
|
1881
|
-
}
|
|
1882
|
-
let publishableKey;
|
|
1883
|
-
if (realResult.provider === "stripe") {
|
|
1884
|
-
publishableKey = realResult.data.stripe?.publishableKey;
|
|
1885
|
-
}
|
|
1886
|
-
if (!publishableKey) publishableKey = fallbackPublishableKey;
|
|
1887
|
-
if (!publishableKey) {
|
|
1888
|
-
throw new FloPayError3(
|
|
1889
|
-
"No publishable key found. Provide fallbackPublishableKey or ensure the session includes gatewayData.publishableKey.",
|
|
1890
|
-
"validation_error"
|
|
1891
|
-
);
|
|
1892
|
-
}
|
|
1893
|
-
const instance = await loadFloPay(publishableKey, {
|
|
1894
|
-
billingApiUrl: resolvedBillingUrl,
|
|
1895
|
-
locale
|
|
1896
|
-
});
|
|
1897
|
-
flopayRef.current = instance;
|
|
1898
|
-
setFloPay(instance);
|
|
1899
1919
|
initializedHashRef.current = cacheKey;
|
|
1900
|
-
|
|
1920
|
+
try {
|
|
1921
|
+
if (patch) {
|
|
1922
|
+
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
1923
|
+
setCreateSessionPatch((prev) => mergeInlineSessionPatches(prev, patch));
|
|
1924
|
+
}
|
|
1925
|
+
const { sid, result: realResult } = resolved;
|
|
1926
|
+
setUnified(realResult);
|
|
1927
|
+
if (realResult.data.session) {
|
|
1928
|
+
setSession(realResult.data.session);
|
|
1929
|
+
}
|
|
1930
|
+
if (sid) {
|
|
1931
|
+
setResolvedSessionId(sid);
|
|
1932
|
+
}
|
|
1933
|
+
let publishableKey;
|
|
1934
|
+
if (realResult.provider === "stripe") {
|
|
1935
|
+
publishableKey = realResult.data.stripe?.publishableKey;
|
|
1936
|
+
}
|
|
1937
|
+
if (!publishableKey) publishableKey = fallbackPublishableKey;
|
|
1938
|
+
if (!publishableKey) {
|
|
1939
|
+
throw new FloPayError3(
|
|
1940
|
+
"No publishable key found. Provide fallbackPublishableKey or ensure the session includes gatewayData.publishableKey.",
|
|
1941
|
+
"validation_error"
|
|
1942
|
+
);
|
|
1943
|
+
}
|
|
1944
|
+
const instance = await loadFloPay(publishableKey, {
|
|
1945
|
+
billingApiUrl: resolvedBillingUrl,
|
|
1946
|
+
locale
|
|
1947
|
+
});
|
|
1948
|
+
flopayRef.current = instance;
|
|
1949
|
+
setFloPay(instance);
|
|
1950
|
+
setIsLoading(false);
|
|
1951
|
+
} catch (err) {
|
|
1952
|
+
if (initializedHashRef.current === cacheKey) {
|
|
1953
|
+
initializedHashRef.current = null;
|
|
1954
|
+
}
|
|
1955
|
+
throw err;
|
|
1956
|
+
}
|
|
1901
1957
|
return resolved;
|
|
1902
1958
|
},
|
|
1903
1959
|
[fallbackPublishableKey, locale, resolvedBillingUrl]
|
|
1904
1960
|
);
|
|
1905
|
-
const
|
|
1906
|
-
if (cardBootstrapPending) return;
|
|
1907
|
-
setLoadError(null);
|
|
1961
|
+
const handleInlineSessionPatch = useCallback2(async (patch) => {
|
|
1962
|
+
if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) return;
|
|
1908
1963
|
setCardBootstrapPending(true);
|
|
1909
1964
|
try {
|
|
1910
|
-
const beforeClickResult = await onBeforeButtonClick?.({
|
|
1911
|
-
method: "card",
|
|
1912
|
-
createSession: effectiveCreateSession
|
|
1913
|
-
});
|
|
1914
|
-
if (beforeClickResult === false) {
|
|
1915
|
-
setDeferredCardOpen(false);
|
|
1916
|
-
return;
|
|
1917
|
-
}
|
|
1918
|
-
const patch = beforeClickResult && typeof beforeClickResult === "object" ? beforeClickResult : void 0;
|
|
1919
|
-
const baseParams = createSessionParamsRef.current;
|
|
1920
|
-
if (!baseParams) {
|
|
1921
|
-
throw new FloPayError3(
|
|
1922
|
-
"createSession is required to bootstrap checkout.",
|
|
1923
|
-
"validation_error"
|
|
1924
|
-
);
|
|
1925
|
-
}
|
|
1926
|
-
ensureInlineSessionReady(mergeInlineSessionPatch(baseParams, patch));
|
|
1927
|
-
setDeferredCardOpen(true);
|
|
1928
|
-
onButtonClick?.("card");
|
|
1929
1965
|
await bootstrapInlineSession(patch);
|
|
1930
|
-
} catch (err) {
|
|
1931
|
-
setDeferredCardOpen(false);
|
|
1932
|
-
const floPayErr = err instanceof FloPayError3 ? err : new FloPayError3(
|
|
1933
|
-
err instanceof Error ? err.message : "Failed to start card checkout.",
|
|
1934
|
-
"api_error"
|
|
1935
|
-
);
|
|
1936
|
-
setLoadError(floPayErr);
|
|
1937
|
-
onErrorRef.current?.(floPayErr);
|
|
1938
1966
|
} finally {
|
|
1939
1967
|
setCardBootstrapPending(false);
|
|
1940
1968
|
}
|
|
1941
1969
|
}, [
|
|
1942
1970
|
bootstrapInlineSession,
|
|
1943
|
-
|
|
1944
|
-
cardBootstrapPending,
|
|
1945
|
-
effectiveCreateSession,
|
|
1946
|
-
onButtonClick,
|
|
1947
|
-
onBeforeButtonClick
|
|
1971
|
+
cardBootstrapPending
|
|
1948
1972
|
]);
|
|
1949
1973
|
useEffect4(() => {
|
|
1950
1974
|
let cancelled = false;
|
|
1951
1975
|
setLoadError(null);
|
|
1952
1976
|
if (createSessionHash) {
|
|
1953
|
-
if (deferInlineSessionUntilCardClick) {
|
|
1954
|
-
if (initializedHashRef.current !== createSessionHash) {
|
|
1955
|
-
setSession(null);
|
|
1956
|
-
setUnified(null);
|
|
1957
|
-
setFloPay(null);
|
|
1958
|
-
setResolvedSessionId("");
|
|
1959
|
-
setDeferredCardOpen(false);
|
|
1960
|
-
flopayRef.current = null;
|
|
1961
|
-
}
|
|
1962
|
-
setCurrentMode(createSessionParamsRef.current?.checkoutMode ?? checkoutModeProp ?? "full");
|
|
1963
|
-
setIsLoading(false);
|
|
1964
|
-
return () => {
|
|
1965
|
-
cancelled = true;
|
|
1966
|
-
};
|
|
1967
|
-
}
|
|
1968
1977
|
if (initializedHashRef.current === createSessionHash) return;
|
|
1969
1978
|
const params = createSessionParamsRef.current;
|
|
1970
1979
|
setSession(buildSyntheticSession(params, checkoutModeProp));
|
|
@@ -2060,7 +2069,7 @@ function FloPayCheckout({
|
|
|
2060
2069
|
return () => {
|
|
2061
2070
|
cancelled = true;
|
|
2062
2071
|
};
|
|
2063
|
-
}, [resolvedSessionId, createSessionHash, checkoutModeProp,
|
|
2072
|
+
}, [resolvedSessionId, createSessionHash, checkoutModeProp, bootstrapInlineSession]);
|
|
2064
2073
|
const handleConfirmCheckout = useCallback2(async () => {
|
|
2065
2074
|
if (confirmProcessing || !session) return;
|
|
2066
2075
|
setConfirmProcessing(true);
|
|
@@ -2103,17 +2112,29 @@ function FloPayCheckout({
|
|
|
2103
2112
|
}
|
|
2104
2113
|
return opts;
|
|
2105
2114
|
}, [unified, session, appearance, resolvedBillingUrl]);
|
|
2115
|
+
const shouldHandleInlineSessionPatch = Boolean(
|
|
2116
|
+
createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && (effectiveCreateSession?.checkoutMode ?? checkoutModeProp ?? "full") === "full"
|
|
2117
|
+
);
|
|
2106
2118
|
const checkoutValue = useMemo3(
|
|
2107
2119
|
() => ({
|
|
2108
2120
|
session,
|
|
2109
2121
|
loading: isLoading,
|
|
2110
2122
|
error: loadError,
|
|
2111
|
-
checkoutMode: currentMode
|
|
2123
|
+
checkoutMode: currentMode,
|
|
2124
|
+
applyInlineSessionPatch: shouldHandleInlineSessionPatch ? handleInlineSessionPatch : void 0,
|
|
2125
|
+
inlineSessionPatchProcessing: cardBootstrapPending
|
|
2112
2126
|
}),
|
|
2113
|
-
[
|
|
2127
|
+
[
|
|
2128
|
+
session,
|
|
2129
|
+
isLoading,
|
|
2130
|
+
loadError,
|
|
2131
|
+
currentMode,
|
|
2132
|
+
shouldHandleInlineSessionPatch,
|
|
2133
|
+
handleInlineSessionPatch,
|
|
2134
|
+
cardBootstrapPending
|
|
2135
|
+
]
|
|
2114
2136
|
);
|
|
2115
2137
|
const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && (!flopay || !providerOptions);
|
|
2116
|
-
const shouldKeepDeferredInterimVisible = shouldShowInterimButtons && deferInlineSessionUntilCardClick;
|
|
2117
2138
|
if (isLoading) {
|
|
2118
2139
|
if (loadingNode) return /* @__PURE__ */ jsx5(Fragment3, { children: loadingNode });
|
|
2119
2140
|
if (layout === "buttons") {
|
|
@@ -2142,7 +2163,7 @@ function FloPayCheckout({
|
|
|
2142
2163
|
/* @__PURE__ */ jsx5("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
2143
2164
|
] });
|
|
2144
2165
|
}
|
|
2145
|
-
if (loadError
|
|
2166
|
+
if (loadError) {
|
|
2146
2167
|
if (errorNode) return /* @__PURE__ */ jsx5(Fragment3, { children: errorNode(loadError) });
|
|
2147
2168
|
return /* @__PURE__ */ jsx5(
|
|
2148
2169
|
"div",
|
|
@@ -2162,13 +2183,9 @@ function FloPayCheckout({
|
|
|
2162
2183
|
InterimButtonsView,
|
|
2163
2184
|
{
|
|
2164
2185
|
onButtonClick,
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
errorMessage: shouldKeepDeferredInterimVisible ? loadError?.message ?? null : null,
|
|
2169
|
-
showPayPal: deferInlineSessionUntilCardClick ? false : showPayPal,
|
|
2170
|
-
showApplePay: deferInlineSessionUntilCardClick ? false : showApplePay,
|
|
2171
|
-
showGooglePay: deferInlineSessionUntilCardClick ? false : showGooglePay,
|
|
2186
|
+
showPayPal,
|
|
2187
|
+
showApplePay,
|
|
2188
|
+
showGooglePay,
|
|
2172
2189
|
buttonsTheme,
|
|
2173
2190
|
buttonsStyles,
|
|
2174
2191
|
cardButtonContent,
|
|
@@ -2255,6 +2272,7 @@ function FloPayCheckout({
|
|
|
2255
2272
|
onComplete,
|
|
2256
2273
|
onError,
|
|
2257
2274
|
onDecline,
|
|
2275
|
+
onFullNameChange,
|
|
2258
2276
|
showPayPal,
|
|
2259
2277
|
showApplePay,
|
|
2260
2278
|
showGooglePay,
|
|
@@ -2269,7 +2287,8 @@ function FloPayCheckout({
|
|
|
2269
2287
|
enableAVS,
|
|
2270
2288
|
avsLayout,
|
|
2271
2289
|
country: session?.customer?.country,
|
|
2272
|
-
|
|
2290
|
+
onCountryChange,
|
|
2291
|
+
onZipChange,
|
|
2273
2292
|
submitLabel,
|
|
2274
2293
|
className
|
|
2275
2294
|
}
|