@flopay/react 1.2.8 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -1
- package/dist/index.cjs +1387 -634
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +104 -4
- package/dist/index.d.ts +104 -4
- package/dist/index.mjs +1187 -437
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -100,7 +100,7 @@ function FloPayProvider({
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
// src/flopay-checkout.tsx
|
|
103
|
-
import
|
|
103
|
+
import React8, { useCallback as useCallback2, useEffect as useEffect6, useMemo as useMemo4, useRef as useRef5, useState as useState4 } from "react";
|
|
104
104
|
import { PaymentAPI as PaymentAPI4 } from "@flopay/js";
|
|
105
105
|
import { SDK_VERSION, FloPayError as FloPayError5, resolveBillingApiUrl as resolveBillingApiUrl3, buildCheckoutDisplayData, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme2, resolveTheme as resolveTheme2 } from "@flopay/shared";
|
|
106
106
|
|
|
@@ -248,9 +248,7 @@ import {
|
|
|
248
248
|
resolveAVSConfig,
|
|
249
249
|
isAVSFieldVisible,
|
|
250
250
|
getStateFromPostalCode,
|
|
251
|
-
filterStripeMethodsByCurrency,
|
|
252
251
|
filterStripeMethodsByCountry,
|
|
253
|
-
filterStripeMethodsByAmount,
|
|
254
252
|
getStripeMethodDisplayName,
|
|
255
253
|
hasVendoredStripeMethodLogo,
|
|
256
254
|
needsStripeMethodExplicitConfirm,
|
|
@@ -259,7 +257,80 @@ import {
|
|
|
259
257
|
stripeExpressMethodToOptionKey
|
|
260
258
|
} from "@flopay/shared";
|
|
261
259
|
import { PaymentAPI as PaymentAPI2 } from "@flopay/js";
|
|
262
|
-
|
|
260
|
+
|
|
261
|
+
// src/vault-card-fields.tsx
|
|
262
|
+
import { useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
263
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
264
|
+
function VaultCardFields({
|
|
265
|
+
capture,
|
|
266
|
+
html,
|
|
267
|
+
messageToken,
|
|
268
|
+
expectedOrigin,
|
|
269
|
+
theme,
|
|
270
|
+
containerStyle,
|
|
271
|
+
onReady,
|
|
272
|
+
onError,
|
|
273
|
+
onValidation
|
|
274
|
+
}) {
|
|
275
|
+
const containerRef = useRef2(null);
|
|
276
|
+
const onReadyRef = useRef2(onReady);
|
|
277
|
+
const onErrorRef = useRef2(onError);
|
|
278
|
+
const onValidationRef = useRef2(onValidation);
|
|
279
|
+
onReadyRef.current = onReady;
|
|
280
|
+
onErrorRef.current = onError;
|
|
281
|
+
onValidationRef.current = onValidation;
|
|
282
|
+
const themeRef = useRef2(theme);
|
|
283
|
+
themeRef.current = theme;
|
|
284
|
+
useEffect3(() => {
|
|
285
|
+
const el = containerRef.current;
|
|
286
|
+
if (!el) return;
|
|
287
|
+
let active = true;
|
|
288
|
+
let readyEmitted = false;
|
|
289
|
+
const emitReadyOnce = () => {
|
|
290
|
+
if (!active || readyEmitted) return;
|
|
291
|
+
readyEmitted = true;
|
|
292
|
+
onReadyRef.current?.();
|
|
293
|
+
};
|
|
294
|
+
const offReady = capture.on("ready", () => {
|
|
295
|
+
emitReadyOnce();
|
|
296
|
+
});
|
|
297
|
+
const offError = capture.on("error", (event) => {
|
|
298
|
+
onErrorRef.current?.(event.message ?? "There was a problem loading the secure card form.");
|
|
299
|
+
});
|
|
300
|
+
const offValidation = capture.on("validation", (event) => {
|
|
301
|
+
onValidationRef.current?.(event.message ?? null);
|
|
302
|
+
});
|
|
303
|
+
const mountOptions = {
|
|
304
|
+
html,
|
|
305
|
+
...messageToken ? { messageToken } : {},
|
|
306
|
+
...expectedOrigin ? { expectedOrigin } : {},
|
|
307
|
+
...themeRef.current ? { theme: themeRef.current } : {}
|
|
308
|
+
};
|
|
309
|
+
capture.mount(el, mountOptions).then(() => {
|
|
310
|
+
emitReadyOnce();
|
|
311
|
+
}).catch((err) => {
|
|
312
|
+
if (active) {
|
|
313
|
+
onErrorRef.current?.(
|
|
314
|
+
err instanceof Error ? err.message : "Failed to load the secure card form."
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
return () => {
|
|
319
|
+
active = false;
|
|
320
|
+
offReady();
|
|
321
|
+
offError();
|
|
322
|
+
offValidation();
|
|
323
|
+
capture.unmount();
|
|
324
|
+
};
|
|
325
|
+
}, [capture, html, messageToken, expectedOrigin]);
|
|
326
|
+
useEffect3(() => {
|
|
327
|
+
if (theme) capture.applyTheme?.(theme);
|
|
328
|
+
}, [capture, theme]);
|
|
329
|
+
return /* @__PURE__ */ jsx4("div", { ref: containerRef, "data-testid": "flopay-vault-card-fields", style: containerStyle });
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// src/split-card-form.tsx
|
|
333
|
+
import React7, { forwardRef, useCallback, useContext as useContext3, useEffect as useEffect5, useImperativeHandle, useMemo as useMemo3, useRef as useRef4, useState as useState3 } from "react";
|
|
263
334
|
|
|
264
335
|
// src/hooks.ts
|
|
265
336
|
import { useContext as useContext2 } from "react";
|
|
@@ -286,14 +357,14 @@ function useBillingApiUrl() {
|
|
|
286
357
|
|
|
287
358
|
// src/processing-overlay.tsx
|
|
288
359
|
import "react";
|
|
289
|
-
import { jsx as
|
|
360
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
290
361
|
var PROCESSING_OVERLAY_SUCCESS_DELAY_MS = 1200;
|
|
291
362
|
var PROCESSING_OVERLAY_ERROR_DELAY_MS = 1500;
|
|
292
363
|
function ProcessingOverlay({
|
|
293
364
|
status,
|
|
294
365
|
errorMessage
|
|
295
366
|
}) {
|
|
296
|
-
return /* @__PURE__ */
|
|
367
|
+
return /* @__PURE__ */ jsx5(
|
|
297
368
|
"div",
|
|
298
369
|
{
|
|
299
370
|
"data-testid": "flopay-processing-overlay",
|
|
@@ -337,14 +408,14 @@ function ProcessingOverlay({
|
|
|
337
408
|
xmlns: "http://www.w3.org/2000/svg",
|
|
338
409
|
style: { animation: "flopay-spin 0.8s linear infinite" },
|
|
339
410
|
children: [
|
|
340
|
-
/* @__PURE__ */
|
|
341
|
-
/* @__PURE__ */
|
|
411
|
+
/* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
|
|
412
|
+
/* @__PURE__ */ jsx5("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
|
|
342
413
|
]
|
|
343
414
|
}
|
|
344
415
|
),
|
|
345
|
-
status === "success" && /* @__PURE__ */
|
|
346
|
-
/* @__PURE__ */
|
|
347
|
-
/* @__PURE__ */
|
|
416
|
+
status === "success" && /* @__PURE__ */ jsx5("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ jsxs2("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
417
|
+
/* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
|
|
418
|
+
/* @__PURE__ */ jsx5(
|
|
348
419
|
"path",
|
|
349
420
|
{
|
|
350
421
|
d: "M7 12.5l3 3 7-7",
|
|
@@ -360,9 +431,9 @@ function ProcessingOverlay({
|
|
|
360
431
|
}
|
|
361
432
|
)
|
|
362
433
|
] }) }),
|
|
363
|
-
status === "error" && /* @__PURE__ */
|
|
364
|
-
/* @__PURE__ */
|
|
365
|
-
/* @__PURE__ */
|
|
434
|
+
status === "error" && /* @__PURE__ */ jsx5("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ jsxs2("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
435
|
+
/* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
|
|
436
|
+
/* @__PURE__ */ jsx5(
|
|
366
437
|
"path",
|
|
367
438
|
{
|
|
368
439
|
d: "M8 8l8 8M16 8l-8 8",
|
|
@@ -394,7 +465,7 @@ function ProcessingOverlay({
|
|
|
394
465
|
]
|
|
395
466
|
}
|
|
396
467
|
),
|
|
397
|
-
status === "success" && /* @__PURE__ */
|
|
468
|
+
status === "success" && /* @__PURE__ */ jsx5(
|
|
398
469
|
"p",
|
|
399
470
|
{
|
|
400
471
|
style: {
|
|
@@ -408,7 +479,7 @@ function ProcessingOverlay({
|
|
|
408
479
|
children: "You will be automatically redirected, do not close or navigate away from this window."
|
|
409
480
|
}
|
|
410
481
|
),
|
|
411
|
-
status === "error" && errorMessage && /* @__PURE__ */
|
|
482
|
+
status === "error" && errorMessage && /* @__PURE__ */ jsx5(
|
|
412
483
|
"p",
|
|
413
484
|
{
|
|
414
485
|
style: {
|
|
@@ -422,7 +493,7 @@ function ProcessingOverlay({
|
|
|
422
493
|
children: errorMessage
|
|
423
494
|
}
|
|
424
495
|
),
|
|
425
|
-
/* @__PURE__ */
|
|
496
|
+
/* @__PURE__ */ jsx5("style", { children: `
|
|
426
497
|
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
427
498
|
@keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
|
|
428
499
|
@keyframes flopay-draw { to { stroke-dashoffset: 0; } }
|
|
@@ -696,11 +767,11 @@ function isInAppBrowser(userAgent) {
|
|
|
696
767
|
}
|
|
697
768
|
|
|
698
769
|
// src/direct-paypal-button.tsx
|
|
699
|
-
import { useEffect as
|
|
770
|
+
import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef3, useState as useState2 } from "react";
|
|
700
771
|
import { loadScript } from "@paypal/paypal-js";
|
|
701
772
|
import { PaymentAPI } from "@flopay/js";
|
|
702
773
|
import { FloPayError as FloPayError2, normalizeGatewayEnvironment } from "@flopay/shared";
|
|
703
|
-
import { jsx as
|
|
774
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
704
775
|
var DEFAULT_BUTTON_HEIGHT = 45;
|
|
705
776
|
function DirectPayPalButton({
|
|
706
777
|
sessionId,
|
|
@@ -723,7 +794,7 @@ function DirectPayPalButton({
|
|
|
723
794
|
existingOrderId,
|
|
724
795
|
debug = false
|
|
725
796
|
}) {
|
|
726
|
-
const containerRef =
|
|
797
|
+
const containerRef = useRef3(null);
|
|
727
798
|
const [ready, setReady] = useState2(false);
|
|
728
799
|
const [failed, setFailed] = useState2(false);
|
|
729
800
|
const [submitting, setSubmitting] = useState2(false);
|
|
@@ -733,52 +804,52 @@ function DirectPayPalButton({
|
|
|
733
804
|
if (!debug) return;
|
|
734
805
|
setDebugLines((prev) => [...prev, `${(/* @__PURE__ */ new Date()).toISOString().slice(11, 23)} ${line}`]);
|
|
735
806
|
};
|
|
736
|
-
const onTokenizedBodyRef =
|
|
737
|
-
const onCompleteRef =
|
|
738
|
-
const onErrorChangeRef =
|
|
739
|
-
const onDeclineRef =
|
|
740
|
-
const onButtonClickRef =
|
|
741
|
-
const onLoadStateChangeRef =
|
|
742
|
-
const runBeforeButtonClickRef =
|
|
743
|
-
const sessionRef =
|
|
744
|
-
const emailRef =
|
|
745
|
-
const nonceRef =
|
|
746
|
-
const beforeClickRef =
|
|
747
|
-
|
|
807
|
+
const onTokenizedBodyRef = useRef3(onTokenizedBody);
|
|
808
|
+
const onCompleteRef = useRef3(onComplete);
|
|
809
|
+
const onErrorChangeRef = useRef3(onErrorChange);
|
|
810
|
+
const onDeclineRef = useRef3(onDecline);
|
|
811
|
+
const onButtonClickRef = useRef3(onButtonClick);
|
|
812
|
+
const onLoadStateChangeRef = useRef3(onLoadStateChange);
|
|
813
|
+
const runBeforeButtonClickRef = useRef3(runBeforeButtonClick);
|
|
814
|
+
const sessionRef = useRef3(session);
|
|
815
|
+
const emailRef = useRef3(email);
|
|
816
|
+
const nonceRef = useRef3(nonce);
|
|
817
|
+
const beforeClickRef = useRef3(null);
|
|
818
|
+
useEffect4(() => {
|
|
748
819
|
onTokenizedBodyRef.current = onTokenizedBody;
|
|
749
820
|
}, [onTokenizedBody]);
|
|
750
|
-
|
|
821
|
+
useEffect4(() => {
|
|
751
822
|
onCompleteRef.current = onComplete;
|
|
752
823
|
}, [onComplete]);
|
|
753
|
-
|
|
824
|
+
useEffect4(() => {
|
|
754
825
|
onErrorChangeRef.current = onErrorChange;
|
|
755
826
|
}, [onErrorChange]);
|
|
756
|
-
|
|
827
|
+
useEffect4(() => {
|
|
757
828
|
onDeclineRef.current = onDecline;
|
|
758
829
|
}, [onDecline]);
|
|
759
|
-
|
|
830
|
+
useEffect4(() => {
|
|
760
831
|
onButtonClickRef.current = onButtonClick;
|
|
761
832
|
}, [onButtonClick]);
|
|
762
|
-
|
|
833
|
+
useEffect4(() => {
|
|
763
834
|
onLoadStateChangeRef.current = onLoadStateChange;
|
|
764
835
|
}, [onLoadStateChange]);
|
|
765
|
-
|
|
836
|
+
useEffect4(() => {
|
|
766
837
|
runBeforeButtonClickRef.current = runBeforeButtonClick;
|
|
767
838
|
}, [runBeforeButtonClick]);
|
|
768
|
-
|
|
839
|
+
useEffect4(() => {
|
|
769
840
|
sessionRef.current = session;
|
|
770
841
|
}, [session]);
|
|
771
|
-
|
|
842
|
+
useEffect4(() => {
|
|
772
843
|
emailRef.current = email;
|
|
773
844
|
}, [email]);
|
|
774
|
-
|
|
845
|
+
useEffect4(() => {
|
|
775
846
|
nonceRef.current = nonce;
|
|
776
847
|
}, [nonce]);
|
|
777
|
-
|
|
848
|
+
useEffect4(() => {
|
|
778
849
|
onLoadStateChangeRef.current?.(ready && !failed);
|
|
779
850
|
}, [ready, failed]);
|
|
780
851
|
const normalizedEnv = normalizeGatewayEnvironment(environment);
|
|
781
|
-
|
|
852
|
+
useEffect4(() => {
|
|
782
853
|
const maskedClient = clientId ? `${clientId.slice(0, 6)}\u2026(len ${clientId.length})` : "(empty)";
|
|
783
854
|
const ua = typeof navigator !== "undefined" ? navigator.userAgent : "(no navigator)";
|
|
784
855
|
appendDebug(`mount clientId=${maskedClient} env=${environment ?? "(unset)"}\u2192${normalizedEnv ?? "live"} ccy=${currency} sub=${isSubscription}`);
|
|
@@ -1215,7 +1286,7 @@ ${debugLines.join("\n")}`
|
|
|
1215
1286
|
}
|
|
1216
1287
|
) : null;
|
|
1217
1288
|
if (failed) {
|
|
1218
|
-
return debug ? /* @__PURE__ */
|
|
1289
|
+
return debug ? /* @__PURE__ */ jsx6("div", { children: debugPanel }) : null;
|
|
1219
1290
|
}
|
|
1220
1291
|
return (
|
|
1221
1292
|
// Single wrapper so the parent flex container sees exactly one flex item
|
|
@@ -1225,7 +1296,7 @@ ${debugLines.join("\n")}`
|
|
|
1225
1296
|
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1226
1297
|
debugPanel,
|
|
1227
1298
|
/* @__PURE__ */ jsxs3("div", { style: { position: "relative", minHeight: DEFAULT_BUTTON_HEIGHT }, children: [
|
|
1228
|
-
!ready && /* @__PURE__ */
|
|
1299
|
+
!ready && /* @__PURE__ */ jsx6(
|
|
1229
1300
|
"div",
|
|
1230
1301
|
{
|
|
1231
1302
|
"data-testid": "flopay-direct-paypal-placeholder",
|
|
@@ -1239,7 +1310,7 @@ ${debugLines.join("\n")}`
|
|
|
1239
1310
|
}
|
|
1240
1311
|
}
|
|
1241
1312
|
),
|
|
1242
|
-
/* @__PURE__ */
|
|
1313
|
+
/* @__PURE__ */ jsx6(
|
|
1243
1314
|
"div",
|
|
1244
1315
|
{
|
|
1245
1316
|
ref: containerRef,
|
|
@@ -1259,10 +1330,28 @@ ${debugLines.join("\n")}`
|
|
|
1259
1330
|
|
|
1260
1331
|
// src/split-card-form.tsx
|
|
1261
1332
|
import { FloPayError as FloPayError3, isSetupIntentClientSecret as isSetupIntentClientSecret2, resolveTheme } from "@flopay/shared";
|
|
1262
|
-
import { Fragment as Fragment2, jsx as
|
|
1333
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1263
1334
|
var STRIPE_RESUME_KEY = "flopay_stripe_resume";
|
|
1264
1335
|
var LEGACY_WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
1265
1336
|
var PAYPAL_RESUME_KEY = "flopay_paypal_resume";
|
|
1337
|
+
function toVaultMount(block) {
|
|
1338
|
+
if (!block?.html) return null;
|
|
1339
|
+
return {
|
|
1340
|
+
html: block.html,
|
|
1341
|
+
...block.messageToken ? { messageToken: block.messageToken } : {},
|
|
1342
|
+
...block.expectedOrigin ? { expectedOrigin: block.expectedOrigin } : {}
|
|
1343
|
+
};
|
|
1344
|
+
}
|
|
1345
|
+
function darkenHex(hex, amount = 0.12) {
|
|
1346
|
+
const match = /^#?([0-9a-fA-F]{6})$/.exec(hex.trim());
|
|
1347
|
+
if (!match) return hex;
|
|
1348
|
+
const value = parseInt(match[1], 16);
|
|
1349
|
+
const scale = Math.max(0, Math.min(1, 1 - amount));
|
|
1350
|
+
const r = Math.round((value >> 16 & 255) * scale);
|
|
1351
|
+
const g = Math.round((value >> 8 & 255) * scale);
|
|
1352
|
+
const b = Math.round((value & 255) * scale);
|
|
1353
|
+
return `#${(1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1)}`;
|
|
1354
|
+
}
|
|
1266
1355
|
var FLOPAY_KEYFRAMES = `
|
|
1267
1356
|
.paypal-buttons { margin: 0 !important; vertical-align: top !important; }
|
|
1268
1357
|
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
@@ -1287,18 +1376,20 @@ var FLOPAY_KEYFRAMES = `
|
|
|
1287
1376
|
`;
|
|
1288
1377
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT = 44;
|
|
1289
1378
|
function derivePrimaryTileStyle(opts) {
|
|
1290
|
-
if (!opts.themeBundle) {
|
|
1379
|
+
if (!opts.themeBundle && !opts.explicitPrimaryColor) {
|
|
1291
1380
|
return {
|
|
1292
1381
|
backgroundColor: "white",
|
|
1293
1382
|
color: "#262833",
|
|
1294
1383
|
border: "1px solid #d1d5db",
|
|
1295
|
-
borderRadius:
|
|
1384
|
+
borderRadius: opts.resolvedBorderRadius,
|
|
1296
1385
|
boxShadow: "0 1px 2px rgba(0,0,0,0.04)"
|
|
1297
1386
|
};
|
|
1298
1387
|
}
|
|
1299
|
-
const submit = opts.submitButtonStyle ?? {};
|
|
1388
|
+
const submit = opts.themeBundle ? opts.submitButtonStyle ?? {} : {};
|
|
1300
1389
|
return {
|
|
1301
|
-
|
|
1390
|
+
// `colorPrimary` wins so a per-checkout override re-skins the card / auto-pay
|
|
1391
|
+
// buttons in lock-step with the submit CTA (which also keys off it).
|
|
1392
|
+
backgroundColor: opts.resolvedPrimaryColor,
|
|
1302
1393
|
color: submit.color ?? "white",
|
|
1303
1394
|
border: submit.border ?? "none",
|
|
1304
1395
|
borderRadius: submit.borderRadius ?? opts.resolvedBorderRadius,
|
|
@@ -1332,7 +1423,7 @@ function normalizeBeforeButtonClickError(method, err) {
|
|
|
1332
1423
|
);
|
|
1333
1424
|
}
|
|
1334
1425
|
function FloPayKeyframes() {
|
|
1335
|
-
return /* @__PURE__ */
|
|
1426
|
+
return /* @__PURE__ */ jsx7("style", { children: FLOPAY_KEYFRAMES });
|
|
1336
1427
|
}
|
|
1337
1428
|
function toCssSize(value) {
|
|
1338
1429
|
if (typeof value === "number") return `${value}px`;
|
|
@@ -1355,7 +1446,7 @@ function ExpressCheckoutReadySwap({
|
|
|
1355
1446
|
}) {
|
|
1356
1447
|
if (state === "unavailable" || state === "load_error") return null;
|
|
1357
1448
|
return /* @__PURE__ */ jsxs4("div", { style: { position: "relative", minHeight: 44 }, children: [
|
|
1358
|
-
/* @__PURE__ */
|
|
1449
|
+
/* @__PURE__ */ jsx7(
|
|
1359
1450
|
"div",
|
|
1360
1451
|
{
|
|
1361
1452
|
"data-testid": placeholderTestId,
|
|
@@ -1374,7 +1465,7 @@ function ExpressCheckoutReadySwap({
|
|
|
1374
1465
|
}
|
|
1375
1466
|
}
|
|
1376
1467
|
),
|
|
1377
|
-
/* @__PURE__ */
|
|
1468
|
+
/* @__PURE__ */ jsx7(
|
|
1378
1469
|
"div",
|
|
1379
1470
|
{
|
|
1380
1471
|
style: {
|
|
@@ -1394,7 +1485,7 @@ function isExpressCheckoutRowVisible(state) {
|
|
|
1394
1485
|
}
|
|
1395
1486
|
var SplitCardForm = forwardRef(
|
|
1396
1487
|
function SplitCardForm2(props, ref) {
|
|
1397
|
-
return /* @__PURE__ */
|
|
1488
|
+
return /* @__PURE__ */ jsx7(SplitCardFormInner, { ...props, innerRef: ref });
|
|
1398
1489
|
}
|
|
1399
1490
|
);
|
|
1400
1491
|
function PayPalButtonInner({
|
|
@@ -1414,14 +1505,14 @@ function PayPalButtonInner({
|
|
|
1414
1505
|
const stripe = useStripeRaw();
|
|
1415
1506
|
const elements = useStripeElements();
|
|
1416
1507
|
const [loadState, setLoadState] = useState3("loading");
|
|
1417
|
-
|
|
1508
|
+
useEffect5(() => {
|
|
1418
1509
|
onLoadStateChange?.(loadState);
|
|
1419
1510
|
}, [loadState, onLoadStateChange]);
|
|
1420
1511
|
const [submitting, setSubmitting] = useState3(false);
|
|
1421
|
-
const paypalResumeAttempted =
|
|
1422
|
-
const beforeClickRef =
|
|
1512
|
+
const paypalResumeAttempted = useRef4(false);
|
|
1513
|
+
const beforeClickRef = useRef4(null);
|
|
1423
1514
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
1424
|
-
|
|
1515
|
+
useEffect5(() => {
|
|
1425
1516
|
if (!stripe || paypalResumeAttempted.current) return;
|
|
1426
1517
|
const params = new URLSearchParams(window.location.search);
|
|
1427
1518
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -1627,13 +1718,13 @@ function PayPalButtonInner({
|
|
|
1627
1718
|
}
|
|
1628
1719
|
}, [stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]);
|
|
1629
1720
|
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1630
|
-
/* @__PURE__ */
|
|
1721
|
+
/* @__PURE__ */ jsx7(
|
|
1631
1722
|
ExpressCheckoutReadySwap,
|
|
1632
1723
|
{
|
|
1633
1724
|
state: loadState,
|
|
1634
1725
|
placeholderTestId: "flopay-paypal-placeholder",
|
|
1635
1726
|
borderRadius: placeholderBorderRadius,
|
|
1636
|
-
children: /* @__PURE__ */
|
|
1727
|
+
children: /* @__PURE__ */ jsx7(
|
|
1637
1728
|
ExpressCheckoutElement,
|
|
1638
1729
|
{
|
|
1639
1730
|
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
|
|
@@ -1660,7 +1751,7 @@ function PayPalButtonInner({
|
|
|
1660
1751
|
)
|
|
1661
1752
|
}
|
|
1662
1753
|
),
|
|
1663
|
-
submitting && /* @__PURE__ */
|
|
1754
|
+
submitting && /* @__PURE__ */ jsx7(ProcessingOverlay, { status: "processing" })
|
|
1664
1755
|
] });
|
|
1665
1756
|
}
|
|
1666
1757
|
function WalletButtonInner({
|
|
@@ -1680,13 +1771,13 @@ function WalletButtonInner({
|
|
|
1680
1771
|
const stripe = useStripeRaw();
|
|
1681
1772
|
const elements = useStripeElements();
|
|
1682
1773
|
const [loadState, setLoadState] = useState3("loading");
|
|
1683
|
-
|
|
1774
|
+
useEffect5(() => {
|
|
1684
1775
|
onLoadStateChange?.(loadState);
|
|
1685
1776
|
}, [loadState, onLoadStateChange]);
|
|
1686
1777
|
const [submitting, setSubmitting] = useState3(false);
|
|
1687
1778
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
1688
|
-
const lastWalletMethodRef =
|
|
1689
|
-
const beforeClickRef =
|
|
1779
|
+
const lastWalletMethodRef = useRef4("card");
|
|
1780
|
+
const beforeClickRef = useRef4(null);
|
|
1690
1781
|
const handleWalletConfirm = useCallback(
|
|
1691
1782
|
async (event) => {
|
|
1692
1783
|
if (!stripe || !elements) return;
|
|
@@ -1796,13 +1887,13 @@ function WalletButtonInner({
|
|
|
1796
1887
|
[expressMethods]
|
|
1797
1888
|
);
|
|
1798
1889
|
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1799
|
-
/* @__PURE__ */
|
|
1890
|
+
/* @__PURE__ */ jsx7(
|
|
1800
1891
|
ExpressCheckoutReadySwap,
|
|
1801
1892
|
{
|
|
1802
1893
|
state: loadState,
|
|
1803
1894
|
placeholderTestId: "flopay-wallet-placeholder",
|
|
1804
1895
|
borderRadius: placeholderBorderRadius,
|
|
1805
|
-
children: /* @__PURE__ */
|
|
1896
|
+
children: /* @__PURE__ */ jsx7(
|
|
1806
1897
|
ExpressCheckoutElement,
|
|
1807
1898
|
{
|
|
1808
1899
|
onReady: (event) => {
|
|
@@ -1841,7 +1932,7 @@ function WalletButtonInner({
|
|
|
1841
1932
|
)
|
|
1842
1933
|
}
|
|
1843
1934
|
),
|
|
1844
|
-
submitting && /* @__PURE__ */
|
|
1935
|
+
submitting && /* @__PURE__ */ jsx7(ProcessingOverlay, { status: "processing" })
|
|
1845
1936
|
] });
|
|
1846
1937
|
}
|
|
1847
1938
|
function StripeMethodButton({
|
|
@@ -1862,7 +1953,7 @@ function StripeMethodButton({
|
|
|
1862
1953
|
const resolvedBackground = brand?.backgroundColor ?? backgroundColor ?? "#ffffff";
|
|
1863
1954
|
const resolvedBorder = brand?.borderColor ?? borderColor ?? "#d1d5db";
|
|
1864
1955
|
const resolvedTextColor = brand?.textColor ?? textColor ?? "#262833";
|
|
1865
|
-
return /* @__PURE__ */
|
|
1956
|
+
return /* @__PURE__ */ jsx7(
|
|
1866
1957
|
"button",
|
|
1867
1958
|
{
|
|
1868
1959
|
type: "button",
|
|
@@ -1909,7 +2000,7 @@ function StripeMethodButton({
|
|
|
1909
2000
|
// Pulse-skeleton parity with the wallet ECE: no spinner, just the
|
|
1910
2001
|
// status text on top of the pulsing background. Keeps the loading
|
|
1911
2002
|
// affordance shape-equivalent across both kinds of tile.
|
|
1912
|
-
/* @__PURE__ */
|
|
2003
|
+
/* @__PURE__ */ jsx7("span", { style: { margin: "0 auto" }, children: `Connecting to ${getStripeMethodDisplayName(method)}\u2026` })
|
|
1913
2004
|
) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1914
2005
|
/* @__PURE__ */ jsxs4(
|
|
1915
2006
|
"span",
|
|
@@ -1924,7 +2015,7 @@ function StripeMethodButton({
|
|
|
1924
2015
|
gap: hasVendoredStripeMethodLogo(method) ? 8 : 0
|
|
1925
2016
|
},
|
|
1926
2017
|
children: [
|
|
1927
|
-
brand?.logoSvg && /* @__PURE__ */
|
|
2018
|
+
brand?.logoSvg && /* @__PURE__ */ jsx7(
|
|
1928
2019
|
"span",
|
|
1929
2020
|
{
|
|
1930
2021
|
"aria-hidden": "true",
|
|
@@ -1943,11 +2034,11 @@ function StripeMethodButton({
|
|
|
1943
2034
|
dangerouslySetInnerHTML: { __html: brand.logoSvg }
|
|
1944
2035
|
}
|
|
1945
2036
|
),
|
|
1946
|
-
/* @__PURE__ */
|
|
2037
|
+
/* @__PURE__ */ jsx7("span", { children: getStripeMethodDisplayName(method) })
|
|
1947
2038
|
]
|
|
1948
2039
|
}
|
|
1949
2040
|
),
|
|
1950
|
-
hasNextStep && /* @__PURE__ */
|
|
2041
|
+
hasNextStep && /* @__PURE__ */ jsx7(
|
|
1951
2042
|
"svg",
|
|
1952
2043
|
{
|
|
1953
2044
|
width: "14",
|
|
@@ -1967,7 +2058,7 @@ function StripeMethodButton({
|
|
|
1967
2058
|
opacity: 0.7
|
|
1968
2059
|
},
|
|
1969
2060
|
"aria-hidden": "true",
|
|
1970
|
-
children: /* @__PURE__ */
|
|
2061
|
+
children: /* @__PURE__ */ jsx7("path", { d: "M9 18l6-6-6-6" })
|
|
1971
2062
|
}
|
|
1972
2063
|
)
|
|
1973
2064
|
] })
|
|
@@ -1990,12 +2081,13 @@ function StripeMethodInlineForm({
|
|
|
1990
2081
|
isProcessing,
|
|
1991
2082
|
submitButtonColor,
|
|
1992
2083
|
submitButtonBorderRadius,
|
|
1993
|
-
submitButtonStyle
|
|
2084
|
+
submitButtonStyle,
|
|
2085
|
+
errorText
|
|
1994
2086
|
}) {
|
|
1995
2087
|
const stripe = useStripeRaw();
|
|
1996
2088
|
const elements = useStripeElements();
|
|
1997
2089
|
const [submitting, setSubmitting] = useState3(false);
|
|
1998
|
-
const submittingRef =
|
|
2090
|
+
const submittingRef = useRef4(false);
|
|
1999
2091
|
const [isMethodComplete, setIsMethodComplete] = useState3(false);
|
|
2000
2092
|
const [loadState, setLoadState] = useState3("loading");
|
|
2001
2093
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
@@ -2140,7 +2232,7 @@ function StripeMethodInlineForm({
|
|
|
2140
2232
|
]);
|
|
2141
2233
|
void onCancel;
|
|
2142
2234
|
return /* @__PURE__ */ jsxs4("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
|
|
2143
|
-
/* @__PURE__ */
|
|
2235
|
+
/* @__PURE__ */ jsx7(
|
|
2144
2236
|
PaymentElement2,
|
|
2145
2237
|
{
|
|
2146
2238
|
onReady: () => setLoadState("ready"),
|
|
@@ -2160,7 +2252,7 @@ function StripeMethodInlineForm({
|
|
|
2160
2252
|
}
|
|
2161
2253
|
}
|
|
2162
2254
|
),
|
|
2163
|
-
/* @__PURE__ */
|
|
2255
|
+
/* @__PURE__ */ jsx7(
|
|
2164
2256
|
"button",
|
|
2165
2257
|
{
|
|
2166
2258
|
type: "button",
|
|
@@ -2186,7 +2278,23 @@ function StripeMethodInlineForm({
|
|
|
2186
2278
|
},
|
|
2187
2279
|
children: submitting ? "Processing\u2026" : `Pay with ${getStripeMethodDisplayName(method)}`
|
|
2188
2280
|
}
|
|
2189
|
-
)
|
|
2281
|
+
),
|
|
2282
|
+
errorText && /* @__PURE__ */ jsxs4("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
2283
|
+
margin: "0.75rem 0 0",
|
|
2284
|
+
padding: "0.625rem 0.875rem",
|
|
2285
|
+
background: "#FEF2F2",
|
|
2286
|
+
border: "1px solid #FECACA",
|
|
2287
|
+
borderRadius: "8px",
|
|
2288
|
+
color: "#991B1B",
|
|
2289
|
+
fontSize: "0.85rem",
|
|
2290
|
+
fontWeight: 600,
|
|
2291
|
+
display: "flex",
|
|
2292
|
+
alignItems: "center",
|
|
2293
|
+
gap: "0.5rem"
|
|
2294
|
+
}, children: [
|
|
2295
|
+
/* @__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" }) }),
|
|
2296
|
+
errorText
|
|
2297
|
+
] })
|
|
2190
2298
|
] });
|
|
2191
2299
|
}
|
|
2192
2300
|
function StripePaymentElementInner({
|
|
@@ -2216,8 +2324,8 @@ function StripePaymentElementInner({
|
|
|
2216
2324
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2217
2325
|
const [expandedMethod, setExpandedMethod] = useState3(null);
|
|
2218
2326
|
const [submittingMethod, setSubmittingMethod] = useState3(null);
|
|
2219
|
-
const submittingRef =
|
|
2220
|
-
|
|
2327
|
+
const submittingRef = useRef4(false);
|
|
2328
|
+
useEffect5(() => {
|
|
2221
2329
|
if (paymentElementMethods.length > 0 && stripeInstance) {
|
|
2222
2330
|
onLoadStateChange?.("ready");
|
|
2223
2331
|
} else if (!stripeInstance) {
|
|
@@ -2385,7 +2493,7 @@ function StripePaymentElementInner({
|
|
|
2385
2493
|
paymentMethodTypes: [localExpandedMethod]
|
|
2386
2494
|
};
|
|
2387
2495
|
}, [localExpandedMethod, paymentElementBaseOptions]);
|
|
2388
|
-
return /* @__PURE__ */
|
|
2496
|
+
return /* @__PURE__ */ jsx7(
|
|
2389
2497
|
"div",
|
|
2390
2498
|
{
|
|
2391
2499
|
"data-testid": "flopay-stripe-payment-element-region",
|
|
@@ -2394,8 +2502,8 @@ function StripePaymentElementInner({
|
|
|
2394
2502
|
const isExpanded = expandedApmMethod === method;
|
|
2395
2503
|
const isSubmittingThis = submittingMethod === method;
|
|
2396
2504
|
const otherInProgress = submittingMethod !== null && submittingMethod !== method || expandedApmMethod !== null && expandedApmMethod !== void 0 && expandedApmMethod !== method;
|
|
2397
|
-
return /* @__PURE__ */ jsxs4(
|
|
2398
|
-
/* @__PURE__ */
|
|
2505
|
+
return /* @__PURE__ */ jsxs4(React7.Fragment, { children: [
|
|
2506
|
+
/* @__PURE__ */ jsx7(
|
|
2399
2507
|
StripeMethodButton,
|
|
2400
2508
|
{
|
|
2401
2509
|
method,
|
|
@@ -2412,12 +2520,12 @@ function StripePaymentElementInner({
|
|
|
2412
2520
|
fontFamily: buttonAppearance?.fontFamily
|
|
2413
2521
|
}
|
|
2414
2522
|
),
|
|
2415
|
-
!onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */
|
|
2523
|
+
!onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ jsx7(
|
|
2416
2524
|
StripeElements,
|
|
2417
2525
|
{
|
|
2418
2526
|
stripe: stripeInstance,
|
|
2419
2527
|
options: localInlineElementsOptions,
|
|
2420
|
-
children: /* @__PURE__ */
|
|
2528
|
+
children: /* @__PURE__ */ jsx7(
|
|
2421
2529
|
StripeMethodInlineForm,
|
|
2422
2530
|
{
|
|
2423
2531
|
method,
|
|
@@ -2470,6 +2578,7 @@ function SplitCardFormInner({
|
|
|
2470
2578
|
showPayPal = true,
|
|
2471
2579
|
showStripe = true,
|
|
2472
2580
|
enabledPaymentMethods,
|
|
2581
|
+
enabledPaymentMethodCountries,
|
|
2473
2582
|
showApplePay = true,
|
|
2474
2583
|
showGooglePay = true,
|
|
2475
2584
|
layout = "default",
|
|
@@ -2484,6 +2593,8 @@ function SplitCardFormInner({
|
|
|
2484
2593
|
onButtonClick,
|
|
2485
2594
|
onBeforeButtonClick,
|
|
2486
2595
|
enableAVS: enableAVSProp,
|
|
2596
|
+
cardFieldOrder,
|
|
2597
|
+
cardPreFormSlot,
|
|
2487
2598
|
avsLayout: avsLayoutProp = "row",
|
|
2488
2599
|
country: countryProp,
|
|
2489
2600
|
zip: zipProp,
|
|
@@ -2520,14 +2631,41 @@ function SplitCardFormInner({
|
|
|
2520
2631
|
const [city, setCity] = useState3(cityProp ?? "");
|
|
2521
2632
|
const [stateValue, setStateValue] = useState3(stateProp ?? "");
|
|
2522
2633
|
const [accountPatch, setAccountPatch] = useState3({});
|
|
2523
|
-
const zipCodeRef =
|
|
2524
|
-
const selectedCountryRef =
|
|
2525
|
-
const addressLine1Ref =
|
|
2526
|
-
const addressLine2Ref =
|
|
2527
|
-
const cityRef =
|
|
2528
|
-
const stateRef =
|
|
2634
|
+
const zipCodeRef = useRef4(zipProp ?? "");
|
|
2635
|
+
const selectedCountryRef = useRef4(countryProp ?? "US");
|
|
2636
|
+
const addressLine1Ref = useRef4(addressLine1Prop ?? "");
|
|
2637
|
+
const addressLine2Ref = useRef4(addressLine2Prop ?? "");
|
|
2638
|
+
const cityRef = useRef4(cityProp ?? "");
|
|
2639
|
+
const stateRef = useRef4(stateProp ?? "");
|
|
2529
2640
|
const avsConfig = useMemo3(() => resolveAVSConfig(enableAVSProp), [enableAVSProp]);
|
|
2530
2641
|
const enableAVS = avsConfig !== null;
|
|
2642
|
+
const vaultBlockReady = Boolean(session?.vault?.html);
|
|
2643
|
+
const vaultGatewayAdvertised = Boolean(session?.gateways?.pcivault);
|
|
2644
|
+
const vaultActive = Boolean(
|
|
2645
|
+
showStripe && (vaultBlockReady || vaultGatewayAdvertised) && flopay && sessionId
|
|
2646
|
+
);
|
|
2647
|
+
const cardCapture = useMemo3(() => {
|
|
2648
|
+
if (!flopay || !vaultActive || !sessionId) return null;
|
|
2649
|
+
return flopay.cardCapture({ sessionId });
|
|
2650
|
+
}, [flopay, vaultActive, sessionId]);
|
|
2651
|
+
const { avsInvalid, invalidAvsFields } = useMemo3(() => {
|
|
2652
|
+
const none = { line1: false, city: false, state: false, zip: false };
|
|
2653
|
+
if (!vaultActive || !avsConfig) return { avsInvalid: false, invalidAvsFields: none };
|
|
2654
|
+
const cc = selectedCountry;
|
|
2655
|
+
const isEmpty = (field, value) => isAVSFieldVisible(field, cc) && !value.trim();
|
|
2656
|
+
const invalidAvsFields2 = {
|
|
2657
|
+
line1: isEmpty(avsConfig.address_line_1, addressLine1),
|
|
2658
|
+
city: isEmpty(avsConfig.city, city),
|
|
2659
|
+
state: isEmpty(avsConfig.state, stateValue),
|
|
2660
|
+
zip: isEmpty(avsConfig.postal_code, zipCode)
|
|
2661
|
+
};
|
|
2662
|
+
const avsInvalid2 = invalidAvsFields2.line1 || invalidAvsFields2.city || invalidAvsFields2.state || invalidAvsFields2.zip;
|
|
2663
|
+
return { avsInvalid: avsInvalid2, invalidAvsFields: invalidAvsFields2 };
|
|
2664
|
+
}, [vaultActive, avsConfig, selectedCountry, addressLine1, city, stateValue, zipCode]);
|
|
2665
|
+
const [hasAttemptedSubmit, setHasAttemptedSubmit] = useState3(false);
|
|
2666
|
+
const [vaultMount, setVaultMount] = useState3(
|
|
2667
|
+
() => toVaultMount(session?.vault)
|
|
2668
|
+
);
|
|
2531
2669
|
const [viewState, setViewState] = useState3(initialCardOpen ? "card" : "buttons");
|
|
2532
2670
|
const [expandedApmMethod, setExpandedApmMethod] = useState3(null);
|
|
2533
2671
|
const showCardForm = viewState === "expanding" || viewState === "card";
|
|
@@ -2552,7 +2690,7 @@ function SplitCardFormInner({
|
|
|
2552
2690
|
setExpandedApmMethod(null);
|
|
2553
2691
|
}, TRANSITION_MS);
|
|
2554
2692
|
}, []);
|
|
2555
|
-
|
|
2693
|
+
useEffect5(() => {
|
|
2556
2694
|
if (layout === "buttons" && initialCardOpen) {
|
|
2557
2695
|
setViewState("card");
|
|
2558
2696
|
}
|
|
@@ -2560,10 +2698,10 @@ function SplitCardFormInner({
|
|
|
2560
2698
|
const [fullName, setFullName] = useState3("");
|
|
2561
2699
|
const [formReady, setFormReady] = useState3(false);
|
|
2562
2700
|
const [overlayStatus, setOverlayStatus] = useState3(null);
|
|
2563
|
-
const processingRef =
|
|
2701
|
+
const processingRef = useRef4(false);
|
|
2564
2702
|
const [paypalDirectRetry, setPaypalDirectRetry] = useState3(null);
|
|
2565
|
-
const paypalDirectRetryRef =
|
|
2566
|
-
|
|
2703
|
+
const paypalDirectRetryRef = useRef4(paypalDirectRetry);
|
|
2704
|
+
useEffect5(() => {
|
|
2567
2705
|
paypalDirectRetryRef.current = paypalDirectRetry;
|
|
2568
2706
|
}, [paypalDirectRetry]);
|
|
2569
2707
|
const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
|
|
@@ -2584,6 +2722,31 @@ function SplitCardFormInner({
|
|
|
2584
2722
|
};
|
|
2585
2723
|
}, [themeBundle, buttonsTheme, buttonsStylesOverride]);
|
|
2586
2724
|
const appearance = appearanceOverride ?? themeBundle?.appearance;
|
|
2725
|
+
const vaultThemeColors = useMemo3(() => {
|
|
2726
|
+
const vars = appearance?.variables;
|
|
2727
|
+
const asString = (value) => typeof value === "string" && value ? value : void 0;
|
|
2728
|
+
const submitButtonStyle = bStyles.submitButton;
|
|
2729
|
+
const primary = asString(vars?.colorPrimary) ?? asString(submitButtonStyle?.backgroundColor) ?? "#4A49FF";
|
|
2730
|
+
const isButtonsLayout = layout === "buttons";
|
|
2731
|
+
const nameInput = bStyles.nameInput;
|
|
2732
|
+
return {
|
|
2733
|
+
primaryColor: primary,
|
|
2734
|
+
primaryHoverColor: asString(vars?.colorPrimaryHover) ?? darkenHex(primary, 0.12),
|
|
2735
|
+
inputBackgroundColor: asString(bStyles.cardInputBackground) ?? asString(vars?.colorBackground) ?? "#ffffff",
|
|
2736
|
+
textColor: asString(bStyles.cardInputColor) ?? asString(nameInput?.color) ?? asString(vars?.colorText) ?? "#262833",
|
|
2737
|
+
borderColor: asString(bStyles.cardInputBorder) ?? (isButtonsLayout ? "#e5e7eb" : "#A4A4FF"),
|
|
2738
|
+
placeholderColor: asString(bStyles.cardInputPlaceholderColor) ?? "#9ca3af",
|
|
2739
|
+
errorColor: asString(vars?.colorDanger) ?? "#dc2626",
|
|
2740
|
+
successColor: "#16a34a",
|
|
2741
|
+
fontFamily: asString(nameInput?.fontFamily) ?? asString(vars?.fontFamily) ?? "Poppins, sans-serif",
|
|
2742
|
+
fontSize: asString(bStyles.cardInputFontSize) ?? asString(vars?.fontSizeBase) ?? "16px",
|
|
2743
|
+
// `resolvedInputFontWeight` equivalent — sent as a string (the widget's
|
|
2744
|
+
// theme applier only honors string values) so vault inputs/placeholders
|
|
2745
|
+
// match the AVS fields' weight per theme (default 400).
|
|
2746
|
+
fontWeight: String(toCssWeight(nameInput?.fontWeight) ?? 400),
|
|
2747
|
+
borderRadius: asString(vars?.borderRadius) ?? "8px"
|
|
2748
|
+
};
|
|
2749
|
+
}, [appearance, bStyles, layout]);
|
|
2587
2750
|
const isInlineSessionPatchProcessing = checkout.inlineSessionPatchProcessing ?? false;
|
|
2588
2751
|
const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
|
|
2589
2752
|
const isSelfContained = !onTokenizedBody;
|
|
@@ -2652,12 +2815,160 @@ function SplitCardFormInner({
|
|
|
2652
2815
|
},
|
|
2653
2816
|
[onErrorChange]
|
|
2654
2817
|
);
|
|
2818
|
+
useEffect5(() => {
|
|
2819
|
+
if (!vaultActive || !cardCapture) return;
|
|
2820
|
+
cardCapture.setSubmitGate?.(avsInvalid);
|
|
2821
|
+
}, [vaultActive, cardCapture, avsInvalid]);
|
|
2822
|
+
useEffect5(() => {
|
|
2823
|
+
if (!vaultActive || !cardCapture) return;
|
|
2824
|
+
cardCapture.setCardFieldOrder?.(cardFieldOrder ?? null, avsConfig == null);
|
|
2825
|
+
}, [vaultActive, cardCapture, cardFieldOrder, avsConfig]);
|
|
2826
|
+
useEffect5(() => {
|
|
2827
|
+
if (viewState === "expanding" || viewState === "collapsing" || viewState === "apm-expanding" || viewState === "apm-collapsing") {
|
|
2828
|
+
updateError(null);
|
|
2829
|
+
}
|
|
2830
|
+
}, [viewState, updateError]);
|
|
2655
2831
|
const emitDecline = useCallback(
|
|
2656
2832
|
(method, input, overrides) => {
|
|
2657
2833
|
onDecline?.(buildDeclineEvent(method, input, overrides));
|
|
2658
2834
|
},
|
|
2659
2835
|
[onDecline]
|
|
2660
2836
|
);
|
|
2837
|
+
useEffect5(() => {
|
|
2838
|
+
if (!vaultActive || !sessionId) {
|
|
2839
|
+
setVaultMount(null);
|
|
2840
|
+
return;
|
|
2841
|
+
}
|
|
2842
|
+
const embedded = toVaultMount(session?.vault);
|
|
2843
|
+
if (embedded) {
|
|
2844
|
+
setVaultMount(embedded);
|
|
2845
|
+
return;
|
|
2846
|
+
}
|
|
2847
|
+
setVaultMount(null);
|
|
2848
|
+
let active = true;
|
|
2849
|
+
new PaymentAPI2(baseUrl).getVaultCapture(sessionId, nonce).then((block) => {
|
|
2850
|
+
if (!active) return;
|
|
2851
|
+
const mount = toVaultMount(block);
|
|
2852
|
+
if (mount) {
|
|
2853
|
+
setVaultMount(mount);
|
|
2854
|
+
} else {
|
|
2855
|
+
updateError("Failed to load the secure card form.");
|
|
2856
|
+
}
|
|
2857
|
+
}).catch((err) => {
|
|
2858
|
+
if (active) {
|
|
2859
|
+
updateError(err instanceof Error ? err.message : "Failed to load the secure card form.");
|
|
2860
|
+
}
|
|
2861
|
+
});
|
|
2862
|
+
return () => {
|
|
2863
|
+
active = false;
|
|
2864
|
+
};
|
|
2865
|
+
}, [
|
|
2866
|
+
vaultActive,
|
|
2867
|
+
sessionId,
|
|
2868
|
+
session?.vault?.html,
|
|
2869
|
+
session?.vault?.messageToken,
|
|
2870
|
+
session?.vault?.expectedOrigin,
|
|
2871
|
+
baseUrl,
|
|
2872
|
+
nonce,
|
|
2873
|
+
updateError
|
|
2874
|
+
]);
|
|
2875
|
+
useEffect5(() => {
|
|
2876
|
+
if (!vaultActive || !cardCapture) return;
|
|
2877
|
+
let cancelled = false;
|
|
2878
|
+
const offSubmitting = cardCapture.on("submitting", () => {
|
|
2879
|
+
setHasAttemptedSubmit(true);
|
|
2880
|
+
setOverlayStatus("processing");
|
|
2881
|
+
if (!sessionId || !nonce) return;
|
|
2882
|
+
const cc = selectedCountryRef.current || resolvedAccount.country || "US";
|
|
2883
|
+
const stateVisible = avsConfig ? isAVSFieldVisible(avsConfig.state, cc) : false;
|
|
2884
|
+
const line1Visible = avsConfig ? isAVSFieldVisible(avsConfig.address_line_1, cc) : false;
|
|
2885
|
+
const zipVisible = avsConfig ? isAVSFieldVisible(avsConfig.postal_code, cc) : false;
|
|
2886
|
+
const cityVisible = avsConfig ? isAVSFieldVisible(avsConfig.city, cc) : false;
|
|
2887
|
+
const line2Visible = avsConfig ? isAVSFieldVisible(avsConfig.address_line_2, cc) : false;
|
|
2888
|
+
const derivedState = line1Visible && !stateVisible && zipVisible ? getStateFromPostalCode(cc, zipCodeRef.current ?? "") : null;
|
|
2889
|
+
const stateValue2 = stateVisible ? stateRef.current : derivedState;
|
|
2890
|
+
void new PaymentAPI2(baseUrl).patchAccountSnapshot(sessionId, nonce, {
|
|
2891
|
+
accountData: {
|
|
2892
|
+
userId: resolvedAccount.userId ?? "",
|
|
2893
|
+
email: resolvedAccount.email ?? "",
|
|
2894
|
+
firstName: resolvedAccount.firstName ?? fullName.trim().split(/\s+/)[0] ?? "",
|
|
2895
|
+
lastName: resolvedAccount.lastName ?? fullName.trim().split(/\s+/).slice(1).join(" ") ?? "",
|
|
2896
|
+
...zipVisible && zipCodeRef.current ? { zip: zipCodeRef.current } : {},
|
|
2897
|
+
...cityVisible && cityRef.current ? { city: cityRef.current } : {},
|
|
2898
|
+
...stateValue2 ? { state: stateValue2 } : {},
|
|
2899
|
+
...line1Visible && addressLine1Ref.current ? { addressLine1: addressLine1Ref.current } : {},
|
|
2900
|
+
...line2Visible && addressLine2Ref.current ? { addressLine2: addressLine2Ref.current } : {},
|
|
2901
|
+
country: cc
|
|
2902
|
+
},
|
|
2903
|
+
...avsCheckProp !== void 0 ? { avsCheck: avsCheckProp } : {},
|
|
2904
|
+
...avsConfig ? {
|
|
2905
|
+
avsConfig: {
|
|
2906
|
+
country: isAVSFieldVisible(avsConfig.country, cc),
|
|
2907
|
+
postal_code: zipVisible,
|
|
2908
|
+
address_line_1: line1Visible,
|
|
2909
|
+
address_line_2: line2Visible,
|
|
2910
|
+
city: cityVisible,
|
|
2911
|
+
state: stateVisible
|
|
2912
|
+
}
|
|
2913
|
+
} : {}
|
|
2914
|
+
}).catch(() => {
|
|
2915
|
+
});
|
|
2916
|
+
});
|
|
2917
|
+
const offComplete = cardCapture.on("complete", async (event) => {
|
|
2918
|
+
markSessionRecentlyCompleted(event.sessionId ?? sessionId);
|
|
2919
|
+
setOverlayStatus("success");
|
|
2920
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_SUCCESS_DELAY_MS));
|
|
2921
|
+
if (cancelled) return;
|
|
2922
|
+
onComplete?.({
|
|
2923
|
+
status: "succeeded",
|
|
2924
|
+
paymentIntentId: event.intentId,
|
|
2925
|
+
checkoutMethod: "card"
|
|
2926
|
+
});
|
|
2927
|
+
});
|
|
2928
|
+
const offDecline = cardCapture.on("decline", async (event) => {
|
|
2929
|
+
const message = event.message ?? "Your payment was declined. Please try another card or contact your bank.";
|
|
2930
|
+
updateError(message);
|
|
2931
|
+
setOverlayStatus("error");
|
|
2932
|
+
emitDecline("card", message, event.declineReason ? { declineCode: event.declineReason } : void 0);
|
|
2933
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
2934
|
+
if (cancelled) return;
|
|
2935
|
+
setOverlayStatus(null);
|
|
2936
|
+
});
|
|
2937
|
+
const offError = cardCapture.on("error", async (event) => {
|
|
2938
|
+
const message = event.message ?? "There was a problem processing your payment. Please try again.";
|
|
2939
|
+
updateError(message);
|
|
2940
|
+
setOverlayStatus("error");
|
|
2941
|
+
onError?.(new FloPayError3(message, "api_error"));
|
|
2942
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
2943
|
+
if (cancelled) return;
|
|
2944
|
+
setOverlayStatus(null);
|
|
2945
|
+
});
|
|
2946
|
+
return () => {
|
|
2947
|
+
cancelled = true;
|
|
2948
|
+
offSubmitting();
|
|
2949
|
+
offComplete();
|
|
2950
|
+
offDecline();
|
|
2951
|
+
offError();
|
|
2952
|
+
};
|
|
2953
|
+
}, [
|
|
2954
|
+
vaultActive,
|
|
2955
|
+
cardCapture,
|
|
2956
|
+
sessionId,
|
|
2957
|
+
nonce,
|
|
2958
|
+
baseUrl,
|
|
2959
|
+
avsConfig,
|
|
2960
|
+
avsCheckProp,
|
|
2961
|
+
resolvedAccount.userId,
|
|
2962
|
+
resolvedAccount.email,
|
|
2963
|
+
resolvedAccount.firstName,
|
|
2964
|
+
resolvedAccount.lastName,
|
|
2965
|
+
resolvedAccount.country,
|
|
2966
|
+
fullName,
|
|
2967
|
+
onComplete,
|
|
2968
|
+
onError,
|
|
2969
|
+
updateError,
|
|
2970
|
+
emitDecline
|
|
2971
|
+
]);
|
|
2661
2972
|
const directPaypalConfigured = !!directPaypal?.clientId;
|
|
2662
2973
|
const hasEnabledMethodsPayload = Array.isArray(enabledPaymentMethods);
|
|
2663
2974
|
const hasEnabledMethods = hasEnabledMethodsPayload && enabledPaymentMethods.length > 0;
|
|
@@ -2681,17 +2992,18 @@ function SplitCardFormInner({
|
|
|
2681
2992
|
}, [showApplePay, showGooglePay]);
|
|
2682
2993
|
const walletExpressMethods = hasEnabledMethodsPayload ? expressMethodsForWalletRow : legacyExpressMethods;
|
|
2683
2994
|
const showWallets = showStripe && walletExpressMethods.length > 0;
|
|
2684
|
-
const
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
)
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2995
|
+
const apmCountry = enableAVS ? selectedCountry : countryProp;
|
|
2996
|
+
const paymentElementMethodsForCurrency = useMemo3(() => {
|
|
2997
|
+
const target = apmCountry?.trim().toUpperCase();
|
|
2998
|
+
if (!target) return paymentElementMethods;
|
|
2999
|
+
if (!enabledPaymentMethodCountries) {
|
|
3000
|
+
return filterStripeMethodsByCountry(paymentElementMethods, apmCountry);
|
|
3001
|
+
}
|
|
3002
|
+
return paymentElementMethods.filter((method) => {
|
|
3003
|
+
const allowed = enabledPaymentMethodCountries[method];
|
|
3004
|
+
return !allowed || allowed.length === 0 || allowed.includes(target);
|
|
3005
|
+
});
|
|
3006
|
+
}, [paymentElementMethods, apmCountry, enabledPaymentMethodCountries]);
|
|
2695
3007
|
const paymentElementBaseOptions = useMemo3(() => ({
|
|
2696
3008
|
mode: "payment",
|
|
2697
3009
|
amount: amountInCents,
|
|
@@ -2704,7 +3016,7 @@ function SplitCardFormInner({
|
|
|
2704
3016
|
const [paymentElementLoadState, setPaymentElementLoadState] = useState3("loading");
|
|
2705
3017
|
const [directPaypalReady, setDirectPaypalReady] = useState3(false);
|
|
2706
3018
|
const [inAppBrowserDetected, setInAppBrowserDetected] = useState3();
|
|
2707
|
-
|
|
3019
|
+
useEffect5(() => {
|
|
2708
3020
|
setInAppBrowserDetected(isInAppBrowser());
|
|
2709
3021
|
}, []);
|
|
2710
3022
|
const shouldShowPayPal = showPayPal && (directPaypalConfigured || (hasEnabledMethodsPayload ? paypalEnabled : inAppBrowserDetected === false));
|
|
@@ -2716,8 +3028,8 @@ function SplitCardFormInner({
|
|
|
2716
3028
|
const shouldDisplayPayPalRow = shouldRenderDirectPayPal ? directPaypalReady : shouldRenderStripePayPal && isExpressCheckoutRowVisible(paypalLoadState);
|
|
2717
3029
|
const shouldDisplayWalletRow = shouldRenderWallets && isExpressCheckoutRowVisible(walletLoadState);
|
|
2718
3030
|
const shouldDisplayPaymentElementRow = shouldRenderPaymentElement && paymentElementLoadState !== "load_error";
|
|
2719
|
-
const validationFiredRef =
|
|
2720
|
-
|
|
3031
|
+
const validationFiredRef = useRef4(false);
|
|
3032
|
+
useEffect5(() => {
|
|
2721
3033
|
if (validationFiredRef.current) return;
|
|
2722
3034
|
if (!showStripe && !showPayPal) {
|
|
2723
3035
|
validationFiredRef.current = true;
|
|
@@ -2737,8 +3049,8 @@ function SplitCardFormInner({
|
|
|
2737
3049
|
updateError(err.message);
|
|
2738
3050
|
}
|
|
2739
3051
|
}, [showStripe, showPayPal, directPaypalConfigured, paypalStripeInstance, onError, updateError]);
|
|
2740
|
-
const deprecationLoggedRef =
|
|
2741
|
-
|
|
3052
|
+
const deprecationLoggedRef = useRef4(false);
|
|
3053
|
+
useEffect5(() => {
|
|
2742
3054
|
if (deprecationLoggedRef.current) return;
|
|
2743
3055
|
if (!hasEnabledMethods) return;
|
|
2744
3056
|
const stale = [];
|
|
@@ -3064,8 +3376,8 @@ function SplitCardFormInner({
|
|
|
3064
3376
|
}
|
|
3065
3377
|
}
|
|
3066
3378
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
3067
|
-
const stripeResumeAttemptedRef =
|
|
3068
|
-
|
|
3379
|
+
const stripeResumeAttemptedRef = useRef4(false);
|
|
3380
|
+
useEffect5(() => {
|
|
3069
3381
|
if (typeof window === "undefined" || stripeResumeAttemptedRef.current) return;
|
|
3070
3382
|
const params = new URLSearchParams(window.location.search);
|
|
3071
3383
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -3147,6 +3459,7 @@ function SplitCardFormInner({
|
|
|
3147
3459
|
async (e) => {
|
|
3148
3460
|
e.preventDefault();
|
|
3149
3461
|
if (!flopay || !elements || isSubmitting || processingRef.current) return;
|
|
3462
|
+
if (vaultActive) return;
|
|
3150
3463
|
if (layout !== "buttons") {
|
|
3151
3464
|
onButtonClick?.("card");
|
|
3152
3465
|
}
|
|
@@ -3174,11 +3487,13 @@ function SplitCardFormInner({
|
|
|
3174
3487
|
return;
|
|
3175
3488
|
}
|
|
3176
3489
|
}
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3490
|
+
if (!vaultActive) {
|
|
3491
|
+
const submitResult = await flopay.submitElements();
|
|
3492
|
+
if (submitResult.error) {
|
|
3493
|
+
updateError(submitResult.error.message);
|
|
3494
|
+
onError?.(submitResult.error);
|
|
3495
|
+
return;
|
|
3496
|
+
}
|
|
3182
3497
|
}
|
|
3183
3498
|
const billingAddress = {};
|
|
3184
3499
|
const cc = selectedCountryRef.current;
|
|
@@ -3203,75 +3518,77 @@ function SplitCardFormInner({
|
|
|
3203
3518
|
...fullName.trim() ? { name: fullName.trim() } : {},
|
|
3204
3519
|
...Object.keys(billingAddress).length > 0 ? { address: billingAddress } : {}
|
|
3205
3520
|
};
|
|
3206
|
-
const pmResult = await flopay.createPaymentMethod(billingDetails);
|
|
3207
|
-
if (pmResult.error || !pmResult.paymentMethodId) {
|
|
3208
|
-
updateError(pmResult.error?.message ?? "Failed to create payment method.");
|
|
3209
|
-
return;
|
|
3210
|
-
}
|
|
3211
3521
|
if (!sessionId || !resolvedAccount.email) {
|
|
3212
3522
|
throw new FloPayError3("Missing sessionId or email", "validation_error");
|
|
3213
3523
|
}
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3524
|
+
{
|
|
3525
|
+
const pmResult = await flopay.createPaymentMethod(billingDetails);
|
|
3526
|
+
if (pmResult.error || !pmResult.paymentMethodId) {
|
|
3527
|
+
updateError(pmResult.error?.message ?? "Failed to create payment method.");
|
|
3528
|
+
return;
|
|
3529
|
+
}
|
|
3530
|
+
const intentHeaders = { "Content-Type": "application/json" };
|
|
3531
|
+
if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
|
|
3532
|
+
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
3533
|
+
method: "POST",
|
|
3534
|
+
headers: intentHeaders,
|
|
3535
|
+
body: JSON.stringify({
|
|
3536
|
+
sessionId,
|
|
3537
|
+
email: resolvedAccount.email,
|
|
3538
|
+
paymentMethodType: pmResult.paymentMethodId,
|
|
3539
|
+
isPaypal: false
|
|
3540
|
+
})
|
|
3541
|
+
});
|
|
3542
|
+
if (!intentResponse.ok) {
|
|
3543
|
+
const intentError = await buildFloPayApiErrorFromResponse(
|
|
3544
|
+
intentResponse,
|
|
3545
|
+
"Failed to create payment intent"
|
|
3546
|
+
);
|
|
3547
|
+
setOverlayStatus("error");
|
|
3548
|
+
updateError(intentError.message);
|
|
3549
|
+
onError?.(intentError);
|
|
3550
|
+
emitDecline("card", intentError);
|
|
3551
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
3552
|
+
return;
|
|
3553
|
+
}
|
|
3554
|
+
const intentJson = await intentResponse.json();
|
|
3555
|
+
const intentClientSecret = intentJson.data?.id;
|
|
3556
|
+
if (!intentClientSecret) throw new FloPayError3("No client_secret in payment intent response", "api_error");
|
|
3557
|
+
const confirmResult = await flopay.confirmCardPayment({
|
|
3558
|
+
clientSecret: intentClientSecret,
|
|
3559
|
+
paymentMethodId: pmResult.paymentMethodId
|
|
3560
|
+
});
|
|
3561
|
+
if (confirmResult.error) {
|
|
3562
|
+
setOverlayStatus("error");
|
|
3563
|
+
updateError(confirmResult.error.message);
|
|
3564
|
+
onError?.(confirmResult.error);
|
|
3565
|
+
emitDecline("card", confirmResult.error);
|
|
3566
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
3567
|
+
return;
|
|
3568
|
+
}
|
|
3569
|
+
const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
|
|
3570
|
+
const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
|
|
3571
|
+
rawProvider,
|
|
3572
|
+
intentClientSecret
|
|
3230
3573
|
);
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
onError?.(confirmResult.error);
|
|
3249
|
-
emitDecline("card", confirmResult.error);
|
|
3250
|
-
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
3251
|
-
return;
|
|
3252
|
-
}
|
|
3253
|
-
const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
|
|
3254
|
-
const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
|
|
3255
|
-
rawProvider,
|
|
3256
|
-
intentClientSecret
|
|
3257
|
-
);
|
|
3258
|
-
const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
|
|
3259
|
-
const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
|
|
3260
|
-
if (!paymentIntentId) {
|
|
3261
|
-
const error2 = new FloPayError3("No payment intent returned after confirmation.", "api_error");
|
|
3262
|
-
setOverlayStatus("error");
|
|
3263
|
-
updateError(error2.message);
|
|
3264
|
-
onError?.(error2);
|
|
3265
|
-
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
3266
|
-
return;
|
|
3574
|
+
const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
|
|
3575
|
+
const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
|
|
3576
|
+
if (!paymentIntentId) {
|
|
3577
|
+
const error2 = new FloPayError3("No payment intent returned after confirmation.", "api_error");
|
|
3578
|
+
setOverlayStatus("error");
|
|
3579
|
+
updateError(error2.message);
|
|
3580
|
+
onError?.(error2);
|
|
3581
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
3582
|
+
return;
|
|
3583
|
+
}
|
|
3584
|
+
handedOff = isSelfContained;
|
|
3585
|
+
dispatchTokenizedBody({
|
|
3586
|
+
id: paymentMethodId,
|
|
3587
|
+
type: "card",
|
|
3588
|
+
threeDSecureActionResultTokenId: paymentIntentId,
|
|
3589
|
+
originalPaymentMethodId: pmResult.paymentMethodId
|
|
3590
|
+
});
|
|
3267
3591
|
}
|
|
3268
|
-
handedOff = isSelfContained;
|
|
3269
|
-
dispatchTokenizedBody({
|
|
3270
|
-
id: paymentMethodId,
|
|
3271
|
-
type: "card",
|
|
3272
|
-
threeDSecureActionResultTokenId: paymentIntentId,
|
|
3273
|
-
originalPaymentMethodId: pmResult.paymentMethodId
|
|
3274
|
-
});
|
|
3275
3592
|
} catch (err) {
|
|
3276
3593
|
setOverlayStatus("error");
|
|
3277
3594
|
updateError(err instanceof Error ? err.message : "An unexpected error occurred");
|
|
@@ -3283,11 +3600,11 @@ function SplitCardFormInner({
|
|
|
3283
3600
|
}
|
|
3284
3601
|
}
|
|
3285
3602
|
},
|
|
3286
|
-
[flopay, elements, isSubmitting, sessionId, nonce, resolvedAccount.email, baseUrl, isSelfContained, dispatchTokenizedBody, onButtonClick, onError, updateError, emitDecline, layout]
|
|
3603
|
+
[flopay, elements, isSubmitting, sessionId, nonce, resolvedAccount.email, baseUrl, isSelfContained, vaultActive, dispatchTokenizedBody, onButtonClick, onError, updateError, emitDecline, layout]
|
|
3287
3604
|
);
|
|
3288
|
-
const isReady = flopay !== null && elements !== null;
|
|
3605
|
+
const isReady = flopay !== null && (vaultActive || elements !== null);
|
|
3289
3606
|
if (!isReady) {
|
|
3290
|
-
return /* @__PURE__ */
|
|
3607
|
+
return /* @__PURE__ */ jsx7("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
|
|
3291
3608
|
}
|
|
3292
3609
|
const isButtons = layout === "buttons";
|
|
3293
3610
|
const appearanceVars = appearance?.variables;
|
|
@@ -3295,6 +3612,8 @@ function SplitCardFormInner({
|
|
|
3295
3612
|
const appearanceColorBg = appearanceVars?.colorBackground;
|
|
3296
3613
|
const themedWrapperBg = appearanceColorBg && !SDK_DEFAULT_WHITES.has(appearanceColorBg) ? appearanceColorBg : void 0;
|
|
3297
3614
|
const resolvedBorder = bStyles.cardInputBorder ?? (isButtons ? "#e5e7eb" : "#A4A4FF");
|
|
3615
|
+
const resolvedDangerColor = appearanceVars?.colorDanger ?? "#dc2626";
|
|
3616
|
+
const avsBorderColor = (fieldInvalid) => hasAttemptedSubmit && fieldInvalid ? resolvedDangerColor : resolvedBorder;
|
|
3298
3617
|
const cardBg = bStyles.cardFormContainer?.backgroundColor ?? themedWrapperBg ?? (isButtons ? "white" : "#EDEDFF");
|
|
3299
3618
|
const cardInputBg = bStyles.cardInputBackground ?? appearanceVars?.colorBackground ?? "white";
|
|
3300
3619
|
const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
|
|
@@ -3306,7 +3625,9 @@ function SplitCardFormInner({
|
|
|
3306
3625
|
const resolvedInputColor = bStyles.cardInputColor ?? (typeof nameInputOverrides?.color === "string" ? nameInputOverrides.color : void 0) ?? appearanceVars?.colorText ?? "#262833";
|
|
3307
3626
|
const resolvedPlaceholderColor = bStyles.cardInputPlaceholderColor ?? "#9ca3af";
|
|
3308
3627
|
const resolvedBorderRadius = appearanceVars?.borderRadius ?? "8px";
|
|
3628
|
+
const buttonBorderRadius = appearanceVars?.borderRadius ?? bStyles.cardButton?.borderRadius ?? resolvedBorderRadius;
|
|
3309
3629
|
const resolvedPrimaryColor = appearanceVars?.colorPrimary ?? "#4A49FF";
|
|
3630
|
+
const resolvedPrimaryHoverColor = appearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
|
|
3310
3631
|
const resolvedTitleColor = appearanceVars?.colorText ?? "#262833";
|
|
3311
3632
|
const sharedInputTypography = {
|
|
3312
3633
|
fontSize: resolvedInputFontSize,
|
|
@@ -3340,14 +3661,73 @@ function SplitCardFormInner({
|
|
|
3340
3661
|
const containerOverrides = bStyles.cardFormContainer ?? {};
|
|
3341
3662
|
const containerPadding = containerOverrides.padding ?? (isButtons ? "0" : "1rem");
|
|
3342
3663
|
const containerRadius = containerOverrides.borderRadius ?? resolvedBorderRadius;
|
|
3664
|
+
const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */ jsx7(
|
|
3665
|
+
VaultCardFields,
|
|
3666
|
+
{
|
|
3667
|
+
capture: cardCapture,
|
|
3668
|
+
html: vaultMount.html,
|
|
3669
|
+
messageToken: vaultMount.messageToken,
|
|
3670
|
+
expectedOrigin: vaultMount.expectedOrigin,
|
|
3671
|
+
theme: vaultThemeColors,
|
|
3672
|
+
onReady: () => {
|
|
3673
|
+
setFormReady(true);
|
|
3674
|
+
if (!avsConfig || typeof document === "undefined") return;
|
|
3675
|
+
const focusFirstAvs = () => {
|
|
3676
|
+
const block = document.querySelector('[data-testid="flopay-avs-fields"]');
|
|
3677
|
+
const first = block?.querySelector(
|
|
3678
|
+
"input:not([disabled]), select:not([disabled])"
|
|
3679
|
+
);
|
|
3680
|
+
first?.focus();
|
|
3681
|
+
};
|
|
3682
|
+
focusFirstAvs();
|
|
3683
|
+
let tries = 0;
|
|
3684
|
+
const timer = window.setInterval(() => {
|
|
3685
|
+
tries += 1;
|
|
3686
|
+
const active = document.activeElement;
|
|
3687
|
+
const onIframe = !!active && active.tagName === "IFRAME" && active.id === "flopay_vault_form_iframe";
|
|
3688
|
+
if (onIframe) {
|
|
3689
|
+
focusFirstAvs();
|
|
3690
|
+
window.clearInterval(timer);
|
|
3691
|
+
} else if (tries >= 50) {
|
|
3692
|
+
window.clearInterval(timer);
|
|
3693
|
+
}
|
|
3694
|
+
}, 100);
|
|
3695
|
+
},
|
|
3696
|
+
onError: (message) => updateError(message),
|
|
3697
|
+
onValidation: (message) => {
|
|
3698
|
+
updateError(message);
|
|
3699
|
+
if (message) setOverlayStatus(null);
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3702
|
+
) : /* @__PURE__ */ jsx7(
|
|
3703
|
+
"div",
|
|
3704
|
+
{
|
|
3705
|
+
"data-testid": "flopay-vault-loading",
|
|
3706
|
+
style: {
|
|
3707
|
+
minHeight: 120,
|
|
3708
|
+
display: "flex",
|
|
3709
|
+
alignItems: "center",
|
|
3710
|
+
justifyContent: "center",
|
|
3711
|
+
color: "#6b7280",
|
|
3712
|
+
fontSize: 14
|
|
3713
|
+
},
|
|
3714
|
+
children: "Loading secure card form\u2026"
|
|
3715
|
+
}
|
|
3716
|
+
);
|
|
3343
3717
|
const cardFormBlock = /* @__PURE__ */ jsxs4("div", { style: {
|
|
3344
3718
|
backgroundColor: cardBg,
|
|
3345
3719
|
borderRadius: containerRadius,
|
|
3346
3720
|
...containerOverrides,
|
|
3347
3721
|
padding: containerPadding,
|
|
3348
|
-
...sharedInputPlaceholderVars
|
|
3722
|
+
...sharedInputPlaceholderVars,
|
|
3723
|
+
// Flex column (BOTH layouts, so default and buttons>card never diverge) so
|
|
3724
|
+
// AVS can be ordered above the vault widget — its submit lives inside the
|
|
3725
|
+
// iframe, so AVS can't sit between fields and button; it goes above the
|
|
3726
|
+
// card form instead of after the button.
|
|
3727
|
+
display: "flex",
|
|
3728
|
+
flexDirection: "column"
|
|
3349
3729
|
}, children: [
|
|
3350
|
-
/* @__PURE__ */
|
|
3730
|
+
/* @__PURE__ */ jsx7("style", { children: `
|
|
3351
3731
|
.flopay-shared-input::placeholder {
|
|
3352
3732
|
color: var(--flopay-input-placeholder-color);
|
|
3353
3733
|
opacity: 1;
|
|
@@ -3359,7 +3739,9 @@ function SplitCardFormInner({
|
|
|
3359
3739
|
isButtons && showCardForm && /* @__PURE__ */ jsxs4("div", { style: {
|
|
3360
3740
|
display: "flex",
|
|
3361
3741
|
alignItems: "center",
|
|
3362
|
-
padding: "0.75rem 0 0.625rem"
|
|
3742
|
+
padding: "0.75rem 0 0.625rem",
|
|
3743
|
+
// Keep the header on top when AVS is ordered above the card on vault.
|
|
3744
|
+
order: vaultActive ? -2 : 0
|
|
3363
3745
|
}, children: [
|
|
3364
3746
|
/* @__PURE__ */ jsxs4(
|
|
3365
3747
|
"button",
|
|
@@ -3383,7 +3765,7 @@ function SplitCardFormInner({
|
|
|
3383
3765
|
},
|
|
3384
3766
|
"aria-label": "Back to payment methods",
|
|
3385
3767
|
children: [
|
|
3386
|
-
/* @__PURE__ */
|
|
3768
|
+
/* @__PURE__ */ jsx7("span", { style: {
|
|
3387
3769
|
display: "inline-flex",
|
|
3388
3770
|
alignItems: "center",
|
|
3389
3771
|
justifyContent: "center",
|
|
@@ -3393,12 +3775,12 @@ function SplitCardFormInner({
|
|
|
3393
3775
|
backgroundColor: "#f3f4f6",
|
|
3394
3776
|
transition: "background-color 0.15s",
|
|
3395
3777
|
...bStyles.backButtonIcon
|
|
3396
|
-
}, children: /* @__PURE__ */
|
|
3397
|
-
/* @__PURE__ */
|
|
3778
|
+
}, 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" }) }) }),
|
|
3779
|
+
/* @__PURE__ */ jsx7(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
3398
3780
|
]
|
|
3399
3781
|
}
|
|
3400
3782
|
),
|
|
3401
|
-
hideTitle ? /* @__PURE__ */
|
|
3783
|
+
hideTitle ? /* @__PURE__ */ jsx7("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx7("div", { style: {
|
|
3402
3784
|
flex: 1,
|
|
3403
3785
|
textAlign: "center",
|
|
3404
3786
|
fontWeight: 600,
|
|
@@ -3406,58 +3788,65 @@ function SplitCardFormInner({
|
|
|
3406
3788
|
color: "#262833",
|
|
3407
3789
|
paddingRight: 80,
|
|
3408
3790
|
...bStyles.title
|
|
3409
|
-
}, children: /* @__PURE__ */
|
|
3791
|
+
}, children: /* @__PURE__ */ jsx7(TitleContentSlot, { content: cardTitleContent }) })
|
|
3410
3792
|
] }),
|
|
3411
|
-
!isButtons && !hideTitle && /* @__PURE__ */
|
|
3793
|
+
!isButtons && !hideTitle && /* @__PURE__ */ jsx7("div", { style: {
|
|
3412
3794
|
textAlign: "center",
|
|
3413
3795
|
fontWeight: 600,
|
|
3414
3796
|
fontSize: "1.1rem",
|
|
3415
3797
|
padding: "0.5rem 0",
|
|
3416
3798
|
color: resolvedTitleColor,
|
|
3799
|
+
// Keep the title at the very top on the vault path. The card-form slot
|
|
3800
|
+
// (-2) and AVS block (-1) are ordered below it but above the card form.
|
|
3801
|
+
order: vaultActive ? -3 : 0,
|
|
3417
3802
|
...bStyles.title
|
|
3418
|
-
}, children: /* @__PURE__ */
|
|
3419
|
-
/* @__PURE__ */
|
|
3420
|
-
|
|
3421
|
-
border: `1px solid ${resolvedBorder}`,
|
|
3422
|
-
borderTopLeftRadius: "8px",
|
|
3423
|
-
borderTopRightRadius: "8px",
|
|
3424
|
-
padding: "10px"
|
|
3425
|
-
}, children: /* @__PURE__ */ jsx6(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
|
|
3426
|
-
/* @__PURE__ */ jsxs4("div", { style: { display: "flex" }, children: [
|
|
3427
|
-
/* @__PURE__ */ jsx6("div", { style: {
|
|
3428
|
-
flex: 1,
|
|
3429
|
-
backgroundColor: cardInputBg,
|
|
3430
|
-
// Longhand only — mixing `border` shorthand with per-side
|
|
3431
|
-
// overrides triggers React's "shorthand vs longhand" warning
|
|
3432
|
-
// because render order isn't deterministic.
|
|
3433
|
-
borderTop: "none",
|
|
3434
|
-
borderRight: "none",
|
|
3435
|
-
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3436
|
-
borderLeft: `1px solid ${resolvedBorder}`,
|
|
3437
|
-
borderBottomLeftRadius: "8px",
|
|
3438
|
-
padding: "10px"
|
|
3439
|
-
}, children: /* @__PURE__ */ jsx6(CardExpiryElement, { options: stripeElementStyle }) }),
|
|
3440
|
-
/* @__PURE__ */ jsx6("div", { style: {
|
|
3441
|
-
flex: 1,
|
|
3803
|
+
}, children: /* @__PURE__ */ jsx7(TitleContentSlot, { content: cardTitleContent }) }),
|
|
3804
|
+
!vaultActive && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
3805
|
+
/* @__PURE__ */ jsx7("div", { style: {
|
|
3442
3806
|
backgroundColor: cardInputBg,
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
borderLeft: `1px solid ${resolvedBorder}`,
|
|
3447
|
-
borderBottomRightRadius: "8px",
|
|
3807
|
+
border: `1px solid ${resolvedBorder}`,
|
|
3808
|
+
borderTopLeftRadius: resolvedBorderRadius,
|
|
3809
|
+
borderTopRightRadius: resolvedBorderRadius,
|
|
3448
3810
|
padding: "10px"
|
|
3449
|
-
}, children: /* @__PURE__ */
|
|
3811
|
+
}, children: /* @__PURE__ */ jsx7(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
|
|
3812
|
+
/* @__PURE__ */ jsxs4("div", { style: { display: "flex" }, children: [
|
|
3813
|
+
/* @__PURE__ */ jsx7("div", { style: {
|
|
3814
|
+
flex: 1,
|
|
3815
|
+
backgroundColor: cardInputBg,
|
|
3816
|
+
// Longhand only — mixing `border` shorthand with per-side
|
|
3817
|
+
// overrides triggers React's "shorthand vs longhand" warning
|
|
3818
|
+
// because render order isn't deterministic.
|
|
3819
|
+
borderTop: "none",
|
|
3820
|
+
borderRight: "none",
|
|
3821
|
+
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3822
|
+
borderLeft: `1px solid ${resolvedBorder}`,
|
|
3823
|
+
borderBottomLeftRadius: resolvedBorderRadius,
|
|
3824
|
+
padding: "10px"
|
|
3825
|
+
}, children: /* @__PURE__ */ jsx7(CardExpiryElement, { options: stripeElementStyle }) }),
|
|
3826
|
+
/* @__PURE__ */ jsx7("div", { style: {
|
|
3827
|
+
flex: 1,
|
|
3828
|
+
backgroundColor: cardInputBg,
|
|
3829
|
+
borderTop: "none",
|
|
3830
|
+
borderRight: `1px solid ${resolvedBorder}`,
|
|
3831
|
+
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3832
|
+
borderLeft: `1px solid ${resolvedBorder}`,
|
|
3833
|
+
borderBottomRightRadius: resolvedBorderRadius,
|
|
3834
|
+
padding: "10px"
|
|
3835
|
+
}, children: /* @__PURE__ */ jsx7(CardCvcElement, { options: stripeElementStyle }) })
|
|
3836
|
+
] })
|
|
3450
3837
|
] }),
|
|
3451
|
-
/* @__PURE__ */
|
|
3838
|
+
!vaultActive && /* @__PURE__ */ jsx7("div", { style: {
|
|
3452
3839
|
backgroundColor: cardInputBg,
|
|
3453
3840
|
border: `1px solid ${resolvedBorder}`,
|
|
3454
|
-
borderRadius:
|
|
3841
|
+
borderRadius: resolvedBorderRadius,
|
|
3455
3842
|
marginTop: "0.5rem",
|
|
3456
3843
|
padding: "10px"
|
|
3457
|
-
}, children: /* @__PURE__ */
|
|
3844
|
+
}, children: /* @__PURE__ */ jsx7(
|
|
3458
3845
|
"input",
|
|
3459
3846
|
{
|
|
3460
3847
|
className: "flopay-shared-input",
|
|
3848
|
+
id: "flopay-cc-name",
|
|
3849
|
+
name: "cc-name",
|
|
3461
3850
|
placeholder: "Full Name on Card",
|
|
3462
3851
|
autoComplete: "cc-name",
|
|
3463
3852
|
value: fullName,
|
|
@@ -3474,32 +3863,32 @@ function SplitCardFormInner({
|
|
|
3474
3863
|
}
|
|
3475
3864
|
}
|
|
3476
3865
|
) }),
|
|
3477
|
-
avsConfig && (() => {
|
|
3866
|
+
avsConfig && /* @__PURE__ */ jsx7("div", { style: { order: vaultActive ? -1 : 0 }, "data-testid": "flopay-avs-fields", children: (() => {
|
|
3478
3867
|
const cc = selectedCountry;
|
|
3479
|
-
const inputWrapStyle = (
|
|
3868
|
+
const inputWrapStyle = (invalid = false) => ({
|
|
3480
3869
|
backgroundColor: cardInputBg,
|
|
3481
|
-
border: `1px solid ${
|
|
3482
|
-
borderRadius:
|
|
3870
|
+
border: `1px solid ${avsBorderColor(invalid)}`,
|
|
3871
|
+
borderRadius: resolvedBorderRadius,
|
|
3483
3872
|
marginTop: "0.5rem",
|
|
3484
|
-
padding: "10px"
|
|
3485
|
-
...isButtons && extraStyle ? extraStyle : {}
|
|
3873
|
+
padding: "10px"
|
|
3486
3874
|
});
|
|
3487
3875
|
const inputFieldStyle = () => ({
|
|
3488
3876
|
width: "100%",
|
|
3489
3877
|
border: "none",
|
|
3490
3878
|
outline: "none",
|
|
3491
3879
|
background: "transparent",
|
|
3492
|
-
...sharedInputTypography
|
|
3493
|
-
...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
|
|
3880
|
+
...sharedInputTypography
|
|
3494
3881
|
});
|
|
3495
3882
|
const stateOpts = getStateOptions(cc);
|
|
3496
3883
|
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
3497
|
-
isAVSFieldVisible(avsConfig.address_line_1, cc) && /* @__PURE__ */
|
|
3884
|
+
isAVSFieldVisible(avsConfig.address_line_1, cc) && /* @__PURE__ */ jsx7("div", { style: inputWrapStyle(invalidAvsFields.line1), children: /* @__PURE__ */ jsx7(
|
|
3498
3885
|
"input",
|
|
3499
3886
|
{
|
|
3500
3887
|
className: "flopay-shared-input",
|
|
3888
|
+
id: "flopay-billing-address-line1",
|
|
3889
|
+
name: "billing-address-line1",
|
|
3501
3890
|
placeholder: "Street Address (e.g. 123 Main St)",
|
|
3502
|
-
autoComplete: "address-line1",
|
|
3891
|
+
autoComplete: "billing address-line1",
|
|
3503
3892
|
value: addressLine1,
|
|
3504
3893
|
onChange: (e) => {
|
|
3505
3894
|
addressLine1Ref.current = e.target.value;
|
|
@@ -3511,12 +3900,14 @@ function SplitCardFormInner({
|
|
|
3511
3900
|
style: inputFieldStyle()
|
|
3512
3901
|
}
|
|
3513
3902
|
) }),
|
|
3514
|
-
isAVSFieldVisible(avsConfig.address_line_2, cc) && /* @__PURE__ */
|
|
3903
|
+
isAVSFieldVisible(avsConfig.address_line_2, cc) && /* @__PURE__ */ jsx7("div", { style: inputWrapStyle(), children: /* @__PURE__ */ jsx7(
|
|
3515
3904
|
"input",
|
|
3516
3905
|
{
|
|
3517
3906
|
className: "flopay-shared-input",
|
|
3907
|
+
id: "flopay-billing-address-line2",
|
|
3908
|
+
name: "billing-address-line2",
|
|
3518
3909
|
placeholder: "Apt, Suite, Unit (optional)",
|
|
3519
|
-
autoComplete: "address-line2",
|
|
3910
|
+
autoComplete: "billing address-line2",
|
|
3520
3911
|
value: addressLine2,
|
|
3521
3912
|
onChange: (e) => {
|
|
3522
3913
|
addressLine2Ref.current = e.target.value;
|
|
@@ -3532,24 +3923,25 @@ function SplitCardFormInner({
|
|
|
3532
3923
|
gap: "0",
|
|
3533
3924
|
marginTop: "0.5rem"
|
|
3534
3925
|
}, children: [
|
|
3535
|
-
isAVSFieldVisible(avsConfig.city, cc) && /* @__PURE__ */
|
|
3926
|
+
isAVSFieldVisible(avsConfig.city, cc) && /* @__PURE__ */ jsx7("div", { style: {
|
|
3536
3927
|
flex: 1,
|
|
3537
3928
|
backgroundColor: cardInputBg,
|
|
3538
|
-
borderTop: `1px solid ${
|
|
3539
|
-
borderRight: `1px solid ${
|
|
3540
|
-
borderBottom: `1px solid ${
|
|
3541
|
-
borderLeft: `1px solid ${
|
|
3929
|
+
borderTop: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
|
|
3930
|
+
borderRight: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
|
|
3931
|
+
borderBottom: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
|
|
3932
|
+
borderLeft: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
|
|
3542
3933
|
padding: "10px",
|
|
3543
|
-
borderTopLeftRadius:
|
|
3544
|
-
borderBottomLeftRadius:
|
|
3545
|
-
...isAVSFieldVisible(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius:
|
|
3546
|
-
|
|
3547
|
-
}, children: /* @__PURE__ */ jsx6(
|
|
3934
|
+
borderTopLeftRadius: resolvedBorderRadius,
|
|
3935
|
+
borderBottomLeftRadius: resolvedBorderRadius,
|
|
3936
|
+
...isAVSFieldVisible(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: resolvedBorderRadius }
|
|
3937
|
+
}, children: /* @__PURE__ */ jsx7(
|
|
3548
3938
|
"input",
|
|
3549
3939
|
{
|
|
3550
3940
|
className: "flopay-shared-input",
|
|
3941
|
+
id: "flopay-billing-city",
|
|
3942
|
+
name: "billing-city",
|
|
3551
3943
|
placeholder: "City",
|
|
3552
|
-
autoComplete: "address-level2",
|
|
3944
|
+
autoComplete: "billing address-level2",
|
|
3553
3945
|
value: city,
|
|
3554
3946
|
onChange: (e) => {
|
|
3555
3947
|
cityRef.current = e.target.value;
|
|
@@ -3561,39 +3953,42 @@ function SplitCardFormInner({
|
|
|
3561
3953
|
style: inputFieldStyle()
|
|
3562
3954
|
}
|
|
3563
3955
|
) }),
|
|
3564
|
-
isAVSFieldVisible(avsConfig.state, cc) && /* @__PURE__ */
|
|
3956
|
+
isAVSFieldVisible(avsConfig.state, cc) && /* @__PURE__ */ jsx7("div", { style: {
|
|
3565
3957
|
flex: 1,
|
|
3566
3958
|
backgroundColor: cardInputBg,
|
|
3567
|
-
border: `1px solid ${
|
|
3959
|
+
border: `1px solid ${avsBorderColor(invalidAvsFields.state)}`,
|
|
3568
3960
|
padding: "10px",
|
|
3569
|
-
borderTopRightRadius:
|
|
3570
|
-
borderBottomRightRadius:
|
|
3571
|
-
...isAVSFieldVisible(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius:
|
|
3572
|
-
...isButtons && bStyles.stateInput ? bStyles.stateInput : {}
|
|
3961
|
+
borderTopRightRadius: resolvedBorderRadius,
|
|
3962
|
+
borderBottomRightRadius: resolvedBorderRadius,
|
|
3963
|
+
...isAVSFieldVisible(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: resolvedBorderRadius }
|
|
3573
3964
|
}, children: stateOpts ? /* @__PURE__ */ jsxs4(
|
|
3574
3965
|
"select",
|
|
3575
3966
|
{
|
|
3967
|
+
id: "flopay-billing-state",
|
|
3968
|
+
name: "billing-state",
|
|
3576
3969
|
value: stateValue,
|
|
3577
3970
|
onChange: (e) => {
|
|
3578
3971
|
stateRef.current = e.target.value;
|
|
3579
3972
|
setStateValue(e.target.value);
|
|
3580
3973
|
},
|
|
3581
3974
|
disabled: isSubmitting,
|
|
3582
|
-
autoComplete: "address-level1",
|
|
3975
|
+
autoComplete: "billing address-level1",
|
|
3583
3976
|
required: true,
|
|
3584
3977
|
"data-testid": "flopay-state",
|
|
3585
3978
|
style: { ...inputFieldStyle(), cursor: "pointer" },
|
|
3586
3979
|
children: [
|
|
3587
|
-
/* @__PURE__ */
|
|
3588
|
-
stateOpts.map((s) => /* @__PURE__ */
|
|
3980
|
+
/* @__PURE__ */ jsx7("option", { value: "", children: getStateLabel(cc) }),
|
|
3981
|
+
stateOpts.map((s) => /* @__PURE__ */ jsx7("option", { value: s.code, children: s.name }, s.code))
|
|
3589
3982
|
]
|
|
3590
3983
|
}
|
|
3591
|
-
) : /* @__PURE__ */
|
|
3984
|
+
) : /* @__PURE__ */ jsx7(
|
|
3592
3985
|
"input",
|
|
3593
3986
|
{
|
|
3594
3987
|
className: "flopay-shared-input",
|
|
3988
|
+
id: "flopay-billing-state",
|
|
3989
|
+
name: "billing-state",
|
|
3595
3990
|
placeholder: getStateLabel(cc),
|
|
3596
|
-
autoComplete: "address-level1",
|
|
3991
|
+
autoComplete: "billing address-level1",
|
|
3597
3992
|
value: stateValue,
|
|
3598
3993
|
onChange: (e) => {
|
|
3599
3994
|
stateRef.current = e.target.value;
|
|
@@ -3612,7 +4007,7 @@ function SplitCardFormInner({
|
|
|
3612
4007
|
gap: avsLayoutProp === "column" ? "0.5rem" : "0",
|
|
3613
4008
|
marginTop: "0.5rem"
|
|
3614
4009
|
}, children: [
|
|
3615
|
-
isAVSFieldVisible(avsConfig.country, cc) && /* @__PURE__ */
|
|
4010
|
+
isAVSFieldVisible(avsConfig.country, cc) && /* @__PURE__ */ jsx7("div", { style: {
|
|
3616
4011
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
3617
4012
|
backgroundColor: cardInputBg,
|
|
3618
4013
|
borderTop: `1px solid ${resolvedBorder}`,
|
|
@@ -3620,11 +4015,12 @@ function SplitCardFormInner({
|
|
|
3620
4015
|
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3621
4016
|
borderLeft: `1px solid ${resolvedBorder}`,
|
|
3622
4017
|
padding: "10px",
|
|
3623
|
-
...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius:
|
|
3624
|
-
|
|
3625
|
-
}, children: /* @__PURE__ */ jsx6(
|
|
4018
|
+
...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: resolvedBorderRadius, borderBottomLeftRadius: resolvedBorderRadius, borderRight: "none" } : { borderRadius: resolvedBorderRadius }
|
|
4019
|
+
}, children: /* @__PURE__ */ jsx7(
|
|
3626
4020
|
"select",
|
|
3627
4021
|
{
|
|
4022
|
+
id: "flopay-billing-country",
|
|
4023
|
+
name: "billing-country",
|
|
3628
4024
|
value: selectedCountry,
|
|
3629
4025
|
onChange: (e) => {
|
|
3630
4026
|
selectedCountryRef.current = e.target.value;
|
|
@@ -3634,7 +4030,7 @@ function SplitCardFormInner({
|
|
|
3634
4030
|
setStateValue("");
|
|
3635
4031
|
},
|
|
3636
4032
|
disabled: isSubmitting,
|
|
3637
|
-
autoComplete: "country",
|
|
4033
|
+
autoComplete: "billing country",
|
|
3638
4034
|
"data-testid": "flopay-country",
|
|
3639
4035
|
style: { ...inputFieldStyle(), cursor: "pointer" },
|
|
3640
4036
|
children: COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ jsxs4("option", { value: c.code, children: [
|
|
@@ -3644,19 +4040,20 @@ function SplitCardFormInner({
|
|
|
3644
4040
|
] }, c.code))
|
|
3645
4041
|
}
|
|
3646
4042
|
) }),
|
|
3647
|
-
isAVSFieldVisible(avsConfig.postal_code, cc) && /* @__PURE__ */
|
|
4043
|
+
isAVSFieldVisible(avsConfig.postal_code, cc) && /* @__PURE__ */ jsx7("div", { style: {
|
|
3648
4044
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
3649
4045
|
backgroundColor: cardInputBg,
|
|
3650
|
-
border: `1px solid ${
|
|
4046
|
+
border: `1px solid ${avsBorderColor(invalidAvsFields.zip)}`,
|
|
3651
4047
|
padding: "10px",
|
|
3652
|
-
...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius:
|
|
3653
|
-
|
|
3654
|
-
}, children: /* @__PURE__ */ jsx6(
|
|
4048
|
+
...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: resolvedBorderRadius, borderBottomRightRadius: resolvedBorderRadius } : { borderRadius: resolvedBorderRadius }
|
|
4049
|
+
}, children: /* @__PURE__ */ jsx7(
|
|
3655
4050
|
"input",
|
|
3656
4051
|
{
|
|
3657
4052
|
className: "flopay-shared-input",
|
|
4053
|
+
id: "flopay-billing-postal-code",
|
|
4054
|
+
name: "billing-postal-code",
|
|
3658
4055
|
placeholder: getPostalCodeLabel(selectedCountry),
|
|
3659
|
-
autoComplete: "postal-code",
|
|
4056
|
+
autoComplete: "billing postal-code",
|
|
3660
4057
|
value: zipCode,
|
|
3661
4058
|
onChange: (e) => {
|
|
3662
4059
|
zipCodeRef.current = e.target.value;
|
|
@@ -3671,7 +4068,9 @@ function SplitCardFormInner({
|
|
|
3671
4068
|
) })
|
|
3672
4069
|
] })
|
|
3673
4070
|
] });
|
|
3674
|
-
})(),
|
|
4071
|
+
})() }),
|
|
4072
|
+
vaultActive && cardPreFormSlot && /* @__PURE__ */ jsx7("div", { style: { order: -2, width: "100%" }, children: cardPreFormSlot }),
|
|
4073
|
+
vaultActive && vaultCardFieldsNode,
|
|
3675
4074
|
displayError && /* @__PURE__ */ jsxs4("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
3676
4075
|
margin: "0.75rem 0",
|
|
3677
4076
|
padding: "0.625rem 0.875rem",
|
|
@@ -3686,15 +4085,21 @@ function SplitCardFormInner({
|
|
|
3686
4085
|
gap: "0.5rem",
|
|
3687
4086
|
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
3688
4087
|
}, children: [
|
|
3689
|
-
/* @__PURE__ */
|
|
4088
|
+
/* @__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" }) }),
|
|
3690
4089
|
displayError
|
|
3691
4090
|
] }),
|
|
3692
|
-
children ?? /* @__PURE__ */
|
|
4091
|
+
!vaultActive && (children ?? /* @__PURE__ */ jsx7(
|
|
3693
4092
|
"button",
|
|
3694
4093
|
{
|
|
3695
4094
|
type: "submit",
|
|
3696
4095
|
disabled: !formReady || isSubmitting,
|
|
3697
4096
|
"data-testid": "flopay-submit",
|
|
4097
|
+
onMouseEnter: (e) => {
|
|
4098
|
+
if (formReady && !isSubmitting) e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
|
|
4099
|
+
},
|
|
4100
|
+
onMouseLeave: (e) => {
|
|
4101
|
+
e.currentTarget.style.backgroundColor = bStyles.submitButton?.backgroundColor ?? resolvedPrimaryColor;
|
|
4102
|
+
},
|
|
3698
4103
|
style: {
|
|
3699
4104
|
width: "100%",
|
|
3700
4105
|
padding: "0.875rem",
|
|
@@ -3707,11 +4112,12 @@ function SplitCardFormInner({
|
|
|
3707
4112
|
fontWeight: 600,
|
|
3708
4113
|
cursor: !formReady || isSubmitting ? "not-allowed" : "pointer",
|
|
3709
4114
|
opacity: !formReady || isSubmitting ? 0.5 : 1,
|
|
4115
|
+
transition: "background-color 0.15s",
|
|
3710
4116
|
...bStyles.submitButton
|
|
3711
4117
|
},
|
|
3712
4118
|
children: isSubmitting ? "PROCESSING..." : submitLabel
|
|
3713
4119
|
}
|
|
3714
|
-
)
|
|
4120
|
+
))
|
|
3715
4121
|
] });
|
|
3716
4122
|
const gateDebugStyle = {
|
|
3717
4123
|
margin: 0,
|
|
@@ -3727,9 +4133,9 @@ function SplitCardFormInner({
|
|
|
3727
4133
|
const renderDirectPaypalGateDebug = (testId) => {
|
|
3728
4134
|
if (!debug) return null;
|
|
3729
4135
|
if (!showPayPal || !directPaypalConfigured) {
|
|
3730
|
-
return /* @__PURE__ */
|
|
4136
|
+
return /* @__PURE__ */ jsx7("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
|
|
3731
4137
|
}
|
|
3732
|
-
return /* @__PURE__ */
|
|
4138
|
+
return /* @__PURE__ */ jsx7("pre", { "data-testid": testId, style: gateDebugStyle, children: [
|
|
3733
4139
|
"FloPay/DirectPayPal-debug (parent gate)",
|
|
3734
4140
|
` showPayPal=${showPayPal}`,
|
|
3735
4141
|
` directPaypalConfigured=${directPaypalConfigured}`,
|
|
@@ -3742,9 +4148,9 @@ function SplitCardFormInner({
|
|
|
3742
4148
|
const renderStripeGateDebug = (testId) => {
|
|
3743
4149
|
if (!debug) return null;
|
|
3744
4150
|
if (!showStripe || !stripeInstance) {
|
|
3745
|
-
return /* @__PURE__ */
|
|
4151
|
+
return /* @__PURE__ */ jsx7("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
|
|
3746
4152
|
}
|
|
3747
|
-
return /* @__PURE__ */
|
|
4153
|
+
return /* @__PURE__ */ jsx7("pre", { "data-testid": testId, style: gateDebugStyle, children: [
|
|
3748
4154
|
"FloPay/Stripe-debug (parent gate)",
|
|
3749
4155
|
` showStripe=${showStripe}`,
|
|
3750
4156
|
` currency=${currency}`,
|
|
@@ -3774,8 +4180,8 @@ function SplitCardFormInner({
|
|
|
3774
4180
|
const buttonsAnim = viewState === "expanding" || viewState === "apm-expanding" ? `flopay-buttons-exit ${TRANSITION_MS}ms cubic-bezier(0.4, 0, 0.2, 1) both` : viewState === "collapsing" || viewState === "apm-collapsing" ? `flopay-buttons-enter ${TRANSITION_MS}ms cubic-bezier(0, 0, 0.2, 1) both` : void 0;
|
|
3775
4181
|
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;
|
|
3776
4182
|
return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
3777
|
-
/* @__PURE__ */
|
|
3778
|
-
overlayStatus && /* @__PURE__ */
|
|
4183
|
+
/* @__PURE__ */ jsx7(FloPayKeyframes, {}),
|
|
4184
|
+
overlayStatus && /* @__PURE__ */ jsx7(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
3779
4185
|
/* @__PURE__ */ jsxs4("div", { style: { display: "grid" }, children: [
|
|
3780
4186
|
/* @__PURE__ */ jsxs4(
|
|
3781
4187
|
"div",
|
|
@@ -3795,7 +4201,7 @@ function SplitCardFormInner({
|
|
|
3795
4201
|
renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug"),
|
|
3796
4202
|
renderStripeGateDebug("flopay-stripe-gate-debug"),
|
|
3797
4203
|
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
3798
|
-
paypalDirectRetry && /* @__PURE__ */
|
|
4204
|
+
paypalDirectRetry && /* @__PURE__ */ jsx7(
|
|
3799
4205
|
"div",
|
|
3800
4206
|
{
|
|
3801
4207
|
"data-testid": "flopay-paypal-direct-retry-notice",
|
|
@@ -3811,7 +4217,7 @@ function SplitCardFormInner({
|
|
|
3811
4217
|
children: "Please confirm your PayPal payment to complete checkout."
|
|
3812
4218
|
}
|
|
3813
4219
|
),
|
|
3814
|
-
/* @__PURE__ */
|
|
4220
|
+
/* @__PURE__ */ jsx7(
|
|
3815
4221
|
DirectPayPalButton,
|
|
3816
4222
|
{
|
|
3817
4223
|
sessionId,
|
|
@@ -3837,7 +4243,7 @@ function SplitCardFormInner({
|
|
|
3837
4243
|
paypalDirectRetry?.orderId ?? "fresh"
|
|
3838
4244
|
)
|
|
3839
4245
|
] }),
|
|
3840
|
-
shouldRenderStripePayPal && /* @__PURE__ */
|
|
4246
|
+
shouldRenderStripePayPal && /* @__PURE__ */ jsx7(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx7(
|
|
3841
4247
|
PayPalButtonInner,
|
|
3842
4248
|
{
|
|
3843
4249
|
sessionId,
|
|
@@ -3851,10 +4257,10 @@ function SplitCardFormInner({
|
|
|
3851
4257
|
onDecline,
|
|
3852
4258
|
runBeforeButtonClick,
|
|
3853
4259
|
onLoadStateChange: setPaypalLoadState,
|
|
3854
|
-
placeholderBorderRadius:
|
|
4260
|
+
placeholderBorderRadius: buttonBorderRadius
|
|
3855
4261
|
}
|
|
3856
4262
|
) }),
|
|
3857
|
-
shouldRenderWallets ? /* @__PURE__ */
|
|
4263
|
+
shouldRenderWallets ? /* @__PURE__ */ jsx7(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx7(
|
|
3858
4264
|
WalletButtonInner,
|
|
3859
4265
|
{
|
|
3860
4266
|
sessionId,
|
|
@@ -3868,10 +4274,10 @@ function SplitCardFormInner({
|
|
|
3868
4274
|
onDecline,
|
|
3869
4275
|
runBeforeButtonClick,
|
|
3870
4276
|
onLoadStateChange: setWalletLoadState,
|
|
3871
|
-
placeholderBorderRadius:
|
|
4277
|
+
placeholderBorderRadius: buttonBorderRadius
|
|
3872
4278
|
}
|
|
3873
|
-
) }) : shouldShowWallets ? /* @__PURE__ */
|
|
3874
|
-
shouldRenderPaymentElement && /* @__PURE__ */
|
|
4279
|
+
) }) : shouldShowWallets ? /* @__PURE__ */ jsx7("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: buttonBorderRadius, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
|
|
4280
|
+
shouldRenderPaymentElement && /* @__PURE__ */ jsx7(
|
|
3875
4281
|
StripePaymentElementInner,
|
|
3876
4282
|
{
|
|
3877
4283
|
sessionId,
|
|
@@ -3899,11 +4305,11 @@ function SplitCardFormInner({
|
|
|
3899
4305
|
backgroundColor: bStyles.cardButton?.backgroundColor,
|
|
3900
4306
|
borderColor: bStyles.cardInputBorder,
|
|
3901
4307
|
textColor: bStyles.cardButton?.color,
|
|
3902
|
-
borderRadius:
|
|
4308
|
+
borderRadius: buttonBorderRadius
|
|
3903
4309
|
}
|
|
3904
4310
|
}
|
|
3905
4311
|
),
|
|
3906
|
-
showStripe && /* @__PURE__ */
|
|
4312
|
+
showStripe && /* @__PURE__ */ jsx7(
|
|
3907
4313
|
"button",
|
|
3908
4314
|
{
|
|
3909
4315
|
type: "button",
|
|
@@ -3931,7 +4337,8 @@ function SplitCardFormInner({
|
|
|
3931
4337
|
themeBundle,
|
|
3932
4338
|
resolvedPrimaryColor,
|
|
3933
4339
|
resolvedBorderRadius,
|
|
3934
|
-
submitButtonStyle: bStyles.submitButton
|
|
4340
|
+
submitButtonStyle: bStyles.submitButton,
|
|
4341
|
+
explicitPrimaryColor: appearanceVars?.colorPrimary
|
|
3935
4342
|
}),
|
|
3936
4343
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
3937
4344
|
fontWeight: 600,
|
|
@@ -3940,17 +4347,25 @@ function SplitCardFormInner({
|
|
|
3940
4347
|
alignItems: "center",
|
|
3941
4348
|
justifyContent: "center",
|
|
3942
4349
|
gap: "0.625rem",
|
|
3943
|
-
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
4350
|
+
transition: "background-color 0.15s, border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
3944
4351
|
position: "relative",
|
|
3945
4352
|
opacity: isSubmitting ? 0.6 : 1
|
|
3946
4353
|
},
|
|
4354
|
+
onMouseEnter: (e) => {
|
|
4355
|
+
if (!isSubmitting && (themeBundle || appearanceVars?.colorPrimary)) {
|
|
4356
|
+
e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
|
|
4357
|
+
}
|
|
4358
|
+
},
|
|
4359
|
+
onMouseLeave: (e) => {
|
|
4360
|
+
if (themeBundle || appearanceVars?.colorPrimary) e.currentTarget.style.backgroundColor = resolvedPrimaryColor;
|
|
4361
|
+
},
|
|
3947
4362
|
onMouseDown: (e) => {
|
|
3948
4363
|
e.currentTarget.style.transform = "scale(0.985)";
|
|
3949
4364
|
},
|
|
3950
4365
|
onMouseUp: (e) => {
|
|
3951
4366
|
e.currentTarget.style.transform = "scale(1)";
|
|
3952
4367
|
},
|
|
3953
|
-
children: /* @__PURE__ */
|
|
4368
|
+
children: /* @__PURE__ */ jsx7(CardButtonContentSlot, { content: cardButtonContent })
|
|
3954
4369
|
}
|
|
3955
4370
|
),
|
|
3956
4371
|
displayError && viewState === "buttons" && /* @__PURE__ */ jsxs4("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
@@ -3967,18 +4382,18 @@ function SplitCardFormInner({
|
|
|
3967
4382
|
gap: "0.5rem",
|
|
3968
4383
|
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
3969
4384
|
}, children: [
|
|
3970
|
-
/* @__PURE__ */
|
|
4385
|
+
/* @__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" }) }),
|
|
3971
4386
|
displayError
|
|
3972
4387
|
] })
|
|
3973
4388
|
]
|
|
3974
4389
|
}
|
|
3975
4390
|
),
|
|
3976
|
-
showStripe && isCardView && /* @__PURE__ */
|
|
4391
|
+
showStripe && isCardView && /* @__PURE__ */ jsx7("div", { style: {
|
|
3977
4392
|
gridArea: "1 / 1",
|
|
3978
4393
|
...cardAnim ? { animation: cardAnim } : {},
|
|
3979
4394
|
...viewState === "collapsing" ? { pointerEvents: "none" } : {}
|
|
3980
4395
|
}, children: cardFormBlock }),
|
|
3981
|
-
showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */
|
|
4396
|
+
showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ jsx7("div", { style: {
|
|
3982
4397
|
gridArea: "1 / 1",
|
|
3983
4398
|
...apmAnim ? { animation: apmAnim } : {},
|
|
3984
4399
|
...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
|
|
@@ -4016,7 +4431,7 @@ function SplitCardFormInner({
|
|
|
4016
4431
|
},
|
|
4017
4432
|
"aria-label": "Back to payment methods",
|
|
4018
4433
|
children: [
|
|
4019
|
-
/* @__PURE__ */
|
|
4434
|
+
/* @__PURE__ */ jsx7("span", { style: {
|
|
4020
4435
|
display: "inline-flex",
|
|
4021
4436
|
alignItems: "center",
|
|
4022
4437
|
justifyContent: "center",
|
|
@@ -4026,12 +4441,12 @@ function SplitCardFormInner({
|
|
|
4026
4441
|
backgroundColor: "#f3f4f6",
|
|
4027
4442
|
transition: "background-color 0.15s",
|
|
4028
4443
|
...bStyles.backButtonIcon
|
|
4029
|
-
}, children: /* @__PURE__ */
|
|
4030
|
-
/* @__PURE__ */
|
|
4444
|
+
}, 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" }) }) }),
|
|
4445
|
+
/* @__PURE__ */ jsx7(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
4031
4446
|
]
|
|
4032
4447
|
}
|
|
4033
4448
|
),
|
|
4034
|
-
/* @__PURE__ */
|
|
4449
|
+
/* @__PURE__ */ jsx7("div", { style: {
|
|
4035
4450
|
flex: 1,
|
|
4036
4451
|
textAlign: "center",
|
|
4037
4452
|
fontWeight: 600,
|
|
@@ -4041,12 +4456,12 @@ function SplitCardFormInner({
|
|
|
4041
4456
|
...bStyles.title
|
|
4042
4457
|
}, children: `Pay with ${getStripeMethodDisplayName(expandedApmMethod)}` })
|
|
4043
4458
|
] }),
|
|
4044
|
-
/* @__PURE__ */
|
|
4459
|
+
/* @__PURE__ */ jsx7(
|
|
4045
4460
|
StripeElements,
|
|
4046
4461
|
{
|
|
4047
4462
|
stripe: stripeInstance,
|
|
4048
4463
|
options: apmInlineOptions,
|
|
4049
|
-
children: /* @__PURE__ */
|
|
4464
|
+
children: /* @__PURE__ */ jsx7(
|
|
4050
4465
|
StripeMethodInlineForm,
|
|
4051
4466
|
{
|
|
4052
4467
|
method: expandedApmMethod,
|
|
@@ -4064,7 +4479,8 @@ function SplitCardFormInner({
|
|
|
4064
4479
|
isProcessing: isSubmitting,
|
|
4065
4480
|
submitButtonColor: resolvedPrimaryColor,
|
|
4066
4481
|
submitButtonBorderRadius: resolvedBorderRadius,
|
|
4067
|
-
submitButtonStyle: bStyles.submitButton
|
|
4482
|
+
submitButtonStyle: bStyles.submitButton,
|
|
4483
|
+
errorText: displayError
|
|
4068
4484
|
}
|
|
4069
4485
|
)
|
|
4070
4486
|
},
|
|
@@ -4076,9 +4492,9 @@ function SplitCardFormInner({
|
|
|
4076
4492
|
}
|
|
4077
4493
|
if (isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && showStripe) {
|
|
4078
4494
|
return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
4079
|
-
/* @__PURE__ */
|
|
4080
|
-
overlayStatus && /* @__PURE__ */
|
|
4081
|
-
/* @__PURE__ */
|
|
4495
|
+
/* @__PURE__ */ jsx7(FloPayKeyframes, {}),
|
|
4496
|
+
overlayStatus && /* @__PURE__ */ jsx7(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
4497
|
+
/* @__PURE__ */ jsx7("div", { style: {
|
|
4082
4498
|
...apmAnim ? { animation: apmAnim } : {},
|
|
4083
4499
|
...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
|
|
4084
4500
|
}, children: /* @__PURE__ */ jsxs4("div", { style: {
|
|
@@ -4115,7 +4531,7 @@ function SplitCardFormInner({
|
|
|
4115
4531
|
},
|
|
4116
4532
|
"aria-label": "Back to payment methods",
|
|
4117
4533
|
children: [
|
|
4118
|
-
/* @__PURE__ */
|
|
4534
|
+
/* @__PURE__ */ jsx7("span", { style: {
|
|
4119
4535
|
display: "inline-flex",
|
|
4120
4536
|
alignItems: "center",
|
|
4121
4537
|
justifyContent: "center",
|
|
@@ -4125,12 +4541,12 @@ function SplitCardFormInner({
|
|
|
4125
4541
|
backgroundColor: "#f3f4f6",
|
|
4126
4542
|
transition: "background-color 0.15s",
|
|
4127
4543
|
...bStyles.backButtonIcon
|
|
4128
|
-
}, children: /* @__PURE__ */
|
|
4129
|
-
/* @__PURE__ */
|
|
4544
|
+
}, 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" }) }) }),
|
|
4545
|
+
/* @__PURE__ */ jsx7(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
4130
4546
|
]
|
|
4131
4547
|
}
|
|
4132
4548
|
),
|
|
4133
|
-
/* @__PURE__ */
|
|
4549
|
+
/* @__PURE__ */ jsx7("div", { style: {
|
|
4134
4550
|
flex: 1,
|
|
4135
4551
|
textAlign: "center",
|
|
4136
4552
|
fontWeight: 600,
|
|
@@ -4140,12 +4556,12 @@ function SplitCardFormInner({
|
|
|
4140
4556
|
...bStyles.title
|
|
4141
4557
|
}, children: `Pay with ${getStripeMethodDisplayName(expandedApmMethod)}` })
|
|
4142
4558
|
] }),
|
|
4143
|
-
/* @__PURE__ */
|
|
4559
|
+
/* @__PURE__ */ jsx7(
|
|
4144
4560
|
StripeElements,
|
|
4145
4561
|
{
|
|
4146
4562
|
stripe: stripeInstance,
|
|
4147
4563
|
options: apmInlineOptions,
|
|
4148
|
-
children: /* @__PURE__ */
|
|
4564
|
+
children: /* @__PURE__ */ jsx7(
|
|
4149
4565
|
StripeMethodInlineForm,
|
|
4150
4566
|
{
|
|
4151
4567
|
method: expandedApmMethod,
|
|
@@ -4163,7 +4579,8 @@ function SplitCardFormInner({
|
|
|
4163
4579
|
isProcessing: isSubmitting,
|
|
4164
4580
|
submitButtonColor: resolvedPrimaryColor,
|
|
4165
4581
|
submitButtonBorderRadius: resolvedBorderRadius,
|
|
4166
|
-
submitButtonStyle: bStyles.submitButton
|
|
4582
|
+
submitButtonStyle: bStyles.submitButton,
|
|
4583
|
+
errorText: displayError
|
|
4167
4584
|
}
|
|
4168
4585
|
)
|
|
4169
4586
|
},
|
|
@@ -4173,13 +4590,13 @@ function SplitCardFormInner({
|
|
|
4173
4590
|
] });
|
|
4174
4591
|
}
|
|
4175
4592
|
return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
4176
|
-
/* @__PURE__ */
|
|
4177
|
-
overlayStatus && /* @__PURE__ */
|
|
4593
|
+
/* @__PURE__ */ jsx7(FloPayKeyframes, {}),
|
|
4594
|
+
overlayStatus && /* @__PURE__ */ jsx7(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
4178
4595
|
/* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
4179
4596
|
renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug-default"),
|
|
4180
4597
|
renderStripeGateDebug("flopay-stripe-gate-debug-default"),
|
|
4181
4598
|
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
4182
|
-
paypalDirectRetry && /* @__PURE__ */
|
|
4599
|
+
paypalDirectRetry && /* @__PURE__ */ jsx7(
|
|
4183
4600
|
"div",
|
|
4184
4601
|
{
|
|
4185
4602
|
"data-testid": "flopay-paypal-direct-retry-notice-default",
|
|
@@ -4195,7 +4612,7 @@ function SplitCardFormInner({
|
|
|
4195
4612
|
children: "Please confirm your PayPal payment to complete checkout."
|
|
4196
4613
|
}
|
|
4197
4614
|
),
|
|
4198
|
-
/* @__PURE__ */
|
|
4615
|
+
/* @__PURE__ */ jsx7(
|
|
4199
4616
|
DirectPayPalButton,
|
|
4200
4617
|
{
|
|
4201
4618
|
sessionId,
|
|
@@ -4221,7 +4638,7 @@ function SplitCardFormInner({
|
|
|
4221
4638
|
paypalDirectRetry?.orderId ?? "fresh"
|
|
4222
4639
|
)
|
|
4223
4640
|
] }),
|
|
4224
|
-
shouldRenderStripePayPal && /* @__PURE__ */
|
|
4641
|
+
shouldRenderStripePayPal && /* @__PURE__ */ jsx7(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx7(
|
|
4225
4642
|
PayPalButtonInner,
|
|
4226
4643
|
{
|
|
4227
4644
|
sessionId,
|
|
@@ -4235,10 +4652,10 @@ function SplitCardFormInner({
|
|
|
4235
4652
|
onDecline,
|
|
4236
4653
|
runBeforeButtonClick,
|
|
4237
4654
|
onLoadStateChange: setPaypalLoadState,
|
|
4238
|
-
placeholderBorderRadius:
|
|
4655
|
+
placeholderBorderRadius: buttonBorderRadius
|
|
4239
4656
|
}
|
|
4240
4657
|
) }),
|
|
4241
|
-
shouldRenderWallets && /* @__PURE__ */
|
|
4658
|
+
shouldRenderWallets && /* @__PURE__ */ jsx7(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx7(
|
|
4242
4659
|
WalletButtonInner,
|
|
4243
4660
|
{
|
|
4244
4661
|
sessionId,
|
|
@@ -4252,10 +4669,10 @@ function SplitCardFormInner({
|
|
|
4252
4669
|
onDecline,
|
|
4253
4670
|
runBeforeButtonClick,
|
|
4254
4671
|
onLoadStateChange: setWalletLoadState,
|
|
4255
|
-
placeholderBorderRadius:
|
|
4672
|
+
placeholderBorderRadius: buttonBorderRadius
|
|
4256
4673
|
}
|
|
4257
4674
|
) }),
|
|
4258
|
-
shouldRenderPaymentElement && /* @__PURE__ */
|
|
4675
|
+
shouldRenderPaymentElement && /* @__PURE__ */ jsx7(
|
|
4259
4676
|
StripePaymentElementInner,
|
|
4260
4677
|
{
|
|
4261
4678
|
sessionId,
|
|
@@ -4283,7 +4700,7 @@ function SplitCardFormInner({
|
|
|
4283
4700
|
backgroundColor: bStyles.cardButton?.backgroundColor,
|
|
4284
4701
|
borderColor: bStyles.cardInputBorder,
|
|
4285
4702
|
textColor: bStyles.cardButton?.color,
|
|
4286
|
-
borderRadius:
|
|
4703
|
+
borderRadius: buttonBorderRadius
|
|
4287
4704
|
}
|
|
4288
4705
|
}
|
|
4289
4706
|
)
|
|
@@ -4296,9 +4713,9 @@ function SplitCardFormInner({
|
|
|
4296
4713
|
color: "#999",
|
|
4297
4714
|
fontSize: "0.85rem"
|
|
4298
4715
|
}, children: [
|
|
4299
|
-
/* @__PURE__ */
|
|
4300
|
-
/* @__PURE__ */
|
|
4301
|
-
/* @__PURE__ */
|
|
4716
|
+
/* @__PURE__ */ jsx7("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
|
|
4717
|
+
/* @__PURE__ */ jsx7("span", { children: "or pay with card" }),
|
|
4718
|
+
/* @__PURE__ */ jsx7("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
|
|
4302
4719
|
] }),
|
|
4303
4720
|
showStripe && cardFormBlock
|
|
4304
4721
|
] });
|
|
@@ -4341,6 +4758,210 @@ function getRedirectResultFromCheckoutProcessError(error) {
|
|
|
4341
4758
|
paymentMethodId: error.paymentMethodId
|
|
4342
4759
|
};
|
|
4343
4760
|
}
|
|
4761
|
+
function isTerminalAutoCheckoutThreeDsOutcome(outcome) {
|
|
4762
|
+
return outcome.status === "succeeded" || outcome.status === "declined";
|
|
4763
|
+
}
|
|
4764
|
+
async function runAutoCheckoutThreeDsChallenge(input) {
|
|
4765
|
+
if (typeof document === "undefined" || typeof window === "undefined") {
|
|
4766
|
+
throw new FloPayError4("3DS challenge requires a browser environment.", "api_error", {
|
|
4767
|
+
code: "three_ds_no_window"
|
|
4768
|
+
});
|
|
4769
|
+
}
|
|
4770
|
+
if (input.signal?.aborted) {
|
|
4771
|
+
throw new FloPayError4("Card authentication was cancelled.", "api_error", {
|
|
4772
|
+
code: "three_ds_aborted"
|
|
4773
|
+
});
|
|
4774
|
+
}
|
|
4775
|
+
const CHALLENGE_TIMEOUT_MS = 3e5;
|
|
4776
|
+
const CHALLENGE_POLL_INTERVAL_MS = 1e3;
|
|
4777
|
+
const COMPLETE_REQUEST_TIMEOUT_MS = 15e3;
|
|
4778
|
+
const completionEndpoint = `${input.billingApiUrl.replace(/\/$/, "")}/v1/checkouts/sessions/${encodeURIComponent(
|
|
4779
|
+
input.sessionId
|
|
4780
|
+
)}/3ds/complete`;
|
|
4781
|
+
const completeThreeDs = async () => {
|
|
4782
|
+
const controller = new AbortController();
|
|
4783
|
+
const onParentAbort = () => controller.abort();
|
|
4784
|
+
if (input.signal?.aborted) {
|
|
4785
|
+
controller.abort();
|
|
4786
|
+
} else {
|
|
4787
|
+
input.signal?.addEventListener("abort", onParentAbort);
|
|
4788
|
+
}
|
|
4789
|
+
const requestTimeout = window.setTimeout(() => controller.abort(), COMPLETE_REQUEST_TIMEOUT_MS);
|
|
4790
|
+
try {
|
|
4791
|
+
const response = await fetch(completionEndpoint, {
|
|
4792
|
+
method: "POST",
|
|
4793
|
+
headers: {
|
|
4794
|
+
"x-checkout-session-token": input.nonce,
|
|
4795
|
+
"content-type": "application/json"
|
|
4796
|
+
},
|
|
4797
|
+
body: "{}",
|
|
4798
|
+
signal: controller.signal
|
|
4799
|
+
});
|
|
4800
|
+
if (!response.ok) {
|
|
4801
|
+
return { status: "unknown" };
|
|
4802
|
+
}
|
|
4803
|
+
const json = await response.json().catch(() => null);
|
|
4804
|
+
return coerceThreeDsOutcome(json);
|
|
4805
|
+
} catch {
|
|
4806
|
+
return { status: "unknown" };
|
|
4807
|
+
} finally {
|
|
4808
|
+
window.clearTimeout(requestTimeout);
|
|
4809
|
+
input.signal?.removeEventListener("abort", onParentAbort);
|
|
4810
|
+
}
|
|
4811
|
+
};
|
|
4812
|
+
const previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
4813
|
+
const backdrop = document.createElement("div");
|
|
4814
|
+
backdrop.setAttribute("data-flopay-auto-3ds-overlay", "1");
|
|
4815
|
+
backdrop.setAttribute("role", "dialog");
|
|
4816
|
+
backdrop.setAttribute("aria-modal", "true");
|
|
4817
|
+
backdrop.setAttribute("aria-label", "Card authentication");
|
|
4818
|
+
backdrop.style.cssText = [
|
|
4819
|
+
"position:fixed",
|
|
4820
|
+
"inset:0",
|
|
4821
|
+
"z-index:2147483647",
|
|
4822
|
+
"background:rgba(15,23,42,0.6)",
|
|
4823
|
+
"display:flex",
|
|
4824
|
+
"align-items:center",
|
|
4825
|
+
"justify-content:center",
|
|
4826
|
+
"padding:16px"
|
|
4827
|
+
].join(";");
|
|
4828
|
+
const frame = document.createElement("iframe");
|
|
4829
|
+
frame.setAttribute("title", "Card authentication");
|
|
4830
|
+
frame.setAttribute("allow", "payment");
|
|
4831
|
+
frame.tabIndex = 0;
|
|
4832
|
+
frame.style.cssText = [
|
|
4833
|
+
"width:min(100%,460px)",
|
|
4834
|
+
"height:min(100%,640px)",
|
|
4835
|
+
"border:0",
|
|
4836
|
+
"border-radius:12px",
|
|
4837
|
+
"background:#fff",
|
|
4838
|
+
"box-shadow:0 12px 30px rgba(0,0,0,0.35)"
|
|
4839
|
+
].join(";");
|
|
4840
|
+
frame.src = input.nextActionRedirectUrl;
|
|
4841
|
+
backdrop.appendChild(frame);
|
|
4842
|
+
document.body.appendChild(backdrop);
|
|
4843
|
+
frame.focus();
|
|
4844
|
+
let expectedReturnOrigin = null;
|
|
4845
|
+
try {
|
|
4846
|
+
expectedReturnOrigin = new URL(input.billingApiUrl, window.location.href).origin;
|
|
4847
|
+
} catch {
|
|
4848
|
+
expectedReturnOrigin = null;
|
|
4849
|
+
}
|
|
4850
|
+
try {
|
|
4851
|
+
const polledOutcome = await new Promise((resolve, reject) => {
|
|
4852
|
+
let settled = false;
|
|
4853
|
+
let timer = 0;
|
|
4854
|
+
let pollTimer = 0;
|
|
4855
|
+
let loadPollTimer = 0;
|
|
4856
|
+
let pollInFlight = false;
|
|
4857
|
+
const cleanup = () => {
|
|
4858
|
+
window.clearTimeout(timer);
|
|
4859
|
+
window.clearInterval(pollTimer);
|
|
4860
|
+
window.clearTimeout(loadPollTimer);
|
|
4861
|
+
window.removeEventListener("message", listener);
|
|
4862
|
+
frame.removeEventListener("load", onFrameLoad);
|
|
4863
|
+
input.signal?.removeEventListener("abort", onAbort);
|
|
4864
|
+
};
|
|
4865
|
+
const maybeResolveFromBackend = async () => {
|
|
4866
|
+
if (settled || pollInFlight) return;
|
|
4867
|
+
pollInFlight = true;
|
|
4868
|
+
try {
|
|
4869
|
+
const outcome = await completeThreeDs();
|
|
4870
|
+
if (settled || !isTerminalAutoCheckoutThreeDsOutcome(outcome)) return;
|
|
4871
|
+
settled = true;
|
|
4872
|
+
cleanup();
|
|
4873
|
+
resolve(outcome);
|
|
4874
|
+
} finally {
|
|
4875
|
+
pollInFlight = false;
|
|
4876
|
+
}
|
|
4877
|
+
};
|
|
4878
|
+
const onFrameLoad = () => {
|
|
4879
|
+
window.clearTimeout(loadPollTimer);
|
|
4880
|
+
loadPollTimer = window.setTimeout(() => {
|
|
4881
|
+
void maybeResolveFromBackend();
|
|
4882
|
+
}, 250);
|
|
4883
|
+
};
|
|
4884
|
+
const onAbort = () => {
|
|
4885
|
+
if (settled) return;
|
|
4886
|
+
settled = true;
|
|
4887
|
+
cleanup();
|
|
4888
|
+
reject(
|
|
4889
|
+
new FloPayError4("Card authentication was cancelled.", "api_error", {
|
|
4890
|
+
code: "three_ds_aborted"
|
|
4891
|
+
})
|
|
4892
|
+
);
|
|
4893
|
+
};
|
|
4894
|
+
const listener = (event) => {
|
|
4895
|
+
if (event.source !== frame.contentWindow) return;
|
|
4896
|
+
if (expectedReturnOrigin && event.origin !== expectedReturnOrigin) return;
|
|
4897
|
+
const data = event.data;
|
|
4898
|
+
if (!data || typeof data !== "object") return;
|
|
4899
|
+
const record = data;
|
|
4900
|
+
if (record["source"] !== "flopay-vault-3ds-return") return;
|
|
4901
|
+
if (settled) return;
|
|
4902
|
+
settled = true;
|
|
4903
|
+
cleanup();
|
|
4904
|
+
resolve(null);
|
|
4905
|
+
};
|
|
4906
|
+
timer = window.setTimeout(() => {
|
|
4907
|
+
if (settled) return;
|
|
4908
|
+
settled = true;
|
|
4909
|
+
cleanup();
|
|
4910
|
+
reject(
|
|
4911
|
+
new FloPayError4("Card authentication timed out.", "api_error", {
|
|
4912
|
+
code: "three_ds_timeout"
|
|
4913
|
+
})
|
|
4914
|
+
);
|
|
4915
|
+
}, CHALLENGE_TIMEOUT_MS);
|
|
4916
|
+
pollTimer = window.setInterval(() => {
|
|
4917
|
+
void maybeResolveFromBackend();
|
|
4918
|
+
}, CHALLENGE_POLL_INTERVAL_MS);
|
|
4919
|
+
frame.addEventListener("load", onFrameLoad);
|
|
4920
|
+
window.addEventListener("message", listener);
|
|
4921
|
+
input.signal?.addEventListener("abort", onAbort);
|
|
4922
|
+
if (input.signal?.aborted) onAbort();
|
|
4923
|
+
});
|
|
4924
|
+
if (polledOutcome) {
|
|
4925
|
+
return polledOutcome;
|
|
4926
|
+
}
|
|
4927
|
+
return await completeThreeDs();
|
|
4928
|
+
} finally {
|
|
4929
|
+
backdrop.parentNode?.removeChild(backdrop);
|
|
4930
|
+
if (previousFocus?.isConnected) {
|
|
4931
|
+
previousFocus.focus();
|
|
4932
|
+
}
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
function coerceThreeDsOutcome(json) {
|
|
4936
|
+
if (!json || typeof json !== "object") return { status: "unknown" };
|
|
4937
|
+
const status = typeof json["status"] === "string" ? json["status"] : "unknown";
|
|
4938
|
+
const providerIntentId = typeof json["providerIntentId"] === "string" ? json["providerIntentId"] : null;
|
|
4939
|
+
switch (status) {
|
|
4940
|
+
case "succeeded":
|
|
4941
|
+
return { status: "succeeded", providerIntentId };
|
|
4942
|
+
case "declined":
|
|
4943
|
+
return {
|
|
4944
|
+
status: "declined",
|
|
4945
|
+
providerIntentId,
|
|
4946
|
+
declineReason: typeof json["declineReason"] === "string" ? json["declineReason"] : null,
|
|
4947
|
+
gatewayDeclineReason: typeof json["gatewayDeclineReason"] === "string" ? json["gatewayDeclineReason"] : null
|
|
4948
|
+
};
|
|
4949
|
+
case "requires_action":
|
|
4950
|
+
return {
|
|
4951
|
+
status: "requires_action",
|
|
4952
|
+
providerIntentId,
|
|
4953
|
+
nextActionRedirectUrl: typeof json["nextActionRedirectUrl"] === "string" ? json["nextActionRedirectUrl"] : null
|
|
4954
|
+
};
|
|
4955
|
+
case "pending":
|
|
4956
|
+
return { status: "pending", providerIntentId };
|
|
4957
|
+
case "timeout":
|
|
4958
|
+
return { status: "timeout", providerIntentId };
|
|
4959
|
+
case "no_attempt":
|
|
4960
|
+
return { status: "no_attempt" };
|
|
4961
|
+
default:
|
|
4962
|
+
return { status: "unknown" };
|
|
4963
|
+
}
|
|
4964
|
+
}
|
|
4344
4965
|
function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment failed. Please try again.", options) {
|
|
4345
4966
|
const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
|
|
4346
4967
|
const rawMessage = error?.message ?? fallbackMessage;
|
|
@@ -4782,7 +5403,7 @@ async function loadSavedPaymentProviders({
|
|
|
4782
5403
|
}
|
|
4783
5404
|
|
|
4784
5405
|
// src/flopay-checkout.tsx
|
|
4785
|
-
import { Fragment as Fragment3, jsx as
|
|
5406
|
+
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4786
5407
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
|
|
4787
5408
|
var PAYPAL_RESUME_STORAGE_KEY = "flopay_checkout_saved_payment_resume";
|
|
4788
5409
|
var sessionInflightMap = /* @__PURE__ */ new Map();
|
|
@@ -4831,6 +5452,36 @@ function clearPayPalResumeState() {
|
|
|
4831
5452
|
console.warn("[FloPayCheckout] Failed to clear PayPal resume state.", error);
|
|
4832
5453
|
}
|
|
4833
5454
|
}
|
|
5455
|
+
function readCachedInlineSession(cacheKey) {
|
|
5456
|
+
if (!canUseStorage()) return null;
|
|
5457
|
+
const raw = window.sessionStorage.getItem(cacheKey);
|
|
5458
|
+
if (!raw) return null;
|
|
5459
|
+
try {
|
|
5460
|
+
const parsed = JSON.parse(raw);
|
|
5461
|
+
if (parsed && typeof parsed.sid === "string" && parsed.sid) {
|
|
5462
|
+
return { sid: parsed.sid, nonce: typeof parsed.nonce === "string" ? parsed.nonce : void 0 };
|
|
5463
|
+
}
|
|
5464
|
+
return null;
|
|
5465
|
+
} catch {
|
|
5466
|
+
return { sid: raw };
|
|
5467
|
+
}
|
|
5468
|
+
}
|
|
5469
|
+
function persistCachedInlineSession(cacheKey, sid, nonce) {
|
|
5470
|
+
if (!canUseStorage()) return;
|
|
5471
|
+
try {
|
|
5472
|
+
window.sessionStorage.setItem(cacheKey, JSON.stringify(nonce ? { sid, nonce } : { sid }));
|
|
5473
|
+
} catch (error) {
|
|
5474
|
+
console.warn("[FloPayCheckout] Failed to persist checkout session cache.", error);
|
|
5475
|
+
}
|
|
5476
|
+
}
|
|
5477
|
+
function clearCachedInlineSession(cacheKey) {
|
|
5478
|
+
if (!canUseStorage()) return;
|
|
5479
|
+
try {
|
|
5480
|
+
window.sessionStorage.removeItem(cacheKey);
|
|
5481
|
+
} catch (error) {
|
|
5482
|
+
console.warn("[FloPayCheckout] Failed to clear checkout session cache.", error);
|
|
5483
|
+
}
|
|
5484
|
+
}
|
|
4834
5485
|
function clearPayPalRedirectParams() {
|
|
4835
5486
|
if (typeof window === "undefined") return;
|
|
4836
5487
|
const url = new URL(window.location.href);
|
|
@@ -4889,6 +5540,8 @@ function FloPayCheckout({
|
|
|
4889
5540
|
onButtonClick,
|
|
4890
5541
|
onBeforeButtonClick,
|
|
4891
5542
|
enableAVS,
|
|
5543
|
+
cardFieldOrder,
|
|
5544
|
+
cardPreFormSlot,
|
|
4892
5545
|
avsLayout,
|
|
4893
5546
|
submitLabel,
|
|
4894
5547
|
className,
|
|
@@ -4906,9 +5559,9 @@ function FloPayCheckout({
|
|
|
4906
5559
|
const checkoutLayout = children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout";
|
|
4907
5560
|
const [unified, setUnified] = useState4(null);
|
|
4908
5561
|
const [flopay, setFloPay] = useState4(null);
|
|
4909
|
-
const flopayRef =
|
|
5562
|
+
const flopayRef = useRef5(null);
|
|
4910
5563
|
const [paypalFlopay, setPaypalFloPay] = useState4(null);
|
|
4911
|
-
const paypalFlopayRef =
|
|
5564
|
+
const paypalFlopayRef = useRef5(null);
|
|
4912
5565
|
const [session, setSession] = useState4(null);
|
|
4913
5566
|
const [resolvedSessionId, setResolvedSessionId] = useState4(sessionIdProp ?? "");
|
|
4914
5567
|
const activeSessionId = sessionIdProp ?? resolvedSessionId;
|
|
@@ -4923,18 +5576,18 @@ function FloPayCheckout({
|
|
|
4923
5576
|
const [createSessionPatch, setCreateSessionPatch] = useState4(void 0);
|
|
4924
5577
|
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = useState4("");
|
|
4925
5578
|
const [cardBootstrapPending, setCardBootstrapPending] = useState4(false);
|
|
4926
|
-
const autoCheckoutAttempted =
|
|
4927
|
-
const paypalResumeAttempted =
|
|
4928
|
-
const savedPaymentKeysRef =
|
|
4929
|
-
const onCompleteRef =
|
|
5579
|
+
const autoCheckoutAttempted = useRef5(false);
|
|
5580
|
+
const paypalResumeAttempted = useRef5(false);
|
|
5581
|
+
const savedPaymentKeysRef = useRef5(null);
|
|
5582
|
+
const onCompleteRef = useRef5(onComplete);
|
|
4930
5583
|
onCompleteRef.current = onComplete;
|
|
4931
|
-
const onErrorRef =
|
|
5584
|
+
const onErrorRef = useRef5(onError);
|
|
4932
5585
|
onErrorRef.current = onError;
|
|
4933
|
-
const onDeclineRef =
|
|
5586
|
+
const onDeclineRef = useRef5(onDecline);
|
|
4934
5587
|
onDeclineRef.current = onDecline;
|
|
4935
|
-
const onSessionCompletedRef =
|
|
5588
|
+
const onSessionCompletedRef = useRef5(onSessionCompleted);
|
|
4936
5589
|
onSessionCompletedRef.current = onSessionCompleted;
|
|
4937
|
-
|
|
5590
|
+
useEffect6(() => {
|
|
4938
5591
|
console.info("[FloPay] Checkout initialized", {
|
|
4939
5592
|
sdk_version: SDK_VERSION,
|
|
4940
5593
|
checkout_type: checkoutType,
|
|
@@ -4962,11 +5615,11 @@ function FloPayCheckout({
|
|
|
4962
5615
|
} : void 0,
|
|
4963
5616
|
[effectiveCreateSessionBase, effectiveCreateSessionMode]
|
|
4964
5617
|
);
|
|
4965
|
-
|
|
5618
|
+
useEffect6(() => {
|
|
4966
5619
|
setCreateSessionPatch(void 0);
|
|
4967
5620
|
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
4968
5621
|
}, [baseCreateSessionHash]);
|
|
4969
|
-
|
|
5622
|
+
useEffect6(() => {
|
|
4970
5623
|
setModeError(initialErrorMessage);
|
|
4971
5624
|
}, [initialErrorMessage]);
|
|
4972
5625
|
const emitDecline = useCallback2(
|
|
@@ -5093,7 +5746,7 @@ function FloPayCheckout({
|
|
|
5093
5746
|
resolvedBillingUrl
|
|
5094
5747
|
]
|
|
5095
5748
|
);
|
|
5096
|
-
|
|
5749
|
+
useEffect6(() => {
|
|
5097
5750
|
if (typeof window === "undefined" || paypalResumeAttempted.current) {
|
|
5098
5751
|
return;
|
|
5099
5752
|
}
|
|
@@ -5210,7 +5863,7 @@ function FloPayCheckout({
|
|
|
5210
5863
|
}
|
|
5211
5864
|
})();
|
|
5212
5865
|
}, [emitDecline, locale, normalizeSavedPaymentError, resolvedBillingUrl]);
|
|
5213
|
-
const initializedHashRef =
|
|
5866
|
+
const initializedHashRef = useRef5(null);
|
|
5214
5867
|
function hashCreateParams(params) {
|
|
5215
5868
|
const key = JSON.stringify({
|
|
5216
5869
|
c: params?.clientId,
|
|
@@ -5247,12 +5900,12 @@ function FloPayCheckout({
|
|
|
5247
5900
|
() => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
|
|
5248
5901
|
[effectiveCreateSession]
|
|
5249
5902
|
);
|
|
5250
|
-
const createSessionParamsRef =
|
|
5903
|
+
const createSessionParamsRef = useRef5(effectiveCreateSession);
|
|
5251
5904
|
createSessionParamsRef.current = effectiveCreateSession;
|
|
5252
|
-
|
|
5905
|
+
useEffect6(() => {
|
|
5253
5906
|
setResolvedSessionId(sessionIdProp ?? "");
|
|
5254
5907
|
}, [sessionIdProp]);
|
|
5255
|
-
|
|
5908
|
+
useEffect6(() => {
|
|
5256
5909
|
autoCheckoutAttempted.current = false;
|
|
5257
5910
|
setModeError(initialErrorMessage);
|
|
5258
5911
|
setModeOverlayError(null);
|
|
@@ -5260,22 +5913,23 @@ function FloPayCheckout({
|
|
|
5260
5913
|
}, [createSessionHash, initialErrorMessage, sessionIdProp]);
|
|
5261
5914
|
async function resolveInlineSession(params, cacheKey) {
|
|
5262
5915
|
const api = new PaymentAPI4(resolvedBillingUrl);
|
|
5263
|
-
|
|
5916
|
+
const cached = readCachedInlineSession(cacheKey);
|
|
5917
|
+
let sid = cached?.sid ?? null;
|
|
5264
5918
|
let realResult = null;
|
|
5265
5919
|
if (sid) {
|
|
5266
5920
|
try {
|
|
5267
|
-
realResult = await api.getUnifiedCheckoutSession(sid);
|
|
5921
|
+
realResult = await api.getUnifiedCheckoutSession(sid, cached?.nonce);
|
|
5268
5922
|
const status = realResult.data.session?.status;
|
|
5269
5923
|
if (status === "complete") {
|
|
5270
5924
|
if (wasSessionRecentlyCompleted(sid)) {
|
|
5271
5925
|
return { sid, result: realResult };
|
|
5272
5926
|
}
|
|
5273
|
-
|
|
5927
|
+
clearCachedInlineSession(cacheKey);
|
|
5274
5928
|
sid = null;
|
|
5275
5929
|
realResult = null;
|
|
5276
5930
|
}
|
|
5277
5931
|
} catch {
|
|
5278
|
-
|
|
5932
|
+
clearCachedInlineSession(cacheKey);
|
|
5279
5933
|
sid = null;
|
|
5280
5934
|
}
|
|
5281
5935
|
}
|
|
@@ -5289,8 +5943,8 @@ function FloPayCheckout({
|
|
|
5289
5943
|
};
|
|
5290
5944
|
realResult = await api.createAndFetchSession(paramsWithAnalytics);
|
|
5291
5945
|
sid = realResult.data.session?.id ?? "";
|
|
5292
|
-
if (sid
|
|
5293
|
-
|
|
5946
|
+
if (sid) {
|
|
5947
|
+
persistCachedInlineSession(cacheKey, sid, realResult.data.session?.clientSecret);
|
|
5294
5948
|
}
|
|
5295
5949
|
}
|
|
5296
5950
|
return { sid: sid ?? "", result: realResult };
|
|
@@ -5379,7 +6033,7 @@ function FloPayCheckout({
|
|
|
5379
6033
|
resolvedSessionId,
|
|
5380
6034
|
session
|
|
5381
6035
|
]);
|
|
5382
|
-
|
|
6036
|
+
useEffect6(() => {
|
|
5383
6037
|
let cancelled = false;
|
|
5384
6038
|
setLoadError(null);
|
|
5385
6039
|
if (createSessionHash) {
|
|
@@ -5601,7 +6255,7 @@ function FloPayCheckout({
|
|
|
5601
6255
|
]
|
|
5602
6256
|
);
|
|
5603
6257
|
const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && !isPaypalOnlySession && (!flopay || !providerOptions);
|
|
5604
|
-
const modeOverlay = modeOverlayStatus ? /* @__PURE__ */
|
|
6258
|
+
const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ jsx8(
|
|
5605
6259
|
ProcessingOverlay,
|
|
5606
6260
|
{
|
|
5607
6261
|
status: modeOverlayStatus,
|
|
@@ -5617,7 +6271,7 @@ function FloPayCheckout({
|
|
|
5617
6271
|
}
|
|
5618
6272
|
if (layout === "buttons") {
|
|
5619
6273
|
const bundleRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
5620
|
-
const skeletonBar = (h) => /* @__PURE__ */
|
|
6274
|
+
const skeletonBar = (h) => /* @__PURE__ */ jsx8("div", { style: {
|
|
5621
6275
|
height: h,
|
|
5622
6276
|
borderRadius: bundleRadius,
|
|
5623
6277
|
background: "#e5e7eb",
|
|
@@ -5628,14 +6282,14 @@ function FloPayCheckout({
|
|
|
5628
6282
|
showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
5629
6283
|
showStripe && (showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
5630
6284
|
showStripe && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
5631
|
-
/* @__PURE__ */
|
|
6285
|
+
/* @__PURE__ */ jsx8("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
5632
6286
|
] }),
|
|
5633
6287
|
modeOverlay
|
|
5634
6288
|
] });
|
|
5635
6289
|
}
|
|
5636
6290
|
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
5637
6291
|
/* @__PURE__ */ jsxs5("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
|
|
5638
|
-
/* @__PURE__ */
|
|
6292
|
+
/* @__PURE__ */ jsx8("div", { style: {
|
|
5639
6293
|
width: 24,
|
|
5640
6294
|
height: 24,
|
|
5641
6295
|
border: "2px solid #e5e7eb",
|
|
@@ -5643,16 +6297,16 @@ function FloPayCheckout({
|
|
|
5643
6297
|
borderRadius: "50%",
|
|
5644
6298
|
animation: "spin 0.6s linear infinite"
|
|
5645
6299
|
} }),
|
|
5646
|
-
/* @__PURE__ */
|
|
6300
|
+
/* @__PURE__ */ jsx8("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
5647
6301
|
] }),
|
|
5648
6302
|
modeOverlay
|
|
5649
6303
|
] });
|
|
5650
6304
|
}
|
|
5651
6305
|
if (loadError) {
|
|
5652
6306
|
if (errorNode) {
|
|
5653
|
-
return /* @__PURE__ */
|
|
6307
|
+
return /* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
|
|
5654
6308
|
}
|
|
5655
|
-
return /* @__PURE__ */
|
|
6309
|
+
return /* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx8(
|
|
5656
6310
|
"div",
|
|
5657
6311
|
{
|
|
5658
6312
|
role: "alert",
|
|
@@ -5669,7 +6323,7 @@ function FloPayCheckout({
|
|
|
5669
6323
|
}
|
|
5670
6324
|
if (shouldShowInterimButtons) {
|
|
5671
6325
|
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
5672
|
-
/* @__PURE__ */
|
|
6326
|
+
/* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx8(
|
|
5673
6327
|
InterimButtonsView,
|
|
5674
6328
|
{
|
|
5675
6329
|
onButtonClick,
|
|
@@ -5690,8 +6344,8 @@ function FloPayCheckout({
|
|
|
5690
6344
|
}
|
|
5691
6345
|
if (isPaypalOnlySession && session && directPaypalConfig) {
|
|
5692
6346
|
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
5693
|
-
/* @__PURE__ */
|
|
5694
|
-
modeError && /* @__PURE__ */
|
|
6347
|
+
/* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsxs5("div", { className, style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
6348
|
+
modeError && /* @__PURE__ */ jsx8(
|
|
5695
6349
|
"div",
|
|
5696
6350
|
{
|
|
5697
6351
|
role: "alert",
|
|
@@ -5708,7 +6362,7 @@ function FloPayCheckout({
|
|
|
5708
6362
|
children: modeError
|
|
5709
6363
|
}
|
|
5710
6364
|
),
|
|
5711
|
-
/* @__PURE__ */
|
|
6365
|
+
/* @__PURE__ */ jsx8(
|
|
5712
6366
|
DirectPayPalButton,
|
|
5713
6367
|
{
|
|
5714
6368
|
sessionId: activeSessionId,
|
|
@@ -5732,12 +6386,12 @@ function FloPayCheckout({
|
|
|
5732
6386
|
] });
|
|
5733
6387
|
}
|
|
5734
6388
|
if (!flopay || !providerOptions) {
|
|
5735
|
-
return /* @__PURE__ */
|
|
6389
|
+
return /* @__PURE__ */ jsx8(Fragment3, { children: modeOverlay });
|
|
5736
6390
|
}
|
|
5737
6391
|
if (currentMode === "confirm") {
|
|
5738
6392
|
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
5739
|
-
/* @__PURE__ */
|
|
5740
|
-
modeError && /* @__PURE__ */
|
|
6393
|
+
/* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx8(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ jsxs5("div", { className, children: [
|
|
6394
|
+
modeError && /* @__PURE__ */ jsx8(
|
|
5741
6395
|
"div",
|
|
5742
6396
|
{
|
|
5743
6397
|
style: {
|
|
@@ -5752,7 +6406,7 @@ function FloPayCheckout({
|
|
|
5752
6406
|
renderConfirmButton ? renderConfirmButton({
|
|
5753
6407
|
onConfirm: handleConfirmCheckout,
|
|
5754
6408
|
isProcessing: confirmProcessing
|
|
5755
|
-
}) : /* @__PURE__ */
|
|
6409
|
+
}) : /* @__PURE__ */ jsx8(
|
|
5756
6410
|
"button",
|
|
5757
6411
|
{
|
|
5758
6412
|
type: "button",
|
|
@@ -5778,8 +6432,8 @@ function FloPayCheckout({
|
|
|
5778
6432
|
] });
|
|
5779
6433
|
}
|
|
5780
6434
|
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
5781
|
-
/* @__PURE__ */
|
|
5782
|
-
modeError && /* @__PURE__ */
|
|
6435
|
+
/* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx8(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
6436
|
+
modeError && /* @__PURE__ */ jsx8(
|
|
5783
6437
|
"div",
|
|
5784
6438
|
{
|
|
5785
6439
|
style: {
|
|
@@ -5794,7 +6448,7 @@ function FloPayCheckout({
|
|
|
5794
6448
|
children: modeError
|
|
5795
6449
|
}
|
|
5796
6450
|
),
|
|
5797
|
-
/* @__PURE__ */
|
|
6451
|
+
/* @__PURE__ */ jsx8(
|
|
5798
6452
|
SessionInjector,
|
|
5799
6453
|
{
|
|
5800
6454
|
sessionId: activeSessionId,
|
|
@@ -5804,7 +6458,7 @@ function FloPayCheckout({
|
|
|
5804
6458
|
children
|
|
5805
6459
|
}
|
|
5806
6460
|
)
|
|
5807
|
-
] }) : /* @__PURE__ */
|
|
6461
|
+
] }) : /* @__PURE__ */ jsx8(
|
|
5808
6462
|
SplitCardForm,
|
|
5809
6463
|
{
|
|
5810
6464
|
sessionId: activeSessionId,
|
|
@@ -5824,6 +6478,7 @@ function FloPayCheckout({
|
|
|
5824
6478
|
showPayPal,
|
|
5825
6479
|
showStripe,
|
|
5826
6480
|
enabledPaymentMethods: unified?.data.stripe?.enabledPaymentMethods,
|
|
6481
|
+
enabledPaymentMethodCountries: unified?.data.stripe?.enabledPaymentMethodCountries,
|
|
5827
6482
|
showApplePay,
|
|
5828
6483
|
showGooglePay,
|
|
5829
6484
|
layout,
|
|
@@ -5837,6 +6492,8 @@ function FloPayCheckout({
|
|
|
5837
6492
|
onButtonClick,
|
|
5838
6493
|
onBeforeButtonClick,
|
|
5839
6494
|
enableAVS,
|
|
6495
|
+
...cardFieldOrder ? { cardFieldOrder } : {},
|
|
6496
|
+
...cardPreFormSlot ? { cardPreFormSlot } : {},
|
|
5840
6497
|
avsLayout,
|
|
5841
6498
|
country: session?.customer?.country,
|
|
5842
6499
|
city: session?.customer?.city,
|
|
@@ -5864,8 +6521,8 @@ function SessionInjector({
|
|
|
5864
6521
|
session,
|
|
5865
6522
|
children
|
|
5866
6523
|
}) {
|
|
5867
|
-
return /* @__PURE__ */
|
|
5868
|
-
if (!
|
|
6524
|
+
return /* @__PURE__ */ jsx8(Fragment3, { children: React8.Children.map(children, (child) => {
|
|
6525
|
+
if (!React8.isValidElement(child)) return child;
|
|
5869
6526
|
const existing = child.props;
|
|
5870
6527
|
const injected = {};
|
|
5871
6528
|
if (!existing.sessionId) injected.sessionId = sessionId;
|
|
@@ -5880,7 +6537,7 @@ function SessionInjector({
|
|
|
5880
6537
|
injected.lastName = session.customer.lastName;
|
|
5881
6538
|
}
|
|
5882
6539
|
if (Object.keys(injected).length === 0) return child;
|
|
5883
|
-
return
|
|
6540
|
+
return React8.cloneElement(child, injected);
|
|
5884
6541
|
}) });
|
|
5885
6542
|
}
|
|
5886
6543
|
function InterimButtonsView({
|
|
@@ -5902,7 +6559,7 @@ function InterimButtonsView({
|
|
|
5902
6559
|
}) {
|
|
5903
6560
|
const [showCardForm, setShowCardForm] = useState4(false);
|
|
5904
6561
|
const isCardOpenControlled = typeof cardOpen === "boolean";
|
|
5905
|
-
|
|
6562
|
+
useEffect6(() => {
|
|
5906
6563
|
if (isCardOpenControlled) {
|
|
5907
6564
|
setShowCardForm(cardOpen);
|
|
5908
6565
|
}
|
|
@@ -5923,7 +6580,7 @@ function InterimButtonsView({
|
|
|
5923
6580
|
};
|
|
5924
6581
|
}, [themeBundle, buttonsTheme, stylesOverride]);
|
|
5925
6582
|
const skeletonRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
5926
|
-
const skeleton = (h) => /* @__PURE__ */
|
|
6583
|
+
const skeleton = (h) => /* @__PURE__ */ jsx8("div", { style: {
|
|
5927
6584
|
height: h,
|
|
5928
6585
|
borderRadius: skeletonRadius,
|
|
5929
6586
|
background: "#e5e7eb",
|
|
@@ -5970,7 +6627,7 @@ function InterimButtonsView({
|
|
|
5970
6627
|
...bStyles.backButton
|
|
5971
6628
|
},
|
|
5972
6629
|
children: [
|
|
5973
|
-
/* @__PURE__ */
|
|
6630
|
+
/* @__PURE__ */ jsx8("span", { style: {
|
|
5974
6631
|
display: "inline-flex",
|
|
5975
6632
|
alignItems: "center",
|
|
5976
6633
|
justifyContent: "center",
|
|
@@ -5979,12 +6636,12 @@ function InterimButtonsView({
|
|
|
5979
6636
|
borderRadius: "50%",
|
|
5980
6637
|
backgroundColor: "#f3f4f6",
|
|
5981
6638
|
...bStyles.backButtonIcon
|
|
5982
|
-
}, children: /* @__PURE__ */
|
|
5983
|
-
/* @__PURE__ */
|
|
6639
|
+
}, children: /* @__PURE__ */ jsx8("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
6640
|
+
/* @__PURE__ */ jsx8(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
5984
6641
|
]
|
|
5985
6642
|
}
|
|
5986
6643
|
),
|
|
5987
|
-
hideTitle ? /* @__PURE__ */
|
|
6644
|
+
hideTitle ? /* @__PURE__ */ jsx8("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx8("div", { style: {
|
|
5988
6645
|
flex: 1,
|
|
5989
6646
|
textAlign: "center",
|
|
5990
6647
|
fontWeight: 600,
|
|
@@ -5992,11 +6649,11 @@ function InterimButtonsView({
|
|
|
5992
6649
|
color: "#262833",
|
|
5993
6650
|
paddingRight: 80,
|
|
5994
6651
|
...bStyles.title
|
|
5995
|
-
}, children: /* @__PURE__ */
|
|
6652
|
+
}, children: /* @__PURE__ */ jsx8(TitleContentSlot, { content: cardTitleContent }) })
|
|
5996
6653
|
] }),
|
|
5997
|
-
/* @__PURE__ */
|
|
6654
|
+
/* @__PURE__ */ jsx8("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx8("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
5998
6655
|
/* @__PURE__ */ jsxs5("div", { style: { display: "flex" }, children: [
|
|
5999
|
-
/* @__PURE__ */
|
|
6656
|
+
/* @__PURE__ */ jsx8("div", { style: {
|
|
6000
6657
|
flex: 1,
|
|
6001
6658
|
backgroundColor: inputBg,
|
|
6002
6659
|
borderTop: "none",
|
|
@@ -6006,8 +6663,8 @@ function InterimButtonsView({
|
|
|
6006
6663
|
borderBottomLeftRadius: 8,
|
|
6007
6664
|
padding: 12,
|
|
6008
6665
|
height: 45
|
|
6009
|
-
}, children: /* @__PURE__ */
|
|
6010
|
-
/* @__PURE__ */
|
|
6666
|
+
}, children: /* @__PURE__ */ jsx8("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
6667
|
+
/* @__PURE__ */ jsx8("div", { style: {
|
|
6011
6668
|
flex: 1,
|
|
6012
6669
|
backgroundColor: inputBg,
|
|
6013
6670
|
borderTop: "none",
|
|
@@ -6017,10 +6674,10 @@ function InterimButtonsView({
|
|
|
6017
6674
|
borderBottomRightRadius: 8,
|
|
6018
6675
|
padding: 12,
|
|
6019
6676
|
height: 45
|
|
6020
|
-
}, children: /* @__PURE__ */
|
|
6677
|
+
}, children: /* @__PURE__ */ jsx8("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
|
|
6021
6678
|
] }),
|
|
6022
|
-
/* @__PURE__ */
|
|
6023
|
-
/* @__PURE__ */
|
|
6679
|
+
/* @__PURE__ */ jsx8("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx8("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
6680
|
+
/* @__PURE__ */ jsx8("div", { style: {
|
|
6024
6681
|
height: 50,
|
|
6025
6682
|
borderRadius: 8,
|
|
6026
6683
|
marginTop: 16,
|
|
@@ -6029,7 +6686,7 @@ function InterimButtonsView({
|
|
|
6029
6686
|
...bStyles.submitButton,
|
|
6030
6687
|
opacity: 0.5
|
|
6031
6688
|
} }),
|
|
6032
|
-
/* @__PURE__ */
|
|
6689
|
+
/* @__PURE__ */ jsx8("style", { children: `
|
|
6033
6690
|
@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
6034
6691
|
@keyframes flopay-interim-expand {
|
|
6035
6692
|
0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
|
|
@@ -6042,7 +6699,7 @@ function InterimButtonsView({
|
|
|
6042
6699
|
return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
6043
6700
|
showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
6044
6701
|
showStripe && (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
6045
|
-
showStripe && /* @__PURE__ */
|
|
6702
|
+
showStripe && /* @__PURE__ */ jsx8(
|
|
6046
6703
|
"button",
|
|
6047
6704
|
{
|
|
6048
6705
|
type: "button",
|
|
@@ -6082,7 +6739,7 @@ function InterimButtonsView({
|
|
|
6082
6739
|
onMouseUp: (e) => {
|
|
6083
6740
|
e.currentTarget.style.transform = "scale(1)";
|
|
6084
6741
|
},
|
|
6085
|
-
children: /* @__PURE__ */
|
|
6742
|
+
children: /* @__PURE__ */ jsx8(CardButtonContentSlot, { content: cardButtonContent })
|
|
6086
6743
|
}
|
|
6087
6744
|
),
|
|
6088
6745
|
errorMessage && /* @__PURE__ */ jsxs5("div", { style: {
|
|
@@ -6099,22 +6756,22 @@ function InterimButtonsView({
|
|
|
6099
6756
|
gap: "0.5rem",
|
|
6100
6757
|
...bStyles.errorBanner
|
|
6101
6758
|
}, children: [
|
|
6102
|
-
/* @__PURE__ */
|
|
6759
|
+
/* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx8("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" }) }),
|
|
6103
6760
|
errorMessage
|
|
6104
6761
|
] }),
|
|
6105
|
-
/* @__PURE__ */
|
|
6762
|
+
/* @__PURE__ */ jsx8("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
6106
6763
|
] });
|
|
6107
6764
|
}
|
|
6108
6765
|
|
|
6109
6766
|
// src/checkout-form.tsx
|
|
6110
6767
|
import { PaymentAPI as PaymentAPI5 } from "@flopay/js";
|
|
6111
6768
|
import { FloPayError as FloPayError6 } from "@flopay/shared";
|
|
6112
|
-
import { forwardRef as forwardRef2, useCallback as useCallback3, useEffect as
|
|
6113
|
-
import { Fragment as Fragment4, jsx as
|
|
6769
|
+
import { forwardRef as forwardRef2, useCallback as useCallback3, useEffect as useEffect7, useImperativeHandle as useImperativeHandle2, useState as useState5 } from "react";
|
|
6770
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
6114
6771
|
var WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
6115
6772
|
var CheckoutForm = forwardRef2(
|
|
6116
6773
|
function CheckoutForm2(props, ref) {
|
|
6117
|
-
return /* @__PURE__ */
|
|
6774
|
+
return /* @__PURE__ */ jsx9(CheckoutFormInner, { ...props, innerRef: ref });
|
|
6118
6775
|
}
|
|
6119
6776
|
);
|
|
6120
6777
|
function CheckoutFormInner({
|
|
@@ -6313,7 +6970,7 @@ function CheckoutFormInner({
|
|
|
6313
6970
|
}
|
|
6314
6971
|
}
|
|
6315
6972
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
6316
|
-
|
|
6973
|
+
useEffect7(() => {
|
|
6317
6974
|
if (typeof window === "undefined") return;
|
|
6318
6975
|
const stored = localStorage.getItem(WALLET_RESUME_KEY);
|
|
6319
6976
|
if (!stored) return;
|
|
@@ -6424,7 +7081,7 @@ function CheckoutFormInner({
|
|
|
6424
7081
|
);
|
|
6425
7082
|
const isReady = flopay !== null && elements !== null;
|
|
6426
7083
|
return /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
6427
|
-
(is3DSActive || isSubmitting) && /* @__PURE__ */
|
|
7084
|
+
(is3DSActive || isSubmitting) && /* @__PURE__ */ jsx9("div", { "data-testid": "flopay-overlay", style: {
|
|
6428
7085
|
position: "absolute",
|
|
6429
7086
|
inset: 0,
|
|
6430
7087
|
background: "rgba(255,255,255,0.7)",
|
|
@@ -6433,12 +7090,12 @@ function CheckoutFormInner({
|
|
|
6433
7090
|
justifyContent: "center",
|
|
6434
7091
|
zIndex: 10
|
|
6435
7092
|
}, children: is3DSActive ? "Verifying payment..." : "Processing..." }),
|
|
6436
|
-
!isReady && /* @__PURE__ */
|
|
7093
|
+
!isReady && /* @__PURE__ */ jsx9("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
|
|
6437
7094
|
isReady && /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
6438
|
-
/* @__PURE__ */
|
|
6439
|
-
showAddress && /* @__PURE__ */
|
|
6440
|
-
displayError && /* @__PURE__ */
|
|
6441
|
-
children ?? /* @__PURE__ */
|
|
7095
|
+
/* @__PURE__ */ jsx9(PaymentElement, { options: { layout } }),
|
|
7096
|
+
showAddress && /* @__PURE__ */ jsx9(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
|
|
7097
|
+
displayError && /* @__PURE__ */ jsx9("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
|
|
7098
|
+
children ?? /* @__PURE__ */ jsx9(
|
|
6442
7099
|
"button",
|
|
6443
7100
|
{
|
|
6444
7101
|
type: "submit",
|
|
@@ -6454,8 +7111,8 @@ function CheckoutFormInner({
|
|
|
6454
7111
|
// src/paypal-button.tsx
|
|
6455
7112
|
import { PaymentAPI as PaymentAPI6 } from "@flopay/js";
|
|
6456
7113
|
import { FloPayError as FloPayError7 } from "@flopay/shared";
|
|
6457
|
-
import { useCallback as useCallback4, useEffect as
|
|
6458
|
-
import { Fragment as Fragment5, jsx as
|
|
7114
|
+
import { useCallback as useCallback4, useEffect as useEffect8, useRef as useRef6, useState as useState6 } from "react";
|
|
7115
|
+
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
6459
7116
|
function PayPalButton({
|
|
6460
7117
|
sessionId,
|
|
6461
7118
|
nonce,
|
|
@@ -6475,7 +7132,7 @@ function PayPalButton({
|
|
|
6475
7132
|
const contextBillingUrl = useBillingApiUrl();
|
|
6476
7133
|
const [ready, setReady] = useState6(false);
|
|
6477
7134
|
const [submitting, setSubmitting] = useState6(false);
|
|
6478
|
-
const paypalResumeAttempted =
|
|
7135
|
+
const paypalResumeAttempted = useRef6(false);
|
|
6479
7136
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
6480
7137
|
const processPaymentInternal = useCallback4(
|
|
6481
7138
|
async (tokenizedBody) => {
|
|
@@ -6515,7 +7172,7 @@ function PayPalButton({
|
|
|
6515
7172
|
},
|
|
6516
7173
|
[onTokenizedBody, processPaymentInternal]
|
|
6517
7174
|
);
|
|
6518
|
-
|
|
7175
|
+
useEffect8(() => {
|
|
6519
7176
|
if (!flopay || paypalResumeAttempted.current) return;
|
|
6520
7177
|
const params = new URLSearchParams(window.location.search);
|
|
6521
7178
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -6597,11 +7254,11 @@ function PayPalButton({
|
|
|
6597
7254
|
}
|
|
6598
7255
|
}, [flopay, elements, sessionId, nonce, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
|
|
6599
7256
|
if (!flopay || !elements) {
|
|
6600
|
-
return /* @__PURE__ */
|
|
7257
|
+
return /* @__PURE__ */ jsx10("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
|
|
6601
7258
|
}
|
|
6602
7259
|
return /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
6603
|
-
!ready && /* @__PURE__ */
|
|
6604
|
-
/* @__PURE__ */
|
|
7260
|
+
!ready && /* @__PURE__ */ jsx10("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
|
|
7261
|
+
/* @__PURE__ */ jsx10("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ jsx10(
|
|
6605
7262
|
"button",
|
|
6606
7263
|
{
|
|
6607
7264
|
type: "button",
|
|
@@ -6623,7 +7280,7 @@ function PayPalButton({
|
|
|
6623
7280
|
children: submitting ? "Processing..." : "PayPal"
|
|
6624
7281
|
}
|
|
6625
7282
|
) }),
|
|
6626
|
-
(submitting || isProcessing) && /* @__PURE__ */
|
|
7283
|
+
(submitting || isProcessing) && /* @__PURE__ */ jsx10("div", { style: {
|
|
6627
7284
|
position: "fixed",
|
|
6628
7285
|
inset: 0,
|
|
6629
7286
|
background: "rgba(0,0,0,0.4)",
|
|
@@ -6631,7 +7288,7 @@ function PayPalButton({
|
|
|
6631
7288
|
alignItems: "center",
|
|
6632
7289
|
justifyContent: "center",
|
|
6633
7290
|
zIndex: 1e3
|
|
6634
|
-
}, children: /* @__PURE__ */
|
|
7291
|
+
}, children: /* @__PURE__ */ jsx10("div", { style: {
|
|
6635
7292
|
background: "white",
|
|
6636
7293
|
borderRadius: 8,
|
|
6637
7294
|
padding: "1.5rem",
|
|
@@ -6643,10 +7300,10 @@ function PayPalButton({
|
|
|
6643
7300
|
}
|
|
6644
7301
|
|
|
6645
7302
|
// src/automatic-payment-button.tsx
|
|
6646
|
-
import { useCallback as useCallback5, useEffect as
|
|
7303
|
+
import { useCallback as useCallback5, useEffect as useEffect9, useMemo as useMemo5, useRef as useRef7, useState as useState7 } from "react";
|
|
6647
7304
|
import { PaymentAPI as PaymentAPI7 } from "@flopay/js";
|
|
6648
7305
|
import { FloPayError as FloPayError8, resolveBillingApiUrl as resolveBillingApiUrl4, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme3, resolveTheme as resolveTheme3 } from "@flopay/shared";
|
|
6649
|
-
import { Fragment as Fragment6, jsx as
|
|
7306
|
+
import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
6650
7307
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
|
|
6651
7308
|
function sleep2(ms) {
|
|
6652
7309
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -6714,6 +7371,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
6714
7371
|
billingApiUrl,
|
|
6715
7372
|
locale,
|
|
6716
7373
|
theme,
|
|
7374
|
+
appearance,
|
|
6717
7375
|
buttonsTheme,
|
|
6718
7376
|
buttonsStyles: stylesOverride,
|
|
6719
7377
|
onSuccess,
|
|
@@ -6761,30 +7419,32 @@ function FloPayAutomaticPaymentButton({
|
|
|
6761
7419
|
const [overlayStatus, setOverlayStatus] = useState7(null);
|
|
6762
7420
|
const [overlayError, setOverlayError] = useState7(null);
|
|
6763
7421
|
const [fallbackSession, setFallbackSession] = useState7(null);
|
|
6764
|
-
const isMountedRef =
|
|
6765
|
-
const
|
|
6766
|
-
const
|
|
6767
|
-
const
|
|
6768
|
-
const
|
|
6769
|
-
|
|
7422
|
+
const isMountedRef = useRef7(true);
|
|
7423
|
+
const threeDsAbortRef = useRef7(null);
|
|
7424
|
+
const fallbackSessionRef = useRef7(fallbackSession);
|
|
7425
|
+
const onSuccessRef = useRef7(onSuccess);
|
|
7426
|
+
const onErrorRef = useRef7(onError);
|
|
7427
|
+
const onDeclineRef = useRef7(onDecline);
|
|
7428
|
+
useEffect9(() => {
|
|
6770
7429
|
fallbackSessionRef.current = fallbackSession;
|
|
6771
7430
|
}, [fallbackSession]);
|
|
6772
|
-
|
|
7431
|
+
useEffect9(() => {
|
|
6773
7432
|
onSuccessRef.current = onSuccess;
|
|
6774
7433
|
}, [onSuccess]);
|
|
6775
|
-
|
|
7434
|
+
useEffect9(() => {
|
|
6776
7435
|
onErrorRef.current = onError;
|
|
6777
7436
|
}, [onError]);
|
|
6778
|
-
|
|
7437
|
+
useEffect9(() => {
|
|
6779
7438
|
onDeclineRef.current = onDecline;
|
|
6780
7439
|
}, [onDecline]);
|
|
6781
|
-
|
|
7440
|
+
useEffect9(() => {
|
|
6782
7441
|
isMountedRef.current = true;
|
|
6783
7442
|
return () => {
|
|
6784
7443
|
isMountedRef.current = false;
|
|
7444
|
+
threeDsAbortRef.current?.abort();
|
|
6785
7445
|
};
|
|
6786
7446
|
}, []);
|
|
6787
|
-
|
|
7447
|
+
useEffect9(() => {
|
|
6788
7448
|
if (!fallbackSession || typeof window === "undefined") {
|
|
6789
7449
|
return;
|
|
6790
7450
|
}
|
|
@@ -6863,6 +7523,62 @@ function FloPayAutomaticPaymentButton({
|
|
|
6863
7523
|
return;
|
|
6864
7524
|
}
|
|
6865
7525
|
if (apiResult.autoProcessingError) {
|
|
7526
|
+
if (apiResult.autoProcessingError.type === "3ds_required" && apiResult.autoProcessingError.nextActionRedirectUrl && resolvedSessionId && effectiveNonce) {
|
|
7527
|
+
const threeDsAbort = new AbortController();
|
|
7528
|
+
threeDsAbortRef.current = threeDsAbort;
|
|
7529
|
+
let outcome;
|
|
7530
|
+
try {
|
|
7531
|
+
outcome = await runAutoCheckoutThreeDsChallenge({
|
|
7532
|
+
billingApiUrl: resolvedBillingUrl,
|
|
7533
|
+
sessionId: resolvedSessionId,
|
|
7534
|
+
nonce: effectiveNonce,
|
|
7535
|
+
nextActionRedirectUrl: apiResult.autoProcessingError.nextActionRedirectUrl,
|
|
7536
|
+
signal: threeDsAbort.signal
|
|
7537
|
+
});
|
|
7538
|
+
} finally {
|
|
7539
|
+
if (threeDsAbortRef.current === threeDsAbort) {
|
|
7540
|
+
threeDsAbortRef.current = null;
|
|
7541
|
+
}
|
|
7542
|
+
}
|
|
7543
|
+
if (outcome.status === "declined") {
|
|
7544
|
+
throw checkoutProcessErrorToFloPayError(
|
|
7545
|
+
{
|
|
7546
|
+
type: outcome.declineReason ?? "decline",
|
|
7547
|
+
message: "Card was declined.",
|
|
7548
|
+
gatewayErrorCode: outcome.gatewayDeclineReason ?? void 0
|
|
7549
|
+
},
|
|
7550
|
+
"Card was declined.",
|
|
7551
|
+
{
|
|
7552
|
+
checkoutMethod: apiResult.autoProcessingError.checkoutMethod
|
|
7553
|
+
}
|
|
7554
|
+
);
|
|
7555
|
+
}
|
|
7556
|
+
const api = new PaymentAPI7(resolvedBillingUrl);
|
|
7557
|
+
const completed = await api.waitForCheckoutSessionCompletion(resolvedSessionId, {
|
|
7558
|
+
initialDelayMs: 0,
|
|
7559
|
+
nonce: effectiveNonce
|
|
7560
|
+
});
|
|
7561
|
+
const completedSession = completed.data.session;
|
|
7562
|
+
if (!completedSession || completedSession.status !== "complete") {
|
|
7563
|
+
throw checkoutProcessErrorToFloPayError(
|
|
7564
|
+
{
|
|
7565
|
+
type: "unknown",
|
|
7566
|
+
message: "Card authentication was not completed."
|
|
7567
|
+
},
|
|
7568
|
+
"Card authentication was not completed.",
|
|
7569
|
+
{
|
|
7570
|
+
checkoutMethod: apiResult.autoProcessingError.checkoutMethod
|
|
7571
|
+
}
|
|
7572
|
+
);
|
|
7573
|
+
}
|
|
7574
|
+
await showSuccess({
|
|
7575
|
+
result: { status: "succeeded" },
|
|
7576
|
+
session: completedSession,
|
|
7577
|
+
sessionId: completedSession.id || resolvedSessionId,
|
|
7578
|
+
autoCompleted: false
|
|
7579
|
+
});
|
|
7580
|
+
return;
|
|
7581
|
+
}
|
|
6866
7582
|
throw checkoutProcessErrorToFloPayError(
|
|
6867
7583
|
apiResult.autoProcessingError,
|
|
6868
7584
|
"Automatic payment failed. Please try again.",
|
|
@@ -7030,9 +7746,26 @@ function FloPayAutomaticPaymentButton({
|
|
|
7030
7746
|
cardButton: { ...base.cardButton, ...stylesOverride.cardButton }
|
|
7031
7747
|
};
|
|
7032
7748
|
}, [themeBundle, buttonsTheme, stylesOverride]);
|
|
7749
|
+
const resolvedAppearance = useMemo5(() => {
|
|
7750
|
+
const bundleAppearance = themeBundle?.appearance;
|
|
7751
|
+
if (!appearance) return bundleAppearance;
|
|
7752
|
+
if (!bundleAppearance) return appearance;
|
|
7753
|
+
return {
|
|
7754
|
+
...bundleAppearance,
|
|
7755
|
+
...appearance,
|
|
7756
|
+
variables: {
|
|
7757
|
+
...bundleAppearance.variables,
|
|
7758
|
+
...appearance.variables
|
|
7759
|
+
}
|
|
7760
|
+
};
|
|
7761
|
+
}, [appearance, themeBundle]);
|
|
7762
|
+
const resolvedAppearanceVars = resolvedAppearance?.variables;
|
|
7763
|
+
const resolvedPrimaryColor = resolvedAppearanceVars?.colorPrimary ?? "#4A49FF";
|
|
7764
|
+
const resolvedPrimaryHoverColor = resolvedAppearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
|
|
7765
|
+
const resolvedButtonBorderRadius = resolvedAppearanceVars?.borderRadius ?? "8px";
|
|
7033
7766
|
const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
7034
7767
|
return /* @__PURE__ */ jsxs8(Fragment6, { children: [
|
|
7035
|
-
/* @__PURE__ */
|
|
7768
|
+
/* @__PURE__ */ jsx11(
|
|
7036
7769
|
"button",
|
|
7037
7770
|
{
|
|
7038
7771
|
...buttonProps,
|
|
@@ -7048,14 +7781,17 @@ function FloPayAutomaticPaymentButton({
|
|
|
7048
7781
|
// on top so the auto-pay button carries the *submit* button's
|
|
7049
7782
|
// background and text colours — making it visually identical to
|
|
7050
7783
|
// the "Confirm Payment" / "Pay with X" actions it stands in for.
|
|
7784
|
+
// `resolvedPrimaryColor` is the *merged* appearance value, so a
|
|
7785
|
+
// per-checkout `colorPrimary` override re-skins this button too.
|
|
7051
7786
|
// Inline `style` consumer override stays at the end so explicit
|
|
7052
7787
|
// per-button overrides still win.
|
|
7053
7788
|
...bStyles.cardButton,
|
|
7054
7789
|
...derivePrimaryTileStyle({
|
|
7055
7790
|
themeBundle,
|
|
7056
|
-
resolvedPrimaryColor
|
|
7057
|
-
resolvedBorderRadius:
|
|
7058
|
-
submitButtonStyle: bStyles.submitButton
|
|
7791
|
+
resolvedPrimaryColor,
|
|
7792
|
+
resolvedBorderRadius: resolvedButtonBorderRadius,
|
|
7793
|
+
submitButtonStyle: bStyles.submitButton,
|
|
7794
|
+
explicitPrimaryColor: resolvedAppearanceVars?.colorPrimary
|
|
7059
7795
|
}),
|
|
7060
7796
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
7061
7797
|
fontWeight: 600,
|
|
@@ -7064,11 +7800,23 @@ function FloPayAutomaticPaymentButton({
|
|
|
7064
7800
|
alignItems: "center",
|
|
7065
7801
|
justifyContent: "center",
|
|
7066
7802
|
gap: "0.625rem",
|
|
7067
|
-
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
7803
|
+
transition: "background-color 0.15s, border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
7068
7804
|
position: "relative",
|
|
7069
7805
|
opacity: disabled || isProcessing ? 0.6 : 1,
|
|
7070
7806
|
...style
|
|
7071
7807
|
},
|
|
7808
|
+
onMouseEnter: (e) => {
|
|
7809
|
+
buttonProps.onMouseEnter?.(e);
|
|
7810
|
+
if (!e.defaultPrevented && !disabled && !isProcessing && (themeBundle || resolvedAppearanceVars?.colorPrimary)) {
|
|
7811
|
+
e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
|
|
7812
|
+
}
|
|
7813
|
+
},
|
|
7814
|
+
onMouseLeave: (e) => {
|
|
7815
|
+
buttonProps.onMouseLeave?.(e);
|
|
7816
|
+
if (!e.defaultPrevented && (themeBundle || resolvedAppearanceVars?.colorPrimary)) {
|
|
7817
|
+
e.currentTarget.style.backgroundColor = resolvedPrimaryColor;
|
|
7818
|
+
}
|
|
7819
|
+
},
|
|
7072
7820
|
onMouseDown: (e) => {
|
|
7073
7821
|
buttonProps.onMouseDown?.(e);
|
|
7074
7822
|
if (!e.defaultPrevented) {
|
|
@@ -7081,17 +7829,17 @@ function FloPayAutomaticPaymentButton({
|
|
|
7081
7829
|
e.currentTarget.style.transform = "scale(1)";
|
|
7082
7830
|
}
|
|
7083
7831
|
},
|
|
7084
|
-
children: /* @__PURE__ */
|
|
7832
|
+
children: /* @__PURE__ */ jsx11(CardButtonContentSlot, { content: children })
|
|
7085
7833
|
}
|
|
7086
7834
|
),
|
|
7087
|
-
overlayStatus && /* @__PURE__ */
|
|
7835
|
+
overlayStatus && /* @__PURE__ */ jsx11(
|
|
7088
7836
|
ProcessingOverlay,
|
|
7089
7837
|
{
|
|
7090
7838
|
status: overlayStatus,
|
|
7091
7839
|
errorMessage: overlayError
|
|
7092
7840
|
}
|
|
7093
7841
|
),
|
|
7094
|
-
fallbackSession && /* @__PURE__ */
|
|
7842
|
+
fallbackSession && /* @__PURE__ */ jsx11(
|
|
7095
7843
|
"div",
|
|
7096
7844
|
{
|
|
7097
7845
|
"data-testid": "flopay-automatic-payment-fallback",
|
|
@@ -7112,7 +7860,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
7112
7860
|
padding: "1.5rem",
|
|
7113
7861
|
zIndex: 1100
|
|
7114
7862
|
},
|
|
7115
|
-
children: /* @__PURE__ */
|
|
7863
|
+
children: /* @__PURE__ */ jsx11(
|
|
7116
7864
|
"div",
|
|
7117
7865
|
{
|
|
7118
7866
|
style: {
|
|
@@ -7128,7 +7876,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
7128
7876
|
flexDirection: "column",
|
|
7129
7877
|
gap: "1rem"
|
|
7130
7878
|
},
|
|
7131
|
-
children: /* @__PURE__ */
|
|
7879
|
+
children: /* @__PURE__ */ jsx11(
|
|
7132
7880
|
FloPayCheckout,
|
|
7133
7881
|
{
|
|
7134
7882
|
sessionId: fallbackSession.sessionId,
|
|
@@ -7137,6 +7885,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
7137
7885
|
billingApiUrl: resolvedBillingUrl,
|
|
7138
7886
|
locale,
|
|
7139
7887
|
theme,
|
|
7888
|
+
...resolvedAppearance ? { appearance: resolvedAppearance } : {},
|
|
7140
7889
|
buttonsTheme,
|
|
7141
7890
|
buttonsStyles: stylesOverride,
|
|
7142
7891
|
initialErrorMessage: fallbackSession.errorMessage,
|
|
@@ -7166,6 +7915,7 @@ export {
|
|
|
7166
7915
|
PayPalButton,
|
|
7167
7916
|
PaymentElement,
|
|
7168
7917
|
SplitCardForm,
|
|
7918
|
+
VaultCardFields,
|
|
7169
7919
|
useCheckout,
|
|
7170
7920
|
useElements,
|
|
7171
7921
|
useFloPay,
|