@flopay/react 1.0.3 → 1.1.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/dist/index.mjs CHANGED
@@ -100,9 +100,9 @@ function FloPayProvider({
100
100
  }
101
101
 
102
102
  // src/flopay-checkout.tsx
103
- import React6, { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
104
- import { PaymentAPI as PaymentAPI3 } from "@flopay/js";
105
- import { SDK_VERSION, FloPayError as FloPayError4, resolveBillingApiUrl as resolveBillingApiUrl3, buildCheckoutDisplayData, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme2 } from "@flopay/shared";
103
+ import React7, { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo4, useRef as useRef4, useState as useState4 } from "react";
104
+ import { PaymentAPI as PaymentAPI4 } from "@flopay/js";
105
+ import { SDK_VERSION, FloPayError as FloPayError5, resolveBillingApiUrl as resolveBillingApiUrl3, buildCheckoutDisplayData, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme2 } from "@flopay/shared";
106
106
 
107
107
  // src/card-button-content.tsx
108
108
  import "react";
@@ -248,8 +248,8 @@ import {
248
248
  isAVSFieldVisible,
249
249
  getStateFromPostalCode
250
250
  } from "@flopay/shared";
251
- import { PaymentAPI } from "@flopay/js";
252
- import { forwardRef, useCallback, useContext as useContext3, useEffect as useEffect3, useImperativeHandle, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
251
+ 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";
253
253
 
254
254
  // src/hooks.ts
255
255
  import { useContext as useContext2 } from "react";
@@ -651,11 +651,562 @@ function isInAppBrowser(userAgent) {
651
651
  return false;
652
652
  }
653
653
 
654
+ // src/direct-paypal-button.tsx
655
+ import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
656
+ import { loadScript } from "@paypal/paypal-js";
657
+ import { PaymentAPI } from "@flopay/js";
658
+ import { FloPayError as FloPayError2, normalizeGatewayEnvironment } from "@flopay/shared";
659
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
660
+ var DEFAULT_BUTTON_HEIGHT = 45;
661
+ function DirectPayPalButton({
662
+ sessionId,
663
+ billingApiUrl,
664
+ email,
665
+ clientId,
666
+ environment,
667
+ currency,
668
+ isSubscription,
669
+ onTokenizedBody,
670
+ onComplete,
671
+ onErrorChange,
672
+ onDecline,
673
+ isProcessing = false,
674
+ onLoadStateChange,
675
+ onButtonClick,
676
+ runBeforeButtonClick,
677
+ session,
678
+ existingOrderId,
679
+ debug = false
680
+ }) {
681
+ const containerRef = useRef2(null);
682
+ const [ready, setReady] = useState2(false);
683
+ const [failed, setFailed] = useState2(false);
684
+ const [submitting, setSubmitting] = useState2(false);
685
+ const baseUrl = useMemo2(() => billingApiUrl.replace(/\/+$/, ""), [billingApiUrl]);
686
+ const [debugLines, setDebugLines] = useState2([]);
687
+ const appendDebug = (line) => {
688
+ if (!debug) return;
689
+ setDebugLines((prev) => [...prev, `${(/* @__PURE__ */ new Date()).toISOString().slice(11, 23)} ${line}`]);
690
+ };
691
+ const onTokenizedBodyRef = useRef2(onTokenizedBody);
692
+ const onCompleteRef = useRef2(onComplete);
693
+ const onErrorChangeRef = useRef2(onErrorChange);
694
+ const onDeclineRef = useRef2(onDecline);
695
+ const onButtonClickRef = useRef2(onButtonClick);
696
+ const onLoadStateChangeRef = useRef2(onLoadStateChange);
697
+ const runBeforeButtonClickRef = useRef2(runBeforeButtonClick);
698
+ const sessionRef = useRef2(session);
699
+ const emailRef = useRef2(email);
700
+ const beforeClickRef = useRef2(null);
701
+ useEffect3(() => {
702
+ onTokenizedBodyRef.current = onTokenizedBody;
703
+ }, [onTokenizedBody]);
704
+ useEffect3(() => {
705
+ onCompleteRef.current = onComplete;
706
+ }, [onComplete]);
707
+ useEffect3(() => {
708
+ onErrorChangeRef.current = onErrorChange;
709
+ }, [onErrorChange]);
710
+ useEffect3(() => {
711
+ onDeclineRef.current = onDecline;
712
+ }, [onDecline]);
713
+ useEffect3(() => {
714
+ onButtonClickRef.current = onButtonClick;
715
+ }, [onButtonClick]);
716
+ useEffect3(() => {
717
+ onLoadStateChangeRef.current = onLoadStateChange;
718
+ }, [onLoadStateChange]);
719
+ useEffect3(() => {
720
+ runBeforeButtonClickRef.current = runBeforeButtonClick;
721
+ }, [runBeforeButtonClick]);
722
+ useEffect3(() => {
723
+ sessionRef.current = session;
724
+ }, [session]);
725
+ useEffect3(() => {
726
+ emailRef.current = email;
727
+ }, [email]);
728
+ useEffect3(() => {
729
+ onLoadStateChangeRef.current?.(ready && !failed);
730
+ }, [ready, failed]);
731
+ const normalizedEnv = normalizeGatewayEnvironment(environment);
732
+ useEffect3(() => {
733
+ const maskedClient = clientId ? `${clientId.slice(0, 6)}\u2026(len ${clientId.length})` : "(empty)";
734
+ const ua = typeof navigator !== "undefined" ? navigator.userAgent : "(no navigator)";
735
+ appendDebug(`mount clientId=${maskedClient} env=${environment ?? "(unset)"}\u2192${normalizedEnv ?? "live"} ccy=${currency} sub=${isSubscription}`);
736
+ appendDebug(`ua=${ua.slice(0, 80)}${ua.length > 80 ? "\u2026" : ""}`);
737
+ if (!clientId) {
738
+ appendDebug("FAIL: clientId empty \u2014 gateway misconfigured");
739
+ setFailed(true);
740
+ onErrorChangeRef.current?.("Direct PayPal gateway is misconfigured.");
741
+ return;
742
+ }
743
+ if (!containerRef.current) {
744
+ appendDebug("FAIL: containerRef not attached");
745
+ return;
746
+ }
747
+ let cancelled = false;
748
+ let activeButtons = null;
749
+ let rendered = false;
750
+ const container = containerRef.current;
751
+ let containerObserver = null;
752
+ let perfObserver = null;
753
+ const watchdogTimers = [];
754
+ const formatDims = (el) => {
755
+ if (!el || typeof el.getBoundingClientRect !== "function") return "(no rect)";
756
+ const rect = el.getBoundingClientRect();
757
+ return `${Math.round(rect.width)}\xD7${Math.round(rect.height)}`;
758
+ };
759
+ const classifyIframeSrc = (raw) => {
760
+ if (!raw) return "(empty)";
761
+ try {
762
+ const url = new URL(raw, typeof window !== "undefined" ? window.location.href : "https://localhost");
763
+ const path = url.pathname.toLowerCase();
764
+ if (path.includes("checkcaptcha") || path.includes("captcha")) return `CAPTCHA(${url.host}${path})`;
765
+ if (path.includes("risk") || path.includes("challenge")) return `RISK(${url.host}${path})`;
766
+ if (path.includes("smart/buttons")) return `smart-buttons(${url.host})`;
767
+ return `${url.host}${path}`.slice(0, 100);
768
+ } catch {
769
+ return raw.slice(0, 80);
770
+ }
771
+ };
772
+ const describeIframe = (frame) => {
773
+ const src = frame.getAttribute("src");
774
+ const srcdoc = frame.getAttribute("srcdoc");
775
+ const name = frame.getAttribute("name");
776
+ const sandbox = frame.getAttribute("sandbox");
777
+ const parts = [];
778
+ if (src) parts.push(`src=${classifyIframeSrc(src)}`);
779
+ if (srcdoc) parts.push(`srcdoc[${srcdoc.length}ch]`);
780
+ if (!src && !srcdoc) parts.push("src=(empty) srcdoc=(empty)");
781
+ if (name) parts.push(`name=${name.slice(0, 40)}`);
782
+ if (sandbox !== null) parts.push(`sandbox="${sandbox.slice(0, 40)}"`);
783
+ return parts.join(" ");
784
+ };
785
+ const inspectFrameContent = (frame) => {
786
+ if (!(frame instanceof HTMLIFrameElement)) return "";
787
+ try {
788
+ const cd = frame.contentDocument;
789
+ if (!cd) return "cd=null";
790
+ const bodyChildren = cd.body?.children.length ?? 0;
791
+ const bodyLen = cd.body?.innerHTML.length ?? 0;
792
+ const headLen = cd.head?.innerHTML.length ?? 0;
793
+ return `cd=same-origin readyState=${cd.readyState} body[${bodyChildren}children,${bodyLen}ch] head[${headLen}ch]`;
794
+ } catch (err) {
795
+ return `cd=cross-origin(${err.message.slice(0, 30)})`;
796
+ }
797
+ };
798
+ const errorMessages = [];
799
+ const onWindowError = (ev) => {
800
+ const msg = ev.message ?? String(ev.error ?? "(no message)");
801
+ if (msg && (msg.toLowerCase().includes("paypal") || msg.toLowerCase().includes("zoid") || msg.toLowerCase().includes("postrobot") || msg.toLowerCase().includes("storage"))) {
802
+ appendDebug(`window:error ${msg.slice(0, 140)}`);
803
+ errorMessages.push(msg);
804
+ }
805
+ };
806
+ const onUnhandledRejection = (ev) => {
807
+ const reason = ev.reason instanceof Error ? ev.reason.message : String(ev.reason ?? "(no reason)");
808
+ if (reason && (reason.toLowerCase().includes("paypal") || reason.toLowerCase().includes("zoid") || reason.toLowerCase().includes("postrobot") || reason.toLowerCase().includes("storage"))) {
809
+ appendDebug(`window:rejection ${reason.slice(0, 140)}`);
810
+ errorMessages.push(reason);
811
+ }
812
+ };
813
+ if (debug && typeof window !== "undefined") {
814
+ window.addEventListener("error", onWindowError);
815
+ window.addEventListener("unhandledrejection", onUnhandledRejection);
816
+ }
817
+ const paypalRequestCount = { value: 0 };
818
+ if (debug && typeof PerformanceObserver !== "undefined") {
819
+ try {
820
+ perfObserver = new PerformanceObserver((list) => {
821
+ for (const entry of list.getEntries()) {
822
+ if (!entry.name.toLowerCase().includes("paypal")) continue;
823
+ paypalRequestCount.value += 1;
824
+ const dur = Math.round(entry.duration);
825
+ appendDebug(`net ${dur}ms ${entry.name.slice(0, 90)}`);
826
+ }
827
+ });
828
+ perfObserver.observe({ type: "resource", buffered: true });
829
+ } catch {
830
+ }
831
+ }
832
+ const stopDiagnostics = () => {
833
+ containerObserver?.disconnect();
834
+ containerObserver = null;
835
+ perfObserver?.disconnect();
836
+ perfObserver = null;
837
+ while (watchdogTimers.length) clearTimeout(watchdogTimers.pop());
838
+ if (debug && typeof window !== "undefined") {
839
+ window.removeEventListener("error", onWindowError);
840
+ window.removeEventListener("unhandledrejection", onUnhandledRejection);
841
+ }
842
+ };
843
+ const isZoidLifecycleMessage = (message) => {
844
+ if (!message) return false;
845
+ const lower = message.toLowerCase();
846
+ return lower.includes("zoid destroyed") || lower.includes("destroyed all components") || lower.includes("window closed") || lower.includes("detected container element removed");
847
+ };
848
+ const forwardError = (message) => {
849
+ if (cancelled) return;
850
+ if (isZoidLifecycleMessage(message)) return;
851
+ onErrorChangeRef.current?.(message);
852
+ };
853
+ const markRenderFailed = (message) => {
854
+ if (cancelled) return;
855
+ if (isZoidLifecycleMessage(message)) {
856
+ appendDebug(`markRenderFailed:skip-zoid msg=${message.slice(0, 80)}`);
857
+ return;
858
+ }
859
+ setFailed(true);
860
+ forwardError(message);
861
+ };
862
+ setFailed(false);
863
+ const dispatchTokenizedBody = async (body) => {
864
+ const prepared = beforeClickRef.current;
865
+ const effectiveSessionId = prepared?.sessionId ?? sessionId;
866
+ if (onTokenizedBodyRef.current) {
867
+ onTokenizedBodyRef.current(body, {
868
+ sessionId: effectiveSessionId,
869
+ accountPatch: prepared?.accountPatch
870
+ });
871
+ return;
872
+ }
873
+ try {
874
+ const currentSession = sessionRef.current;
875
+ const currentEmail = prepared?.accountPatch?.email ?? emailRef.current;
876
+ const effectiveUserId = prepared?.accountPatch?.userId ?? currentSession?.customer?.id ?? currentSession?.accountData?.userId ?? "";
877
+ const api = new PaymentAPI(baseUrl);
878
+ const response = await api.processPayment(
879
+ effectiveUserId,
880
+ {
881
+ sessionId: effectiveSessionId,
882
+ tokenizedData: body,
883
+ accountData: {
884
+ userId: effectiveUserId,
885
+ email: currentEmail ?? currentSession?.customer?.email ?? "",
886
+ firstName: prepared?.accountPatch?.firstName ?? currentSession?.customer?.firstName ?? currentSession?.accountData?.firstName ?? "",
887
+ lastName: prepared?.accountPatch?.lastName ?? currentSession?.customer?.lastName ?? currentSession?.accountData?.lastName ?? "",
888
+ country: prepared?.accountPatch?.country ?? currentSession?.customer?.country ?? currentSession?.accountData?.country ?? void 0,
889
+ zip: prepared?.accountPatch?.zip ?? currentSession?.customer?.zip ?? currentSession?.accountData?.zip ?? void 0
890
+ }
891
+ }
892
+ );
893
+ if (response.ok) {
894
+ onCompleteRef.current?.({ status: "succeeded", checkoutMethod: "paypal" });
895
+ return;
896
+ }
897
+ const json = await response.json().catch(() => null);
898
+ const message = json?.["message"] ?? "PayPal payment failed.";
899
+ forwardError(message);
900
+ onDeclineRef.current?.(buildDeclineEvent("paypal", message, {
901
+ code: json?.["code"],
902
+ declineCode: json?.["declineCode"]
903
+ }));
904
+ } catch (err) {
905
+ const message = err instanceof Error ? err.message : "PayPal payment failed.";
906
+ forwardError(message);
907
+ onDeclineRef.current?.(buildDeclineEvent("paypal", message));
908
+ }
909
+ };
910
+ const createPaypalIntent = async (fallbackMessage) => {
911
+ const prepared = beforeClickRef.current;
912
+ const effectiveSessionId = prepared?.sessionId ?? sessionId;
913
+ const effectiveEmail = prepared?.accountPatch?.email ?? emailRef.current;
914
+ const response = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
915
+ method: "POST",
916
+ headers: { "Content-Type": "application/json" },
917
+ body: JSON.stringify({
918
+ sessionId: effectiveSessionId,
919
+ email: effectiveEmail,
920
+ paymentMethodType: "paypal",
921
+ isPaypal: "true"
922
+ })
923
+ });
924
+ const json = await response.json().catch(() => null);
925
+ if (!response.ok) {
926
+ throw new Error(json?.message ?? fallbackMessage);
927
+ }
928
+ const id = json?.data?.id;
929
+ if (!id) {
930
+ throw new Error(fallbackMessage);
931
+ }
932
+ return id;
933
+ };
934
+ appendDebug("loadScript:scheduled (deferred 1 tick)");
935
+ let loadPromise = null;
936
+ const startTimer = setTimeout(() => {
937
+ if (cancelled) {
938
+ appendDebug("loadScript:skipped (cancelled before defer ran)");
939
+ return;
940
+ }
941
+ appendDebug("loadScript:start");
942
+ const paypalSdkEnv = normalizedEnv === "live" ? "production" : normalizedEnv;
943
+ loadPromise = loadScript({
944
+ clientId,
945
+ currency,
946
+ // Subscriptions need the `subscription` vault intent; one-time payments
947
+ // use a standard order capture.
948
+ intent: isSubscription ? "subscription" : "capture",
949
+ vault: isSubscription ? true : void 0,
950
+ // Tell PayPal which environment the clientId belongs to. Without
951
+ // this, PayPal defaults to live endpoints — and a sandbox clientId
952
+ // sent to live silently stalls in zoid's prerender forever (no
953
+ // error, no rejection).
954
+ ...paypalSdkEnv ? { environment: paypalSdkEnv } : {},
955
+ // Namespace the sandbox SDK so it can coexist with a production SDK on
956
+ // the same page without clobbering `window.paypal`.
957
+ ...paypalSdkEnv === "sandbox" ? { dataNamespace: "paypal_sandbox" } : {}
958
+ });
959
+ loadPromise.then((paypal) => {
960
+ appendDebug(`loadScript:resolved cancelled=${cancelled} ns=${!!paypal} buttons=${!!paypal?.Buttons}`);
961
+ if (cancelled || !paypal?.Buttons) {
962
+ if (!cancelled && !paypal?.Buttons) appendDebug("FAIL: namespace missing Buttons factory");
963
+ return;
964
+ }
965
+ const handleApprove = async (data) => {
966
+ try {
967
+ setSubmitting(true);
968
+ onErrorChangeRef.current?.(null);
969
+ const token = data.subscriptionID ?? data.orderID ?? "";
970
+ if (!token) {
971
+ throw new FloPayError2(
972
+ "PayPal did not return an approval token.",
973
+ "api_error",
974
+ { code: "paypal_missing_token" }
975
+ );
976
+ }
977
+ await dispatchTokenizedBody({
978
+ id: token,
979
+ isPaypal: true
980
+ });
981
+ } catch (err) {
982
+ forwardError(err instanceof Error ? err.message : "PayPal capture failed.");
983
+ } finally {
984
+ setSubmitting(false);
985
+ }
986
+ };
987
+ const buttons = paypal.Buttons({
988
+ style: { layout: "horizontal", height: DEFAULT_BUTTON_HEIGHT, tagline: false },
989
+ // PayPal's SDK awaits a Promise returned from `onClick` and aborts
990
+ // the create-order/create-subscription step when `actions.reject()`
991
+ // is invoked. Run the consumer's `runBeforeButtonClick` here so
992
+ // inline-session/account patches land before the order is created,
993
+ // matching the Stripe-rendered PayPal flow.
994
+ onClick: async (_data, actions) => {
995
+ const runner = runBeforeButtonClickRef.current;
996
+ if (runner) {
997
+ try {
998
+ const beforeClick = await runner("paypal");
999
+ if (!beforeClick.proceed) {
1000
+ beforeClickRef.current = null;
1001
+ await actions.reject();
1002
+ return;
1003
+ }
1004
+ beforeClickRef.current = {
1005
+ sessionId: beforeClick.sessionId,
1006
+ accountPatch: beforeClick.accountPatch
1007
+ };
1008
+ } catch (err) {
1009
+ appendDebug(`onClick:runBeforeButtonClick rejected msg=${(err instanceof Error ? err.message : String(err)).slice(0, 120)}`);
1010
+ beforeClickRef.current = null;
1011
+ await actions.reject();
1012
+ return;
1013
+ }
1014
+ } else {
1015
+ beforeClickRef.current = null;
1016
+ }
1017
+ onButtonClickRef.current?.("paypal");
1018
+ await actions.resolve();
1019
+ },
1020
+ // When the SDK is already holding an order/subscription id from a
1021
+ // prior backend round-trip (the `paypal_direct_required` retry
1022
+ // path), feed it straight to PayPal instead of creating a new one.
1023
+ // Otherwise fall back to the normal create-intent call.
1024
+ createOrder: isSubscription ? void 0 : existingOrderId ? () => Promise.resolve(existingOrderId) : () => createPaypalIntent("Failed to create PayPal order."),
1025
+ createSubscription: isSubscription ? existingOrderId ? () => Promise.resolve(existingOrderId) : () => createPaypalIntent("Failed to create PayPal subscription.") : void 0,
1026
+ onApprove: handleApprove,
1027
+ onCancel: () => {
1028
+ beforeClickRef.current = null;
1029
+ onDeclineRef.current?.(buildDeclineEvent("paypal", "PayPal checkout was cancelled."));
1030
+ },
1031
+ onError: (err) => {
1032
+ const message = err instanceof Error ? err.message : "PayPal failed to render.";
1033
+ appendDebug(`onError rendered=${rendered} msg=${message.slice(0, 120)}`);
1034
+ if (rendered) {
1035
+ forwardError(message);
1036
+ onDeclineRef.current?.(buildDeclineEvent("paypal", message));
1037
+ return;
1038
+ }
1039
+ markRenderFailed(message);
1040
+ }
1041
+ });
1042
+ const eligible = buttons.isEligible();
1043
+ appendDebug(`isEligible=${eligible}`);
1044
+ if (!eligible) {
1045
+ setReady(false);
1046
+ markRenderFailed(
1047
+ "PayPal buttons are not eligible to render in this context (paypal_ineligible)."
1048
+ );
1049
+ return;
1050
+ }
1051
+ const typedButtons = buttons;
1052
+ if (debug) {
1053
+ appendDebug(`container:dims ${formatDims(container)} visibility=${typeof document !== "undefined" ? document.visibilityState : "(no document)"}`);
1054
+ }
1055
+ if (debug && typeof MutationObserver !== "undefined") {
1056
+ containerObserver = new MutationObserver((mutations) => {
1057
+ for (const mutation of mutations) {
1058
+ if (mutation.type === "childList") {
1059
+ mutation.addedNodes.forEach((node) => {
1060
+ if (!(node instanceof Element)) return;
1061
+ const tag = node.tagName.toLowerCase();
1062
+ const title = (node.getAttribute("title") ?? "").slice(0, 40);
1063
+ const detail = tag === "iframe" ? ` ${describeIframe(node)}` : "";
1064
+ appendDebug(`child+ ${tag}${title ? ` title="${title}"` : ""}${detail} dims=${formatDims(node)}`);
1065
+ });
1066
+ } else if (mutation.type === "attributes" && mutation.target instanceof Element) {
1067
+ const target = mutation.target;
1068
+ if (target.tagName.toLowerCase() !== "iframe") continue;
1069
+ const attr = mutation.attributeName;
1070
+ if (attr === "src" || attr === "srcdoc") {
1071
+ appendDebug(`attr~ iframe ${attr}=${attr === "srcdoc" ? `[${(target.getAttribute("srcdoc") ?? "").length}ch]` : classifyIframeSrc(target.getAttribute("src"))} dims=${formatDims(target)}`);
1072
+ }
1073
+ }
1074
+ }
1075
+ });
1076
+ containerObserver.observe(container, {
1077
+ childList: true,
1078
+ subtree: true,
1079
+ attributes: true,
1080
+ attributeFilter: ["src", "srcdoc"]
1081
+ });
1082
+ }
1083
+ const snapshotContainer = (when) => {
1084
+ if (cancelled || rendered) return;
1085
+ const iframes = container.querySelectorAll("iframe");
1086
+ const hasStorageAccess = typeof document !== "undefined" && "hasStorageAccess" in document;
1087
+ appendDebug(`watchdog:${when} container=${formatDims(container)} children=${container.childElementCount} iframes=${iframes.length} visibility=${typeof document !== "undefined" ? document.visibilityState : "(no document)"} cookies=${typeof navigator !== "undefined" ? navigator.cookieEnabled : "?"} hasStorageAccessApi=${hasStorageAccess} paypalNetRequests=${paypalRequestCount.value}`);
1088
+ iframes.forEach((frame, i) => {
1089
+ const title = (frame.getAttribute("title") ?? "").slice(0, 40);
1090
+ appendDebug(` iframe[${i}] ${formatDims(frame)}${title ? ` title="${title}"` : ""} ${describeIframe(frame)}`);
1091
+ const content = inspectFrameContent(frame);
1092
+ if (content) appendDebug(` ${content}`);
1093
+ });
1094
+ if (errorMessages.length === 0) {
1095
+ appendDebug(` (no PayPal/zoid window errors captured)`);
1096
+ }
1097
+ };
1098
+ if (debug) {
1099
+ watchdogTimers.push(setTimeout(() => snapshotContainer("3s"), 3e3));
1100
+ watchdogTimers.push(setTimeout(() => snapshotContainer("8s"), 8e3));
1101
+ watchdogTimers.push(setTimeout(() => snapshotContainer("15s"), 15e3));
1102
+ }
1103
+ appendDebug("render:start");
1104
+ buttons.render(container).then(() => {
1105
+ appendDebug(`render:resolved cancelled=${cancelled}`);
1106
+ stopDiagnostics();
1107
+ if (cancelled) {
1108
+ typedButtons.close().catch(() => {
1109
+ });
1110
+ return;
1111
+ }
1112
+ activeButtons = typedButtons;
1113
+ rendered = true;
1114
+ setReady(true);
1115
+ }).catch((err) => {
1116
+ const message = err instanceof Error ? err.message : "PayPal failed to render.";
1117
+ appendDebug(`render:rejected msg=${message.slice(0, 120)}`);
1118
+ stopDiagnostics();
1119
+ markRenderFailed(message);
1120
+ });
1121
+ }).catch((err) => {
1122
+ const message = err instanceof Error ? err.message : "PayPal SDK failed to load.";
1123
+ appendDebug(`loadScript:rejected msg=${message.slice(0, 120)}`);
1124
+ markRenderFailed(message);
1125
+ });
1126
+ }, 0);
1127
+ return () => {
1128
+ cancelled = true;
1129
+ clearTimeout(startTimer);
1130
+ stopDiagnostics();
1131
+ if (activeButtons) {
1132
+ activeButtons.close().catch(() => {
1133
+ });
1134
+ }
1135
+ };
1136
+ }, [baseUrl, clientId, currency, environment, isSubscription, sessionId, existingOrderId]);
1137
+ const debugPanel = debug ? /* @__PURE__ */ jsxs3(
1138
+ "pre",
1139
+ {
1140
+ "data-testid": "flopay-direct-paypal-debug",
1141
+ style: {
1142
+ margin: "0 0 8px 0",
1143
+ padding: "6px 8px",
1144
+ background: failed ? "#fef2f2" : "#f3f4f6",
1145
+ border: `1px solid ${failed ? "#fca5a5" : "#d1d5db"}`,
1146
+ borderRadius: 6,
1147
+ color: "#111827",
1148
+ font: "11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace",
1149
+ whiteSpace: "pre-wrap",
1150
+ wordBreak: "break-word",
1151
+ maxHeight: 220,
1152
+ overflowY: "auto"
1153
+ },
1154
+ children: [
1155
+ `FloPay/DirectPayPal-debug (ready=${ready} failed=${failed})`,
1156
+ debugLines.length === 0 ? "\n(waiting for first lifecycle event\u2026)" : `
1157
+ ${debugLines.join("\n")}`
1158
+ ]
1159
+ }
1160
+ ) : null;
1161
+ if (failed) {
1162
+ return debug ? /* @__PURE__ */ jsx5("div", { children: debugPanel }) : null;
1163
+ }
1164
+ return (
1165
+ // Single wrapper so the parent flex container sees exactly one flex item
1166
+ // (otherwise the fragment's placeholder + container become two siblings
1167
+ // and any spacing-sensitive layout has to reason about both). The wrapper
1168
+ // intentionally has no margin/padding so the parent owns all spacing.
1169
+ /* @__PURE__ */ jsxs3("div", { children: [
1170
+ debugPanel,
1171
+ /* @__PURE__ */ jsxs3("div", { style: { position: "relative", minHeight: DEFAULT_BUTTON_HEIGHT }, children: [
1172
+ !ready && /* @__PURE__ */ jsx5(
1173
+ "div",
1174
+ {
1175
+ "data-testid": "flopay-direct-paypal-placeholder",
1176
+ style: {
1177
+ position: "absolute",
1178
+ inset: 0,
1179
+ borderRadius: 8,
1180
+ background: "#e5e7eb",
1181
+ animation: "flopay-pulse 1.5s ease-in-out infinite",
1182
+ pointerEvents: "none"
1183
+ }
1184
+ }
1185
+ ),
1186
+ /* @__PURE__ */ jsx5(
1187
+ "div",
1188
+ {
1189
+ ref: containerRef,
1190
+ "data-testid": "flopay-direct-paypal-container",
1191
+ style: {
1192
+ minHeight: DEFAULT_BUTTON_HEIGHT,
1193
+ display: "flex",
1194
+ opacity: ready ? 1 : 0
1195
+ },
1196
+ "aria-busy": submitting || isProcessing
1197
+ }
1198
+ )
1199
+ ] })
1200
+ ] })
1201
+ );
1202
+ }
1203
+
654
1204
  // src/split-card-form.tsx
655
- import { FloPayError as FloPayError2 } from "@flopay/shared";
656
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1205
+ import { FloPayError as FloPayError3 } from "@flopay/shared";
1206
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
657
1207
  var WALLET_RESUME_KEY = "flopay_wallet_resume";
658
1208
  var FLOPAY_KEYFRAMES = `
1209
+ .paypal-buttons { margin: 0 !important; vertical-align: top !important; }
659
1210
  @keyframes flopay-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
660
1211
  @keyframes flopay-fade-in { 0% { opacity: 0; } 100% { opacity: 1; } }
661
1212
  @keyframes flopay-buttons-enter {
@@ -689,13 +1240,13 @@ function getButtonMethodLabel(method) {
689
1240
  }
690
1241
  }
691
1242
  function normalizeBeforeButtonClickError(method, err) {
692
- return err instanceof FloPayError2 ? err : new FloPayError2(
1243
+ return err instanceof FloPayError3 ? err : new FloPayError3(
693
1244
  err instanceof Error ? err.message : `${getButtonMethodLabel(method)} before-click hook failed.`,
694
1245
  "validation_error"
695
1246
  );
696
1247
  }
697
1248
  function FloPayKeyframes() {
698
- return /* @__PURE__ */ jsx5("style", { children: FLOPAY_KEYFRAMES });
1249
+ return /* @__PURE__ */ jsx6("style", { children: FLOPAY_KEYFRAMES });
699
1250
  }
700
1251
  function toCssSize(value) {
701
1252
  if (typeof value === "number") return `${value}px`;
@@ -716,8 +1267,8 @@ function ExpressCheckoutReadySwap({
716
1267
  children
717
1268
  }) {
718
1269
  if (state === "unavailable" || state === "load_error") return null;
719
- return /* @__PURE__ */ jsxs3("div", { style: { position: "relative", minHeight: 44 }, children: [
720
- /* @__PURE__ */ jsx5(
1270
+ return /* @__PURE__ */ jsxs4("div", { style: { position: "relative", minHeight: 44 }, children: [
1271
+ /* @__PURE__ */ jsx6(
721
1272
  "div",
722
1273
  {
723
1274
  "data-testid": placeholderTestId,
@@ -736,7 +1287,7 @@ function ExpressCheckoutReadySwap({
736
1287
  }
737
1288
  }
738
1289
  ),
739
- /* @__PURE__ */ jsx5(
1290
+ /* @__PURE__ */ jsx6(
740
1291
  "div",
741
1292
  {
742
1293
  style: {
@@ -756,7 +1307,7 @@ function isExpressCheckoutRowVisible(state) {
756
1307
  }
757
1308
  var SplitCardForm = forwardRef(
758
1309
  function SplitCardForm2(props, ref) {
759
- return /* @__PURE__ */ jsx5(SplitCardFormInner, { ...props, innerRef: ref });
1310
+ return /* @__PURE__ */ jsx6(SplitCardFormInner, { ...props, innerRef: ref });
760
1311
  }
761
1312
  );
762
1313
  function PayPalButtonInner({
@@ -773,15 +1324,15 @@ function PayPalButtonInner({
773
1324
  }) {
774
1325
  const stripe = useStripeRaw();
775
1326
  const elements = useStripeElements();
776
- const [loadState, setLoadState] = useState2("loading");
777
- useEffect3(() => {
1327
+ const [loadState, setLoadState] = useState3("loading");
1328
+ useEffect4(() => {
778
1329
  onLoadStateChange?.(loadState);
779
1330
  }, [loadState, onLoadStateChange]);
780
- const [submitting, setSubmitting] = useState2(false);
781
- const paypalResumeAttempted = useRef2(false);
782
- const beforeClickRef = useRef2(null);
1331
+ const [submitting, setSubmitting] = useState3(false);
1332
+ const paypalResumeAttempted = useRef3(false);
1333
+ const beforeClickRef = useRef3(null);
783
1334
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
784
- useEffect3(() => {
1335
+ useEffect4(() => {
785
1336
  if (!stripe || paypalResumeAttempted.current) return;
786
1337
  const params = new URLSearchParams(window.location.search);
787
1338
  const paymentIntentId = params.get("payment_intent");
@@ -938,8 +1489,8 @@ function PayPalButtonInner({
938
1489
  setSubmitting(false);
939
1490
  }
940
1491
  }, [stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]);
941
- return /* @__PURE__ */ jsxs3(Fragment2, { children: [
942
- /* @__PURE__ */ jsx5(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-paypal-placeholder", children: /* @__PURE__ */ jsx5(
1492
+ return /* @__PURE__ */ jsxs4(Fragment2, { children: [
1493
+ /* @__PURE__ */ jsx6(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-paypal-placeholder", children: /* @__PURE__ */ jsx6(
943
1494
  ExpressCheckoutElement,
944
1495
  {
945
1496
  onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
@@ -964,7 +1515,7 @@ function PayPalButtonInner({
964
1515
  }
965
1516
  }
966
1517
  ) }),
967
- submitting && /* @__PURE__ */ jsx5(ProcessingOverlay, { status: "processing" })
1518
+ submitting && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: "processing" })
968
1519
  ] });
969
1520
  }
970
1521
  function WalletButtonInner({
@@ -982,14 +1533,14 @@ function WalletButtonInner({
982
1533
  }) {
983
1534
  const stripe = useStripeRaw();
984
1535
  const elements = useStripeElements();
985
- const [loadState, setLoadState] = useState2("loading");
986
- useEffect3(() => {
1536
+ const [loadState, setLoadState] = useState3("loading");
1537
+ useEffect4(() => {
987
1538
  onLoadStateChange?.(loadState);
988
1539
  }, [loadState, onLoadStateChange]);
989
- const [submitting, setSubmitting] = useState2(false);
1540
+ const [submitting, setSubmitting] = useState3(false);
990
1541
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
991
- const lastWalletMethodRef = useRef2("card");
992
- const beforeClickRef = useRef2(null);
1542
+ const lastWalletMethodRef = useRef3("card");
1543
+ const beforeClickRef = useRef3(null);
993
1544
  const handleWalletConfirm = useCallback(
994
1545
  async (event) => {
995
1546
  if (!stripe || !elements) return;
@@ -1079,12 +1630,16 @@ function WalletButtonInner({
1079
1630
  },
1080
1631
  [stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]
1081
1632
  );
1082
- return /* @__PURE__ */ jsxs3(Fragment2, { children: [
1083
- /* @__PURE__ */ jsx5(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-wallet-placeholder", children: /* @__PURE__ */ jsx5(
1633
+ return /* @__PURE__ */ jsxs4(Fragment2, { children: [
1634
+ /* @__PURE__ */ jsx6(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-wallet-placeholder", children: /* @__PURE__ */ jsx6(
1084
1635
  ExpressCheckoutElement,
1085
1636
  {
1086
- onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["applePay", "googlePay"])),
1087
- onLoadError: () => setLoadState("load_error"),
1637
+ onReady: (event) => {
1638
+ setLoadState(resolveExpressCheckoutLoadState(event, ["applePay", "googlePay"]));
1639
+ },
1640
+ onLoadError: (e) => {
1641
+ setLoadState("load_error");
1642
+ },
1088
1643
  onClick: async (event) => {
1089
1644
  lastWalletMethodRef.current = event.expressPaymentType === "apple_pay" ? "apple_pay" : "google_pay";
1090
1645
  const beforeClick = runBeforeButtonClick ? await runBeforeButtonClick(lastWalletMethodRef.current) : { proceed: true };
@@ -1119,7 +1674,7 @@ function WalletButtonInner({
1119
1674
  }
1120
1675
  }
1121
1676
  ) }),
1122
- submitting && /* @__PURE__ */ jsx5(ProcessingOverlay, { status: "processing" })
1677
+ submitting && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: "processing" })
1123
1678
  ] });
1124
1679
  }
1125
1680
  function SplitCardFormInner({
@@ -1171,6 +1726,10 @@ function SplitCardFormInner({
1171
1726
  totalAmount = 0,
1172
1727
  currency = "usd",
1173
1728
  initialCardOpen = false,
1729
+ directPaypal,
1730
+ isSubscription = false,
1731
+ session,
1732
+ debug = false,
1174
1733
  innerRef
1175
1734
  }) {
1176
1735
  const flopay = useFloPay();
@@ -1178,25 +1737,25 @@ function SplitCardFormInner({
1178
1737
  const elements = useElements();
1179
1738
  const checkout = useContext3(CheckoutContext);
1180
1739
  const contextBillingUrl = useBillingApiUrl();
1181
- const [processing, setProcessing] = useState2(false);
1182
- const [error, setError] = useState2(null);
1183
- const [is3DSActive, setIs3DSActive] = useState2(false);
1184
- const [selectedCountry, setSelectedCountry] = useState2(countryProp ?? "US");
1185
- const [zipCode, setZipCode] = useState2(zipProp ?? "");
1186
- const [addressLine1, setAddressLine1] = useState2(addressLine1Prop ?? "");
1187
- const [addressLine2, setAddressLine2] = useState2(addressLine2Prop ?? "");
1188
- const [city, setCity] = useState2(cityProp ?? "");
1189
- const [stateValue, setStateValue] = useState2(stateProp ?? "");
1190
- const [accountPatch, setAccountPatch] = useState2({});
1191
- const zipCodeRef = useRef2(zipProp ?? "");
1192
- const selectedCountryRef = useRef2(countryProp ?? "US");
1193
- const addressLine1Ref = useRef2(addressLine1Prop ?? "");
1194
- const addressLine2Ref = useRef2(addressLine2Prop ?? "");
1195
- const cityRef = useRef2(cityProp ?? "");
1196
- const stateRef = useRef2(stateProp ?? "");
1197
- const avsConfig = useMemo2(() => resolveAVSConfig(enableAVSProp), [enableAVSProp]);
1740
+ const [processing, setProcessing] = useState3(false);
1741
+ const [error, setError] = useState3(null);
1742
+ const [is3DSActive, setIs3DSActive] = useState3(false);
1743
+ const [selectedCountry, setSelectedCountry] = useState3(countryProp ?? "US");
1744
+ const [zipCode, setZipCode] = useState3(zipProp ?? "");
1745
+ const [addressLine1, setAddressLine1] = useState3(addressLine1Prop ?? "");
1746
+ const [addressLine2, setAddressLine2] = useState3(addressLine2Prop ?? "");
1747
+ const [city, setCity] = useState3(cityProp ?? "");
1748
+ const [stateValue, setStateValue] = useState3(stateProp ?? "");
1749
+ const [accountPatch, setAccountPatch] = useState3({});
1750
+ const zipCodeRef = useRef3(zipProp ?? "");
1751
+ const selectedCountryRef = useRef3(countryProp ?? "US");
1752
+ const addressLine1Ref = useRef3(addressLine1Prop ?? "");
1753
+ const addressLine2Ref = useRef3(addressLine2Prop ?? "");
1754
+ const cityRef = useRef3(cityProp ?? "");
1755
+ const stateRef = useRef3(stateProp ?? "");
1756
+ const avsConfig = useMemo3(() => resolveAVSConfig(enableAVSProp), [enableAVSProp]);
1198
1757
  const enableAVS = avsConfig !== null;
1199
- const [viewState, setViewState] = useState2(initialCardOpen ? "card" : "buttons");
1758
+ const [viewState, setViewState] = useState3(initialCardOpen ? "card" : "buttons");
1200
1759
  const showCardForm = viewState === "expanding" || viewState === "card";
1201
1760
  const TRANSITION_MS = 280;
1202
1761
  const expandToCard = useCallback(() => {
@@ -1207,18 +1766,23 @@ function SplitCardFormInner({
1207
1766
  setViewState("collapsing");
1208
1767
  setTimeout(() => setViewState("buttons"), TRANSITION_MS);
1209
1768
  }, []);
1210
- useEffect3(() => {
1769
+ useEffect4(() => {
1211
1770
  if (layout === "buttons" && initialCardOpen) {
1212
1771
  setViewState("card");
1213
1772
  }
1214
1773
  }, [layout, initialCardOpen]);
1215
- const [fullName, setFullName] = useState2("");
1216
- const [formReady, setFormReady] = useState2(false);
1217
- const [overlayStatus, setOverlayStatus] = useState2(null);
1218
- const processingRef = useRef2(false);
1774
+ const [fullName, setFullName] = useState3("");
1775
+ const [formReady, setFormReady] = useState3(false);
1776
+ const [overlayStatus, setOverlayStatus] = useState3(null);
1777
+ const processingRef = useRef3(false);
1778
+ const [paypalDirectRetry, setPaypalDirectRetry] = useState3(null);
1779
+ const paypalDirectRetryRef = useRef3(paypalDirectRetry);
1780
+ useEffect4(() => {
1781
+ paypalDirectRetryRef.current = paypalDirectRetry;
1782
+ }, [paypalDirectRetry]);
1219
1783
  const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
1220
1784
  const displayError = externalError ?? error;
1221
- const bStyles = useMemo2(() => {
1785
+ const bStyles = useMemo3(() => {
1222
1786
  const base = resolveButtonsLayoutTheme(buttonsTheme);
1223
1787
  if (!buttonsStylesOverride) return base;
1224
1788
  return {
@@ -1236,7 +1800,7 @@ function SplitCardFormInner({
1236
1800
  const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
1237
1801
  const isSelfContained = !onTokenizedBody;
1238
1802
  const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
1239
- const resolvedAccount = useMemo2(() => mergeAccountPatch({
1803
+ const resolvedAccount = useMemo3(() => mergeAccountPatch({
1240
1804
  userId,
1241
1805
  email,
1242
1806
  firstName,
@@ -1244,23 +1808,23 @@ function SplitCardFormInner({
1244
1808
  country: countryProp,
1245
1809
  zip: zipProp
1246
1810
  }, accountPatch), [userId, email, firstName, lastName, countryProp, zipProp, accountPatch]);
1247
- const stripeInstance = useMemo2(() => {
1811
+ const stripeInstance = useMemo3(() => {
1248
1812
  if (!flopay) return null;
1249
1813
  return flopay.getRawProvider();
1250
1814
  }, [flopay]);
1251
- const paypalStripeInstance = useMemo2(() => {
1815
+ const paypalStripeInstance = useMemo3(() => {
1252
1816
  if (!paypalFlopay) return null;
1253
1817
  return paypalFlopay.getRawProvider();
1254
1818
  }, [paypalFlopay]);
1255
1819
  const amountInCents = totalAmount || 100;
1256
- const walletOptions = useMemo2(() => ({
1820
+ const walletOptions = useMemo3(() => ({
1257
1821
  mode: "payment",
1258
1822
  amount: amountInCents,
1259
1823
  currency: currency.toLowerCase(),
1260
1824
  paymentMethodCreation: "manual",
1261
1825
  captureMethod: "manual"
1262
1826
  }), [amountInCents, currency]);
1263
- const paypalOptions = useMemo2(() => ({
1827
+ const paypalOptions = useMemo3(() => ({
1264
1828
  mode: "payment",
1265
1829
  amount: amountInCents,
1266
1830
  currency: currency.toLowerCase(),
@@ -1281,17 +1845,20 @@ function SplitCardFormInner({
1281
1845
  [onDecline]
1282
1846
  );
1283
1847
  const showWallets = showApplePay || showGooglePay;
1284
- const [paypalLoadState, setPaypalLoadState] = useState2("loading");
1285
- const [walletLoadState, setWalletLoadState] = useState2("loading");
1286
- const [inAppBrowserDetected, setInAppBrowserDetected] = useState2();
1287
- useEffect3(() => {
1848
+ const [paypalLoadState, setPaypalLoadState] = useState3("loading");
1849
+ const [walletLoadState, setWalletLoadState] = useState3("loading");
1850
+ const [directPaypalReady, setDirectPaypalReady] = useState3(false);
1851
+ const [inAppBrowserDetected, setInAppBrowserDetected] = useState3();
1852
+ useEffect4(() => {
1288
1853
  setInAppBrowserDetected(isInAppBrowser());
1289
1854
  }, []);
1290
- const shouldShowPayPal = showPayPal && inAppBrowserDetected === false;
1291
- const shouldShowWallets = showWallets && inAppBrowserDetected === false;
1292
- const shouldRenderPayPal = shouldShowPayPal && !!paypalStripeInstance;
1855
+ const directPaypalConfigured = !!directPaypal?.clientId;
1856
+ const shouldShowPayPal = showPayPal && (directPaypalConfigured || inAppBrowserDetected === false);
1857
+ const shouldShowWallets = showWallets;
1858
+ const shouldRenderDirectPayPal = shouldShowPayPal && directPaypalConfigured;
1859
+ const shouldRenderStripePayPal = shouldShowPayPal && !directPaypalConfigured && !!paypalStripeInstance;
1293
1860
  const shouldRenderWallets = shouldShowWallets && !!stripeInstance;
1294
- const shouldDisplayPayPalRow = shouldRenderPayPal && isExpressCheckoutRowVisible(paypalLoadState);
1861
+ const shouldDisplayPayPalRow = shouldRenderDirectPayPal ? directPaypalReady : shouldRenderStripePayPal && isExpressCheckoutRowVisible(paypalLoadState);
1295
1862
  const shouldDisplayWalletRow = shouldRenderWallets && isExpressCheckoutRowVisible(walletLoadState);
1296
1863
  const handleNameChange = useCallback((value) => {
1297
1864
  setFullName(value);
@@ -1365,7 +1932,7 @@ function SplitCardFormInner({
1365
1932
  const resolvedCompletionPaymentMethodId = overrides?.completionPaymentMethodId ?? resolveTokenizedPaymentMethodId(tokenizedBody);
1366
1933
  const requestTokenizedBody = tokenizedBody.originalPaymentMethodId ? { ...tokenizedBody, originalPaymentMethodId: void 0 } : tokenizedBody;
1367
1934
  try {
1368
- const api = new PaymentAPI(baseUrl);
1935
+ const api = new PaymentAPI2(baseUrl);
1369
1936
  const response = await api.processPayment(effectiveAccount.userId ?? "", {
1370
1937
  sessionId: effectiveSessionId,
1371
1938
  tokenizedData: requestTokenizedBody,
@@ -1410,6 +1977,7 @@ function SplitCardFormInner({
1410
1977
  if (response.ok) {
1411
1978
  markSessionRecentlyCompleted(effectiveSessionId);
1412
1979
  setOverlayStatus("success");
1980
+ setPaypalDirectRetry(null);
1413
1981
  await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_SUCCESS_DELAY_MS));
1414
1982
  onComplete?.({
1415
1983
  status: "succeeded",
@@ -1517,6 +2085,24 @@ function SplitCardFormInner({
1517
2085
  }
1518
2086
  return;
1519
2087
  }
2088
+ if (json?.type === "paypal_direct_required") {
2089
+ const orderId = json["orderId"];
2090
+ if (!orderId) {
2091
+ setOverlayStatus("error");
2092
+ updateError("PayPal retry required but no order id provided.");
2093
+ return;
2094
+ }
2095
+ const prevAttempts = paypalDirectRetryRef.current?.attempts ?? 0;
2096
+ if (prevAttempts >= 2) {
2097
+ setOverlayStatus("error");
2098
+ updateError("PayPal payment could not be completed after multiple attempts.");
2099
+ emitDecline("paypal", "paypal_direct_required retry limit exceeded");
2100
+ return;
2101
+ }
2102
+ setPaypalDirectRetry({ orderId, attempts: prevAttempts + 1 });
2103
+ setOverlayStatus(null);
2104
+ return;
2105
+ }
1520
2106
  setOverlayStatus("error");
1521
2107
  const message = json?.message ?? "Payment failed. Please try again.";
1522
2108
  updateError(message);
@@ -1574,7 +2160,7 @@ function SplitCardFormInner({
1574
2160
  }
1575
2161
  }
1576
2162
  }), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
1577
- useEffect3(() => {
2163
+ useEffect4(() => {
1578
2164
  if (typeof window === "undefined") return;
1579
2165
  const stored = localStorage.getItem(WALLET_RESUME_KEY);
1580
2166
  if (!stored) return;
@@ -1658,7 +2244,7 @@ function SplitCardFormInner({
1658
2244
  return;
1659
2245
  }
1660
2246
  if (!sessionId || !resolvedAccount.email) {
1661
- throw new FloPayError2("Missing sessionId or email", "validation_error");
2247
+ throw new FloPayError3("Missing sessionId or email", "validation_error");
1662
2248
  }
1663
2249
  const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
1664
2250
  method: "POST",
@@ -1684,7 +2270,7 @@ function SplitCardFormInner({
1684
2270
  }
1685
2271
  const intentJson = await intentResponse.json();
1686
2272
  const intentClientSecret = intentJson.data?.id;
1687
- if (!intentClientSecret) throw new FloPayError2("No client_secret in payment intent response", "api_error");
2273
+ if (!intentClientSecret) throw new FloPayError3("No client_secret in payment intent response", "api_error");
1688
2274
  const confirmResult = await flopay.confirmCardPayment({
1689
2275
  clientSecret: intentClientSecret,
1690
2276
  paymentMethodId: pmResult.paymentMethodId
@@ -1705,7 +2291,7 @@ function SplitCardFormInner({
1705
2291
  const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
1706
2292
  const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
1707
2293
  if (!paymentIntentId) {
1708
- const error2 = new FloPayError2("No payment intent returned after confirmation.", "api_error");
2294
+ const error2 = new FloPayError3("No payment intent returned after confirmation.", "api_error");
1709
2295
  setOverlayStatus("error");
1710
2296
  updateError(error2.message);
1711
2297
  onError?.(error2);
@@ -1734,7 +2320,7 @@ function SplitCardFormInner({
1734
2320
  );
1735
2321
  const isReady = flopay !== null && elements !== null;
1736
2322
  if (!isReady) {
1737
- return /* @__PURE__ */ jsx5("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
2323
+ return /* @__PURE__ */ jsx6("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
1738
2324
  }
1739
2325
  const isButtons = layout === "buttons";
1740
2326
  const resolvedBorder = isButtons ? bStyles.cardInputBorder ?? "#e5e7eb" : "#A4A4FF";
@@ -1777,7 +2363,7 @@ function SplitCardFormInner({
1777
2363
  invalid: { color: "#ef4444" }
1778
2364
  }
1779
2365
  };
1780
- const cardFormBlock = /* @__PURE__ */ jsxs3("div", { style: {
2366
+ const cardFormBlock = /* @__PURE__ */ jsxs4("div", { style: {
1781
2367
  backgroundColor: cardBg,
1782
2368
  borderRadius: "8px",
1783
2369
  padding: isButtons ? "0" : "1rem",
@@ -1785,7 +2371,7 @@ function SplitCardFormInner({
1785
2371
  ...isButtons ? { padding: bStyles.cardFormContainer?.padding ?? "0" } : {},
1786
2372
  ...sharedInputPlaceholderVars
1787
2373
  }, children: [
1788
- /* @__PURE__ */ jsx5("style", { children: `
2374
+ /* @__PURE__ */ jsx6("style", { children: `
1789
2375
  .flopay-shared-input::placeholder {
1790
2376
  color: var(--flopay-input-placeholder-color);
1791
2377
  opacity: 1;
@@ -1794,12 +2380,12 @@ function SplitCardFormInner({
1794
2380
  font-weight: var(--flopay-input-font-weight);
1795
2381
  }
1796
2382
  ` }),
1797
- isButtons && showCardForm && /* @__PURE__ */ jsxs3("div", { style: {
2383
+ isButtons && showCardForm && /* @__PURE__ */ jsxs4("div", { style: {
1798
2384
  display: "flex",
1799
2385
  alignItems: "center",
1800
2386
  padding: "0.75rem 0 0.625rem"
1801
2387
  }, children: [
1802
- /* @__PURE__ */ jsxs3(
2388
+ /* @__PURE__ */ jsxs4(
1803
2389
  "button",
1804
2390
  {
1805
2391
  type: "button",
@@ -1821,7 +2407,7 @@ function SplitCardFormInner({
1821
2407
  },
1822
2408
  "aria-label": "Back to payment methods",
1823
2409
  children: [
1824
- /* @__PURE__ */ jsx5("span", { style: {
2410
+ /* @__PURE__ */ jsx6("span", { style: {
1825
2411
  display: "inline-flex",
1826
2412
  alignItems: "center",
1827
2413
  justifyContent: "center",
@@ -1831,12 +2417,12 @@ function SplitCardFormInner({
1831
2417
  backgroundColor: "#f3f4f6",
1832
2418
  transition: "background-color 0.15s",
1833
2419
  ...bStyles.backButtonIcon
1834
- }, children: /* @__PURE__ */ jsx5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx5("path", { d: "M15 18l-6-6 6-6" }) }) }),
1835
- /* @__PURE__ */ jsx5(BackButtonContentSlot, { content: cardBackButtonContent })
2420
+ }, 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" }) }) }),
2421
+ /* @__PURE__ */ jsx6(BackButtonContentSlot, { content: cardBackButtonContent })
1836
2422
  ]
1837
2423
  }
1838
2424
  ),
1839
- hideTitle ? /* @__PURE__ */ jsx5("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx5("div", { style: {
2425
+ hideTitle ? /* @__PURE__ */ jsx6("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx6("div", { style: {
1840
2426
  flex: 1,
1841
2427
  textAlign: "center",
1842
2428
  fontWeight: 600,
@@ -1844,18 +2430,18 @@ function SplitCardFormInner({
1844
2430
  color: "#262833",
1845
2431
  paddingRight: 80,
1846
2432
  ...bStyles.title
1847
- }, children: /* @__PURE__ */ jsx5(TitleContentSlot, { content: cardTitleContent }) })
2433
+ }, children: /* @__PURE__ */ jsx6(TitleContentSlot, { content: cardTitleContent }) })
1848
2434
  ] }),
1849
- !isButtons && !hideTitle && /* @__PURE__ */ jsx5("div", { style: { textAlign: "center", fontWeight: 600, fontSize: "1.1rem", padding: "0.5rem 0", color: "#262833" }, children: /* @__PURE__ */ jsx5(TitleContentSlot, { content: cardTitleContent }) }),
1850
- /* @__PURE__ */ jsx5("div", { style: {
2435
+ !isButtons && !hideTitle && /* @__PURE__ */ jsx6("div", { style: { textAlign: "center", fontWeight: 600, fontSize: "1.1rem", padding: "0.5rem 0", color: "#262833" }, children: /* @__PURE__ */ jsx6(TitleContentSlot, { content: cardTitleContent }) }),
2436
+ /* @__PURE__ */ jsx6("div", { style: {
1851
2437
  backgroundColor: cardInputBg,
1852
2438
  border: `1px solid ${resolvedBorder}`,
1853
2439
  borderTopLeftRadius: "8px",
1854
2440
  borderTopRightRadius: "8px",
1855
2441
  padding: "10px"
1856
- }, children: /* @__PURE__ */ jsx5(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
1857
- /* @__PURE__ */ jsxs3("div", { style: { display: "flex" }, children: [
1858
- /* @__PURE__ */ jsx5("div", { style: {
2442
+ }, children: /* @__PURE__ */ jsx6(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
2443
+ /* @__PURE__ */ jsxs4("div", { style: { display: "flex" }, children: [
2444
+ /* @__PURE__ */ jsx6("div", { style: {
1859
2445
  flex: 1,
1860
2446
  backgroundColor: cardInputBg,
1861
2447
  border: `1px solid ${resolvedBorder}`,
@@ -1863,23 +2449,23 @@ function SplitCardFormInner({
1863
2449
  borderRight: "none",
1864
2450
  borderBottomLeftRadius: "8px",
1865
2451
  padding: "10px"
1866
- }, children: /* @__PURE__ */ jsx5(CardExpiryElement, { options: stripeElementStyle }) }),
1867
- /* @__PURE__ */ jsx5("div", { style: {
2452
+ }, children: /* @__PURE__ */ jsx6(CardExpiryElement, { options: stripeElementStyle }) }),
2453
+ /* @__PURE__ */ jsx6("div", { style: {
1868
2454
  flex: 1,
1869
2455
  backgroundColor: cardInputBg,
1870
2456
  border: `1px solid ${resolvedBorder}`,
1871
2457
  borderTop: "none",
1872
2458
  borderBottomRightRadius: "8px",
1873
2459
  padding: "10px"
1874
- }, children: /* @__PURE__ */ jsx5(CardCvcElement, { options: stripeElementStyle }) })
2460
+ }, children: /* @__PURE__ */ jsx6(CardCvcElement, { options: stripeElementStyle }) })
1875
2461
  ] }),
1876
- /* @__PURE__ */ jsx5("div", { style: {
2462
+ /* @__PURE__ */ jsx6("div", { style: {
1877
2463
  backgroundColor: cardInputBg,
1878
2464
  border: `1px solid ${resolvedBorder}`,
1879
2465
  borderRadius: "8px",
1880
2466
  marginTop: "0.5rem",
1881
2467
  padding: "10px"
1882
- }, children: /* @__PURE__ */ jsx5(
2468
+ }, children: /* @__PURE__ */ jsx6(
1883
2469
  "input",
1884
2470
  {
1885
2471
  className: "flopay-shared-input",
@@ -1918,8 +2504,8 @@ function SplitCardFormInner({
1918
2504
  ...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
1919
2505
  });
1920
2506
  const stateOpts = getStateOptions(cc);
1921
- return /* @__PURE__ */ jsxs3(Fragment2, { children: [
1922
- isAVSFieldVisible(avsConfig.address_line_1, cc) && /* @__PURE__ */ jsx5("div", { style: inputWrapStyle(bStyles.addressLine1Input), children: /* @__PURE__ */ jsx5(
2507
+ return /* @__PURE__ */ jsxs4(Fragment2, { children: [
2508
+ isAVSFieldVisible(avsConfig.address_line_1, cc) && /* @__PURE__ */ jsx6("div", { style: inputWrapStyle(bStyles.addressLine1Input), children: /* @__PURE__ */ jsx6(
1923
2509
  "input",
1924
2510
  {
1925
2511
  className: "flopay-shared-input",
@@ -1936,7 +2522,7 @@ function SplitCardFormInner({
1936
2522
  style: inputFieldStyle()
1937
2523
  }
1938
2524
  ) }),
1939
- isAVSFieldVisible(avsConfig.address_line_2, cc) && /* @__PURE__ */ jsx5("div", { style: inputWrapStyle(bStyles.addressLine2Input), children: /* @__PURE__ */ jsx5(
2525
+ isAVSFieldVisible(avsConfig.address_line_2, cc) && /* @__PURE__ */ jsx6("div", { style: inputWrapStyle(bStyles.addressLine2Input), children: /* @__PURE__ */ jsx6(
1940
2526
  "input",
1941
2527
  {
1942
2528
  className: "flopay-shared-input",
@@ -1952,12 +2538,12 @@ function SplitCardFormInner({
1952
2538
  style: inputFieldStyle()
1953
2539
  }
1954
2540
  ) }),
1955
- (isAVSFieldVisible(avsConfig.city, cc) || isAVSFieldVisible(avsConfig.state, cc)) && /* @__PURE__ */ jsxs3("div", { style: {
2541
+ (isAVSFieldVisible(avsConfig.city, cc) || isAVSFieldVisible(avsConfig.state, cc)) && /* @__PURE__ */ jsxs4("div", { style: {
1956
2542
  display: "flex",
1957
2543
  gap: "0",
1958
2544
  marginTop: "0.5rem"
1959
2545
  }, children: [
1960
- isAVSFieldVisible(avsConfig.city, cc) && /* @__PURE__ */ jsx5("div", { style: {
2546
+ isAVSFieldVisible(avsConfig.city, cc) && /* @__PURE__ */ jsx6("div", { style: {
1961
2547
  flex: 1,
1962
2548
  backgroundColor: cardInputBg,
1963
2549
  border: `1px solid ${resolvedBorder}`,
@@ -1966,7 +2552,7 @@ function SplitCardFormInner({
1966
2552
  borderBottomLeftRadius: "8px",
1967
2553
  ...isAVSFieldVisible(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: "8px" },
1968
2554
  ...isButtons && bStyles.cityInput ? bStyles.cityInput : {}
1969
- }, children: /* @__PURE__ */ jsx5(
2555
+ }, children: /* @__PURE__ */ jsx6(
1970
2556
  "input",
1971
2557
  {
1972
2558
  className: "flopay-shared-input",
@@ -1983,7 +2569,7 @@ function SplitCardFormInner({
1983
2569
  style: inputFieldStyle()
1984
2570
  }
1985
2571
  ) }),
1986
- isAVSFieldVisible(avsConfig.state, cc) && /* @__PURE__ */ jsx5("div", { style: {
2572
+ isAVSFieldVisible(avsConfig.state, cc) && /* @__PURE__ */ jsx6("div", { style: {
1987
2573
  flex: 1,
1988
2574
  backgroundColor: cardInputBg,
1989
2575
  border: `1px solid ${resolvedBorder}`,
@@ -1992,7 +2578,7 @@ function SplitCardFormInner({
1992
2578
  borderBottomRightRadius: "8px",
1993
2579
  ...isAVSFieldVisible(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: "8px" },
1994
2580
  ...isButtons && bStyles.stateInput ? bStyles.stateInput : {}
1995
- }, children: stateOpts ? /* @__PURE__ */ jsxs3(
2581
+ }, children: stateOpts ? /* @__PURE__ */ jsxs4(
1996
2582
  "select",
1997
2583
  {
1998
2584
  value: stateValue,
@@ -2006,11 +2592,11 @@ function SplitCardFormInner({
2006
2592
  "data-testid": "flopay-state",
2007
2593
  style: { ...inputFieldStyle(), cursor: "pointer" },
2008
2594
  children: [
2009
- /* @__PURE__ */ jsx5("option", { value: "", children: getStateLabel(cc) }),
2010
- stateOpts.map((s) => /* @__PURE__ */ jsx5("option", { value: s.code, children: s.name }, s.code))
2595
+ /* @__PURE__ */ jsx6("option", { value: "", children: getStateLabel(cc) }),
2596
+ stateOpts.map((s) => /* @__PURE__ */ jsx6("option", { value: s.code, children: s.name }, s.code))
2011
2597
  ]
2012
2598
  }
2013
- ) : /* @__PURE__ */ jsx5(
2599
+ ) : /* @__PURE__ */ jsx6(
2014
2600
  "input",
2015
2601
  {
2016
2602
  className: "flopay-shared-input",
@@ -2028,20 +2614,20 @@ function SplitCardFormInner({
2028
2614
  }
2029
2615
  ) })
2030
2616
  ] }),
2031
- (isAVSFieldVisible(avsConfig.country, cc) || isAVSFieldVisible(avsConfig.postal_code, cc)) && /* @__PURE__ */ jsxs3("div", { style: {
2617
+ (isAVSFieldVisible(avsConfig.country, cc) || isAVSFieldVisible(avsConfig.postal_code, cc)) && /* @__PURE__ */ jsxs4("div", { style: {
2032
2618
  display: "flex",
2033
2619
  flexDirection: avsLayoutProp === "column" ? "column" : "row",
2034
2620
  gap: avsLayoutProp === "column" ? "0.5rem" : "0",
2035
2621
  marginTop: "0.5rem"
2036
2622
  }, children: [
2037
- isAVSFieldVisible(avsConfig.country, cc) && /* @__PURE__ */ jsx5("div", { style: {
2623
+ isAVSFieldVisible(avsConfig.country, cc) && /* @__PURE__ */ jsx6("div", { style: {
2038
2624
  flex: avsLayoutProp === "row" ? 1 : void 0,
2039
2625
  backgroundColor: cardInputBg,
2040
2626
  border: `1px solid ${resolvedBorder}`,
2041
2627
  padding: "10px",
2042
2628
  ...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: "8px", borderBottomLeftRadius: "8px", borderRight: "none" } : { borderRadius: "8px" },
2043
2629
  ...isButtons && bStyles.countrySelect ? bStyles.countrySelect : {}
2044
- }, children: /* @__PURE__ */ jsx5(
2630
+ }, children: /* @__PURE__ */ jsx6(
2045
2631
  "select",
2046
2632
  {
2047
2633
  value: selectedCountry,
@@ -2056,21 +2642,21 @@ function SplitCardFormInner({
2056
2642
  autoComplete: "country",
2057
2643
  "data-testid": "flopay-country",
2058
2644
  style: { ...inputFieldStyle(), cursor: "pointer" },
2059
- children: COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ jsxs3("option", { value: c.code, children: [
2645
+ children: COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ jsxs4("option", { value: c.code, children: [
2060
2646
  c.flag,
2061
2647
  " ",
2062
2648
  c.name
2063
2649
  ] }, c.code))
2064
2650
  }
2065
2651
  ) }),
2066
- isAVSFieldVisible(avsConfig.postal_code, cc) && /* @__PURE__ */ jsx5("div", { style: {
2652
+ isAVSFieldVisible(avsConfig.postal_code, cc) && /* @__PURE__ */ jsx6("div", { style: {
2067
2653
  flex: avsLayoutProp === "row" ? 1 : void 0,
2068
2654
  backgroundColor: cardInputBg,
2069
2655
  border: `1px solid ${resolvedBorder}`,
2070
2656
  padding: "10px",
2071
2657
  ...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: "8px", borderBottomRightRadius: "8px" } : { borderRadius: "8px" },
2072
2658
  ...isButtons && bStyles.zipInput ? bStyles.zipInput : {}
2073
- }, children: /* @__PURE__ */ jsx5(
2659
+ }, children: /* @__PURE__ */ jsx6(
2074
2660
  "input",
2075
2661
  {
2076
2662
  className: "flopay-shared-input",
@@ -2091,7 +2677,7 @@ function SplitCardFormInner({
2091
2677
  ] })
2092
2678
  ] });
2093
2679
  })(),
2094
- displayError && /* @__PURE__ */ jsxs3("div", { role: "alert", "data-testid": "flopay-error", style: {
2680
+ displayError && /* @__PURE__ */ jsxs4("div", { role: "alert", "data-testid": "flopay-error", style: {
2095
2681
  margin: "0.75rem 0",
2096
2682
  padding: "0.625rem 0.875rem",
2097
2683
  background: "#FEF2F2",
@@ -2105,10 +2691,10 @@ function SplitCardFormInner({
2105
2691
  gap: "0.5rem",
2106
2692
  ...isButtons && bStyles.errorBanner ? bStyles.errorBanner : {}
2107
2693
  }, children: [
2108
- /* @__PURE__ */ jsx5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx5("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
2694
+ /* @__PURE__ */ jsx6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx6("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
2109
2695
  displayError
2110
2696
  ] }),
2111
- children ?? /* @__PURE__ */ jsx5(
2697
+ children ?? /* @__PURE__ */ jsx6(
2112
2698
  "button",
2113
2699
  {
2114
2700
  type: "submit",
@@ -2131,7 +2717,7 @@ function SplitCardFormInner({
2131
2717
  children: isSubmitting ? "PROCESSING..." : submitLabel
2132
2718
  }
2133
2719
  ),
2134
- !isButtons && showSecurityFooter && /* @__PURE__ */ jsx5("div", { style: {
2720
+ !isButtons && showSecurityFooter && /* @__PURE__ */ jsx6("div", { style: {
2135
2721
  backgroundColor: "#EFF9F0",
2136
2722
  borderRadius: "8px",
2137
2723
  padding: "0.75rem",
@@ -2148,11 +2734,11 @@ function SplitCardFormInner({
2148
2734
  const cardButtonSizing = cardButtonContent === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
2149
2735
  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;
2150
2736
  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;
2151
- return /* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
2152
- /* @__PURE__ */ jsx5(FloPayKeyframes, {}),
2153
- overlayStatus && /* @__PURE__ */ jsx5(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
2154
- /* @__PURE__ */ jsxs3("div", { style: { display: "grid" }, children: [
2155
- /* @__PURE__ */ jsxs3("div", { style: {
2737
+ return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
2738
+ /* @__PURE__ */ jsx6(FloPayKeyframes, {}),
2739
+ overlayStatus && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
2740
+ /* @__PURE__ */ jsxs4("div", { style: { display: "grid" }, children: [
2741
+ /* @__PURE__ */ jsxs4("div", { style: {
2156
2742
  gridArea: "1 / 1",
2157
2743
  display: "flex",
2158
2744
  flexDirection: "column",
@@ -2161,7 +2747,75 @@ function SplitCardFormInner({
2161
2747
  ...!isButtonsView && !buttonsAnim ? { visibility: "hidden", position: "absolute", pointerEvents: "none", width: "100%" } : {},
2162
2748
  ...buttonsAnim ? { animation: buttonsAnim, pointerEvents: "none" } : {}
2163
2749
  }, children: [
2164
- shouldRenderPayPal && /* @__PURE__ */ jsx5(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx5(
2750
+ debug && showPayPal && /* @__PURE__ */ jsx6(
2751
+ "pre",
2752
+ {
2753
+ "data-testid": "flopay-direct-paypal-gate-debug",
2754
+ style: {
2755
+ margin: 0,
2756
+ padding: "6px 8px",
2757
+ background: "#eef2ff",
2758
+ border: "1px solid #c7d2fe",
2759
+ borderRadius: 6,
2760
+ color: "#111827",
2761
+ font: "11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace",
2762
+ whiteSpace: "pre-wrap",
2763
+ wordBreak: "break-word"
2764
+ },
2765
+ children: [
2766
+ "FloPay/DirectPayPal-debug (parent gate)",
2767
+ ` showPayPal=${showPayPal}`,
2768
+ ` directPaypalConfigured=${directPaypalConfigured}`,
2769
+ ` inAppBrowserDetected=${String(inAppBrowserDetected)}`,
2770
+ ` shouldRenderDirectPayPal=${shouldRenderDirectPayPal}`,
2771
+ ` shouldRenderStripePayPal=${shouldRenderStripePayPal}`,
2772
+ ` hasPaypalStripeInstance=${!!paypalStripeInstance}`
2773
+ ].join("\n")
2774
+ }
2775
+ ),
2776
+ shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ jsxs4(Fragment2, { children: [
2777
+ paypalDirectRetry && /* @__PURE__ */ jsx6(
2778
+ "div",
2779
+ {
2780
+ "data-testid": "flopay-paypal-direct-retry-notice",
2781
+ style: {
2782
+ padding: "8px 10px",
2783
+ background: "#fef3c7",
2784
+ border: "1px solid #fcd34d",
2785
+ borderRadius: 6,
2786
+ color: "#78350f",
2787
+ fontSize: 13,
2788
+ lineHeight: 1.4
2789
+ },
2790
+ children: "Please confirm your PayPal payment to complete checkout."
2791
+ }
2792
+ ),
2793
+ /* @__PURE__ */ jsx6(
2794
+ DirectPayPalButton,
2795
+ {
2796
+ sessionId,
2797
+ billingApiUrl: resolvedBillingApiUrl,
2798
+ email: resolvedAccount.email,
2799
+ clientId: directPaypal.clientId,
2800
+ environment: directPaypal.environment,
2801
+ currency: currency.toUpperCase(),
2802
+ isSubscription,
2803
+ onTokenizedBody: dispatchTokenizedBody,
2804
+ onComplete,
2805
+ onErrorChange: updateError,
2806
+ onDecline,
2807
+ onButtonClick,
2808
+ runBeforeButtonClick,
2809
+ isProcessing: isSubmitting,
2810
+ onLoadStateChange: setDirectPaypalReady,
2811
+ session: session ?? null,
2812
+ existingOrderId: paypalDirectRetry?.orderId,
2813
+ debug
2814
+ },
2815
+ paypalDirectRetry?.orderId ?? "fresh"
2816
+ )
2817
+ ] }),
2818
+ shouldRenderStripePayPal && /* @__PURE__ */ jsx6(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx6(
2165
2819
  PayPalButtonInner,
2166
2820
  {
2167
2821
  sessionId,
@@ -2176,7 +2830,7 @@ function SplitCardFormInner({
2176
2830
  onLoadStateChange: setPaypalLoadState
2177
2831
  }
2178
2832
  ) }),
2179
- shouldRenderWallets ? /* @__PURE__ */ jsx5(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx5(
2833
+ shouldRenderWallets ? /* @__PURE__ */ jsx6(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx6(
2180
2834
  WalletButtonInner,
2181
2835
  {
2182
2836
  sessionId,
@@ -2191,8 +2845,8 @@ function SplitCardFormInner({
2191
2845
  runBeforeButtonClick,
2192
2846
  onLoadStateChange: setWalletLoadState
2193
2847
  }
2194
- ) }) : shouldShowWallets ? /* @__PURE__ */ jsx5("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: 8, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
2195
- /* @__PURE__ */ jsx5(
2848
+ ) }) : shouldShowWallets ? /* @__PURE__ */ jsx6("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: 8, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
2849
+ /* @__PURE__ */ jsx6(
2196
2850
  "button",
2197
2851
  {
2198
2852
  type: "button",
@@ -2230,10 +2884,10 @@ function SplitCardFormInner({
2230
2884
  onMouseUp: (e) => {
2231
2885
  e.currentTarget.style.transform = "scale(1)";
2232
2886
  },
2233
- children: /* @__PURE__ */ jsx5(CardButtonContentSlot, { content: cardButtonContent })
2887
+ children: /* @__PURE__ */ jsx6(CardButtonContentSlot, { content: cardButtonContent })
2234
2888
  }
2235
2889
  ),
2236
- displayError && viewState === "buttons" && /* @__PURE__ */ jsxs3("div", { role: "alert", "data-testid": "flopay-error", style: {
2890
+ displayError && viewState === "buttons" && /* @__PURE__ */ jsxs4("div", { role: "alert", "data-testid": "flopay-error", style: {
2237
2891
  margin: "0.25rem 0",
2238
2892
  padding: "0.625rem 0.875rem",
2239
2893
  background: "#FEF2F2",
@@ -2247,11 +2901,11 @@ function SplitCardFormInner({
2247
2901
  gap: "0.5rem",
2248
2902
  ...bStyles.errorBanner ? bStyles.errorBanner : {}
2249
2903
  }, children: [
2250
- /* @__PURE__ */ jsx5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx5("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
2904
+ /* @__PURE__ */ jsx6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx6("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
2251
2905
  displayError
2252
2906
  ] })
2253
2907
  ] }),
2254
- isCardView && /* @__PURE__ */ jsx5("div", { style: {
2908
+ isCardView && /* @__PURE__ */ jsx6("div", { style: {
2255
2909
  gridArea: "1 / 1",
2256
2910
  ...cardAnim ? { animation: cardAnim } : {},
2257
2911
  ...viewState === "collapsing" ? { pointerEvents: "none" } : {}
@@ -2259,37 +2913,111 @@ function SplitCardFormInner({
2259
2913
  ] })
2260
2914
  ] });
2261
2915
  }
2262
- return /* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
2263
- /* @__PURE__ */ jsx5(FloPayKeyframes, {}),
2264
- overlayStatus && /* @__PURE__ */ jsx5(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
2265
- shouldRenderWallets && /* @__PURE__ */ jsx5(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx5(
2266
- WalletButtonInner,
2267
- {
2268
- sessionId,
2269
- email: resolvedAccount.email,
2270
- billingApiUrl: resolvedBillingApiUrl,
2271
- showApplePay,
2272
- showGooglePay,
2273
- onTokenizedBody: dispatchTokenizedBody,
2274
- onErrorChange: updateError,
2275
- onDecline,
2276
- onLoadStateChange: setWalletLoadState
2277
- }
2278
- ) }),
2279
- shouldRenderPayPal && /* @__PURE__ */ jsx5(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx5(
2280
- PayPalButtonInner,
2281
- {
2282
- sessionId,
2283
- email: resolvedAccount.email,
2284
- billingApiUrl: resolvedBillingApiUrl,
2285
- onTokenizedBody: dispatchTokenizedBody,
2286
- onErrorChange: updateError,
2287
- isProcessing: isSubmitting,
2288
- onDecline,
2289
- onLoadStateChange: setPaypalLoadState
2290
- }
2291
- ) }),
2292
- (shouldDisplayWalletRow || shouldDisplayPayPalRow) && /* @__PURE__ */ jsxs3("div", { style: {
2916
+ return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
2917
+ /* @__PURE__ */ jsx6(FloPayKeyframes, {}),
2918
+ overlayStatus && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
2919
+ /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
2920
+ debug && showPayPal && /* @__PURE__ */ jsx6(
2921
+ "pre",
2922
+ {
2923
+ "data-testid": "flopay-direct-paypal-gate-debug-default",
2924
+ style: {
2925
+ margin: 0,
2926
+ padding: "6px 8px",
2927
+ background: "#eef2ff",
2928
+ border: "1px solid #c7d2fe",
2929
+ borderRadius: 6,
2930
+ color: "#111827",
2931
+ font: "11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace",
2932
+ whiteSpace: "pre-wrap",
2933
+ wordBreak: "break-word"
2934
+ },
2935
+ children: [
2936
+ "FloPay/DirectPayPal-debug (parent gate)",
2937
+ ` showPayPal=${showPayPal}`,
2938
+ ` directPaypalConfigured=${directPaypalConfigured}`,
2939
+ ` inAppBrowserDetected=${String(inAppBrowserDetected)}`,
2940
+ ` shouldRenderDirectPayPal=${shouldRenderDirectPayPal}`,
2941
+ ` shouldRenderStripePayPal=${shouldRenderStripePayPal}`,
2942
+ ` hasPaypalStripeInstance=${!!paypalStripeInstance}`
2943
+ ].join("\n")
2944
+ }
2945
+ ),
2946
+ shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ jsxs4(Fragment2, { children: [
2947
+ paypalDirectRetry && /* @__PURE__ */ jsx6(
2948
+ "div",
2949
+ {
2950
+ "data-testid": "flopay-paypal-direct-retry-notice-default",
2951
+ style: {
2952
+ padding: "8px 10px",
2953
+ background: "#fef3c7",
2954
+ border: "1px solid #fcd34d",
2955
+ borderRadius: 6,
2956
+ color: "#78350f",
2957
+ fontSize: 13,
2958
+ lineHeight: 1.4
2959
+ },
2960
+ children: "Please confirm your PayPal payment to complete checkout."
2961
+ }
2962
+ ),
2963
+ /* @__PURE__ */ jsx6(
2964
+ DirectPayPalButton,
2965
+ {
2966
+ sessionId,
2967
+ billingApiUrl: resolvedBillingApiUrl,
2968
+ email: resolvedAccount.email,
2969
+ clientId: directPaypal.clientId,
2970
+ environment: directPaypal.environment,
2971
+ currency: currency.toUpperCase(),
2972
+ isSubscription,
2973
+ onTokenizedBody: dispatchTokenizedBody,
2974
+ onComplete,
2975
+ onErrorChange: updateError,
2976
+ onDecline,
2977
+ onButtonClick,
2978
+ runBeforeButtonClick,
2979
+ isProcessing: isSubmitting,
2980
+ onLoadStateChange: setDirectPaypalReady,
2981
+ session: session ?? null,
2982
+ existingOrderId: paypalDirectRetry?.orderId,
2983
+ debug
2984
+ },
2985
+ paypalDirectRetry?.orderId ?? "fresh"
2986
+ )
2987
+ ] }),
2988
+ shouldRenderStripePayPal && /* @__PURE__ */ jsx6(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx6(
2989
+ PayPalButtonInner,
2990
+ {
2991
+ sessionId,
2992
+ email: resolvedAccount.email,
2993
+ billingApiUrl: resolvedBillingApiUrl,
2994
+ onTokenizedBody: dispatchTokenizedBody,
2995
+ onErrorChange: updateError,
2996
+ isProcessing: isSubmitting,
2997
+ onButtonClick,
2998
+ onDecline,
2999
+ runBeforeButtonClick,
3000
+ onLoadStateChange: setPaypalLoadState
3001
+ }
3002
+ ) }),
3003
+ shouldRenderWallets && /* @__PURE__ */ jsx6(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx6(
3004
+ WalletButtonInner,
3005
+ {
3006
+ sessionId,
3007
+ email: resolvedAccount.email,
3008
+ billingApiUrl: resolvedBillingApiUrl,
3009
+ showApplePay,
3010
+ showGooglePay,
3011
+ onTokenizedBody: dispatchTokenizedBody,
3012
+ onErrorChange: updateError,
3013
+ onButtonClick,
3014
+ onDecline,
3015
+ runBeforeButtonClick,
3016
+ onLoadStateChange: setWalletLoadState
3017
+ }
3018
+ ) })
3019
+ ] }),
3020
+ (shouldDisplayWalletRow || shouldDisplayPayPalRow) && /* @__PURE__ */ jsxs4("div", { style: {
2293
3021
  display: "flex",
2294
3022
  alignItems: "center",
2295
3023
  gap: "0.75rem",
@@ -2297,17 +3025,17 @@ function SplitCardFormInner({
2297
3025
  color: "#999",
2298
3026
  fontSize: "0.85rem"
2299
3027
  }, children: [
2300
- /* @__PURE__ */ jsx5("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
2301
- /* @__PURE__ */ jsx5("span", { children: "or pay with card" }),
2302
- /* @__PURE__ */ jsx5("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
3028
+ /* @__PURE__ */ jsx6("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
3029
+ /* @__PURE__ */ jsx6("span", { children: "or pay with card" }),
3030
+ /* @__PURE__ */ jsx6("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
2303
3031
  ] }),
2304
3032
  cardFormBlock
2305
3033
  ] });
2306
3034
  }
2307
3035
 
2308
3036
  // src/saved-payment-flow.ts
2309
- import { loadFloPay, PaymentAPI as PaymentAPI2 } from "@flopay/js";
2310
- import { FloPayError as FloPayError3 } from "@flopay/shared";
3037
+ import { loadFloPay, PaymentAPI as PaymentAPI3 } from "@flopay/js";
3038
+ import { FloPayError as FloPayError4 } from "@flopay/shared";
2311
3039
  var DEFAULT_SAVED_PAYMENT_DECLINE_METHOD = "card";
2312
3040
  function getRedirectResultFromCheckoutProcessError(error) {
2313
3041
  if (!error?.type || !error.threeDSecureToken) {
@@ -2325,7 +3053,7 @@ function getRedirectResultFromCheckoutProcessError(error) {
2325
3053
  function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment failed. Please try again.", options) {
2326
3054
  const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
2327
3055
  return Object.assign(
2328
- new FloPayError3(
3056
+ new FloPayError4(
2329
3057
  error?.message ?? fallbackMessage,
2330
3058
  "api_error",
2331
3059
  {
@@ -2380,16 +3108,19 @@ function getRedirectTokenFromProcessResponse(json, options) {
2380
3108
  return candidate;
2381
3109
  }
2382
3110
  }
2383
- const nestedGatewayData = nestedRecord.gatewayData;
2384
- if (nestedGatewayData && typeof nestedGatewayData === "object") {
2385
- const nestedGatewayDataRecord = nestedGatewayData;
2386
- const gatewayCandidates = [
2387
- nestedGatewayDataRecord.stripeClientSecret,
2388
- nestedGatewayDataRecord.clientSecret
2389
- ];
2390
- for (const candidate of gatewayCandidates) {
2391
- if (typeof candidate === "string" && candidate.length > 0 && (!options?.requirePaymentIntentClientSecret || isStripePaymentIntentClientSecret(candidate))) {
2392
- return candidate;
3111
+ const nestedGateways = nestedRecord.gateways;
3112
+ if (nestedGateways && typeof nestedGateways === "object") {
3113
+ const stripeGateway = nestedGateways.stripe;
3114
+ if (stripeGateway && typeof stripeGateway === "object") {
3115
+ const stripeRecord = stripeGateway;
3116
+ const gatewayCandidates = [
3117
+ stripeRecord.stripeClientSecret,
3118
+ stripeRecord.clientSecret
3119
+ ];
3120
+ for (const candidate of gatewayCandidates) {
3121
+ if (typeof candidate === "string" && candidate.length > 0 && (!options?.requirePaymentIntentClientSecret || isStripePaymentIntentClientSecret(candidate))) {
3122
+ return candidate;
3123
+ }
2393
3124
  }
2394
3125
  }
2395
3126
  }
@@ -2414,9 +3145,9 @@ async function recover3DSRedirectResult({
2414
3145
  return null;
2415
3146
  }
2416
3147
  try {
2417
- const api = new PaymentAPI2(billingApiUrl);
3148
+ const api = new PaymentAPI3(billingApiUrl);
2418
3149
  const unified = await api.getUnifiedCheckoutSession(sessionId);
2419
- const refreshedToken = unified.provider === "stripe" ? unified.data.stripe?.clientSecret : void 0;
3150
+ const refreshedToken = unified.data.stripe?.clientSecret;
2420
3151
  if (isStripePaymentIntentClientSecret(refreshedToken)) {
2421
3152
  return {
2422
3153
  type: "3ds_required",
@@ -2442,7 +3173,7 @@ async function processSavedPaymentForMode({
2442
3173
  const lastName = session.customer?.lastName ?? session.accountData?.lastName ?? "";
2443
3174
  const country = session.customer?.country ?? session.accountData?.country ?? void 0;
2444
3175
  const zip = session.customer?.zip ?? session.accountData?.zip ?? void 0;
2445
- const api = new PaymentAPI2(baseUrl);
3176
+ const api = new PaymentAPI3(baseUrl);
2446
3177
  const response = await retryOnceOnFetchFailure(() => api.processPayment(customerId, {
2447
3178
  sessionId: resolvedSessionId,
2448
3179
  tokenizedData,
@@ -2471,7 +3202,7 @@ async function processSavedPaymentForMode({
2471
3202
  if (json?.type === "paypal_redirect_required" || json?.type === "3ds_required") {
2472
3203
  const redirectToken = getRedirectTokenFromProcessResponse(json);
2473
3204
  if (!redirectToken) {
2474
- throw new FloPayError3(
3205
+ throw new FloPayError4(
2475
3206
  "Authentication is required but no redirect token was provided.",
2476
3207
  "api_error",
2477
3208
  { code: "authentication_required" }
@@ -2493,7 +3224,7 @@ async function processSavedPaymentForMode({
2493
3224
  return recoveredRedirect;
2494
3225
  }
2495
3226
  throw Object.assign(
2496
- new FloPayError3(
3227
+ new FloPayError4(
2497
3228
  "Your card requires authentication. Please enter your payment details below.",
2498
3229
  "api_error",
2499
3230
  { code: "authentication_required" }
@@ -2501,7 +3232,7 @@ async function processSavedPaymentForMode({
2501
3232
  { checkoutMethod: "card" }
2502
3233
  );
2503
3234
  }
2504
- throw new FloPayError3(
3235
+ throw new FloPayError4(
2505
3236
  json?.message ?? "Payment failed. Please try again.",
2506
3237
  "api_error",
2507
3238
  {
@@ -2521,13 +3252,13 @@ async function processSavedPaymentWithIntent({
2521
3252
  const customerEmail = session.customer?.email ?? session.accountData?.email ?? "";
2522
3253
  if (!customerEmail) {
2523
3254
  throw Object.assign(
2524
- new FloPayError3("Customer email is required to create a payment intent.", "validation_error", {
3255
+ new FloPayError4("Customer email is required to create a payment intent.", "validation_error", {
2525
3256
  param: "email"
2526
3257
  }),
2527
3258
  { checkoutMethod: "card" }
2528
3259
  );
2529
3260
  }
2530
- const api = new PaymentAPI2(billingApiUrl);
3261
+ const api = new PaymentAPI3(billingApiUrl);
2531
3262
  const intentResponse = await retryOnceOnFetchFailure(() => api.createPaymentIntent(
2532
3263
  sessionId,
2533
3264
  customerEmail,
@@ -2549,7 +3280,7 @@ async function processSavedPaymentWithIntent({
2549
3280
  });
2550
3281
  if (!intentClientSecret) {
2551
3282
  throw Object.assign(
2552
- new FloPayError3("No client secret in payment intent response.", "api_error"),
3283
+ new FloPayError4("No client secret in payment intent response.", "api_error"),
2553
3284
  { checkoutMethod: "card" }
2554
3285
  );
2555
3286
  }
@@ -2572,7 +3303,7 @@ async function processSavedPaymentWithIntent({
2572
3303
  const confirmedPaymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? paymentMethodId;
2573
3304
  if (!confirmedPaymentIntentId || confirmResult.status !== "succeeded" && confirmResult.status !== "processing" && confirmResult.status !== "requires_capture") {
2574
3305
  throw Object.assign(
2575
- new FloPayError3(
3306
+ new FloPayError4(
2576
3307
  `Unfortunately, your payment could not be processed. Please try again using a different payment method or contact your bank for assistance. If the issue persists, feel free to reach out to us for support.`,
2577
3308
  "api_error",
2578
3309
  {
@@ -2620,12 +3351,12 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
2620
3351
  }) {
2621
3352
  const stripe = flopay?.getRawProvider();
2622
3353
  if (!stripe) {
2623
- throw new FloPayError3("Payment provider is not available.", "api_error");
3354
+ throw new FloPayError4("Payment provider is not available.", "api_error");
2624
3355
  }
2625
3356
  if (redirectResult.type === "3ds_required") {
2626
3357
  if (!attempt3DS || !redirectResult.threeDSecureToken) {
2627
3358
  throw Object.assign(
2628
- new FloPayError3(
3359
+ new FloPayError4(
2629
3360
  "Your card requires authentication. Please enter your payment details below.",
2630
3361
  "api_error",
2631
3362
  { code: "authentication_required" }
@@ -2641,7 +3372,7 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
2641
3372
  );
2642
3373
  if (retrieveError) {
2643
3374
  throw Object.assign(
2644
- new FloPayError3(
3375
+ new FloPayError4(
2645
3376
  retrieveError.message ?? "Failed to retrieve 3DS payment status.",
2646
3377
  "api_error",
2647
3378
  { code: retrieveError.code }
@@ -2667,7 +3398,7 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
2667
3398
  );
2668
3399
  if (confirmError) {
2669
3400
  throw Object.assign(
2670
- new FloPayError3(
3401
+ new FloPayError4(
2671
3402
  confirmError.message ?? "3DS authentication failed.",
2672
3403
  "api_error",
2673
3404
  { code: confirmError.code }
@@ -2682,7 +3413,7 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
2682
3413
  });
2683
3414
  if (nextActionError) {
2684
3415
  throw Object.assign(
2685
- new FloPayError3(
3416
+ new FloPayError4(
2686
3417
  nextActionError.message ?? "3DS authentication failed.",
2687
3418
  "api_error",
2688
3419
  { code: nextActionError.code }
@@ -2722,7 +3453,7 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
2722
3453
  });
2723
3454
  }
2724
3455
  throw Object.assign(
2725
- new FloPayError3("3DS authentication did not complete successfully.", "api_error"),
3456
+ new FloPayError4("3DS authentication did not complete successfully.", "api_error"),
2726
3457
  { checkoutMethod: "card" }
2727
3458
  );
2728
3459
  }
@@ -2730,7 +3461,7 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
2730
3461
  const paypalStripe = (paypalFlopay ?? flopay)?.getRawProvider();
2731
3462
  if (!paypalStripe) {
2732
3463
  throw Object.assign(
2733
- new FloPayError3("PayPal is not available.", "api_error"),
3464
+ new FloPayError4("PayPal is not available.", "api_error"),
2734
3465
  { checkoutMethod: "paypal" }
2735
3466
  );
2736
3467
  }
@@ -2740,7 +3471,7 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
2740
3471
  });
2741
3472
  if (error2) {
2742
3473
  throw Object.assign(
2743
- new FloPayError3(
3474
+ new FloPayError4(
2744
3475
  error2.message ?? "PayPal authorization failed.",
2745
3476
  "api_error",
2746
3477
  { code: error2.code }
@@ -2763,7 +3494,7 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
2763
3494
  });
2764
3495
  if (error) {
2765
3496
  throw Object.assign(
2766
- new FloPayError3(
3497
+ new FloPayError4(
2767
3498
  error.message ?? "PayPal authorization failed.",
2768
3499
  "api_error",
2769
3500
  { code: error.code }
@@ -2776,33 +3507,33 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
2776
3507
  checkoutMethod: "paypal"
2777
3508
  };
2778
3509
  }
2779
- throw new FloPayError3("Unsupported payment redirect state.", "api_error");
3510
+ throw new FloPayError4("Unsupported payment redirect state.", "api_error");
2780
3511
  }
2781
3512
  function normalizeSavedPaymentError(err) {
2782
- if (err instanceof FloPayError3) {
3513
+ if (err instanceof FloPayError4) {
2783
3514
  return err;
2784
3515
  }
2785
- return new FloPayError3(
3516
+ return new FloPayError4(
2786
3517
  err instanceof Error ? err.message : "Payment failed. Please try again.",
2787
3518
  "api_error"
2788
3519
  );
2789
3520
  }
2790
3521
  function resolveSavedPaymentPublishableKeys(unified) {
2791
- let publishableKey;
2792
- let paypalPublishableKey;
2793
- if (unified.provider === "stripe") {
2794
- publishableKey = unified.data.stripe?.publishableKey;
2795
- paypalPublishableKey = unified.data.stripe?.paypalPublishableKey ?? void 0;
2796
- }
3522
+ const publishableKey = unified.data.stripe?.publishableKey;
2797
3523
  if (!publishableKey) {
2798
- throw new FloPayError3(
2799
- "No publishable key found in the checkout session. Ensure the session includes gatewayData.publishableKey.",
3524
+ throw new FloPayError4(
3525
+ "No publishable key found in the checkout session. Ensure the session advertises gateways.stripe.",
2800
3526
  "validation_error"
2801
3527
  );
2802
3528
  }
2803
3529
  return {
2804
3530
  publishableKey,
2805
- paypalPublishableKey
3531
+ // Direct-PayPal sessions can still use Stripe's PayPal Element for the
3532
+ // saved-PM redirect leg. Prefer the dedicated Stripe-PayPal sub-account
3533
+ // publishable key when the backend advertises one; fall back to the
3534
+ // primary Stripe publishable key so the resume flow still has a Stripe
3535
+ // instance to drive Stripe's PayPal PI.
3536
+ paypalPublishableKey: unified.data.stripe?.paypalPublishableKey ?? publishableKey
2806
3537
  };
2807
3538
  }
2808
3539
  async function loadSavedPaymentProviders({
@@ -2832,13 +3563,21 @@ async function loadSavedPaymentProviders({
2832
3563
  }
2833
3564
 
2834
3565
  // src/flopay-checkout.tsx
2835
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
3566
+ import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
2836
3567
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
2837
3568
  var PAYPAL_RESUME_STORAGE_KEY = "flopay_checkout_saved_payment_resume";
2838
3569
  var sessionInflightMap = /* @__PURE__ */ new Map();
2839
3570
  function sleep(ms) {
2840
3571
  return new Promise((resolve) => setTimeout(resolve, ms));
2841
3572
  }
3573
+ function resolveDirectPaypalConfig(unified) {
3574
+ const clientId = unified?.data.paypal?.publishableKey;
3575
+ if (!clientId) return void 0;
3576
+ return {
3577
+ clientId,
3578
+ environment: unified?.data.paypal?.environment
3579
+ };
3580
+ }
2842
3581
  function canUseStorage() {
2843
3582
  return typeof window !== "undefined" && typeof window.sessionStorage !== "undefined";
2844
3583
  }
@@ -2912,6 +3651,7 @@ function FloPayCheckout({
2912
3651
  showPayPal = true,
2913
3652
  showApplePay = true,
2914
3653
  showGooglePay = true,
3654
+ debug = false,
2915
3655
  layout,
2916
3656
  buttonsTheme,
2917
3657
  buttonsStyles,
@@ -2935,37 +3675,37 @@ function FloPayCheckout({
2935
3675
  const resolvedBillingUrl = resolveBillingApiUrl3(billingApiUrl);
2936
3676
  const checkoutType = createSessionParams ? "embedded_checkout" : "standard_checkout";
2937
3677
  const checkoutLayout = children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout";
2938
- const [unified, setUnified] = useState3(null);
2939
- const [flopay, setFloPay] = useState3(null);
2940
- const flopayRef = useRef3(null);
2941
- const [paypalFlopay, setPaypalFloPay] = useState3(null);
2942
- const paypalFlopayRef = useRef3(null);
2943
- const [session, setSession] = useState3(null);
2944
- const [resolvedSessionId, setResolvedSessionId] = useState3(sessionIdProp ?? "");
3678
+ const [unified, setUnified] = useState4(null);
3679
+ const [flopay, setFloPay] = useState4(null);
3680
+ const flopayRef = useRef4(null);
3681
+ const [paypalFlopay, setPaypalFloPay] = useState4(null);
3682
+ const paypalFlopayRef = useRef4(null);
3683
+ const [session, setSession] = useState4(null);
3684
+ const [resolvedSessionId, setResolvedSessionId] = useState4(sessionIdProp ?? "");
2945
3685
  const activeSessionId = sessionIdProp ?? resolvedSessionId;
2946
3686
  const initSessionDependency = createSessionParams ? "" : activeSessionId;
2947
- const [isLoading, setIsLoading] = useState3(true);
2948
- const [loadError, setLoadError] = useState3(null);
2949
- const [currentMode, setCurrentMode] = useState3("full");
2950
- const [confirmProcessing, setConfirmProcessing] = useState3(false);
2951
- const [modeError, setModeError] = useState3(initialErrorMessage);
2952
- const [modeOverlayStatus, setModeOverlayStatus] = useState3(null);
2953
- const [modeOverlayError, setModeOverlayError] = useState3(null);
2954
- const [createSessionPatch, setCreateSessionPatch] = useState3(void 0);
2955
- const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = useState3("");
2956
- const [cardBootstrapPending, setCardBootstrapPending] = useState3(false);
2957
- const autoCheckoutAttempted = useRef3(false);
2958
- const paypalResumeAttempted = useRef3(false);
2959
- const savedPaymentKeysRef = useRef3(null);
2960
- const onCompleteRef = useRef3(onComplete);
3687
+ const [isLoading, setIsLoading] = useState4(true);
3688
+ const [loadError, setLoadError] = useState4(null);
3689
+ const [currentMode, setCurrentMode] = useState4("full");
3690
+ const [confirmProcessing, setConfirmProcessing] = useState4(false);
3691
+ const [modeError, setModeError] = useState4(initialErrorMessage);
3692
+ const [modeOverlayStatus, setModeOverlayStatus] = useState4(null);
3693
+ const [modeOverlayError, setModeOverlayError] = useState4(null);
3694
+ const [createSessionPatch, setCreateSessionPatch] = useState4(void 0);
3695
+ const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = useState4("");
3696
+ const [cardBootstrapPending, setCardBootstrapPending] = useState4(false);
3697
+ const autoCheckoutAttempted = useRef4(false);
3698
+ const paypalResumeAttempted = useRef4(false);
3699
+ const savedPaymentKeysRef = useRef4(null);
3700
+ const onCompleteRef = useRef4(onComplete);
2961
3701
  onCompleteRef.current = onComplete;
2962
- const onErrorRef = useRef3(onError);
3702
+ const onErrorRef = useRef4(onError);
2963
3703
  onErrorRef.current = onError;
2964
- const onDeclineRef = useRef3(onDecline);
3704
+ const onDeclineRef = useRef4(onDecline);
2965
3705
  onDeclineRef.current = onDecline;
2966
- const onSessionCompletedRef = useRef3(onSessionCompleted);
3706
+ const onSessionCompletedRef = useRef4(onSessionCompleted);
2967
3707
  onSessionCompletedRef.current = onSessionCompleted;
2968
- useEffect4(() => {
3708
+ useEffect5(() => {
2969
3709
  console.info("[FloPay] Checkout initialized", {
2970
3710
  sdk_version: SDK_VERSION,
2971
3711
  checkout_type: checkoutType,
@@ -2973,31 +3713,31 @@ function FloPayCheckout({
2973
3713
  billing_api_url: resolvedBillingUrl
2974
3714
  });
2975
3715
  }, [checkoutLayout, checkoutType, resolvedBillingUrl]);
2976
- const baseCreateSessionHash = useMemo3(
3716
+ const baseCreateSessionHash = useMemo4(
2977
3717
  () => createSessionParams ? hashCreateParams(createSessionParams) : "",
2978
3718
  [createSessionParams]
2979
3719
  );
2980
- const activeCreateSessionPatch = useMemo3(
3720
+ const activeCreateSessionPatch = useMemo4(
2981
3721
  () => createSessionPatchBaseHash === baseCreateSessionHash ? createSessionPatch : void 0,
2982
3722
  [createSessionPatch, createSessionPatchBaseHash, baseCreateSessionHash]
2983
3723
  );
2984
- const effectiveCreateSessionBase = useMemo3(
3724
+ const effectiveCreateSessionBase = useMemo4(
2985
3725
  () => createSessionParams ? mergeInlineSessionPatch(createSessionParams, activeCreateSessionPatch) : void 0,
2986
3726
  [createSessionParams, activeCreateSessionPatch]
2987
3727
  );
2988
3728
  const effectiveCreateSessionMode = checkoutModeProp ?? effectiveCreateSessionBase?.checkoutMode ?? "full";
2989
- const effectiveCreateSession = useMemo3(
3729
+ const effectiveCreateSession = useMemo4(
2990
3730
  () => effectiveCreateSessionBase ? {
2991
3731
  ...effectiveCreateSessionBase,
2992
3732
  checkoutMode: effectiveCreateSessionMode
2993
3733
  } : void 0,
2994
3734
  [effectiveCreateSessionBase, effectiveCreateSessionMode]
2995
3735
  );
2996
- useEffect4(() => {
3736
+ useEffect5(() => {
2997
3737
  setCreateSessionPatch(void 0);
2998
3738
  setCreateSessionPatchBaseHash(baseCreateSessionHash);
2999
3739
  }, [baseCreateSessionHash]);
3000
- useEffect4(() => {
3740
+ useEffect5(() => {
3001
3741
  setModeError(initialErrorMessage);
3002
3742
  }, [initialErrorMessage]);
3003
3743
  const emitDecline = useCallback2(
@@ -3035,12 +3775,12 @@ function FloPayCheckout({
3035
3775
  clearPayPalResumeState();
3036
3776
  }
3037
3777
  } else if (options?.initialAutoProcessingPending) {
3038
- const api = new PaymentAPI3(resolvedBillingUrl);
3778
+ const api = new PaymentAPI4(resolvedBillingUrl);
3039
3779
  const completed = await api.waitForCheckoutSessionCompletion(options.initialAutoProcessingPending.sessionId, {
3040
3780
  initialDelayMs: options.initialAutoProcessingPending.retryAfterMs
3041
3781
  });
3042
3782
  if (completed.data.session?.status !== "complete") {
3043
- throw new FloPayError4("Automatic payment failed. Please try again.", "api_error", {
3783
+ throw new FloPayError5("Automatic payment failed. Please try again.", "api_error", {
3044
3784
  code: completed.data.session?.status === "expired" ? "checkout_session_expired" : "checkout_processing_timeout"
3045
3785
  });
3046
3786
  }
@@ -3124,7 +3864,7 @@ function FloPayCheckout({
3124
3864
  resolvedBillingUrl
3125
3865
  ]
3126
3866
  );
3127
- useEffect4(() => {
3867
+ useEffect5(() => {
3128
3868
  if (typeof window === "undefined" || paypalResumeAttempted.current) {
3129
3869
  return;
3130
3870
  }
@@ -3146,7 +3886,7 @@ function FloPayCheckout({
3146
3886
  try {
3147
3887
  if (params.get("redirect_status") === "failed") {
3148
3888
  throw Object.assign(
3149
- new FloPayError4("PayPal payment was declined. Please try again.", "api_error"),
3889
+ new FloPayError5("PayPal payment was declined. Please try again.", "api_error"),
3150
3890
  { checkoutMethod: "paypal" }
3151
3891
  );
3152
3892
  }
@@ -3162,14 +3902,14 @@ function FloPayCheckout({
3162
3902
  const paypalStripe = (resumePaypalFlopay ?? resumeFlopay).getRawProvider();
3163
3903
  if (!paypalStripe) {
3164
3904
  throw Object.assign(
3165
- new FloPayError4("PayPal is not available.", "api_error"),
3905
+ new FloPayError5("PayPal is not available.", "api_error"),
3166
3906
  { checkoutMethod: "paypal" }
3167
3907
  );
3168
3908
  }
3169
3909
  const { paymentIntent, error } = await paypalStripe.retrievePaymentIntent(clientSecret);
3170
3910
  if (error) {
3171
3911
  throw Object.assign(
3172
- new FloPayError4(
3912
+ new FloPayError5(
3173
3913
  error.message ?? "Failed to retrieve PayPal payment status.",
3174
3914
  "api_error",
3175
3915
  { code: error.code }
@@ -3180,14 +3920,14 @@ function FloPayCheckout({
3180
3920
  const resultStatus = mapPayPalIntentStatusToPaymentResult(paymentIntent?.status);
3181
3921
  if (!paymentIntent || resultStatus === "failed") {
3182
3922
  throw Object.assign(
3183
- new FloPayError4("PayPal payment was not completed. Please try again.", "api_error"),
3923
+ new FloPayError5("PayPal payment was not completed. Please try again.", "api_error"),
3184
3924
  { checkoutMethod: "paypal" }
3185
3925
  );
3186
3926
  }
3187
3927
  const paymentMethodId = typeof paymentIntent.payment_method === "string" ? paymentIntent.payment_method : paymentIntent.payment_method?.id;
3188
3928
  let finalResultStatus = resultStatus;
3189
3929
  if (resumeState.sessionId) {
3190
- const resumeApi = new PaymentAPI3(resolvedBillingUrl);
3930
+ const resumeApi = new PaymentAPI4(resolvedBillingUrl);
3191
3931
  const resumeSessionResult = await resumeApi.getUnifiedCheckoutSession(resumeState.sessionId);
3192
3932
  const resumeSession = resumeSessionResult.data.session;
3193
3933
  if (resumeSession && resumeSession.status !== "complete") {
@@ -3204,7 +3944,7 @@ function FloPayCheckout({
3204
3944
  });
3205
3945
  if (processResult.type !== "success") {
3206
3946
  throw Object.assign(
3207
- new FloPayError4("Failed to finalize PayPal payment.", "api_error"),
3947
+ new FloPayError5("Failed to finalize PayPal payment.", "api_error"),
3208
3948
  { checkoutMethod: "paypal" }
3209
3949
  );
3210
3950
  }
@@ -3241,7 +3981,7 @@ function FloPayCheckout({
3241
3981
  }
3242
3982
  })();
3243
3983
  }, [emitDecline, locale, normalizeSavedPaymentError, resolvedBillingUrl]);
3244
- const initializedHashRef = useRef3(null);
3984
+ const initializedHashRef = useRef4(null);
3245
3985
  function hashCreateParams(params) {
3246
3986
  const key = JSON.stringify({
3247
3987
  c: params?.clientId,
@@ -3266,23 +4006,23 @@ function FloPayCheckout({
3266
4006
  }
3267
4007
  return `flopay_session_${Math.abs(h).toString(36)}`;
3268
4008
  }
3269
- const createSessionHash = useMemo3(
4009
+ const createSessionHash = useMemo4(
3270
4010
  () => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
3271
4011
  [effectiveCreateSession]
3272
4012
  );
3273
- const createSessionParamsRef = useRef3(effectiveCreateSession);
4013
+ const createSessionParamsRef = useRef4(effectiveCreateSession);
3274
4014
  createSessionParamsRef.current = effectiveCreateSession;
3275
- useEffect4(() => {
4015
+ useEffect5(() => {
3276
4016
  setResolvedSessionId(sessionIdProp ?? "");
3277
4017
  }, [sessionIdProp]);
3278
- useEffect4(() => {
4018
+ useEffect5(() => {
3279
4019
  autoCheckoutAttempted.current = false;
3280
4020
  setModeError(initialErrorMessage);
3281
4021
  setModeOverlayError(null);
3282
4022
  setModeOverlayStatus(null);
3283
4023
  }, [createSessionHash, initialErrorMessage, sessionIdProp]);
3284
4024
  async function resolveInlineSession(params, cacheKey) {
3285
- const api = new PaymentAPI3(resolvedBillingUrl);
4025
+ const api = new PaymentAPI4(resolvedBillingUrl);
3286
4026
  let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
3287
4027
  let realResult = null;
3288
4028
  if (sid) {
@@ -3322,7 +4062,7 @@ function FloPayCheckout({
3322
4062
  async (patch) => {
3323
4063
  const baseParams = createSessionParamsRef.current;
3324
4064
  if (!baseParams) {
3325
- throw new FloPayError4("createSession is required to bootstrap checkout.", "validation_error");
4065
+ throw new FloPayError5("createSession is required to bootstrap checkout.", "validation_error");
3326
4066
  }
3327
4067
  const mergedParams = mergeInlineSessionPatch(baseParams, patch);
3328
4068
  const cacheKey = hashCreateParams(mergedParams);
@@ -3402,7 +4142,7 @@ function FloPayCheckout({
3402
4142
  resolvedSessionId,
3403
4143
  session
3404
4144
  ]);
3405
- useEffect4(() => {
4145
+ useEffect5(() => {
3406
4146
  let cancelled = false;
3407
4147
  setLoadError(null);
3408
4148
  if (createSessionHash) {
@@ -3446,7 +4186,7 @@ function FloPayCheckout({
3446
4186
  }
3447
4187
  } catch (err) {
3448
4188
  if (cancelled) return;
3449
- const errorCode = err instanceof FloPayError4 ? err.code : typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
4189
+ const errorCode = err instanceof FloPayError5 ? err.code : typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
3450
4190
  if (shouldAutoProcessInlineSession && errorCode === "session_auto_completed") {
3451
4191
  autoCheckoutAttempted.current = true;
3452
4192
  setModeOverlayStatus("success");
@@ -3462,7 +4202,7 @@ function FloPayCheckout({
3462
4202
  setModeOverlayStatus(null);
3463
4203
  setModeOverlayError(null);
3464
4204
  }
3465
- const floPayErr = err instanceof FloPayError4 ? err : new FloPayError4(err instanceof Error ? err.message : "Failed to create session", "api_error");
4205
+ const floPayErr = err instanceof FloPayError5 ? err : new FloPayError5(err instanceof Error ? err.message : "Failed to create session", "api_error");
3466
4206
  setLoadError(floPayErr);
3467
4207
  }
3468
4208
  })();
@@ -3473,14 +4213,14 @@ function FloPayCheckout({
3473
4213
  setIsLoading(true);
3474
4214
  async function init() {
3475
4215
  try {
3476
- const api = new PaymentAPI3(resolvedBillingUrl);
4216
+ const api = new PaymentAPI4(resolvedBillingUrl);
3477
4217
  const result = await api.getUnifiedCheckoutSession(activeSessionId);
3478
4218
  if (cancelled) return;
3479
4219
  setUnified(result);
3480
4220
  const sess = result.data.session ?? null;
3481
4221
  setSession(sess);
3482
4222
  if (!sess) {
3483
- throw new FloPayError4("No session data returned", "api_error");
4223
+ throw new FloPayError5("No session data returned", "api_error");
3484
4224
  }
3485
4225
  if (sess.status === "complete") {
3486
4226
  setIsLoading(false);
@@ -3488,7 +4228,7 @@ function FloPayCheckout({
3488
4228
  return;
3489
4229
  }
3490
4230
  if (sess.status === "expired") {
3491
- throw new FloPayError4("Checkout session has expired.", "api_error", {
4231
+ throw new FloPayError5("Checkout session has expired.", "api_error", {
3492
4232
  code: "checkout_session_expired"
3493
4233
  });
3494
4234
  }
@@ -3522,7 +4262,7 @@ function FloPayCheckout({
3522
4262
  if (!cancelled) setIsLoading(false);
3523
4263
  } catch (err) {
3524
4264
  if (cancelled) return;
3525
- const floPayErr = err instanceof FloPayError4 ? err : new FloPayError4(err instanceof Error ? err.message : "Failed to initialize checkout", "api_error");
4265
+ const floPayErr = err instanceof FloPayError5 ? err : new FloPayError5(err instanceof Error ? err.message : "Failed to initialize checkout", "api_error");
3526
4266
  setLoadError(floPayErr);
3527
4267
  setIsLoading(false);
3528
4268
  }
@@ -3575,14 +4315,14 @@ function FloPayCheckout({
3575
4315
  setConfirmProcessing(false);
3576
4316
  }
3577
4317
  }, [activeSessionId, confirmProcessing, runSavedPaymentFlow, session]);
3578
- const providerOptions = useMemo3(() => {
4318
+ const providerOptions = useMemo4(() => {
3579
4319
  if (!unified || !session) return void 0;
3580
4320
  const opts = {
3581
4321
  appearance,
3582
4322
  paymentMethodCreation: "manual",
3583
4323
  billingApiUrl: resolvedBillingUrl
3584
4324
  };
3585
- if (unified.provider === "stripe" && unified.data.stripe?.clientSecret) {
4325
+ if (unified.data.stripe?.clientSecret) {
3586
4326
  opts.clientSecret = unified.data.stripe.clientSecret;
3587
4327
  } else {
3588
4328
  const displayTotal = buildCheckoutDisplayData(session).total;
@@ -3594,7 +4334,7 @@ function FloPayCheckout({
3594
4334
  const shouldHandleInlineSessionPatch = Boolean(
3595
4335
  createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && effectiveCreateSessionMode === "full"
3596
4336
  );
3597
- const checkoutValue = useMemo3(
4337
+ const checkoutValue = useMemo4(
3598
4338
  () => ({
3599
4339
  session,
3600
4340
  loading: isLoading,
@@ -3616,7 +4356,7 @@ function FloPayCheckout({
3616
4356
  ]
3617
4357
  );
3618
4358
  const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && (!flopay || !providerOptions);
3619
- const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ jsx6(
4359
+ const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ jsx7(
3620
4360
  ProcessingOverlay,
3621
4361
  {
3622
4362
  status: modeOverlayStatus,
@@ -3625,31 +4365,31 @@ function FloPayCheckout({
3625
4365
  ) : null;
3626
4366
  if (isLoading) {
3627
4367
  if (loadingNode) {
3628
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
4368
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
3629
4369
  loadingNode,
3630
4370
  modeOverlay
3631
4371
  ] });
3632
4372
  }
3633
4373
  if (layout === "buttons") {
3634
- const skeletonBar = (h) => /* @__PURE__ */ jsx6("div", { style: {
4374
+ const skeletonBar = (h) => /* @__PURE__ */ jsx7("div", { style: {
3635
4375
  height: h,
3636
4376
  borderRadius: 8,
3637
4377
  background: "#e5e7eb",
3638
4378
  animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
3639
4379
  } });
3640
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
3641
- /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
4380
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
4381
+ /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
3642
4382
  showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
3643
4383
  (showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
3644
4384
  skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
3645
- /* @__PURE__ */ jsx6("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
4385
+ /* @__PURE__ */ jsx7("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
3646
4386
  ] }),
3647
4387
  modeOverlay
3648
4388
  ] });
3649
4389
  }
3650
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
3651
- /* @__PURE__ */ jsxs4("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
3652
- /* @__PURE__ */ jsx6("div", { style: {
4390
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
4391
+ /* @__PURE__ */ jsxs5("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
4392
+ /* @__PURE__ */ jsx7("div", { style: {
3653
4393
  width: 24,
3654
4394
  height: 24,
3655
4395
  border: "2px solid #e5e7eb",
@@ -3657,16 +4397,16 @@ function FloPayCheckout({
3657
4397
  borderRadius: "50%",
3658
4398
  animation: "spin 0.6s linear infinite"
3659
4399
  } }),
3660
- /* @__PURE__ */ jsx6("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
4400
+ /* @__PURE__ */ jsx7("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
3661
4401
  ] }),
3662
4402
  modeOverlay
3663
4403
  ] });
3664
4404
  }
3665
4405
  if (loadError) {
3666
4406
  if (errorNode) {
3667
- return /* @__PURE__ */ jsx6(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
4407
+ return /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
3668
4408
  }
3669
- return /* @__PURE__ */ jsx6(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx6(
4409
+ return /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx7(
3670
4410
  "div",
3671
4411
  {
3672
4412
  style: {
@@ -3680,8 +4420,8 @@ function FloPayCheckout({
3680
4420
  ) });
3681
4421
  }
3682
4422
  if (shouldShowInterimButtons) {
3683
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
3684
- /* @__PURE__ */ jsx6(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx6(
4423
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
4424
+ /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx7(
3685
4425
  InterimButtonsView,
3686
4426
  {
3687
4427
  onButtonClick,
@@ -3699,12 +4439,12 @@ function FloPayCheckout({
3699
4439
  ] });
3700
4440
  }
3701
4441
  if (!flopay || !providerOptions) {
3702
- return /* @__PURE__ */ jsx6(Fragment3, { children: modeOverlay });
4442
+ return /* @__PURE__ */ jsx7(Fragment3, { children: modeOverlay });
3703
4443
  }
3704
4444
  if (currentMode === "confirm") {
3705
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
3706
- /* @__PURE__ */ jsx6(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx6(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ jsxs4("div", { className, children: [
3707
- modeError && /* @__PURE__ */ jsx6(
4445
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
4446
+ /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx7(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ jsxs5("div", { className, children: [
4447
+ modeError && /* @__PURE__ */ jsx7(
3708
4448
  "div",
3709
4449
  {
3710
4450
  style: {
@@ -3719,7 +4459,7 @@ function FloPayCheckout({
3719
4459
  renderConfirmButton ? renderConfirmButton({
3720
4460
  onConfirm: handleConfirmCheckout,
3721
4461
  isProcessing: confirmProcessing
3722
- }) : /* @__PURE__ */ jsx6(
4462
+ }) : /* @__PURE__ */ jsx7(
3723
4463
  "button",
3724
4464
  {
3725
4465
  type: "button",
@@ -3744,9 +4484,9 @@ function FloPayCheckout({
3744
4484
  modeOverlay
3745
4485
  ] });
3746
4486
  }
3747
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
3748
- /* @__PURE__ */ jsx6(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx6(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
3749
- modeError && /* @__PURE__ */ jsx6(
4487
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
4488
+ /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx7(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
4489
+ modeError && /* @__PURE__ */ jsx7(
3750
4490
  "div",
3751
4491
  {
3752
4492
  style: {
@@ -3761,7 +4501,7 @@ function FloPayCheckout({
3761
4501
  children: modeError
3762
4502
  }
3763
4503
  ),
3764
- /* @__PURE__ */ jsx6(
4504
+ /* @__PURE__ */ jsx7(
3765
4505
  SessionInjector,
3766
4506
  {
3767
4507
  sessionId: activeSessionId,
@@ -3770,7 +4510,7 @@ function FloPayCheckout({
3770
4510
  children
3771
4511
  }
3772
4512
  )
3773
- ] }) : /* @__PURE__ */ jsx6(
4513
+ ] }) : /* @__PURE__ */ jsx7(
3774
4514
  SplitCardForm,
3775
4515
  {
3776
4516
  sessionId: activeSessionId,
@@ -3809,7 +4549,11 @@ function FloPayCheckout({
3809
4549
  checkoutType: createSessionParams ? "embedded_checkout" : "standard_checkout",
3810
4550
  checkoutLayout: children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout",
3811
4551
  submitLabel,
3812
- className
4552
+ className,
4553
+ directPaypal: resolveDirectPaypalConfig(unified),
4554
+ isSubscription: session?.mode === "subscription",
4555
+ session,
4556
+ debug
3813
4557
  }
3814
4558
  ) }) }),
3815
4559
  modeOverlay
@@ -3821,8 +4565,8 @@ function SessionInjector({
3821
4565
  session,
3822
4566
  children
3823
4567
  }) {
3824
- return /* @__PURE__ */ jsx6(Fragment3, { children: React6.Children.map(children, (child) => {
3825
- if (!React6.isValidElement(child)) return child;
4568
+ return /* @__PURE__ */ jsx7(Fragment3, { children: React7.Children.map(children, (child) => {
4569
+ if (!React7.isValidElement(child)) return child;
3826
4570
  const existing = child.props;
3827
4571
  const injected = {};
3828
4572
  if (!existing.sessionId) injected.sessionId = sessionId;
@@ -3836,7 +4580,7 @@ function SessionInjector({
3836
4580
  injected.lastName = session.customer.lastName;
3837
4581
  }
3838
4582
  if (Object.keys(injected).length === 0) return child;
3839
- return React6.cloneElement(child, injected);
4583
+ return React7.cloneElement(child, injected);
3840
4584
  }) });
3841
4585
  }
3842
4586
  function InterimButtonsView({
@@ -3854,14 +4598,14 @@ function InterimButtonsView({
3854
4598
  cardBackButtonContent,
3855
4599
  cardTitleContent
3856
4600
  }) {
3857
- const [showCardForm, setShowCardForm] = useState3(false);
4601
+ const [showCardForm, setShowCardForm] = useState4(false);
3858
4602
  const isCardOpenControlled = typeof cardOpen === "boolean";
3859
- useEffect4(() => {
4603
+ useEffect5(() => {
3860
4604
  if (isCardOpenControlled) {
3861
4605
  setShowCardForm(cardOpen);
3862
4606
  }
3863
4607
  }, [cardOpen, isCardOpenControlled]);
3864
- const bStyles = useMemo3(() => {
4608
+ const bStyles = useMemo4(() => {
3865
4609
  const base = resolveButtonsLayoutTheme2(buttonsTheme);
3866
4610
  if (!stylesOverride) return base;
3867
4611
  return {
@@ -3875,7 +4619,7 @@ function InterimButtonsView({
3875
4619
  title: { ...base.title, ...stylesOverride.title }
3876
4620
  };
3877
4621
  }, [buttonsTheme, stylesOverride]);
3878
- const skeleton = (h) => /* @__PURE__ */ jsx6("div", { style: {
4622
+ const skeleton = (h) => /* @__PURE__ */ jsx7("div", { style: {
3879
4623
  height: h,
3880
4624
  borderRadius: 8,
3881
4625
  background: "#e5e7eb",
@@ -3887,15 +4631,15 @@ function InterimButtonsView({
3887
4631
  const inputBg = bStyles.cardInputBackground ?? "white";
3888
4632
  const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
3889
4633
  const hideTitle = isEmptySlotContent(cardTitleContent);
3890
- return /* @__PURE__ */ jsxs4("div", { style: {
4634
+ return /* @__PURE__ */ jsxs5("div", { style: {
3891
4635
  backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
3892
4636
  borderRadius: "8px",
3893
4637
  animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
3894
4638
  overflow: "hidden",
3895
4639
  ...bStyles.cardFormContainer
3896
4640
  }, children: [
3897
- /* @__PURE__ */ jsxs4("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
3898
- /* @__PURE__ */ jsxs4(
4641
+ /* @__PURE__ */ jsxs5("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
4642
+ /* @__PURE__ */ jsxs5(
3899
4643
  "button",
3900
4644
  {
3901
4645
  type: "button",
@@ -3922,7 +4666,7 @@ function InterimButtonsView({
3922
4666
  ...bStyles.backButton
3923
4667
  },
3924
4668
  children: [
3925
- /* @__PURE__ */ jsx6("span", { style: {
4669
+ /* @__PURE__ */ jsx7("span", { style: {
3926
4670
  display: "inline-flex",
3927
4671
  alignItems: "center",
3928
4672
  justifyContent: "center",
@@ -3931,12 +4675,12 @@ function InterimButtonsView({
3931
4675
  borderRadius: "50%",
3932
4676
  backgroundColor: "#f3f4f6",
3933
4677
  ...bStyles.backButtonIcon
3934
- }, 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" }) }) }),
3935
- /* @__PURE__ */ jsx6(BackButtonContentSlot, { content: cardBackButtonContent })
4678
+ }, children: /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: "M15 18l-6-6 6-6" }) }) }),
4679
+ /* @__PURE__ */ jsx7(BackButtonContentSlot, { content: cardBackButtonContent })
3936
4680
  ]
3937
4681
  }
3938
4682
  ),
3939
- hideTitle ? /* @__PURE__ */ jsx6("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx6("div", { style: {
4683
+ hideTitle ? /* @__PURE__ */ jsx7("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx7("div", { style: {
3940
4684
  flex: 1,
3941
4685
  textAlign: "center",
3942
4686
  fontWeight: 600,
@@ -3944,15 +4688,15 @@ function InterimButtonsView({
3944
4688
  color: "#262833",
3945
4689
  paddingRight: 80,
3946
4690
  ...bStyles.title
3947
- }, children: /* @__PURE__ */ jsx6(TitleContentSlot, { content: cardTitleContent }) })
4691
+ }, children: /* @__PURE__ */ jsx7(TitleContentSlot, { content: cardTitleContent }) })
3948
4692
  ] }),
3949
- /* @__PURE__ */ jsx6("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx6("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
3950
- /* @__PURE__ */ jsxs4("div", { style: { display: "flex" }, children: [
3951
- /* @__PURE__ */ jsx6("div", { style: { flex: 1, backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTop: "none", borderRight: "none", borderBottomLeftRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx6("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
3952
- /* @__PURE__ */ jsx6("div", { style: { flex: 1, backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTop: "none", borderBottomRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx6("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
4693
+ /* @__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" } }) }),
4694
+ /* @__PURE__ */ jsxs5("div", { style: { display: "flex" }, children: [
4695
+ /* @__PURE__ */ jsx7("div", { style: { flex: 1, backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTop: "none", borderRight: "none", borderBottomLeftRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx7("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
4696
+ /* @__PURE__ */ jsx7("div", { style: { flex: 1, backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTop: "none", borderBottomRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx7("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
3953
4697
  ] }),
3954
- /* @__PURE__ */ jsx6("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx6("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
3955
- /* @__PURE__ */ jsx6("div", { style: {
4698
+ /* @__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" } }) }),
4699
+ /* @__PURE__ */ jsx7("div", { style: {
3956
4700
  height: 50,
3957
4701
  borderRadius: 8,
3958
4702
  marginTop: 16,
@@ -3961,7 +4705,7 @@ function InterimButtonsView({
3961
4705
  ...bStyles.submitButton,
3962
4706
  opacity: 0.5
3963
4707
  } }),
3964
- /* @__PURE__ */ jsx6("style", { children: `
4708
+ /* @__PURE__ */ jsx7("style", { children: `
3965
4709
  @keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
3966
4710
  @keyframes flopay-interim-expand {
3967
4711
  0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
@@ -3971,10 +4715,10 @@ function InterimButtonsView({
3971
4715
  ` })
3972
4716
  ] });
3973
4717
  }
3974
- return /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
4718
+ return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
3975
4719
  showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
3976
4720
  (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
3977
- /* @__PURE__ */ jsx6(
4721
+ /* @__PURE__ */ jsx7(
3978
4722
  "button",
3979
4723
  {
3980
4724
  type: "button",
@@ -4014,10 +4758,10 @@ function InterimButtonsView({
4014
4758
  onMouseUp: (e) => {
4015
4759
  e.currentTarget.style.transform = "scale(1)";
4016
4760
  },
4017
- children: /* @__PURE__ */ jsx6(CardButtonContentSlot, { content: cardButtonContent })
4761
+ children: /* @__PURE__ */ jsx7(CardButtonContentSlot, { content: cardButtonContent })
4018
4762
  }
4019
4763
  ),
4020
- errorMessage && /* @__PURE__ */ jsxs4("div", { style: {
4764
+ errorMessage && /* @__PURE__ */ jsxs5("div", { style: {
4021
4765
  margin: "0.25rem 0",
4022
4766
  padding: "0.625rem 0.875rem",
4023
4767
  background: "#FEF2F2",
@@ -4031,22 +4775,22 @@ function InterimButtonsView({
4031
4775
  gap: "0.5rem",
4032
4776
  ...bStyles.errorBanner
4033
4777
  }, children: [
4034
- /* @__PURE__ */ jsx6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx6("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
4778
+ /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx7("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
4035
4779
  errorMessage
4036
4780
  ] }),
4037
- /* @__PURE__ */ jsx6("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
4781
+ /* @__PURE__ */ jsx7("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
4038
4782
  ] });
4039
4783
  }
4040
4784
 
4041
4785
  // src/checkout-form.tsx
4042
- import { PaymentAPI as PaymentAPI4 } from "@flopay/js";
4043
- import { FloPayError as FloPayError5 } from "@flopay/shared";
4044
- import { forwardRef as forwardRef2, useCallback as useCallback3, useEffect as useEffect5, useImperativeHandle as useImperativeHandle2, useState as useState4 } from "react";
4045
- import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
4786
+ import { PaymentAPI as PaymentAPI5 } from "@flopay/js";
4787
+ import { FloPayError as FloPayError6 } from "@flopay/shared";
4788
+ import { forwardRef as forwardRef2, useCallback as useCallback3, useEffect as useEffect6, useImperativeHandle as useImperativeHandle2, useState as useState5 } from "react";
4789
+ import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
4046
4790
  var WALLET_RESUME_KEY2 = "flopay_wallet_resume";
4047
4791
  var CheckoutForm = forwardRef2(
4048
4792
  function CheckoutForm2(props, ref) {
4049
- return /* @__PURE__ */ jsx7(CheckoutFormInner, { ...props, innerRef: ref });
4793
+ return /* @__PURE__ */ jsx8(CheckoutFormInner, { ...props, innerRef: ref });
4050
4794
  }
4051
4795
  );
4052
4796
  function CheckoutFormInner({
@@ -4075,9 +4819,9 @@ function CheckoutFormInner({
4075
4819
  const paypalFlopay = usePayPalFloPay();
4076
4820
  const elements = useElements();
4077
4821
  const contextBillingUrl = useBillingApiUrl();
4078
- const [processing, setProcessing] = useState4(false);
4079
- const [error, setError] = useState4(null);
4080
- const [is3DSActive, setIs3DSActive] = useState4(false);
4822
+ const [processing, setProcessing] = useState5(false);
4823
+ const [error, setError] = useState5(null);
4824
+ const [is3DSActive, setIs3DSActive] = useState5(false);
4081
4825
  const displayError = externalError ?? error;
4082
4826
  const isSubmitting = externalProcessing ?? processing;
4083
4827
  const isSelfContained = !onTokenizedBody;
@@ -4102,7 +4846,7 @@ function CheckoutFormInner({
4102
4846
  const resolvedCompletionPaymentMethodId = completionPaymentMethodId ?? resolveTokenizedPaymentMethodId(tokenizedBody);
4103
4847
  const requestTokenizedBody = tokenizedBody.originalPaymentMethodId ? { ...tokenizedBody, originalPaymentMethodId: void 0 } : tokenizedBody;
4104
4848
  try {
4105
- const api = new PaymentAPI4(baseUrl);
4849
+ const api = new PaymentAPI5(baseUrl);
4106
4850
  const response = await api.processPayment(userId ?? "", {
4107
4851
  sessionId,
4108
4852
  tokenizedData: requestTokenizedBody,
@@ -4243,7 +4987,7 @@ function CheckoutFormInner({
4243
4987
  }
4244
4988
  }
4245
4989
  }), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
4246
- useEffect5(() => {
4990
+ useEffect6(() => {
4247
4991
  if (typeof window === "undefined") return;
4248
4992
  const stored = localStorage.getItem(WALLET_RESUME_KEY2);
4249
4993
  if (!stored) return;
@@ -4285,7 +5029,7 @@ function CheckoutFormInner({
4285
5029
  return;
4286
5030
  }
4287
5031
  if (!sessionId || !email) {
4288
- throw new FloPayError5("Missing sessionId or email", "validation_error");
5032
+ throw new FloPayError6("Missing sessionId or email", "validation_error");
4289
5033
  }
4290
5034
  const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
4291
5035
  method: "POST",
@@ -4309,7 +5053,7 @@ function CheckoutFormInner({
4309
5053
  }
4310
5054
  const intentJson = await intentResponse.json();
4311
5055
  const intentClientSecret = intentJson.data?.id;
4312
- if (!intentClientSecret) throw new FloPayError5("No client_secret in payment intent response", "api_error");
5056
+ if (!intentClientSecret) throw new FloPayError6("No client_secret in payment intent response", "api_error");
4313
5057
  const confirmResult = await flopay.confirmCardPayment({
4314
5058
  clientSecret: intentClientSecret,
4315
5059
  paymentMethodId: pmResult.paymentMethodId
@@ -4328,7 +5072,7 @@ function CheckoutFormInner({
4328
5072
  const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
4329
5073
  const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
4330
5074
  if (!paymentIntentId) {
4331
- const error2 = new FloPayError5("No payment intent returned after confirmation.", "api_error");
5075
+ const error2 = new FloPayError6("No payment intent returned after confirmation.", "api_error");
4332
5076
  updateError(error2.message);
4333
5077
  onError?.(error2);
4334
5078
  return;
@@ -4351,8 +5095,8 @@ function CheckoutFormInner({
4351
5095
  [flopay, elements, isSubmitting, sessionId, email, baseUrl, isSelfContained, dispatchTokenizedBody, onError, updateError, emitDecline]
4352
5096
  );
4353
5097
  const isReady = flopay !== null && elements !== null;
4354
- return /* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4355
- (is3DSActive || isSubmitting) && /* @__PURE__ */ jsx7("div", { "data-testid": "flopay-overlay", style: {
5098
+ return /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
5099
+ (is3DSActive || isSubmitting) && /* @__PURE__ */ jsx8("div", { "data-testid": "flopay-overlay", style: {
4356
5100
  position: "absolute",
4357
5101
  inset: 0,
4358
5102
  background: "rgba(255,255,255,0.7)",
@@ -4361,12 +5105,12 @@ function CheckoutFormInner({
4361
5105
  justifyContent: "center",
4362
5106
  zIndex: 10
4363
5107
  }, children: is3DSActive ? "Verifying payment..." : "Processing..." }),
4364
- !isReady && /* @__PURE__ */ jsx7("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
4365
- isReady && /* @__PURE__ */ jsxs5(Fragment4, { children: [
4366
- /* @__PURE__ */ jsx7(PaymentElement, { options: { layout } }),
4367
- showAddress && /* @__PURE__ */ jsx7(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
4368
- displayError && /* @__PURE__ */ jsx7("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
4369
- children ?? /* @__PURE__ */ jsx7(
5108
+ !isReady && /* @__PURE__ */ jsx8("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
5109
+ isReady && /* @__PURE__ */ jsxs6(Fragment4, { children: [
5110
+ /* @__PURE__ */ jsx8(PaymentElement, { options: { layout } }),
5111
+ showAddress && /* @__PURE__ */ jsx8(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
5112
+ displayError && /* @__PURE__ */ jsx8("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
5113
+ children ?? /* @__PURE__ */ jsx8(
4370
5114
  "button",
4371
5115
  {
4372
5116
  type: "submit",
@@ -4380,10 +5124,10 @@ function CheckoutFormInner({
4380
5124
  }
4381
5125
 
4382
5126
  // src/paypal-button.tsx
4383
- import { PaymentAPI as PaymentAPI5 } from "@flopay/js";
4384
- import { FloPayError as FloPayError6 } from "@flopay/shared";
4385
- import { useCallback as useCallback4, useEffect as useEffect6, useRef as useRef4, useState as useState5 } from "react";
4386
- import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
5127
+ import { PaymentAPI as PaymentAPI6 } from "@flopay/js";
5128
+ import { FloPayError as FloPayError7 } from "@flopay/shared";
5129
+ import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef5, useState as useState6 } from "react";
5130
+ import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
4387
5131
  function PayPalButton({
4388
5132
  sessionId,
4389
5133
  billingApiUrl,
@@ -4400,14 +5144,14 @@ function PayPalButton({
4400
5144
  const flopay = useFloPay();
4401
5145
  const elements = useElements();
4402
5146
  const contextBillingUrl = useBillingApiUrl();
4403
- const [ready, setReady] = useState5(false);
4404
- const [submitting, setSubmitting] = useState5(false);
4405
- const paypalResumeAttempted = useRef4(false);
5147
+ const [ready, setReady] = useState6(false);
5148
+ const [submitting, setSubmitting] = useState6(false);
5149
+ const paypalResumeAttempted = useRef5(false);
4406
5150
  const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
4407
5151
  const processPaymentInternal = useCallback4(
4408
5152
  async (tokenizedBody) => {
4409
5153
  try {
4410
- const api = new PaymentAPI5(baseUrl);
5154
+ const api = new PaymentAPI6(baseUrl);
4411
5155
  const response = await api.processPayment(userId ?? "", {
4412
5156
  sessionId,
4413
5157
  tokenizedData: tokenizedBody,
@@ -4441,7 +5185,7 @@ function PayPalButton({
4441
5185
  },
4442
5186
  [onTokenizedBody, processPaymentInternal]
4443
5187
  );
4444
- useEffect6(() => {
5188
+ useEffect7(() => {
4445
5189
  if (!flopay || paypalResumeAttempted.current) return;
4446
5190
  const params = new URLSearchParams(window.location.search);
4447
5191
  const paymentIntentId = params.get("payment_intent");
@@ -4495,7 +5239,7 @@ function PayPalButton({
4495
5239
  setSubmitting(true);
4496
5240
  onErrorChange?.(null);
4497
5241
  if (!sessionId || !email) {
4498
- throw new FloPayError6("Missing sessionId or email for PayPal payment", "validation_error");
5242
+ throw new FloPayError7("Missing sessionId or email for PayPal payment", "validation_error");
4499
5243
  }
4500
5244
  const result = await flopay.confirmPayPalPayment({
4501
5245
  billingApiUrl: baseUrl,
@@ -4522,11 +5266,11 @@ function PayPalButton({
4522
5266
  }
4523
5267
  }, [flopay, elements, sessionId, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
4524
5268
  if (!flopay || !elements) {
4525
- return /* @__PURE__ */ jsx8("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
5269
+ return /* @__PURE__ */ jsx9("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
4526
5270
  }
4527
- return /* @__PURE__ */ jsxs6(Fragment5, { children: [
4528
- !ready && /* @__PURE__ */ jsx8("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
4529
- /* @__PURE__ */ jsx8("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ jsx8(
5271
+ return /* @__PURE__ */ jsxs7(Fragment5, { children: [
5272
+ !ready && /* @__PURE__ */ jsx9("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
5273
+ /* @__PURE__ */ jsx9("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ jsx9(
4530
5274
  "button",
4531
5275
  {
4532
5276
  type: "button",
@@ -4548,7 +5292,7 @@ function PayPalButton({
4548
5292
  children: submitting ? "Processing..." : "PayPal"
4549
5293
  }
4550
5294
  ) }),
4551
- (submitting || isProcessing) && /* @__PURE__ */ jsx8("div", { style: {
5295
+ (submitting || isProcessing) && /* @__PURE__ */ jsx9("div", { style: {
4552
5296
  position: "fixed",
4553
5297
  inset: 0,
4554
5298
  background: "rgba(0,0,0,0.4)",
@@ -4556,7 +5300,7 @@ function PayPalButton({
4556
5300
  alignItems: "center",
4557
5301
  justifyContent: "center",
4558
5302
  zIndex: 1e3
4559
- }, children: /* @__PURE__ */ jsx8("div", { style: {
5303
+ }, children: /* @__PURE__ */ jsx9("div", { style: {
4560
5304
  background: "white",
4561
5305
  borderRadius: 8,
4562
5306
  padding: "1.5rem",
@@ -4568,20 +5312,20 @@ function PayPalButton({
4568
5312
  }
4569
5313
 
4570
5314
  // src/automatic-payment-button.tsx
4571
- import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo4, useRef as useRef5, useState as useState6 } from "react";
4572
- import { PaymentAPI as PaymentAPI6 } from "@flopay/js";
4573
- import { FloPayError as FloPayError7, resolveBillingApiUrl as resolveBillingApiUrl4, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme3 } from "@flopay/shared";
4574
- import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
5315
+ import { useCallback as useCallback5, useEffect as useEffect8, useMemo as useMemo5, useRef as useRef6, useState as useState7 } from "react";
5316
+ import { PaymentAPI as PaymentAPI7 } from "@flopay/js";
5317
+ import { FloPayError as FloPayError8, resolveBillingApiUrl as resolveBillingApiUrl4, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme3 } from "@flopay/shared";
5318
+ import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
4575
5319
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
4576
5320
  var PAYPAL_RESUME_STORAGE_KEY2 = "flopay_automatic_payment_button_resume";
4577
5321
  function sleep2(ms) {
4578
5322
  return new Promise((resolve) => setTimeout(resolve, ms));
4579
5323
  }
4580
5324
  function coerceError(err, fallbackMessage) {
4581
- if (err instanceof FloPayError7) {
5325
+ if (err instanceof FloPayError8) {
4582
5326
  return err;
4583
5327
  }
4584
- return new FloPayError7(
5328
+ return new FloPayError8(
4585
5329
  err instanceof Error ? err.message : fallbackMessage,
4586
5330
  "api_error"
4587
5331
  );
@@ -4688,11 +5432,11 @@ function FloPayAutomaticPaymentButton({
4688
5432
  style,
4689
5433
  ...buttonProps
4690
5434
  }) {
4691
- const resolvedBillingUrl = useMemo4(
5435
+ const resolvedBillingUrl = useMemo5(
4692
5436
  () => resolveBillingApiUrl4(billingApiUrl),
4693
5437
  [billingApiUrl]
4694
5438
  );
4695
- const createSessionDraft = useMemo4(
5439
+ const createSessionDraft = useMemo5(
4696
5440
  () => resolveCreateSessionDraft({
4697
5441
  createSession,
4698
5442
  clientId,
@@ -4718,43 +5462,47 @@ function FloPayAutomaticPaymentButton({
4718
5462
  utmMetadata
4719
5463
  ]
4720
5464
  );
4721
- const [isProcessing, setIsProcessing] = useState6(false);
4722
- const [overlayStatus, setOverlayStatus] = useState6(null);
4723
- const [overlayError, setOverlayError] = useState6(null);
4724
- const [fallbackSession, setFallbackSession] = useState6(null);
4725
- const automaticPaymentToken = useMemo4(
5465
+ const [isProcessing, setIsProcessing] = useState7(false);
5466
+ const [overlayStatus, setOverlayStatus] = useState7(null);
5467
+ const [overlayError, setOverlayError] = useState7(null);
5468
+ const [fallbackSession, setFallbackSession] = useState7(null);
5469
+ const automaticPaymentToken = useMemo5(
4726
5470
  () => paymentMethodId ? {
4727
5471
  id: paymentMethodId,
4728
- type: "card",
5472
+ // Saved PayPal `user_payment_method` records are submitted with
5473
+ // `type: 'paypal'` so the backend routes the upsell through the
5474
+ // direct PayPal gateway's vaulted-token flow. Card and wallet PMs
5475
+ // continue to use `type: 'card'`.
5476
+ type: checkoutMethod === "paypal" ? "paypal" : "card",
4729
5477
  ...checkoutMethod === "paypal" ? { isPaypal: true } : {}
4730
5478
  } : void 0,
4731
5479
  [checkoutMethod, paymentMethodId]
4732
5480
  );
4733
- const isMountedRef = useRef5(true);
4734
- const resumeAttemptedRef = useRef5(false);
4735
- const fallbackSessionRef = useRef5(fallbackSession);
4736
- const onSuccessRef = useRef5(onSuccess);
4737
- const onErrorRef = useRef5(onError);
4738
- const onDeclineRef = useRef5(onDecline);
4739
- useEffect7(() => {
5481
+ const isMountedRef = useRef6(true);
5482
+ const resumeAttemptedRef = useRef6(false);
5483
+ const fallbackSessionRef = useRef6(fallbackSession);
5484
+ const onSuccessRef = useRef6(onSuccess);
5485
+ const onErrorRef = useRef6(onError);
5486
+ const onDeclineRef = useRef6(onDecline);
5487
+ useEffect8(() => {
4740
5488
  fallbackSessionRef.current = fallbackSession;
4741
5489
  }, [fallbackSession]);
4742
- useEffect7(() => {
5490
+ useEffect8(() => {
4743
5491
  onSuccessRef.current = onSuccess;
4744
5492
  }, [onSuccess]);
4745
- useEffect7(() => {
5493
+ useEffect8(() => {
4746
5494
  onErrorRef.current = onError;
4747
5495
  }, [onError]);
4748
- useEffect7(() => {
5496
+ useEffect8(() => {
4749
5497
  onDeclineRef.current = onDecline;
4750
5498
  }, [onDecline]);
4751
- useEffect7(() => {
5499
+ useEffect8(() => {
4752
5500
  isMountedRef.current = true;
4753
5501
  return () => {
4754
5502
  isMountedRef.current = false;
4755
5503
  };
4756
5504
  }, []);
4757
- useEffect7(() => {
5505
+ useEffect8(() => {
4758
5506
  if (!fallbackSession || typeof window === "undefined") {
4759
5507
  return;
4760
5508
  }
@@ -4795,7 +5543,7 @@ function FloPayAutomaticPaymentButton({
4795
5543
  const processResolvedSession = useCallback5(async (apiResult, resolvedSessionId, options) => {
4796
5544
  const session = apiResult.data.session ?? null;
4797
5545
  if (!session) {
4798
- throw new FloPayError7("No session data returned", "api_error");
5546
+ throw new FloPayError8("No session data returned", "api_error");
4799
5547
  }
4800
5548
  if (session.status === "complete") {
4801
5549
  await showSuccess({
@@ -4807,7 +5555,7 @@ function FloPayAutomaticPaymentButton({
4807
5555
  return;
4808
5556
  }
4809
5557
  if (session.status === "expired") {
4810
- throw new FloPayError7("Checkout session has expired.", "api_error", {
5558
+ throw new FloPayError8("Checkout session has expired.", "api_error", {
4811
5559
  code: "checkout_session_expired"
4812
5560
  });
4813
5561
  }
@@ -4817,13 +5565,13 @@ function FloPayAutomaticPaymentButton({
4817
5565
  const shouldTreatCreateSessionFlowAsServerAutoAttempt = options?.fromCreateSession && (apiResult.autoProcessingAttempted === true || !!apiResult.autoProcessingError || !!redirectResult);
4818
5566
  const shouldRetryPayPalClientSide = checkoutMethod === "paypal" && automaticPaymentToken?.isPaypal === true && options?.fromCreateSession === true;
4819
5567
  if (apiResult.autoProcessingPending) {
4820
- const api = new PaymentAPI6(resolvedBillingUrl);
5568
+ const api = new PaymentAPI7(resolvedBillingUrl);
4821
5569
  const completed = await api.waitForCheckoutSessionCompletion(apiResult.autoProcessingPending.sessionId, {
4822
5570
  initialDelayMs: apiResult.autoProcessingPending.retryAfterMs
4823
5571
  });
4824
5572
  const completedSession = completed.data.session;
4825
5573
  if (!completedSession || completedSession.status !== "complete") {
4826
- throw new FloPayError7("Automatic payment failed. Please try again.", "api_error", {
5574
+ throw new FloPayError8("Automatic payment failed. Please try again.", "api_error", {
4827
5575
  code: completedSession?.status === "expired" ? "checkout_session_expired" : "checkout_processing_timeout"
4828
5576
  });
4829
5577
  }
@@ -5022,7 +5770,7 @@ function FloPayAutomaticPaymentButton({
5022
5770
  }
5023
5771
  setFallbackSession(null);
5024
5772
  if (sessionId && createSessionDraft) {
5025
- const error = new FloPayError7(
5773
+ const error = new FloPayError8(
5026
5774
  "Provide either sessionId or create-session props, not both.",
5027
5775
  "validation_error"
5028
5776
  );
@@ -5034,7 +5782,7 @@ function FloPayAutomaticPaymentButton({
5034
5782
  return;
5035
5783
  }
5036
5784
  if (!sessionId && !createSessionDraft) {
5037
- const error = new FloPayError7(
5785
+ const error = new FloPayError8(
5038
5786
  "Provide a sessionId or the props required to create an automatic payment session.",
5039
5787
  "validation_error"
5040
5788
  );
@@ -5049,7 +5797,7 @@ function FloPayAutomaticPaymentButton({
5049
5797
  setOverlayError(null);
5050
5798
  setOverlayStatus("processing");
5051
5799
  try {
5052
- const api = new PaymentAPI6(resolvedBillingUrl);
5800
+ const api = new PaymentAPI7(resolvedBillingUrl);
5053
5801
  if (sessionId) {
5054
5802
  const result = await api.getUnifiedCheckoutSession(sessionId);
5055
5803
  await processResolvedSession(result, sessionId);
@@ -5064,7 +5812,7 @@ function FloPayAutomaticPaymentButton({
5064
5812
  fromCreateSession: true
5065
5813
  });
5066
5814
  } catch (err) {
5067
- if (err instanceof FloPayError7 && err.code === "session_auto_completed") {
5815
+ if (err instanceof FloPayError8 && err.code === "session_auto_completed") {
5068
5816
  await showSuccess({
5069
5817
  result: { status: "succeeded" },
5070
5818
  session: null,
@@ -5113,7 +5861,7 @@ function FloPayAutomaticPaymentButton({
5113
5861
  const handleFallbackDecline = useCallback5((decline) => {
5114
5862
  onDeclineRef.current?.(decline);
5115
5863
  }, []);
5116
- useEffect7(() => {
5864
+ useEffect8(() => {
5117
5865
  if (typeof window === "undefined" || resumeAttemptedRef.current) {
5118
5866
  return;
5119
5867
  }
@@ -5134,7 +5882,7 @@ function FloPayAutomaticPaymentButton({
5134
5882
  try {
5135
5883
  if (params.get("redirect_status") === "failed") {
5136
5884
  throw Object.assign(
5137
- new FloPayError7("PayPal payment was declined. Please try again.", "api_error"),
5885
+ new FloPayError8("PayPal payment was declined. Please try again.", "api_error"),
5138
5886
  { checkoutMethod: "paypal" }
5139
5887
  );
5140
5888
  }
@@ -5150,14 +5898,14 @@ function FloPayAutomaticPaymentButton({
5150
5898
  const paypalStripe = (paypalFlopay ?? flopay).getRawProvider();
5151
5899
  if (!paypalStripe) {
5152
5900
  throw Object.assign(
5153
- new FloPayError7("PayPal is not available.", "api_error"),
5901
+ new FloPayError8("PayPal is not available.", "api_error"),
5154
5902
  { checkoutMethod: "paypal" }
5155
5903
  );
5156
5904
  }
5157
5905
  const { paymentIntent, error } = await paypalStripe.retrievePaymentIntent(clientSecret);
5158
5906
  if (error) {
5159
5907
  throw Object.assign(
5160
- new FloPayError7(
5908
+ new FloPayError8(
5161
5909
  error.message ?? "Failed to retrieve PayPal payment status.",
5162
5910
  "api_error",
5163
5911
  { code: error.code }
@@ -5168,23 +5916,23 @@ function FloPayAutomaticPaymentButton({
5168
5916
  const resultStatus = mapPayPalIntentStatusToPaymentResult(paymentIntent?.status);
5169
5917
  if (!paymentIntent || resultStatus === "failed") {
5170
5918
  throw Object.assign(
5171
- new FloPayError7("PayPal payment was not completed. Please try again.", "api_error"),
5919
+ new FloPayError8("PayPal payment was not completed. Please try again.", "api_error"),
5172
5920
  { checkoutMethod: "paypal" }
5173
5921
  );
5174
5922
  }
5175
5923
  const paymentMethodId2 = typeof paymentIntent.payment_method === "string" ? paymentIntent.payment_method : paymentIntent.payment_method?.id;
5176
5924
  if (!resumeState.sessionId) {
5177
5925
  throw Object.assign(
5178
- new FloPayError7("Missing session id on PayPal resume.", "api_error"),
5926
+ new FloPayError8("Missing session id on PayPal resume.", "api_error"),
5179
5927
  { checkoutMethod: "paypal" }
5180
5928
  );
5181
5929
  }
5182
- const api = new PaymentAPI6(resolvedBillingUrl);
5930
+ const api = new PaymentAPI7(resolvedBillingUrl);
5183
5931
  const sessionResult = await api.getUnifiedCheckoutSession(resumeState.sessionId);
5184
5932
  let resumeSession = sessionResult.data.session;
5185
5933
  if (!resumeSession) {
5186
5934
  throw Object.assign(
5187
- new FloPayError7("Could not load session to capture PayPal payment.", "api_error"),
5935
+ new FloPayError8("Could not load session to capture PayPal payment.", "api_error"),
5188
5936
  { checkoutMethod: "paypal" }
5189
5937
  );
5190
5938
  }
@@ -5203,7 +5951,7 @@ function FloPayAutomaticPaymentButton({
5203
5951
  });
5204
5952
  if (processResult.type !== "success") {
5205
5953
  throw Object.assign(
5206
- new FloPayError7("Failed to finalize PayPal payment.", "api_error"),
5954
+ new FloPayError8("Failed to finalize PayPal payment.", "api_error"),
5207
5955
  { checkoutMethod: "paypal" }
5208
5956
  );
5209
5957
  }
@@ -5244,7 +5992,7 @@ function FloPayAutomaticPaymentButton({
5244
5992
  }
5245
5993
  })();
5246
5994
  }, [locale, resolvedBillingUrl, showError, showSuccess]);
5247
- const bStyles = useMemo4(() => {
5995
+ const bStyles = useMemo5(() => {
5248
5996
  const base = resolveButtonsLayoutTheme3(buttonsTheme);
5249
5997
  if (!stylesOverride) return base;
5250
5998
  return {
@@ -5254,8 +6002,8 @@ function FloPayAutomaticPaymentButton({
5254
6002
  };
5255
6003
  }, [buttonsTheme, stylesOverride]);
5256
6004
  const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
5257
- return /* @__PURE__ */ jsxs7(Fragment6, { children: [
5258
- /* @__PURE__ */ jsx9(
6005
+ return /* @__PURE__ */ jsxs8(Fragment6, { children: [
6006
+ /* @__PURE__ */ jsx10(
5259
6007
  "button",
5260
6008
  {
5261
6009
  ...buttonProps,
@@ -5296,17 +6044,17 @@ function FloPayAutomaticPaymentButton({
5296
6044
  e.currentTarget.style.transform = "scale(1)";
5297
6045
  }
5298
6046
  },
5299
- children: /* @__PURE__ */ jsx9(CardButtonContentSlot, { content: children })
6047
+ children: /* @__PURE__ */ jsx10(CardButtonContentSlot, { content: children })
5300
6048
  }
5301
6049
  ),
5302
- overlayStatus && /* @__PURE__ */ jsx9(
6050
+ overlayStatus && /* @__PURE__ */ jsx10(
5303
6051
  ProcessingOverlay,
5304
6052
  {
5305
6053
  status: overlayStatus,
5306
6054
  errorMessage: overlayError
5307
6055
  }
5308
6056
  ),
5309
- fallbackSession && /* @__PURE__ */ jsx9(
6057
+ fallbackSession && /* @__PURE__ */ jsx10(
5310
6058
  "div",
5311
6059
  {
5312
6060
  "data-testid": "flopay-automatic-payment-fallback",
@@ -5327,7 +6075,7 @@ function FloPayAutomaticPaymentButton({
5327
6075
  padding: "1.5rem",
5328
6076
  zIndex: 1100
5329
6077
  },
5330
- children: /* @__PURE__ */ jsx9(
6078
+ children: /* @__PURE__ */ jsx10(
5331
6079
  "div",
5332
6080
  {
5333
6081
  style: {
@@ -5343,7 +6091,7 @@ function FloPayAutomaticPaymentButton({
5343
6091
  flexDirection: "column",
5344
6092
  gap: "1rem"
5345
6093
  },
5346
- children: /* @__PURE__ */ jsx9(
6094
+ children: /* @__PURE__ */ jsx10(
5347
6095
  FloPayCheckout,
5348
6096
  {
5349
6097
  sessionId: fallbackSession.sessionId,
@@ -5370,6 +6118,7 @@ export {
5370
6118
  CardExpiryElement,
5371
6119
  CardNumberElement,
5372
6120
  CheckoutForm,
6121
+ DirectPayPalButton,
5373
6122
  FloPayAutomaticPaymentButton,
5374
6123
  FloPayCheckout,
5375
6124
  FloPayProvider,