@flopay/react 1.2.7 → 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 +1468 -675
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +104 -5
- package/dist/index.d.ts +104 -5
- package/dist/index.mjs +1272 -482
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,7 @@ __export(index_exports, {
|
|
|
43
43
|
PayPalButton: () => PayPalButton,
|
|
44
44
|
PaymentElement: () => PaymentElement,
|
|
45
45
|
SplitCardForm: () => SplitCardForm,
|
|
46
|
+
VaultCardFields: () => VaultCardFields,
|
|
46
47
|
useCheckout: () => useCheckout,
|
|
47
48
|
useElements: () => useElements,
|
|
48
49
|
useFloPay: () => useFloPay,
|
|
@@ -152,7 +153,7 @@ function FloPayProvider({
|
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
// src/flopay-checkout.tsx
|
|
155
|
-
var
|
|
156
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
156
157
|
var import_js4 = require("@flopay/js");
|
|
157
158
|
var import_shared8 = require("@flopay/shared");
|
|
158
159
|
|
|
@@ -287,41 +288,114 @@ var AddressElement = createElementComponent("address", "AddressElement");
|
|
|
287
288
|
var import_react_stripe_js = require("@stripe/react-stripe-js");
|
|
288
289
|
var import_shared5 = require("@flopay/shared");
|
|
289
290
|
var import_js2 = require("@flopay/js");
|
|
290
|
-
var import_react8 = __toESM(require("react"), 1);
|
|
291
291
|
|
|
292
|
-
// src/
|
|
292
|
+
// src/vault-card-fields.tsx
|
|
293
293
|
var import_react5 = require("react");
|
|
294
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
295
|
+
function VaultCardFields({
|
|
296
|
+
capture,
|
|
297
|
+
html,
|
|
298
|
+
messageToken,
|
|
299
|
+
expectedOrigin,
|
|
300
|
+
theme,
|
|
301
|
+
containerStyle,
|
|
302
|
+
onReady,
|
|
303
|
+
onError,
|
|
304
|
+
onValidation
|
|
305
|
+
}) {
|
|
306
|
+
const containerRef = (0, import_react5.useRef)(null);
|
|
307
|
+
const onReadyRef = (0, import_react5.useRef)(onReady);
|
|
308
|
+
const onErrorRef = (0, import_react5.useRef)(onError);
|
|
309
|
+
const onValidationRef = (0, import_react5.useRef)(onValidation);
|
|
310
|
+
onReadyRef.current = onReady;
|
|
311
|
+
onErrorRef.current = onError;
|
|
312
|
+
onValidationRef.current = onValidation;
|
|
313
|
+
const themeRef = (0, import_react5.useRef)(theme);
|
|
314
|
+
themeRef.current = theme;
|
|
315
|
+
(0, import_react5.useEffect)(() => {
|
|
316
|
+
const el = containerRef.current;
|
|
317
|
+
if (!el) return;
|
|
318
|
+
let active = true;
|
|
319
|
+
let readyEmitted = false;
|
|
320
|
+
const emitReadyOnce = () => {
|
|
321
|
+
if (!active || readyEmitted) return;
|
|
322
|
+
readyEmitted = true;
|
|
323
|
+
onReadyRef.current?.();
|
|
324
|
+
};
|
|
325
|
+
const offReady = capture.on("ready", () => {
|
|
326
|
+
emitReadyOnce();
|
|
327
|
+
});
|
|
328
|
+
const offError = capture.on("error", (event) => {
|
|
329
|
+
onErrorRef.current?.(event.message ?? "There was a problem loading the secure card form.");
|
|
330
|
+
});
|
|
331
|
+
const offValidation = capture.on("validation", (event) => {
|
|
332
|
+
onValidationRef.current?.(event.message ?? null);
|
|
333
|
+
});
|
|
334
|
+
const mountOptions = {
|
|
335
|
+
html,
|
|
336
|
+
...messageToken ? { messageToken } : {},
|
|
337
|
+
...expectedOrigin ? { expectedOrigin } : {},
|
|
338
|
+
...themeRef.current ? { theme: themeRef.current } : {}
|
|
339
|
+
};
|
|
340
|
+
capture.mount(el, mountOptions).then(() => {
|
|
341
|
+
emitReadyOnce();
|
|
342
|
+
}).catch((err) => {
|
|
343
|
+
if (active) {
|
|
344
|
+
onErrorRef.current?.(
|
|
345
|
+
err instanceof Error ? err.message : "Failed to load the secure card form."
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
return () => {
|
|
350
|
+
active = false;
|
|
351
|
+
offReady();
|
|
352
|
+
offError();
|
|
353
|
+
offValidation();
|
|
354
|
+
capture.unmount();
|
|
355
|
+
};
|
|
356
|
+
}, [capture, html, messageToken, expectedOrigin]);
|
|
357
|
+
(0, import_react5.useEffect)(() => {
|
|
358
|
+
if (theme) capture.applyTheme?.(theme);
|
|
359
|
+
}, [capture, theme]);
|
|
360
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: containerRef, "data-testid": "flopay-vault-card-fields", style: containerStyle });
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// src/split-card-form.tsx
|
|
364
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
365
|
+
|
|
366
|
+
// src/hooks.ts
|
|
367
|
+
var import_react6 = require("react");
|
|
294
368
|
var import_shared2 = require("@flopay/shared");
|
|
295
369
|
function useFloPay() {
|
|
296
|
-
const ctx = (0,
|
|
370
|
+
const ctx = (0, import_react6.useContext)(FloPayContext);
|
|
297
371
|
return ctx.flopay;
|
|
298
372
|
}
|
|
299
373
|
function usePayPalFloPay() {
|
|
300
|
-
const ctx = (0,
|
|
374
|
+
const ctx = (0, import_react6.useContext)(FloPayContext);
|
|
301
375
|
return ctx.paypalFlopay ?? null;
|
|
302
376
|
}
|
|
303
377
|
function useElements() {
|
|
304
|
-
const ctx = (0,
|
|
378
|
+
const ctx = (0, import_react6.useContext)(FloPayContext);
|
|
305
379
|
return ctx.elements;
|
|
306
380
|
}
|
|
307
381
|
function useCheckout() {
|
|
308
|
-
return (0,
|
|
382
|
+
return (0, import_react6.useContext)(CheckoutContext);
|
|
309
383
|
}
|
|
310
384
|
function useBillingApiUrl() {
|
|
311
|
-
const ctx = (0,
|
|
385
|
+
const ctx = (0, import_react6.useContext)(FloPayContext);
|
|
312
386
|
return ctx.billingApiUrl || (0, import_shared2.resolveBillingApiUrl)();
|
|
313
387
|
}
|
|
314
388
|
|
|
315
389
|
// src/processing-overlay.tsx
|
|
316
|
-
var
|
|
317
|
-
var
|
|
390
|
+
var import_react7 = require("react");
|
|
391
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
318
392
|
var PROCESSING_OVERLAY_SUCCESS_DELAY_MS = 1200;
|
|
319
393
|
var PROCESSING_OVERLAY_ERROR_DELAY_MS = 1500;
|
|
320
394
|
function ProcessingOverlay({
|
|
321
395
|
status,
|
|
322
396
|
errorMessage
|
|
323
397
|
}) {
|
|
324
|
-
return /* @__PURE__ */ (0,
|
|
398
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
325
399
|
"div",
|
|
326
400
|
{
|
|
327
401
|
"data-testid": "flopay-processing-overlay",
|
|
@@ -338,7 +412,7 @@ function ProcessingOverlay({
|
|
|
338
412
|
zIndex: 1e3,
|
|
339
413
|
backdropFilter: "blur(2px)"
|
|
340
414
|
},
|
|
341
|
-
children: /* @__PURE__ */ (0,
|
|
415
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
342
416
|
"div",
|
|
343
417
|
{
|
|
344
418
|
style: {
|
|
@@ -354,8 +428,8 @@ function ProcessingOverlay({
|
|
|
354
428
|
gap: 16
|
|
355
429
|
},
|
|
356
430
|
children: [
|
|
357
|
-
/* @__PURE__ */ (0,
|
|
358
|
-
status === "processing" && /* @__PURE__ */ (0,
|
|
431
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { width: 48, height: 48, position: "relative" }, children: [
|
|
432
|
+
status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
359
433
|
"svg",
|
|
360
434
|
{
|
|
361
435
|
width: "48",
|
|
@@ -365,14 +439,14 @@ function ProcessingOverlay({
|
|
|
365
439
|
xmlns: "http://www.w3.org/2000/svg",
|
|
366
440
|
style: { animation: "flopay-spin 0.8s linear infinite" },
|
|
367
441
|
children: [
|
|
368
|
-
/* @__PURE__ */ (0,
|
|
369
|
-
/* @__PURE__ */ (0,
|
|
442
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
|
|
443
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
|
|
370
444
|
]
|
|
371
445
|
}
|
|
372
446
|
),
|
|
373
|
-
status === "success" && /* @__PURE__ */ (0,
|
|
374
|
-
/* @__PURE__ */ (0,
|
|
375
|
-
/* @__PURE__ */ (0,
|
|
447
|
+
status === "success" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
448
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
|
|
449
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
376
450
|
"path",
|
|
377
451
|
{
|
|
378
452
|
d: "M7 12.5l3 3 7-7",
|
|
@@ -388,9 +462,9 @@ function ProcessingOverlay({
|
|
|
388
462
|
}
|
|
389
463
|
)
|
|
390
464
|
] }) }),
|
|
391
|
-
status === "error" && /* @__PURE__ */ (0,
|
|
392
|
-
/* @__PURE__ */ (0,
|
|
393
|
-
/* @__PURE__ */ (0,
|
|
465
|
+
status === "error" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
466
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
|
|
467
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
394
468
|
"path",
|
|
395
469
|
{
|
|
396
470
|
d: "M8 8l8 8M16 8l-8 8",
|
|
@@ -406,7 +480,7 @@ function ProcessingOverlay({
|
|
|
406
480
|
)
|
|
407
481
|
] }) })
|
|
408
482
|
] }),
|
|
409
|
-
/* @__PURE__ */ (0,
|
|
483
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
410
484
|
"span",
|
|
411
485
|
{
|
|
412
486
|
style: {
|
|
@@ -422,7 +496,7 @@ function ProcessingOverlay({
|
|
|
422
496
|
]
|
|
423
497
|
}
|
|
424
498
|
),
|
|
425
|
-
status === "success" && /* @__PURE__ */ (0,
|
|
499
|
+
status === "success" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
426
500
|
"p",
|
|
427
501
|
{
|
|
428
502
|
style: {
|
|
@@ -436,7 +510,7 @@ function ProcessingOverlay({
|
|
|
436
510
|
children: "You will be automatically redirected, do not close or navigate away from this window."
|
|
437
511
|
}
|
|
438
512
|
),
|
|
439
|
-
status === "error" && errorMessage && /* @__PURE__ */ (0,
|
|
513
|
+
status === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
440
514
|
"p",
|
|
441
515
|
{
|
|
442
516
|
style: {
|
|
@@ -450,7 +524,7 @@ function ProcessingOverlay({
|
|
|
450
524
|
children: errorMessage
|
|
451
525
|
}
|
|
452
526
|
),
|
|
453
|
-
/* @__PURE__ */ (0,
|
|
527
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
|
|
454
528
|
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
455
529
|
@keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
|
|
456
530
|
@keyframes flopay-draw { to { stroke-dashoffset: 0; } }
|
|
@@ -633,6 +707,18 @@ function resolvePaymentIntentPaymentMethodId(paymentIntent) {
|
|
|
633
707
|
}
|
|
634
708
|
async function retrievePaymentIntentFromProvider(provider, clientSecret) {
|
|
635
709
|
const retriever = provider;
|
|
710
|
+
if ((0, import_shared3.isSetupIntentClientSecret)(clientSecret)) {
|
|
711
|
+
if (!retriever?.retrieveSetupIntent) {
|
|
712
|
+
return null;
|
|
713
|
+
}
|
|
714
|
+
const { setupIntent, error: error2 } = await retriever.retrieveSetupIntent(clientSecret);
|
|
715
|
+
if (error2) {
|
|
716
|
+
throw new import_shared3.FloPayError(error2.message ?? "Failed to retrieve setup intent.", "api_error", {
|
|
717
|
+
...error2.code ? { code: error2.code } : {}
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
return setupIntent ?? null;
|
|
721
|
+
}
|
|
636
722
|
if (!retriever?.retrievePaymentIntent) {
|
|
637
723
|
return null;
|
|
638
724
|
}
|
|
@@ -644,6 +730,12 @@ async function retrievePaymentIntentFromProvider(provider, clientSecret) {
|
|
|
644
730
|
}
|
|
645
731
|
return paymentIntent ?? null;
|
|
646
732
|
}
|
|
733
|
+
function resolveWalletElementsMode(amountInMinorUnits) {
|
|
734
|
+
if (typeof amountInMinorUnits !== "number" || !Number.isFinite(amountInMinorUnits) || amountInMinorUnits <= 0) {
|
|
735
|
+
return { mode: "setup" };
|
|
736
|
+
}
|
|
737
|
+
return { mode: "payment", amount: amountInMinorUnits };
|
|
738
|
+
}
|
|
647
739
|
function resolveTokenizedPaymentMethodId(tokenizedBody) {
|
|
648
740
|
const candidates = [
|
|
649
741
|
tokenizedBody?.id,
|
|
@@ -706,11 +798,11 @@ function isInAppBrowser(userAgent) {
|
|
|
706
798
|
}
|
|
707
799
|
|
|
708
800
|
// src/direct-paypal-button.tsx
|
|
709
|
-
var
|
|
801
|
+
var import_react8 = require("react");
|
|
710
802
|
var import_paypal_js = require("@paypal/paypal-js");
|
|
711
803
|
var import_js = require("@flopay/js");
|
|
712
804
|
var import_shared4 = require("@flopay/shared");
|
|
713
|
-
var
|
|
805
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
714
806
|
var DEFAULT_BUTTON_HEIGHT = 45;
|
|
715
807
|
function DirectPayPalButton({
|
|
716
808
|
sessionId,
|
|
@@ -733,62 +825,62 @@ function DirectPayPalButton({
|
|
|
733
825
|
existingOrderId,
|
|
734
826
|
debug = false
|
|
735
827
|
}) {
|
|
736
|
-
const containerRef = (0,
|
|
737
|
-
const [ready, setReady] = (0,
|
|
738
|
-
const [failed, setFailed] = (0,
|
|
739
|
-
const [submitting, setSubmitting] = (0,
|
|
740
|
-
const baseUrl = (0,
|
|
741
|
-
const [debugLines, setDebugLines] = (0,
|
|
828
|
+
const containerRef = (0, import_react8.useRef)(null);
|
|
829
|
+
const [ready, setReady] = (0, import_react8.useState)(false);
|
|
830
|
+
const [failed, setFailed] = (0, import_react8.useState)(false);
|
|
831
|
+
const [submitting, setSubmitting] = (0, import_react8.useState)(false);
|
|
832
|
+
const baseUrl = (0, import_react8.useMemo)(() => billingApiUrl.replace(/\/+$/, ""), [billingApiUrl]);
|
|
833
|
+
const [debugLines, setDebugLines] = (0, import_react8.useState)([]);
|
|
742
834
|
const appendDebug = (line) => {
|
|
743
835
|
if (!debug) return;
|
|
744
836
|
setDebugLines((prev) => [...prev, `${(/* @__PURE__ */ new Date()).toISOString().slice(11, 23)} ${line}`]);
|
|
745
837
|
};
|
|
746
|
-
const onTokenizedBodyRef = (0,
|
|
747
|
-
const onCompleteRef = (0,
|
|
748
|
-
const onErrorChangeRef = (0,
|
|
749
|
-
const onDeclineRef = (0,
|
|
750
|
-
const onButtonClickRef = (0,
|
|
751
|
-
const onLoadStateChangeRef = (0,
|
|
752
|
-
const runBeforeButtonClickRef = (0,
|
|
753
|
-
const sessionRef = (0,
|
|
754
|
-
const emailRef = (0,
|
|
755
|
-
const nonceRef = (0,
|
|
756
|
-
const beforeClickRef = (0,
|
|
757
|
-
(0,
|
|
838
|
+
const onTokenizedBodyRef = (0, import_react8.useRef)(onTokenizedBody);
|
|
839
|
+
const onCompleteRef = (0, import_react8.useRef)(onComplete);
|
|
840
|
+
const onErrorChangeRef = (0, import_react8.useRef)(onErrorChange);
|
|
841
|
+
const onDeclineRef = (0, import_react8.useRef)(onDecline);
|
|
842
|
+
const onButtonClickRef = (0, import_react8.useRef)(onButtonClick);
|
|
843
|
+
const onLoadStateChangeRef = (0, import_react8.useRef)(onLoadStateChange);
|
|
844
|
+
const runBeforeButtonClickRef = (0, import_react8.useRef)(runBeforeButtonClick);
|
|
845
|
+
const sessionRef = (0, import_react8.useRef)(session);
|
|
846
|
+
const emailRef = (0, import_react8.useRef)(email);
|
|
847
|
+
const nonceRef = (0, import_react8.useRef)(nonce);
|
|
848
|
+
const beforeClickRef = (0, import_react8.useRef)(null);
|
|
849
|
+
(0, import_react8.useEffect)(() => {
|
|
758
850
|
onTokenizedBodyRef.current = onTokenizedBody;
|
|
759
851
|
}, [onTokenizedBody]);
|
|
760
|
-
(0,
|
|
852
|
+
(0, import_react8.useEffect)(() => {
|
|
761
853
|
onCompleteRef.current = onComplete;
|
|
762
854
|
}, [onComplete]);
|
|
763
|
-
(0,
|
|
855
|
+
(0, import_react8.useEffect)(() => {
|
|
764
856
|
onErrorChangeRef.current = onErrorChange;
|
|
765
857
|
}, [onErrorChange]);
|
|
766
|
-
(0,
|
|
858
|
+
(0, import_react8.useEffect)(() => {
|
|
767
859
|
onDeclineRef.current = onDecline;
|
|
768
860
|
}, [onDecline]);
|
|
769
|
-
(0,
|
|
861
|
+
(0, import_react8.useEffect)(() => {
|
|
770
862
|
onButtonClickRef.current = onButtonClick;
|
|
771
863
|
}, [onButtonClick]);
|
|
772
|
-
(0,
|
|
864
|
+
(0, import_react8.useEffect)(() => {
|
|
773
865
|
onLoadStateChangeRef.current = onLoadStateChange;
|
|
774
866
|
}, [onLoadStateChange]);
|
|
775
|
-
(0,
|
|
867
|
+
(0, import_react8.useEffect)(() => {
|
|
776
868
|
runBeforeButtonClickRef.current = runBeforeButtonClick;
|
|
777
869
|
}, [runBeforeButtonClick]);
|
|
778
|
-
(0,
|
|
870
|
+
(0, import_react8.useEffect)(() => {
|
|
779
871
|
sessionRef.current = session;
|
|
780
872
|
}, [session]);
|
|
781
|
-
(0,
|
|
873
|
+
(0, import_react8.useEffect)(() => {
|
|
782
874
|
emailRef.current = email;
|
|
783
875
|
}, [email]);
|
|
784
|
-
(0,
|
|
876
|
+
(0, import_react8.useEffect)(() => {
|
|
785
877
|
nonceRef.current = nonce;
|
|
786
878
|
}, [nonce]);
|
|
787
|
-
(0,
|
|
879
|
+
(0, import_react8.useEffect)(() => {
|
|
788
880
|
onLoadStateChangeRef.current?.(ready && !failed);
|
|
789
881
|
}, [ready, failed]);
|
|
790
882
|
const normalizedEnv = (0, import_shared4.normalizeGatewayEnvironment)(environment);
|
|
791
|
-
(0,
|
|
883
|
+
(0, import_react8.useEffect)(() => {
|
|
792
884
|
const maskedClient = clientId ? `${clientId.slice(0, 6)}\u2026(len ${clientId.length})` : "(empty)";
|
|
793
885
|
const ua = typeof navigator !== "undefined" ? navigator.userAgent : "(no navigator)";
|
|
794
886
|
appendDebug(`mount clientId=${maskedClient} env=${environment ?? "(unset)"}\u2192${normalizedEnv ?? "live"} ccy=${currency} sub=${isSubscription}`);
|
|
@@ -1200,7 +1292,7 @@ function DirectPayPalButton({
|
|
|
1200
1292
|
}
|
|
1201
1293
|
};
|
|
1202
1294
|
}, [baseUrl, clientId, currency, environment, isSubscription, sessionId, existingOrderId]);
|
|
1203
|
-
const debugPanel = debug ? /* @__PURE__ */ (0,
|
|
1295
|
+
const debugPanel = debug ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1204
1296
|
"pre",
|
|
1205
1297
|
{
|
|
1206
1298
|
"data-testid": "flopay-direct-paypal-debug",
|
|
@@ -1225,17 +1317,17 @@ ${debugLines.join("\n")}`
|
|
|
1225
1317
|
}
|
|
1226
1318
|
) : null;
|
|
1227
1319
|
if (failed) {
|
|
1228
|
-
return debug ? /* @__PURE__ */ (0,
|
|
1320
|
+
return debug ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: debugPanel }) : null;
|
|
1229
1321
|
}
|
|
1230
1322
|
return (
|
|
1231
1323
|
// Single wrapper so the parent flex container sees exactly one flex item
|
|
1232
1324
|
// (otherwise the fragment's placeholder + container become two siblings
|
|
1233
1325
|
// and any spacing-sensitive layout has to reason about both). The wrapper
|
|
1234
1326
|
// intentionally has no margin/padding so the parent owns all spacing.
|
|
1235
|
-
/* @__PURE__ */ (0,
|
|
1327
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
1236
1328
|
debugPanel,
|
|
1237
|
-
/* @__PURE__ */ (0,
|
|
1238
|
-
!ready && /* @__PURE__ */ (0,
|
|
1329
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { position: "relative", minHeight: DEFAULT_BUTTON_HEIGHT }, children: [
|
|
1330
|
+
!ready && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1239
1331
|
"div",
|
|
1240
1332
|
{
|
|
1241
1333
|
"data-testid": "flopay-direct-paypal-placeholder",
|
|
@@ -1249,7 +1341,7 @@ ${debugLines.join("\n")}`
|
|
|
1249
1341
|
}
|
|
1250
1342
|
}
|
|
1251
1343
|
),
|
|
1252
|
-
/* @__PURE__ */ (0,
|
|
1344
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1253
1345
|
"div",
|
|
1254
1346
|
{
|
|
1255
1347
|
ref: containerRef,
|
|
@@ -1269,10 +1361,28 @@ ${debugLines.join("\n")}`
|
|
|
1269
1361
|
|
|
1270
1362
|
// src/split-card-form.tsx
|
|
1271
1363
|
var import_shared6 = require("@flopay/shared");
|
|
1272
|
-
var
|
|
1364
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1273
1365
|
var STRIPE_RESUME_KEY = "flopay_stripe_resume";
|
|
1274
1366
|
var LEGACY_WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
1275
1367
|
var PAYPAL_RESUME_KEY = "flopay_paypal_resume";
|
|
1368
|
+
function toVaultMount(block) {
|
|
1369
|
+
if (!block?.html) return null;
|
|
1370
|
+
return {
|
|
1371
|
+
html: block.html,
|
|
1372
|
+
...block.messageToken ? { messageToken: block.messageToken } : {},
|
|
1373
|
+
...block.expectedOrigin ? { expectedOrigin: block.expectedOrigin } : {}
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
function darkenHex(hex, amount = 0.12) {
|
|
1377
|
+
const match = /^#?([0-9a-fA-F]{6})$/.exec(hex.trim());
|
|
1378
|
+
if (!match) return hex;
|
|
1379
|
+
const value = parseInt(match[1], 16);
|
|
1380
|
+
const scale = Math.max(0, Math.min(1, 1 - amount));
|
|
1381
|
+
const r = Math.round((value >> 16 & 255) * scale);
|
|
1382
|
+
const g = Math.round((value >> 8 & 255) * scale);
|
|
1383
|
+
const b = Math.round((value & 255) * scale);
|
|
1384
|
+
return `#${(1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1)}`;
|
|
1385
|
+
}
|
|
1276
1386
|
var FLOPAY_KEYFRAMES = `
|
|
1277
1387
|
.paypal-buttons { margin: 0 !important; vertical-align: top !important; }
|
|
1278
1388
|
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
@@ -1297,18 +1407,20 @@ var FLOPAY_KEYFRAMES = `
|
|
|
1297
1407
|
`;
|
|
1298
1408
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT = 44;
|
|
1299
1409
|
function derivePrimaryTileStyle(opts) {
|
|
1300
|
-
if (!opts.themeBundle) {
|
|
1410
|
+
if (!opts.themeBundle && !opts.explicitPrimaryColor) {
|
|
1301
1411
|
return {
|
|
1302
1412
|
backgroundColor: "white",
|
|
1303
1413
|
color: "#262833",
|
|
1304
1414
|
border: "1px solid #d1d5db",
|
|
1305
|
-
borderRadius:
|
|
1415
|
+
borderRadius: opts.resolvedBorderRadius,
|
|
1306
1416
|
boxShadow: "0 1px 2px rgba(0,0,0,0.04)"
|
|
1307
1417
|
};
|
|
1308
1418
|
}
|
|
1309
|
-
const submit = opts.submitButtonStyle ?? {};
|
|
1419
|
+
const submit = opts.themeBundle ? opts.submitButtonStyle ?? {} : {};
|
|
1310
1420
|
return {
|
|
1311
|
-
|
|
1421
|
+
// `colorPrimary` wins so a per-checkout override re-skins the card / auto-pay
|
|
1422
|
+
// buttons in lock-step with the submit CTA (which also keys off it).
|
|
1423
|
+
backgroundColor: opts.resolvedPrimaryColor,
|
|
1312
1424
|
color: submit.color ?? "white",
|
|
1313
1425
|
border: submit.border ?? "none",
|
|
1314
1426
|
borderRadius: submit.borderRadius ?? opts.resolvedBorderRadius,
|
|
@@ -1342,7 +1454,7 @@ function normalizeBeforeButtonClickError(method, err) {
|
|
|
1342
1454
|
);
|
|
1343
1455
|
}
|
|
1344
1456
|
function FloPayKeyframes() {
|
|
1345
|
-
return /* @__PURE__ */ (0,
|
|
1457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: FLOPAY_KEYFRAMES });
|
|
1346
1458
|
}
|
|
1347
1459
|
function toCssSize(value) {
|
|
1348
1460
|
if (typeof value === "number") return `${value}px`;
|
|
@@ -1364,8 +1476,8 @@ function ExpressCheckoutReadySwap({
|
|
|
1364
1476
|
children
|
|
1365
1477
|
}) {
|
|
1366
1478
|
if (state === "unavailable" || state === "load_error") return null;
|
|
1367
|
-
return /* @__PURE__ */ (0,
|
|
1368
|
-
/* @__PURE__ */ (0,
|
|
1479
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { position: "relative", minHeight: 44 }, children: [
|
|
1480
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1369
1481
|
"div",
|
|
1370
1482
|
{
|
|
1371
1483
|
"data-testid": placeholderTestId,
|
|
@@ -1384,7 +1496,7 @@ function ExpressCheckoutReadySwap({
|
|
|
1384
1496
|
}
|
|
1385
1497
|
}
|
|
1386
1498
|
),
|
|
1387
|
-
/* @__PURE__ */ (0,
|
|
1499
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1388
1500
|
"div",
|
|
1389
1501
|
{
|
|
1390
1502
|
style: {
|
|
@@ -1402,9 +1514,9 @@ function ExpressCheckoutReadySwap({
|
|
|
1402
1514
|
function isExpressCheckoutRowVisible(state) {
|
|
1403
1515
|
return state !== "unavailable" && state !== "load_error";
|
|
1404
1516
|
}
|
|
1405
|
-
var SplitCardForm = (0,
|
|
1517
|
+
var SplitCardForm = (0, import_react9.forwardRef)(
|
|
1406
1518
|
function SplitCardForm2(props, ref) {
|
|
1407
|
-
return /* @__PURE__ */ (0,
|
|
1519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SplitCardFormInner, { ...props, innerRef: ref });
|
|
1408
1520
|
}
|
|
1409
1521
|
);
|
|
1410
1522
|
function PayPalButtonInner({
|
|
@@ -1423,15 +1535,15 @@ function PayPalButtonInner({
|
|
|
1423
1535
|
}) {
|
|
1424
1536
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
1425
1537
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
1426
|
-
const [loadState, setLoadState] = (0,
|
|
1427
|
-
(0,
|
|
1538
|
+
const [loadState, setLoadState] = (0, import_react9.useState)("loading");
|
|
1539
|
+
(0, import_react9.useEffect)(() => {
|
|
1428
1540
|
onLoadStateChange?.(loadState);
|
|
1429
1541
|
}, [loadState, onLoadStateChange]);
|
|
1430
|
-
const [submitting, setSubmitting] = (0,
|
|
1431
|
-
const paypalResumeAttempted = (0,
|
|
1432
|
-
const beforeClickRef = (0,
|
|
1542
|
+
const [submitting, setSubmitting] = (0, import_react9.useState)(false);
|
|
1543
|
+
const paypalResumeAttempted = (0, import_react9.useRef)(false);
|
|
1544
|
+
const beforeClickRef = (0, import_react9.useRef)(null);
|
|
1433
1545
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
1434
|
-
(0,
|
|
1546
|
+
(0, import_react9.useEffect)(() => {
|
|
1435
1547
|
if (!stripe || paypalResumeAttempted.current) return;
|
|
1436
1548
|
const params = new URLSearchParams(window.location.search);
|
|
1437
1549
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -1497,7 +1609,7 @@ function PayPalButtonInner({
|
|
|
1497
1609
|
}
|
|
1498
1610
|
})();
|
|
1499
1611
|
}, [stripe, onTokenizedBody, onErrorChange, onDecline]);
|
|
1500
|
-
const handlePayPalClick = (0,
|
|
1612
|
+
const handlePayPalClick = (0, import_react9.useCallback)(async (event) => {
|
|
1501
1613
|
if (isProcessing || submitting) {
|
|
1502
1614
|
event.reject();
|
|
1503
1615
|
return;
|
|
@@ -1516,7 +1628,7 @@ function PayPalButtonInner({
|
|
|
1516
1628
|
onButtonClick?.("paypal");
|
|
1517
1629
|
event.resolve();
|
|
1518
1630
|
}, [isProcessing, onButtonClick, runBeforeButtonClick, submitting]);
|
|
1519
|
-
const handlePayPalConfirm = (0,
|
|
1631
|
+
const handlePayPalConfirm = (0, import_react9.useCallback)(async (event) => {
|
|
1520
1632
|
if (!stripe || !elements) return;
|
|
1521
1633
|
let prepared = beforeClickRef.current;
|
|
1522
1634
|
beforeClickRef.current = null;
|
|
@@ -1636,14 +1748,14 @@ function PayPalButtonInner({
|
|
|
1636
1748
|
setSubmitting(false);
|
|
1637
1749
|
}
|
|
1638
1750
|
}, [stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]);
|
|
1639
|
-
return /* @__PURE__ */ (0,
|
|
1640
|
-
/* @__PURE__ */ (0,
|
|
1751
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1752
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1641
1753
|
ExpressCheckoutReadySwap,
|
|
1642
1754
|
{
|
|
1643
1755
|
state: loadState,
|
|
1644
1756
|
placeholderTestId: "flopay-paypal-placeholder",
|
|
1645
1757
|
borderRadius: placeholderBorderRadius,
|
|
1646
|
-
children: /* @__PURE__ */ (0,
|
|
1758
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1647
1759
|
import_react_stripe_js.ExpressCheckoutElement,
|
|
1648
1760
|
{
|
|
1649
1761
|
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
|
|
@@ -1670,7 +1782,7 @@ function PayPalButtonInner({
|
|
|
1670
1782
|
)
|
|
1671
1783
|
}
|
|
1672
1784
|
),
|
|
1673
|
-
submitting && /* @__PURE__ */ (0,
|
|
1785
|
+
submitting && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: "processing" })
|
|
1674
1786
|
] });
|
|
1675
1787
|
}
|
|
1676
1788
|
function WalletButtonInner({
|
|
@@ -1689,15 +1801,15 @@ function WalletButtonInner({
|
|
|
1689
1801
|
}) {
|
|
1690
1802
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
1691
1803
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
1692
|
-
const [loadState, setLoadState] = (0,
|
|
1693
|
-
(0,
|
|
1804
|
+
const [loadState, setLoadState] = (0, import_react9.useState)("loading");
|
|
1805
|
+
(0, import_react9.useEffect)(() => {
|
|
1694
1806
|
onLoadStateChange?.(loadState);
|
|
1695
1807
|
}, [loadState, onLoadStateChange]);
|
|
1696
|
-
const [submitting, setSubmitting] = (0,
|
|
1808
|
+
const [submitting, setSubmitting] = (0, import_react9.useState)(false);
|
|
1697
1809
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
1698
|
-
const lastWalletMethodRef = (0,
|
|
1699
|
-
const beforeClickRef = (0,
|
|
1700
|
-
const handleWalletConfirm = (0,
|
|
1810
|
+
const lastWalletMethodRef = (0, import_react9.useRef)("card");
|
|
1811
|
+
const beforeClickRef = (0, import_react9.useRef)(null);
|
|
1812
|
+
const handleWalletConfirm = (0, import_react9.useCallback)(
|
|
1701
1813
|
async (event) => {
|
|
1702
1814
|
if (!stripe || !elements) return;
|
|
1703
1815
|
const walletType = event.expressPaymentType;
|
|
@@ -1761,10 +1873,7 @@ function WalletButtonInner({
|
|
|
1761
1873
|
const intentJson = await intentResponse.json();
|
|
1762
1874
|
const intentClientSecret = intentJson.data?.id;
|
|
1763
1875
|
if (!intentClientSecret) throw new Error("No client_secret in payment intent response");
|
|
1764
|
-
const { error: confirmError,
|
|
1765
|
-
intentClientSecret,
|
|
1766
|
-
{ payment_method: paymentMethod.id }
|
|
1767
|
-
);
|
|
1876
|
+
const { error: confirmError, intentId } = (0, import_shared6.isSetupIntentClientSecret)(intentClientSecret) ? await stripe.confirmCardSetup(intentClientSecret, { payment_method: paymentMethod.id }).then((r) => ({ error: r.error, intentId: r.setupIntent?.id })) : await stripe.confirmCardPayment(intentClientSecret, { payment_method: paymentMethod.id }).then((r) => ({ error: r.error, intentId: r.paymentIntent?.id }));
|
|
1768
1877
|
if (confirmError) {
|
|
1769
1878
|
const message = confirmError.message ?? "Wallet payment failed.";
|
|
1770
1879
|
onErrorChange?.(message);
|
|
@@ -1776,7 +1885,7 @@ function WalletButtonInner({
|
|
|
1776
1885
|
onTokenizedBody({
|
|
1777
1886
|
id: paymentMethod.id,
|
|
1778
1887
|
type: "card",
|
|
1779
|
-
threeDSecureActionResultTokenId:
|
|
1888
|
+
threeDSecureActionResultTokenId: intentId
|
|
1780
1889
|
}, {
|
|
1781
1890
|
accountPatch: prepared?.accountPatch,
|
|
1782
1891
|
sessionId: effectiveSessionId,
|
|
@@ -1790,7 +1899,7 @@ function WalletButtonInner({
|
|
|
1790
1899
|
},
|
|
1791
1900
|
[stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]
|
|
1792
1901
|
);
|
|
1793
|
-
const expressMethodMap = (0,
|
|
1902
|
+
const expressMethodMap = (0, import_react9.useMemo)(() => {
|
|
1794
1903
|
const allKeys = ["applePay", "googlePay", "paypal", "link", "amazonPay", "klarna"];
|
|
1795
1904
|
const alwaysCapable = /* @__PURE__ */ new Set(["applePay", "googlePay"]);
|
|
1796
1905
|
const enabledKeys = new Set(expressMethods.map(import_shared5.stripeExpressMethodToOptionKey));
|
|
@@ -1804,18 +1913,18 @@ function WalletButtonInner({
|
|
|
1804
1913
|
}
|
|
1805
1914
|
return out;
|
|
1806
1915
|
}, [expressMethods]);
|
|
1807
|
-
const availableMethodKeys = (0,
|
|
1916
|
+
const availableMethodKeys = (0, import_react9.useMemo)(
|
|
1808
1917
|
() => expressMethods.map(import_shared5.stripeExpressMethodToOptionKey),
|
|
1809
1918
|
[expressMethods]
|
|
1810
1919
|
);
|
|
1811
|
-
return /* @__PURE__ */ (0,
|
|
1812
|
-
/* @__PURE__ */ (0,
|
|
1920
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1921
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1813
1922
|
ExpressCheckoutReadySwap,
|
|
1814
1923
|
{
|
|
1815
1924
|
state: loadState,
|
|
1816
1925
|
placeholderTestId: "flopay-wallet-placeholder",
|
|
1817
1926
|
borderRadius: placeholderBorderRadius,
|
|
1818
|
-
children: /* @__PURE__ */ (0,
|
|
1927
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1819
1928
|
import_react_stripe_js.ExpressCheckoutElement,
|
|
1820
1929
|
{
|
|
1821
1930
|
onReady: (event) => {
|
|
@@ -1854,7 +1963,7 @@ function WalletButtonInner({
|
|
|
1854
1963
|
)
|
|
1855
1964
|
}
|
|
1856
1965
|
),
|
|
1857
|
-
submitting && /* @__PURE__ */ (0,
|
|
1966
|
+
submitting && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: "processing" })
|
|
1858
1967
|
] });
|
|
1859
1968
|
}
|
|
1860
1969
|
function StripeMethodButton({
|
|
@@ -1875,7 +1984,7 @@ function StripeMethodButton({
|
|
|
1875
1984
|
const resolvedBackground = brand?.backgroundColor ?? backgroundColor ?? "#ffffff";
|
|
1876
1985
|
const resolvedBorder = brand?.borderColor ?? borderColor ?? "#d1d5db";
|
|
1877
1986
|
const resolvedTextColor = brand?.textColor ?? textColor ?? "#262833";
|
|
1878
|
-
return /* @__PURE__ */ (0,
|
|
1987
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1879
1988
|
"button",
|
|
1880
1989
|
{
|
|
1881
1990
|
type: "button",
|
|
@@ -1922,9 +2031,9 @@ function StripeMethodButton({
|
|
|
1922
2031
|
// Pulse-skeleton parity with the wallet ECE: no spinner, just the
|
|
1923
2032
|
// status text on top of the pulsing background. Keeps the loading
|
|
1924
2033
|
// affordance shape-equivalent across both kinds of tile.
|
|
1925
|
-
/* @__PURE__ */ (0,
|
|
1926
|
-
) : /* @__PURE__ */ (0,
|
|
1927
|
-
/* @__PURE__ */ (0,
|
|
2034
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { margin: "0 auto" }, children: `Connecting to ${(0, import_shared5.getStripeMethodDisplayName)(method)}\u2026` })
|
|
2035
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2036
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1928
2037
|
"span",
|
|
1929
2038
|
{
|
|
1930
2039
|
style: {
|
|
@@ -1937,7 +2046,7 @@ function StripeMethodButton({
|
|
|
1937
2046
|
gap: (0, import_shared5.hasVendoredStripeMethodLogo)(method) ? 8 : 0
|
|
1938
2047
|
},
|
|
1939
2048
|
children: [
|
|
1940
|
-
brand?.logoSvg && /* @__PURE__ */ (0,
|
|
2049
|
+
brand?.logoSvg && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1941
2050
|
"span",
|
|
1942
2051
|
{
|
|
1943
2052
|
"aria-hidden": "true",
|
|
@@ -1956,11 +2065,11 @@ function StripeMethodButton({
|
|
|
1956
2065
|
dangerouslySetInnerHTML: { __html: brand.logoSvg }
|
|
1957
2066
|
}
|
|
1958
2067
|
),
|
|
1959
|
-
/* @__PURE__ */ (0,
|
|
2068
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: (0, import_shared5.getStripeMethodDisplayName)(method) })
|
|
1960
2069
|
]
|
|
1961
2070
|
}
|
|
1962
2071
|
),
|
|
1963
|
-
hasNextStep && /* @__PURE__ */ (0,
|
|
2072
|
+
hasNextStep && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1964
2073
|
"svg",
|
|
1965
2074
|
{
|
|
1966
2075
|
width: "14",
|
|
@@ -1980,7 +2089,7 @@ function StripeMethodButton({
|
|
|
1980
2089
|
opacity: 0.7
|
|
1981
2090
|
},
|
|
1982
2091
|
"aria-hidden": "true",
|
|
1983
|
-
children: /* @__PURE__ */ (0,
|
|
2092
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 18l6-6-6-6" })
|
|
1984
2093
|
}
|
|
1985
2094
|
)
|
|
1986
2095
|
] })
|
|
@@ -2003,16 +2112,17 @@ function StripeMethodInlineForm({
|
|
|
2003
2112
|
isProcessing,
|
|
2004
2113
|
submitButtonColor,
|
|
2005
2114
|
submitButtonBorderRadius,
|
|
2006
|
-
submitButtonStyle
|
|
2115
|
+
submitButtonStyle,
|
|
2116
|
+
errorText
|
|
2007
2117
|
}) {
|
|
2008
2118
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
2009
2119
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
2010
|
-
const [submitting, setSubmitting] = (0,
|
|
2011
|
-
const submittingRef = (0,
|
|
2012
|
-
const [isMethodComplete, setIsMethodComplete] = (0,
|
|
2013
|
-
const [loadState, setLoadState] = (0,
|
|
2120
|
+
const [submitting, setSubmitting] = (0, import_react9.useState)(false);
|
|
2121
|
+
const submittingRef = (0, import_react9.useRef)(false);
|
|
2122
|
+
const [isMethodComplete, setIsMethodComplete] = (0, import_react9.useState)(false);
|
|
2123
|
+
const [loadState, setLoadState] = (0, import_react9.useState)("loading");
|
|
2014
2124
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2015
|
-
const handlePay = (0,
|
|
2125
|
+
const handlePay = (0, import_react9.useCallback)(async () => {
|
|
2016
2126
|
if (!stripe || !elements || isProcessing || submittingRef.current || !isMethodComplete) return;
|
|
2017
2127
|
submittingRef.current = true;
|
|
2018
2128
|
setSubmitting(true);
|
|
@@ -2152,8 +2262,8 @@ function StripeMethodInlineForm({
|
|
|
2152
2262
|
onDecline
|
|
2153
2263
|
]);
|
|
2154
2264
|
void onCancel;
|
|
2155
|
-
return /* @__PURE__ */ (0,
|
|
2156
|
-
/* @__PURE__ */ (0,
|
|
2265
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
|
|
2266
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2157
2267
|
import_react_stripe_js.PaymentElement,
|
|
2158
2268
|
{
|
|
2159
2269
|
onReady: () => setLoadState("ready"),
|
|
@@ -2173,7 +2283,7 @@ function StripeMethodInlineForm({
|
|
|
2173
2283
|
}
|
|
2174
2284
|
}
|
|
2175
2285
|
),
|
|
2176
|
-
/* @__PURE__ */ (0,
|
|
2286
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2177
2287
|
"button",
|
|
2178
2288
|
{
|
|
2179
2289
|
type: "button",
|
|
@@ -2199,7 +2309,23 @@ function StripeMethodInlineForm({
|
|
|
2199
2309
|
},
|
|
2200
2310
|
children: submitting ? "Processing\u2026" : `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(method)}`
|
|
2201
2311
|
}
|
|
2202
|
-
)
|
|
2312
|
+
),
|
|
2313
|
+
errorText && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
2314
|
+
margin: "0.75rem 0 0",
|
|
2315
|
+
padding: "0.625rem 0.875rem",
|
|
2316
|
+
background: "#FEF2F2",
|
|
2317
|
+
border: "1px solid #FECACA",
|
|
2318
|
+
borderRadius: "8px",
|
|
2319
|
+
color: "#991B1B",
|
|
2320
|
+
fontSize: "0.85rem",
|
|
2321
|
+
fontWeight: 600,
|
|
2322
|
+
display: "flex",
|
|
2323
|
+
alignItems: "center",
|
|
2324
|
+
gap: "0.5rem"
|
|
2325
|
+
}, children: [
|
|
2326
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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" }) }),
|
|
2327
|
+
errorText
|
|
2328
|
+
] })
|
|
2203
2329
|
] });
|
|
2204
2330
|
}
|
|
2205
2331
|
function StripePaymentElementInner({
|
|
@@ -2227,17 +2353,17 @@ function StripePaymentElementInner({
|
|
|
2227
2353
|
expandedApmMethod
|
|
2228
2354
|
}) {
|
|
2229
2355
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2230
|
-
const [expandedMethod, setExpandedMethod] = (0,
|
|
2231
|
-
const [submittingMethod, setSubmittingMethod] = (0,
|
|
2232
|
-
const submittingRef = (0,
|
|
2233
|
-
(0,
|
|
2356
|
+
const [expandedMethod, setExpandedMethod] = (0, import_react9.useState)(null);
|
|
2357
|
+
const [submittingMethod, setSubmittingMethod] = (0, import_react9.useState)(null);
|
|
2358
|
+
const submittingRef = (0, import_react9.useRef)(false);
|
|
2359
|
+
(0, import_react9.useEffect)(() => {
|
|
2234
2360
|
if (paymentElementMethods.length > 0 && stripeInstance) {
|
|
2235
2361
|
onLoadStateChange?.("ready");
|
|
2236
2362
|
} else if (!stripeInstance) {
|
|
2237
2363
|
onLoadStateChange?.("loading");
|
|
2238
2364
|
}
|
|
2239
2365
|
}, [paymentElementMethods.length, stripeInstance, onLoadStateChange]);
|
|
2240
|
-
const handleAutoConfirm = (0,
|
|
2366
|
+
const handleAutoConfirm = (0, import_react9.useCallback)(async (method) => {
|
|
2241
2367
|
if (!stripeInstance) return;
|
|
2242
2368
|
if (submittingRef.current || isProcessing) return;
|
|
2243
2369
|
submittingRef.current = true;
|
|
@@ -2376,9 +2502,9 @@ function StripePaymentElementInner({
|
|
|
2376
2502
|
onErrorChange,
|
|
2377
2503
|
onDecline
|
|
2378
2504
|
]);
|
|
2379
|
-
const [localExpandedMethod, setLocalExpandedMethod] = (0,
|
|
2505
|
+
const [localExpandedMethod, setLocalExpandedMethod] = (0, import_react9.useState)(null);
|
|
2380
2506
|
const activeExpandedMethod = onExpandApm ? expandedApmMethod ?? null : localExpandedMethod;
|
|
2381
|
-
const handleMethodClick = (0,
|
|
2507
|
+
const handleMethodClick = (0, import_react9.useCallback)((method) => {
|
|
2382
2508
|
if (submittingRef.current || isProcessing) return;
|
|
2383
2509
|
if (activeExpandedMethod && activeExpandedMethod !== method) return;
|
|
2384
2510
|
if ((0, import_shared5.needsStripeMethodExplicitConfirm)(method)) {
|
|
@@ -2391,14 +2517,14 @@ function StripePaymentElementInner({
|
|
|
2391
2517
|
void handleAutoConfirm(method);
|
|
2392
2518
|
}
|
|
2393
2519
|
}, [activeExpandedMethod, isProcessing, handleAutoConfirm, onExpandApm]);
|
|
2394
|
-
const localInlineElementsOptions = (0,
|
|
2520
|
+
const localInlineElementsOptions = (0, import_react9.useMemo)(() => {
|
|
2395
2521
|
if (!localExpandedMethod) return null;
|
|
2396
2522
|
return {
|
|
2397
2523
|
...paymentElementBaseOptions,
|
|
2398
2524
|
paymentMethodTypes: [localExpandedMethod]
|
|
2399
2525
|
};
|
|
2400
2526
|
}, [localExpandedMethod, paymentElementBaseOptions]);
|
|
2401
|
-
return /* @__PURE__ */ (0,
|
|
2527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2402
2528
|
"div",
|
|
2403
2529
|
{
|
|
2404
2530
|
"data-testid": "flopay-stripe-payment-element-region",
|
|
@@ -2407,8 +2533,8 @@ function StripePaymentElementInner({
|
|
|
2407
2533
|
const isExpanded = expandedApmMethod === method;
|
|
2408
2534
|
const isSubmittingThis = submittingMethod === method;
|
|
2409
2535
|
const otherInProgress = submittingMethod !== null && submittingMethod !== method || expandedApmMethod !== null && expandedApmMethod !== void 0 && expandedApmMethod !== method;
|
|
2410
|
-
return /* @__PURE__ */ (0,
|
|
2411
|
-
/* @__PURE__ */ (0,
|
|
2536
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react9.default.Fragment, { children: [
|
|
2537
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2412
2538
|
StripeMethodButton,
|
|
2413
2539
|
{
|
|
2414
2540
|
method,
|
|
@@ -2425,12 +2551,12 @@ function StripePaymentElementInner({
|
|
|
2425
2551
|
fontFamily: buttonAppearance?.fontFamily
|
|
2426
2552
|
}
|
|
2427
2553
|
),
|
|
2428
|
-
!onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ (0,
|
|
2554
|
+
!onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2429
2555
|
import_react_stripe_js.Elements,
|
|
2430
2556
|
{
|
|
2431
2557
|
stripe: stripeInstance,
|
|
2432
2558
|
options: localInlineElementsOptions,
|
|
2433
|
-
children: /* @__PURE__ */ (0,
|
|
2559
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2434
2560
|
StripeMethodInlineForm,
|
|
2435
2561
|
{
|
|
2436
2562
|
method,
|
|
@@ -2483,6 +2609,7 @@ function SplitCardFormInner({
|
|
|
2483
2609
|
showPayPal = true,
|
|
2484
2610
|
showStripe = true,
|
|
2485
2611
|
enabledPaymentMethods,
|
|
2612
|
+
enabledPaymentMethodCountries,
|
|
2486
2613
|
showApplePay = true,
|
|
2487
2614
|
showGooglePay = true,
|
|
2488
2615
|
layout = "default",
|
|
@@ -2497,6 +2624,8 @@ function SplitCardFormInner({
|
|
|
2497
2624
|
onButtonClick,
|
|
2498
2625
|
onBeforeButtonClick,
|
|
2499
2626
|
enableAVS: enableAVSProp,
|
|
2627
|
+
cardFieldOrder,
|
|
2628
|
+
cardPreFormSlot,
|
|
2500
2629
|
avsLayout: avsLayoutProp = "row",
|
|
2501
2630
|
country: countryProp,
|
|
2502
2631
|
zip: zipProp,
|
|
@@ -2521,68 +2650,95 @@ function SplitCardFormInner({
|
|
|
2521
2650
|
const flopay = useFloPay();
|
|
2522
2651
|
const paypalFlopay = usePayPalFloPay();
|
|
2523
2652
|
const elements = useElements();
|
|
2524
|
-
const checkout = (0,
|
|
2653
|
+
const checkout = (0, import_react9.useContext)(CheckoutContext);
|
|
2525
2654
|
const contextBillingUrl = useBillingApiUrl();
|
|
2526
|
-
const [processing, setProcessing] = (0,
|
|
2527
|
-
const [error, setError] = (0,
|
|
2528
|
-
const [is3DSActive, setIs3DSActive] = (0,
|
|
2529
|
-
const [selectedCountry, setSelectedCountry] = (0,
|
|
2530
|
-
const [zipCode, setZipCode] = (0,
|
|
2531
|
-
const [addressLine1, setAddressLine1] = (0,
|
|
2532
|
-
const [addressLine2, setAddressLine2] = (0,
|
|
2533
|
-
const [city, setCity] = (0,
|
|
2534
|
-
const [stateValue, setStateValue] = (0,
|
|
2535
|
-
const [accountPatch, setAccountPatch] = (0,
|
|
2536
|
-
const zipCodeRef = (0,
|
|
2537
|
-
const selectedCountryRef = (0,
|
|
2538
|
-
const addressLine1Ref = (0,
|
|
2539
|
-
const addressLine2Ref = (0,
|
|
2540
|
-
const cityRef = (0,
|
|
2541
|
-
const stateRef = (0,
|
|
2542
|
-
const avsConfig = (0,
|
|
2655
|
+
const [processing, setProcessing] = (0, import_react9.useState)(false);
|
|
2656
|
+
const [error, setError] = (0, import_react9.useState)(null);
|
|
2657
|
+
const [is3DSActive, setIs3DSActive] = (0, import_react9.useState)(false);
|
|
2658
|
+
const [selectedCountry, setSelectedCountry] = (0, import_react9.useState)(countryProp ?? "US");
|
|
2659
|
+
const [zipCode, setZipCode] = (0, import_react9.useState)(zipProp ?? "");
|
|
2660
|
+
const [addressLine1, setAddressLine1] = (0, import_react9.useState)(addressLine1Prop ?? "");
|
|
2661
|
+
const [addressLine2, setAddressLine2] = (0, import_react9.useState)(addressLine2Prop ?? "");
|
|
2662
|
+
const [city, setCity] = (0, import_react9.useState)(cityProp ?? "");
|
|
2663
|
+
const [stateValue, setStateValue] = (0, import_react9.useState)(stateProp ?? "");
|
|
2664
|
+
const [accountPatch, setAccountPatch] = (0, import_react9.useState)({});
|
|
2665
|
+
const zipCodeRef = (0, import_react9.useRef)(zipProp ?? "");
|
|
2666
|
+
const selectedCountryRef = (0, import_react9.useRef)(countryProp ?? "US");
|
|
2667
|
+
const addressLine1Ref = (0, import_react9.useRef)(addressLine1Prop ?? "");
|
|
2668
|
+
const addressLine2Ref = (0, import_react9.useRef)(addressLine2Prop ?? "");
|
|
2669
|
+
const cityRef = (0, import_react9.useRef)(cityProp ?? "");
|
|
2670
|
+
const stateRef = (0, import_react9.useRef)(stateProp ?? "");
|
|
2671
|
+
const avsConfig = (0, import_react9.useMemo)(() => (0, import_shared5.resolveAVSConfig)(enableAVSProp), [enableAVSProp]);
|
|
2543
2672
|
const enableAVS = avsConfig !== null;
|
|
2544
|
-
const
|
|
2545
|
-
const
|
|
2673
|
+
const vaultBlockReady = Boolean(session?.vault?.html);
|
|
2674
|
+
const vaultGatewayAdvertised = Boolean(session?.gateways?.pcivault);
|
|
2675
|
+
const vaultActive = Boolean(
|
|
2676
|
+
showStripe && (vaultBlockReady || vaultGatewayAdvertised) && flopay && sessionId
|
|
2677
|
+
);
|
|
2678
|
+
const cardCapture = (0, import_react9.useMemo)(() => {
|
|
2679
|
+
if (!flopay || !vaultActive || !sessionId) return null;
|
|
2680
|
+
return flopay.cardCapture({ sessionId });
|
|
2681
|
+
}, [flopay, vaultActive, sessionId]);
|
|
2682
|
+
const { avsInvalid, invalidAvsFields } = (0, import_react9.useMemo)(() => {
|
|
2683
|
+
const none = { line1: false, city: false, state: false, zip: false };
|
|
2684
|
+
if (!vaultActive || !avsConfig) return { avsInvalid: false, invalidAvsFields: none };
|
|
2685
|
+
const cc = selectedCountry;
|
|
2686
|
+
const isEmpty = (field, value) => (0, import_shared5.isAVSFieldVisible)(field, cc) && !value.trim();
|
|
2687
|
+
const invalidAvsFields2 = {
|
|
2688
|
+
line1: isEmpty(avsConfig.address_line_1, addressLine1),
|
|
2689
|
+
city: isEmpty(avsConfig.city, city),
|
|
2690
|
+
state: isEmpty(avsConfig.state, stateValue),
|
|
2691
|
+
zip: isEmpty(avsConfig.postal_code, zipCode)
|
|
2692
|
+
};
|
|
2693
|
+
const avsInvalid2 = invalidAvsFields2.line1 || invalidAvsFields2.city || invalidAvsFields2.state || invalidAvsFields2.zip;
|
|
2694
|
+
return { avsInvalid: avsInvalid2, invalidAvsFields: invalidAvsFields2 };
|
|
2695
|
+
}, [vaultActive, avsConfig, selectedCountry, addressLine1, city, stateValue, zipCode]);
|
|
2696
|
+
const [hasAttemptedSubmit, setHasAttemptedSubmit] = (0, import_react9.useState)(false);
|
|
2697
|
+
const [vaultMount, setVaultMount] = (0, import_react9.useState)(
|
|
2698
|
+
() => toVaultMount(session?.vault)
|
|
2699
|
+
);
|
|
2700
|
+
const [viewState, setViewState] = (0, import_react9.useState)(initialCardOpen ? "card" : "buttons");
|
|
2701
|
+
const [expandedApmMethod, setExpandedApmMethod] = (0, import_react9.useState)(null);
|
|
2546
2702
|
const showCardForm = viewState === "expanding" || viewState === "card";
|
|
2547
2703
|
const TRANSITION_MS = 280;
|
|
2548
|
-
const expandToCard = (0,
|
|
2704
|
+
const expandToCard = (0, import_react9.useCallback)(() => {
|
|
2549
2705
|
setViewState("expanding");
|
|
2550
2706
|
setTimeout(() => setViewState("card"), TRANSITION_MS);
|
|
2551
2707
|
}, []);
|
|
2552
|
-
const collapseToButtons = (0,
|
|
2708
|
+
const collapseToButtons = (0, import_react9.useCallback)(() => {
|
|
2553
2709
|
setViewState("collapsing");
|
|
2554
2710
|
setTimeout(() => setViewState("buttons"), TRANSITION_MS);
|
|
2555
2711
|
}, []);
|
|
2556
|
-
const expandToApm = (0,
|
|
2712
|
+
const expandToApm = (0, import_react9.useCallback)((method) => {
|
|
2557
2713
|
setExpandedApmMethod(method);
|
|
2558
2714
|
setViewState("apm-expanding");
|
|
2559
2715
|
setTimeout(() => setViewState("apm-form"), TRANSITION_MS);
|
|
2560
2716
|
}, []);
|
|
2561
|
-
const collapseFromApm = (0,
|
|
2717
|
+
const collapseFromApm = (0, import_react9.useCallback)(() => {
|
|
2562
2718
|
setViewState("apm-collapsing");
|
|
2563
2719
|
setTimeout(() => {
|
|
2564
2720
|
setViewState("buttons");
|
|
2565
2721
|
setExpandedApmMethod(null);
|
|
2566
2722
|
}, TRANSITION_MS);
|
|
2567
2723
|
}, []);
|
|
2568
|
-
(0,
|
|
2724
|
+
(0, import_react9.useEffect)(() => {
|
|
2569
2725
|
if (layout === "buttons" && initialCardOpen) {
|
|
2570
2726
|
setViewState("card");
|
|
2571
2727
|
}
|
|
2572
2728
|
}, [layout, initialCardOpen]);
|
|
2573
|
-
const [fullName, setFullName] = (0,
|
|
2574
|
-
const [formReady, setFormReady] = (0,
|
|
2575
|
-
const [overlayStatus, setOverlayStatus] = (0,
|
|
2576
|
-
const processingRef = (0,
|
|
2577
|
-
const [paypalDirectRetry, setPaypalDirectRetry] = (0,
|
|
2578
|
-
const paypalDirectRetryRef = (0,
|
|
2579
|
-
(0,
|
|
2729
|
+
const [fullName, setFullName] = (0, import_react9.useState)("");
|
|
2730
|
+
const [formReady, setFormReady] = (0, import_react9.useState)(false);
|
|
2731
|
+
const [overlayStatus, setOverlayStatus] = (0, import_react9.useState)(null);
|
|
2732
|
+
const processingRef = (0, import_react9.useRef)(false);
|
|
2733
|
+
const [paypalDirectRetry, setPaypalDirectRetry] = (0, import_react9.useState)(null);
|
|
2734
|
+
const paypalDirectRetryRef = (0, import_react9.useRef)(paypalDirectRetry);
|
|
2735
|
+
(0, import_react9.useEffect)(() => {
|
|
2580
2736
|
paypalDirectRetryRef.current = paypalDirectRetry;
|
|
2581
2737
|
}, [paypalDirectRetry]);
|
|
2582
2738
|
const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
|
|
2583
2739
|
const displayError = externalError ?? error;
|
|
2584
|
-
const themeBundle = (0,
|
|
2585
|
-
const bStyles = (0,
|
|
2740
|
+
const themeBundle = (0, import_react9.useMemo)(() => (0, import_shared6.resolveTheme)(theme), [theme]);
|
|
2741
|
+
const bStyles = (0, import_react9.useMemo)(() => {
|
|
2586
2742
|
const base = themeBundle?.buttonsLayout ?? (0, import_shared5.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
2587
2743
|
if (!buttonsStylesOverride) return base;
|
|
2588
2744
|
return {
|
|
@@ -2597,11 +2753,36 @@ function SplitCardFormInner({
|
|
|
2597
2753
|
};
|
|
2598
2754
|
}, [themeBundle, buttonsTheme, buttonsStylesOverride]);
|
|
2599
2755
|
const appearance = appearanceOverride ?? themeBundle?.appearance;
|
|
2756
|
+
const vaultThemeColors = (0, import_react9.useMemo)(() => {
|
|
2757
|
+
const vars = appearance?.variables;
|
|
2758
|
+
const asString = (value) => typeof value === "string" && value ? value : void 0;
|
|
2759
|
+
const submitButtonStyle = bStyles.submitButton;
|
|
2760
|
+
const primary = asString(vars?.colorPrimary) ?? asString(submitButtonStyle?.backgroundColor) ?? "#4A49FF";
|
|
2761
|
+
const isButtonsLayout = layout === "buttons";
|
|
2762
|
+
const nameInput = bStyles.nameInput;
|
|
2763
|
+
return {
|
|
2764
|
+
primaryColor: primary,
|
|
2765
|
+
primaryHoverColor: asString(vars?.colorPrimaryHover) ?? darkenHex(primary, 0.12),
|
|
2766
|
+
inputBackgroundColor: asString(bStyles.cardInputBackground) ?? asString(vars?.colorBackground) ?? "#ffffff",
|
|
2767
|
+
textColor: asString(bStyles.cardInputColor) ?? asString(nameInput?.color) ?? asString(vars?.colorText) ?? "#262833",
|
|
2768
|
+
borderColor: asString(bStyles.cardInputBorder) ?? (isButtonsLayout ? "#e5e7eb" : "#A4A4FF"),
|
|
2769
|
+
placeholderColor: asString(bStyles.cardInputPlaceholderColor) ?? "#9ca3af",
|
|
2770
|
+
errorColor: asString(vars?.colorDanger) ?? "#dc2626",
|
|
2771
|
+
successColor: "#16a34a",
|
|
2772
|
+
fontFamily: asString(nameInput?.fontFamily) ?? asString(vars?.fontFamily) ?? "Poppins, sans-serif",
|
|
2773
|
+
fontSize: asString(bStyles.cardInputFontSize) ?? asString(vars?.fontSizeBase) ?? "16px",
|
|
2774
|
+
// `resolvedInputFontWeight` equivalent — sent as a string (the widget's
|
|
2775
|
+
// theme applier only honors string values) so vault inputs/placeholders
|
|
2776
|
+
// match the AVS fields' weight per theme (default 400).
|
|
2777
|
+
fontWeight: String(toCssWeight(nameInput?.fontWeight) ?? 400),
|
|
2778
|
+
borderRadius: asString(vars?.borderRadius) ?? "8px"
|
|
2779
|
+
};
|
|
2780
|
+
}, [appearance, bStyles, layout]);
|
|
2600
2781
|
const isInlineSessionPatchProcessing = checkout.inlineSessionPatchProcessing ?? false;
|
|
2601
2782
|
const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
|
|
2602
2783
|
const isSelfContained = !onTokenizedBody;
|
|
2603
2784
|
const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
|
|
2604
|
-
const resolvedAccount = (0,
|
|
2785
|
+
const resolvedAccount = (0, import_react9.useMemo)(() => mergeAccountPatch({
|
|
2605
2786
|
userId,
|
|
2606
2787
|
email,
|
|
2607
2788
|
firstName,
|
|
@@ -2609,17 +2790,17 @@ function SplitCardFormInner({
|
|
|
2609
2790
|
country: countryProp,
|
|
2610
2791
|
zip: zipProp
|
|
2611
2792
|
}, accountPatch), [userId, email, firstName, lastName, countryProp, zipProp, accountPatch]);
|
|
2612
|
-
const stripeInstance = (0,
|
|
2793
|
+
const stripeInstance = (0, import_react9.useMemo)(() => {
|
|
2613
2794
|
if (!flopay) return null;
|
|
2614
2795
|
return flopay.getRawProvider();
|
|
2615
2796
|
}, [flopay]);
|
|
2616
|
-
const paypalStripeInstance = (0,
|
|
2797
|
+
const paypalStripeInstance = (0, import_react9.useMemo)(() => {
|
|
2617
2798
|
if (!paypalFlopay) return null;
|
|
2618
2799
|
return paypalFlopay.getRawProvider();
|
|
2619
2800
|
}, [paypalFlopay]);
|
|
2620
2801
|
const amountInCents = totalAmount || 100;
|
|
2621
2802
|
const stripeAppearanceProp = appearance ? { appearance } : null;
|
|
2622
|
-
const paymentElementAppearance = (0,
|
|
2803
|
+
const paymentElementAppearance = (0, import_react9.useMemo)(() => {
|
|
2623
2804
|
const base = appearance ?? {};
|
|
2624
2805
|
const baseRules = base.rules ?? {};
|
|
2625
2806
|
return {
|
|
@@ -2639,15 +2820,18 @@ function SplitCardFormInner({
|
|
|
2639
2820
|
}
|
|
2640
2821
|
};
|
|
2641
2822
|
}, [appearance]);
|
|
2642
|
-
const walletOptions = (0,
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2823
|
+
const walletOptions = (0, import_react9.useMemo)(() => {
|
|
2824
|
+
const modeOptions = resolveWalletElementsMode(totalAmount);
|
|
2825
|
+
return {
|
|
2826
|
+
...modeOptions,
|
|
2827
|
+
currency: currency.toLowerCase(),
|
|
2828
|
+
paymentMethodCreation: "manual",
|
|
2829
|
+
// captureMethod only applies to payment mode; Stripe rejects it in setup.
|
|
2830
|
+
...modeOptions.mode === "payment" ? { captureMethod: "manual" } : {},
|
|
2831
|
+
...stripeAppearanceProp
|
|
2832
|
+
};
|
|
2833
|
+
}, [totalAmount, currency, stripeAppearanceProp]);
|
|
2834
|
+
const paypalOptions = (0, import_react9.useMemo)(() => ({
|
|
2651
2835
|
mode: "payment",
|
|
2652
2836
|
amount: amountInCents,
|
|
2653
2837
|
currency: currency.toLowerCase(),
|
|
@@ -2655,35 +2839,183 @@ function SplitCardFormInner({
|
|
|
2655
2839
|
setupFutureUsage: "off_session",
|
|
2656
2840
|
...stripeAppearanceProp
|
|
2657
2841
|
}), [amountInCents, currency, stripeAppearanceProp]);
|
|
2658
|
-
const updateError = (0,
|
|
2842
|
+
const updateError = (0, import_react9.useCallback)(
|
|
2659
2843
|
(err) => {
|
|
2660
2844
|
setError(err);
|
|
2661
2845
|
onErrorChange?.(err);
|
|
2662
2846
|
},
|
|
2663
2847
|
[onErrorChange]
|
|
2664
2848
|
);
|
|
2665
|
-
|
|
2849
|
+
(0, import_react9.useEffect)(() => {
|
|
2850
|
+
if (!vaultActive || !cardCapture) return;
|
|
2851
|
+
cardCapture.setSubmitGate?.(avsInvalid);
|
|
2852
|
+
}, [vaultActive, cardCapture, avsInvalid]);
|
|
2853
|
+
(0, import_react9.useEffect)(() => {
|
|
2854
|
+
if (!vaultActive || !cardCapture) return;
|
|
2855
|
+
cardCapture.setCardFieldOrder?.(cardFieldOrder ?? null, avsConfig == null);
|
|
2856
|
+
}, [vaultActive, cardCapture, cardFieldOrder, avsConfig]);
|
|
2857
|
+
(0, import_react9.useEffect)(() => {
|
|
2858
|
+
if (viewState === "expanding" || viewState === "collapsing" || viewState === "apm-expanding" || viewState === "apm-collapsing") {
|
|
2859
|
+
updateError(null);
|
|
2860
|
+
}
|
|
2861
|
+
}, [viewState, updateError]);
|
|
2862
|
+
const emitDecline = (0, import_react9.useCallback)(
|
|
2666
2863
|
(method, input, overrides) => {
|
|
2667
2864
|
onDecline?.(buildDeclineEvent(method, input, overrides));
|
|
2668
2865
|
},
|
|
2669
2866
|
[onDecline]
|
|
2670
2867
|
);
|
|
2868
|
+
(0, import_react9.useEffect)(() => {
|
|
2869
|
+
if (!vaultActive || !sessionId) {
|
|
2870
|
+
setVaultMount(null);
|
|
2871
|
+
return;
|
|
2872
|
+
}
|
|
2873
|
+
const embedded = toVaultMount(session?.vault);
|
|
2874
|
+
if (embedded) {
|
|
2875
|
+
setVaultMount(embedded);
|
|
2876
|
+
return;
|
|
2877
|
+
}
|
|
2878
|
+
setVaultMount(null);
|
|
2879
|
+
let active = true;
|
|
2880
|
+
new import_js2.PaymentAPI(baseUrl).getVaultCapture(sessionId, nonce).then((block) => {
|
|
2881
|
+
if (!active) return;
|
|
2882
|
+
const mount = toVaultMount(block);
|
|
2883
|
+
if (mount) {
|
|
2884
|
+
setVaultMount(mount);
|
|
2885
|
+
} else {
|
|
2886
|
+
updateError("Failed to load the secure card form.");
|
|
2887
|
+
}
|
|
2888
|
+
}).catch((err) => {
|
|
2889
|
+
if (active) {
|
|
2890
|
+
updateError(err instanceof Error ? err.message : "Failed to load the secure card form.");
|
|
2891
|
+
}
|
|
2892
|
+
});
|
|
2893
|
+
return () => {
|
|
2894
|
+
active = false;
|
|
2895
|
+
};
|
|
2896
|
+
}, [
|
|
2897
|
+
vaultActive,
|
|
2898
|
+
sessionId,
|
|
2899
|
+
session?.vault?.html,
|
|
2900
|
+
session?.vault?.messageToken,
|
|
2901
|
+
session?.vault?.expectedOrigin,
|
|
2902
|
+
baseUrl,
|
|
2903
|
+
nonce,
|
|
2904
|
+
updateError
|
|
2905
|
+
]);
|
|
2906
|
+
(0, import_react9.useEffect)(() => {
|
|
2907
|
+
if (!vaultActive || !cardCapture) return;
|
|
2908
|
+
let cancelled = false;
|
|
2909
|
+
const offSubmitting = cardCapture.on("submitting", () => {
|
|
2910
|
+
setHasAttemptedSubmit(true);
|
|
2911
|
+
setOverlayStatus("processing");
|
|
2912
|
+
if (!sessionId || !nonce) return;
|
|
2913
|
+
const cc = selectedCountryRef.current || resolvedAccount.country || "US";
|
|
2914
|
+
const stateVisible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) : false;
|
|
2915
|
+
const line1Visible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_1, cc) : false;
|
|
2916
|
+
const zipVisible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) : false;
|
|
2917
|
+
const cityVisible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) : false;
|
|
2918
|
+
const line2Visible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_2, cc) : false;
|
|
2919
|
+
const derivedState = line1Visible && !stateVisible && zipVisible ? (0, import_shared5.getStateFromPostalCode)(cc, zipCodeRef.current ?? "") : null;
|
|
2920
|
+
const stateValue2 = stateVisible ? stateRef.current : derivedState;
|
|
2921
|
+
void new import_js2.PaymentAPI(baseUrl).patchAccountSnapshot(sessionId, nonce, {
|
|
2922
|
+
accountData: {
|
|
2923
|
+
userId: resolvedAccount.userId ?? "",
|
|
2924
|
+
email: resolvedAccount.email ?? "",
|
|
2925
|
+
firstName: resolvedAccount.firstName ?? fullName.trim().split(/\s+/)[0] ?? "",
|
|
2926
|
+
lastName: resolvedAccount.lastName ?? fullName.trim().split(/\s+/).slice(1).join(" ") ?? "",
|
|
2927
|
+
...zipVisible && zipCodeRef.current ? { zip: zipCodeRef.current } : {},
|
|
2928
|
+
...cityVisible && cityRef.current ? { city: cityRef.current } : {},
|
|
2929
|
+
...stateValue2 ? { state: stateValue2 } : {},
|
|
2930
|
+
...line1Visible && addressLine1Ref.current ? { addressLine1: addressLine1Ref.current } : {},
|
|
2931
|
+
...line2Visible && addressLine2Ref.current ? { addressLine2: addressLine2Ref.current } : {},
|
|
2932
|
+
country: cc
|
|
2933
|
+
},
|
|
2934
|
+
...avsCheckProp !== void 0 ? { avsCheck: avsCheckProp } : {},
|
|
2935
|
+
...avsConfig ? {
|
|
2936
|
+
avsConfig: {
|
|
2937
|
+
country: (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc),
|
|
2938
|
+
postal_code: zipVisible,
|
|
2939
|
+
address_line_1: line1Visible,
|
|
2940
|
+
address_line_2: line2Visible,
|
|
2941
|
+
city: cityVisible,
|
|
2942
|
+
state: stateVisible
|
|
2943
|
+
}
|
|
2944
|
+
} : {}
|
|
2945
|
+
}).catch(() => {
|
|
2946
|
+
});
|
|
2947
|
+
});
|
|
2948
|
+
const offComplete = cardCapture.on("complete", async (event) => {
|
|
2949
|
+
markSessionRecentlyCompleted(event.sessionId ?? sessionId);
|
|
2950
|
+
setOverlayStatus("success");
|
|
2951
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_SUCCESS_DELAY_MS));
|
|
2952
|
+
if (cancelled) return;
|
|
2953
|
+
onComplete?.({
|
|
2954
|
+
status: "succeeded",
|
|
2955
|
+
paymentIntentId: event.intentId,
|
|
2956
|
+
checkoutMethod: "card"
|
|
2957
|
+
});
|
|
2958
|
+
});
|
|
2959
|
+
const offDecline = cardCapture.on("decline", async (event) => {
|
|
2960
|
+
const message = event.message ?? "Your payment was declined. Please try another card or contact your bank.";
|
|
2961
|
+
updateError(message);
|
|
2962
|
+
setOverlayStatus("error");
|
|
2963
|
+
emitDecline("card", message, event.declineReason ? { declineCode: event.declineReason } : void 0);
|
|
2964
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
2965
|
+
if (cancelled) return;
|
|
2966
|
+
setOverlayStatus(null);
|
|
2967
|
+
});
|
|
2968
|
+
const offError = cardCapture.on("error", async (event) => {
|
|
2969
|
+
const message = event.message ?? "There was a problem processing your payment. Please try again.";
|
|
2970
|
+
updateError(message);
|
|
2971
|
+
setOverlayStatus("error");
|
|
2972
|
+
onError?.(new import_shared6.FloPayError(message, "api_error"));
|
|
2973
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
2974
|
+
if (cancelled) return;
|
|
2975
|
+
setOverlayStatus(null);
|
|
2976
|
+
});
|
|
2977
|
+
return () => {
|
|
2978
|
+
cancelled = true;
|
|
2979
|
+
offSubmitting();
|
|
2980
|
+
offComplete();
|
|
2981
|
+
offDecline();
|
|
2982
|
+
offError();
|
|
2983
|
+
};
|
|
2984
|
+
}, [
|
|
2985
|
+
vaultActive,
|
|
2986
|
+
cardCapture,
|
|
2987
|
+
sessionId,
|
|
2988
|
+
nonce,
|
|
2989
|
+
baseUrl,
|
|
2990
|
+
avsConfig,
|
|
2991
|
+
avsCheckProp,
|
|
2992
|
+
resolvedAccount.userId,
|
|
2993
|
+
resolvedAccount.email,
|
|
2994
|
+
resolvedAccount.firstName,
|
|
2995
|
+
resolvedAccount.lastName,
|
|
2996
|
+
resolvedAccount.country,
|
|
2997
|
+
fullName,
|
|
2998
|
+
onComplete,
|
|
2999
|
+
onError,
|
|
3000
|
+
updateError,
|
|
3001
|
+
emitDecline
|
|
3002
|
+
]);
|
|
2671
3003
|
const directPaypalConfigured = !!directPaypal?.clientId;
|
|
2672
3004
|
const hasEnabledMethodsPayload = Array.isArray(enabledPaymentMethods);
|
|
2673
3005
|
const hasEnabledMethods = hasEnabledMethodsPayload && enabledPaymentMethods.length > 0;
|
|
2674
3006
|
const paypalEnabled = hasEnabledMethodsPayload && enabledPaymentMethods.includes("paypal");
|
|
2675
|
-
const { expressMethods, paymentElementMethods } = (0,
|
|
3007
|
+
const { expressMethods, paymentElementMethods } = (0, import_react9.useMemo)(
|
|
2676
3008
|
() => (0, import_shared5.partitionStripeMethods)(enabledPaymentMethods, {
|
|
2677
3009
|
excludePaypal: directPaypalConfigured
|
|
2678
3010
|
}),
|
|
2679
3011
|
[enabledPaymentMethods, directPaypalConfigured]
|
|
2680
3012
|
);
|
|
2681
3013
|
const paypalRenderedSeparately = directPaypalConfigured || !!paypalFlopay;
|
|
2682
|
-
const expressMethodsForWalletRow = (0,
|
|
3014
|
+
const expressMethodsForWalletRow = (0, import_react9.useMemo)(
|
|
2683
3015
|
() => paypalRenderedSeparately ? expressMethods.filter((m) => m !== "paypal") : expressMethods,
|
|
2684
3016
|
[expressMethods, paypalRenderedSeparately]
|
|
2685
3017
|
);
|
|
2686
|
-
const legacyExpressMethods = (0,
|
|
3018
|
+
const legacyExpressMethods = (0, import_react9.useMemo)(() => {
|
|
2687
3019
|
const out = [];
|
|
2688
3020
|
if (showApplePay) out.push("apple_pay");
|
|
2689
3021
|
if (showGooglePay) out.push("google_pay");
|
|
@@ -2691,30 +3023,31 @@ function SplitCardFormInner({
|
|
|
2691
3023
|
}, [showApplePay, showGooglePay]);
|
|
2692
3024
|
const walletExpressMethods = hasEnabledMethodsPayload ? expressMethodsForWalletRow : legacyExpressMethods;
|
|
2693
3025
|
const showWallets = showStripe && walletExpressMethods.length > 0;
|
|
2694
|
-
const
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
),
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
3026
|
+
const apmCountry = enableAVS ? selectedCountry : countryProp;
|
|
3027
|
+
const paymentElementMethodsForCurrency = (0, import_react9.useMemo)(() => {
|
|
3028
|
+
const target = apmCountry?.trim().toUpperCase();
|
|
3029
|
+
if (!target) return paymentElementMethods;
|
|
3030
|
+
if (!enabledPaymentMethodCountries) {
|
|
3031
|
+
return (0, import_shared5.filterStripeMethodsByCountry)(paymentElementMethods, apmCountry);
|
|
3032
|
+
}
|
|
3033
|
+
return paymentElementMethods.filter((method) => {
|
|
3034
|
+
const allowed = enabledPaymentMethodCountries[method];
|
|
3035
|
+
return !allowed || allowed.length === 0 || allowed.includes(target);
|
|
3036
|
+
});
|
|
3037
|
+
}, [paymentElementMethods, apmCountry, enabledPaymentMethodCountries]);
|
|
3038
|
+
const paymentElementBaseOptions = (0, import_react9.useMemo)(() => ({
|
|
2706
3039
|
mode: "payment",
|
|
2707
3040
|
amount: amountInCents,
|
|
2708
3041
|
currency: currency.toLowerCase(),
|
|
2709
3042
|
paymentMethodCreation: "manual",
|
|
2710
3043
|
appearance: paymentElementAppearance
|
|
2711
3044
|
}), [amountInCents, currency, paymentElementAppearance]);
|
|
2712
|
-
const [paypalLoadState, setPaypalLoadState] = (0,
|
|
2713
|
-
const [walletLoadState, setWalletLoadState] = (0,
|
|
2714
|
-
const [paymentElementLoadState, setPaymentElementLoadState] = (0,
|
|
2715
|
-
const [directPaypalReady, setDirectPaypalReady] = (0,
|
|
2716
|
-
const [inAppBrowserDetected, setInAppBrowserDetected] = (0,
|
|
2717
|
-
(0,
|
|
3045
|
+
const [paypalLoadState, setPaypalLoadState] = (0, import_react9.useState)("loading");
|
|
3046
|
+
const [walletLoadState, setWalletLoadState] = (0, import_react9.useState)("loading");
|
|
3047
|
+
const [paymentElementLoadState, setPaymentElementLoadState] = (0, import_react9.useState)("loading");
|
|
3048
|
+
const [directPaypalReady, setDirectPaypalReady] = (0, import_react9.useState)(false);
|
|
3049
|
+
const [inAppBrowserDetected, setInAppBrowserDetected] = (0, import_react9.useState)();
|
|
3050
|
+
(0, import_react9.useEffect)(() => {
|
|
2718
3051
|
setInAppBrowserDetected(isInAppBrowser());
|
|
2719
3052
|
}, []);
|
|
2720
3053
|
const shouldShowPayPal = showPayPal && (directPaypalConfigured || (hasEnabledMethodsPayload ? paypalEnabled : inAppBrowserDetected === false));
|
|
@@ -2726,8 +3059,8 @@ function SplitCardFormInner({
|
|
|
2726
3059
|
const shouldDisplayPayPalRow = shouldRenderDirectPayPal ? directPaypalReady : shouldRenderStripePayPal && isExpressCheckoutRowVisible(paypalLoadState);
|
|
2727
3060
|
const shouldDisplayWalletRow = shouldRenderWallets && isExpressCheckoutRowVisible(walletLoadState);
|
|
2728
3061
|
const shouldDisplayPaymentElementRow = shouldRenderPaymentElement && paymentElementLoadState !== "load_error";
|
|
2729
|
-
const validationFiredRef = (0,
|
|
2730
|
-
(0,
|
|
3062
|
+
const validationFiredRef = (0, import_react9.useRef)(false);
|
|
3063
|
+
(0, import_react9.useEffect)(() => {
|
|
2731
3064
|
if (validationFiredRef.current) return;
|
|
2732
3065
|
if (!showStripe && !showPayPal) {
|
|
2733
3066
|
validationFiredRef.current = true;
|
|
@@ -2747,8 +3080,8 @@ function SplitCardFormInner({
|
|
|
2747
3080
|
updateError(err.message);
|
|
2748
3081
|
}
|
|
2749
3082
|
}, [showStripe, showPayPal, directPaypalConfigured, paypalStripeInstance, onError, updateError]);
|
|
2750
|
-
const deprecationLoggedRef = (0,
|
|
2751
|
-
(0,
|
|
3083
|
+
const deprecationLoggedRef = (0, import_react9.useRef)(false);
|
|
3084
|
+
(0, import_react9.useEffect)(() => {
|
|
2752
3085
|
if (deprecationLoggedRef.current) return;
|
|
2753
3086
|
if (!hasEnabledMethods) return;
|
|
2754
3087
|
const stale = [];
|
|
@@ -2760,14 +3093,14 @@ function SplitCardFormInner({
|
|
|
2760
3093
|
`[FloPay] ${stale.join(" / ")} ${stale.length === 1 ? "is" : "are"} deprecated: the Apple Pay / Google Pay surface is now driven by \`gateways.stripe.enabledPaymentMethods\` on the session response. Remove the legacy prop(s) to silence this warning.`
|
|
2761
3094
|
);
|
|
2762
3095
|
}, [hasEnabledMethods, showApplePay, showGooglePay]);
|
|
2763
|
-
const handleNameChange = (0,
|
|
3096
|
+
const handleNameChange = (0, import_react9.useCallback)((value) => {
|
|
2764
3097
|
setFullName(value);
|
|
2765
3098
|
onFullNameChange?.(value);
|
|
2766
3099
|
const parts = value.trim().split(/\s+/);
|
|
2767
3100
|
onFirstNameChange?.(parts[0] ?? "");
|
|
2768
3101
|
onLastNameChange?.(parts.length > 1 ? parts.slice(1).join(" ") : "");
|
|
2769
3102
|
}, [onFullNameChange, onFirstNameChange, onLastNameChange]);
|
|
2770
|
-
const applyInlineSessionPatch = (0,
|
|
3103
|
+
const applyInlineSessionPatch = (0, import_react9.useCallback)(
|
|
2771
3104
|
(patch, method) => {
|
|
2772
3105
|
if (!checkout.applyInlineSessionPatch) {
|
|
2773
3106
|
return Promise.resolve({ error: null, sessionId, nonce });
|
|
@@ -2789,7 +3122,7 @@ function SplitCardFormInner({
|
|
|
2789
3122
|
},
|
|
2790
3123
|
[checkout.applyInlineSessionPatch, nonce, onError, sessionId, updateError]
|
|
2791
3124
|
);
|
|
2792
|
-
const runBeforeButtonClick = (0,
|
|
3125
|
+
const runBeforeButtonClick = (0, import_react9.useCallback)(async (method) => {
|
|
2793
3126
|
if (!onBeforeButtonClick) return { proceed: true };
|
|
2794
3127
|
try {
|
|
2795
3128
|
const result = await onBeforeButtonClick({
|
|
@@ -2826,7 +3159,7 @@ function SplitCardFormInner({
|
|
|
2826
3159
|
return { proceed: false };
|
|
2827
3160
|
}
|
|
2828
3161
|
}, [applyInlineSessionPatch, checkout.inlineSessionDraft, onBeforeButtonClick, onError, sessionId, updateError]);
|
|
2829
|
-
const processPaymentInternal = (0,
|
|
3162
|
+
const processPaymentInternal = (0, import_react9.useCallback)(
|
|
2830
3163
|
async (tokenizedBody, overrides) => {
|
|
2831
3164
|
if (processingRef.current) return;
|
|
2832
3165
|
processingRef.current = true;
|
|
@@ -3037,7 +3370,7 @@ function SplitCardFormInner({
|
|
|
3037
3370
|
},
|
|
3038
3371
|
[baseUrl, sessionId, nonce, resolvedAccount, fullName, chv, flopay, paypalFlopay, onComplete, onError, updateError, emitDecline]
|
|
3039
3372
|
);
|
|
3040
|
-
const dispatchTokenizedBody = (0,
|
|
3373
|
+
const dispatchTokenizedBody = (0, import_react9.useCallback)(
|
|
3041
3374
|
(tokenizedBody, overrides) => {
|
|
3042
3375
|
if (onTokenizedBody) {
|
|
3043
3376
|
onTokenizedBody(tokenizedBody);
|
|
@@ -3047,7 +3380,7 @@ function SplitCardFormInner({
|
|
|
3047
3380
|
},
|
|
3048
3381
|
[onTokenizedBody, processPaymentInternal]
|
|
3049
3382
|
);
|
|
3050
|
-
(0,
|
|
3383
|
+
(0, import_react9.useImperativeHandle)(innerRef, () => ({
|
|
3051
3384
|
async handleNextAction(secret) {
|
|
3052
3385
|
if (!flopay) return;
|
|
3053
3386
|
setIs3DSActive(true);
|
|
@@ -3074,8 +3407,8 @@ function SplitCardFormInner({
|
|
|
3074
3407
|
}
|
|
3075
3408
|
}
|
|
3076
3409
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
3077
|
-
const stripeResumeAttemptedRef = (0,
|
|
3078
|
-
(0,
|
|
3410
|
+
const stripeResumeAttemptedRef = (0, import_react9.useRef)(false);
|
|
3411
|
+
(0, import_react9.useEffect)(() => {
|
|
3079
3412
|
if (typeof window === "undefined" || stripeResumeAttemptedRef.current) return;
|
|
3080
3413
|
const params = new URLSearchParams(window.location.search);
|
|
3081
3414
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -3153,10 +3486,11 @@ function SplitCardFormInner({
|
|
|
3153
3486
|
}, persistedOverrides);
|
|
3154
3487
|
})();
|
|
3155
3488
|
}, [sessionId, dispatchTokenizedBody, flopay, updateError, emitDecline]);
|
|
3156
|
-
const handleSubmit = (0,
|
|
3489
|
+
const handleSubmit = (0, import_react9.useCallback)(
|
|
3157
3490
|
async (e) => {
|
|
3158
3491
|
e.preventDefault();
|
|
3159
3492
|
if (!flopay || !elements || isSubmitting || processingRef.current) return;
|
|
3493
|
+
if (vaultActive) return;
|
|
3160
3494
|
if (layout !== "buttons") {
|
|
3161
3495
|
onButtonClick?.("card");
|
|
3162
3496
|
}
|
|
@@ -3184,11 +3518,13 @@ function SplitCardFormInner({
|
|
|
3184
3518
|
return;
|
|
3185
3519
|
}
|
|
3186
3520
|
}
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3521
|
+
if (!vaultActive) {
|
|
3522
|
+
const submitResult = await flopay.submitElements();
|
|
3523
|
+
if (submitResult.error) {
|
|
3524
|
+
updateError(submitResult.error.message);
|
|
3525
|
+
onError?.(submitResult.error);
|
|
3526
|
+
return;
|
|
3527
|
+
}
|
|
3192
3528
|
}
|
|
3193
3529
|
const billingAddress = {};
|
|
3194
3530
|
const cc = selectedCountryRef.current;
|
|
@@ -3213,75 +3549,77 @@ function SplitCardFormInner({
|
|
|
3213
3549
|
...fullName.trim() ? { name: fullName.trim() } : {},
|
|
3214
3550
|
...Object.keys(billingAddress).length > 0 ? { address: billingAddress } : {}
|
|
3215
3551
|
};
|
|
3216
|
-
const pmResult = await flopay.createPaymentMethod(billingDetails);
|
|
3217
|
-
if (pmResult.error || !pmResult.paymentMethodId) {
|
|
3218
|
-
updateError(pmResult.error?.message ?? "Failed to create payment method.");
|
|
3219
|
-
return;
|
|
3220
|
-
}
|
|
3221
3552
|
if (!sessionId || !resolvedAccount.email) {
|
|
3222
3553
|
throw new import_shared6.FloPayError("Missing sessionId or email", "validation_error");
|
|
3223
3554
|
}
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3555
|
+
{
|
|
3556
|
+
const pmResult = await flopay.createPaymentMethod(billingDetails);
|
|
3557
|
+
if (pmResult.error || !pmResult.paymentMethodId) {
|
|
3558
|
+
updateError(pmResult.error?.message ?? "Failed to create payment method.");
|
|
3559
|
+
return;
|
|
3560
|
+
}
|
|
3561
|
+
const intentHeaders = { "Content-Type": "application/json" };
|
|
3562
|
+
if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
|
|
3563
|
+
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
3564
|
+
method: "POST",
|
|
3565
|
+
headers: intentHeaders,
|
|
3566
|
+
body: JSON.stringify({
|
|
3567
|
+
sessionId,
|
|
3568
|
+
email: resolvedAccount.email,
|
|
3569
|
+
paymentMethodType: pmResult.paymentMethodId,
|
|
3570
|
+
isPaypal: false
|
|
3571
|
+
})
|
|
3572
|
+
});
|
|
3573
|
+
if (!intentResponse.ok) {
|
|
3574
|
+
const intentError = await buildFloPayApiErrorFromResponse(
|
|
3575
|
+
intentResponse,
|
|
3576
|
+
"Failed to create payment intent"
|
|
3577
|
+
);
|
|
3578
|
+
setOverlayStatus("error");
|
|
3579
|
+
updateError(intentError.message);
|
|
3580
|
+
onError?.(intentError);
|
|
3581
|
+
emitDecline("card", intentError);
|
|
3582
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
3583
|
+
return;
|
|
3584
|
+
}
|
|
3585
|
+
const intentJson = await intentResponse.json();
|
|
3586
|
+
const intentClientSecret = intentJson.data?.id;
|
|
3587
|
+
if (!intentClientSecret) throw new import_shared6.FloPayError("No client_secret in payment intent response", "api_error");
|
|
3588
|
+
const confirmResult = await flopay.confirmCardPayment({
|
|
3589
|
+
clientSecret: intentClientSecret,
|
|
3590
|
+
paymentMethodId: pmResult.paymentMethodId
|
|
3591
|
+
});
|
|
3592
|
+
if (confirmResult.error) {
|
|
3593
|
+
setOverlayStatus("error");
|
|
3594
|
+
updateError(confirmResult.error.message);
|
|
3595
|
+
onError?.(confirmResult.error);
|
|
3596
|
+
emitDecline("card", confirmResult.error);
|
|
3597
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
3598
|
+
return;
|
|
3599
|
+
}
|
|
3600
|
+
const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
|
|
3601
|
+
const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
|
|
3602
|
+
rawProvider,
|
|
3603
|
+
intentClientSecret
|
|
3240
3604
|
);
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
onError?.(confirmResult.error);
|
|
3259
|
-
emitDecline("card", confirmResult.error);
|
|
3260
|
-
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
3261
|
-
return;
|
|
3262
|
-
}
|
|
3263
|
-
const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
|
|
3264
|
-
const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
|
|
3265
|
-
rawProvider,
|
|
3266
|
-
intentClientSecret
|
|
3267
|
-
);
|
|
3268
|
-
const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
|
|
3269
|
-
const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
|
|
3270
|
-
if (!paymentIntentId) {
|
|
3271
|
-
const error2 = new import_shared6.FloPayError("No payment intent returned after confirmation.", "api_error");
|
|
3272
|
-
setOverlayStatus("error");
|
|
3273
|
-
updateError(error2.message);
|
|
3274
|
-
onError?.(error2);
|
|
3275
|
-
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
3276
|
-
return;
|
|
3605
|
+
const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
|
|
3606
|
+
const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
|
|
3607
|
+
if (!paymentIntentId) {
|
|
3608
|
+
const error2 = new import_shared6.FloPayError("No payment intent returned after confirmation.", "api_error");
|
|
3609
|
+
setOverlayStatus("error");
|
|
3610
|
+
updateError(error2.message);
|
|
3611
|
+
onError?.(error2);
|
|
3612
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
3613
|
+
return;
|
|
3614
|
+
}
|
|
3615
|
+
handedOff = isSelfContained;
|
|
3616
|
+
dispatchTokenizedBody({
|
|
3617
|
+
id: paymentMethodId,
|
|
3618
|
+
type: "card",
|
|
3619
|
+
threeDSecureActionResultTokenId: paymentIntentId,
|
|
3620
|
+
originalPaymentMethodId: pmResult.paymentMethodId
|
|
3621
|
+
});
|
|
3277
3622
|
}
|
|
3278
|
-
handedOff = isSelfContained;
|
|
3279
|
-
dispatchTokenizedBody({
|
|
3280
|
-
id: paymentMethodId,
|
|
3281
|
-
type: "card",
|
|
3282
|
-
threeDSecureActionResultTokenId: paymentIntentId,
|
|
3283
|
-
originalPaymentMethodId: pmResult.paymentMethodId
|
|
3284
|
-
});
|
|
3285
3623
|
} catch (err) {
|
|
3286
3624
|
setOverlayStatus("error");
|
|
3287
3625
|
updateError(err instanceof Error ? err.message : "An unexpected error occurred");
|
|
@@ -3293,11 +3631,11 @@ function SplitCardFormInner({
|
|
|
3293
3631
|
}
|
|
3294
3632
|
}
|
|
3295
3633
|
},
|
|
3296
|
-
[flopay, elements, isSubmitting, sessionId, nonce, resolvedAccount.email, baseUrl, isSelfContained, dispatchTokenizedBody, onButtonClick, onError, updateError, emitDecline, layout]
|
|
3634
|
+
[flopay, elements, isSubmitting, sessionId, nonce, resolvedAccount.email, baseUrl, isSelfContained, vaultActive, dispatchTokenizedBody, onButtonClick, onError, updateError, emitDecline, layout]
|
|
3297
3635
|
);
|
|
3298
|
-
const isReady = flopay !== null && elements !== null;
|
|
3636
|
+
const isReady = flopay !== null && (vaultActive || elements !== null);
|
|
3299
3637
|
if (!isReady) {
|
|
3300
|
-
return /* @__PURE__ */ (0,
|
|
3638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
|
|
3301
3639
|
}
|
|
3302
3640
|
const isButtons = layout === "buttons";
|
|
3303
3641
|
const appearanceVars = appearance?.variables;
|
|
@@ -3305,6 +3643,8 @@ function SplitCardFormInner({
|
|
|
3305
3643
|
const appearanceColorBg = appearanceVars?.colorBackground;
|
|
3306
3644
|
const themedWrapperBg = appearanceColorBg && !SDK_DEFAULT_WHITES.has(appearanceColorBg) ? appearanceColorBg : void 0;
|
|
3307
3645
|
const resolvedBorder = bStyles.cardInputBorder ?? (isButtons ? "#e5e7eb" : "#A4A4FF");
|
|
3646
|
+
const resolvedDangerColor = appearanceVars?.colorDanger ?? "#dc2626";
|
|
3647
|
+
const avsBorderColor = (fieldInvalid) => hasAttemptedSubmit && fieldInvalid ? resolvedDangerColor : resolvedBorder;
|
|
3308
3648
|
const cardBg = bStyles.cardFormContainer?.backgroundColor ?? themedWrapperBg ?? (isButtons ? "white" : "#EDEDFF");
|
|
3309
3649
|
const cardInputBg = bStyles.cardInputBackground ?? appearanceVars?.colorBackground ?? "white";
|
|
3310
3650
|
const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
|
|
@@ -3316,7 +3656,9 @@ function SplitCardFormInner({
|
|
|
3316
3656
|
const resolvedInputColor = bStyles.cardInputColor ?? (typeof nameInputOverrides?.color === "string" ? nameInputOverrides.color : void 0) ?? appearanceVars?.colorText ?? "#262833";
|
|
3317
3657
|
const resolvedPlaceholderColor = bStyles.cardInputPlaceholderColor ?? "#9ca3af";
|
|
3318
3658
|
const resolvedBorderRadius = appearanceVars?.borderRadius ?? "8px";
|
|
3659
|
+
const buttonBorderRadius = appearanceVars?.borderRadius ?? bStyles.cardButton?.borderRadius ?? resolvedBorderRadius;
|
|
3319
3660
|
const resolvedPrimaryColor = appearanceVars?.colorPrimary ?? "#4A49FF";
|
|
3661
|
+
const resolvedPrimaryHoverColor = appearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
|
|
3320
3662
|
const resolvedTitleColor = appearanceVars?.colorText ?? "#262833";
|
|
3321
3663
|
const sharedInputTypography = {
|
|
3322
3664
|
fontSize: resolvedInputFontSize,
|
|
@@ -3350,14 +3692,73 @@ function SplitCardFormInner({
|
|
|
3350
3692
|
const containerOverrides = bStyles.cardFormContainer ?? {};
|
|
3351
3693
|
const containerPadding = containerOverrides.padding ?? (isButtons ? "0" : "1rem");
|
|
3352
3694
|
const containerRadius = containerOverrides.borderRadius ?? resolvedBorderRadius;
|
|
3353
|
-
const
|
|
3695
|
+
const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3696
|
+
VaultCardFields,
|
|
3697
|
+
{
|
|
3698
|
+
capture: cardCapture,
|
|
3699
|
+
html: vaultMount.html,
|
|
3700
|
+
messageToken: vaultMount.messageToken,
|
|
3701
|
+
expectedOrigin: vaultMount.expectedOrigin,
|
|
3702
|
+
theme: vaultThemeColors,
|
|
3703
|
+
onReady: () => {
|
|
3704
|
+
setFormReady(true);
|
|
3705
|
+
if (!avsConfig || typeof document === "undefined") return;
|
|
3706
|
+
const focusFirstAvs = () => {
|
|
3707
|
+
const block = document.querySelector('[data-testid="flopay-avs-fields"]');
|
|
3708
|
+
const first = block?.querySelector(
|
|
3709
|
+
"input:not([disabled]), select:not([disabled])"
|
|
3710
|
+
);
|
|
3711
|
+
first?.focus();
|
|
3712
|
+
};
|
|
3713
|
+
focusFirstAvs();
|
|
3714
|
+
let tries = 0;
|
|
3715
|
+
const timer = window.setInterval(() => {
|
|
3716
|
+
tries += 1;
|
|
3717
|
+
const active = document.activeElement;
|
|
3718
|
+
const onIframe = !!active && active.tagName === "IFRAME" && active.id === "flopay_vault_form_iframe";
|
|
3719
|
+
if (onIframe) {
|
|
3720
|
+
focusFirstAvs();
|
|
3721
|
+
window.clearInterval(timer);
|
|
3722
|
+
} else if (tries >= 50) {
|
|
3723
|
+
window.clearInterval(timer);
|
|
3724
|
+
}
|
|
3725
|
+
}, 100);
|
|
3726
|
+
},
|
|
3727
|
+
onError: (message) => updateError(message),
|
|
3728
|
+
onValidation: (message) => {
|
|
3729
|
+
updateError(message);
|
|
3730
|
+
if (message) setOverlayStatus(null);
|
|
3731
|
+
}
|
|
3732
|
+
}
|
|
3733
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3734
|
+
"div",
|
|
3735
|
+
{
|
|
3736
|
+
"data-testid": "flopay-vault-loading",
|
|
3737
|
+
style: {
|
|
3738
|
+
minHeight: 120,
|
|
3739
|
+
display: "flex",
|
|
3740
|
+
alignItems: "center",
|
|
3741
|
+
justifyContent: "center",
|
|
3742
|
+
color: "#6b7280",
|
|
3743
|
+
fontSize: 14
|
|
3744
|
+
},
|
|
3745
|
+
children: "Loading secure card form\u2026"
|
|
3746
|
+
}
|
|
3747
|
+
);
|
|
3748
|
+
const cardFormBlock = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
|
|
3354
3749
|
backgroundColor: cardBg,
|
|
3355
3750
|
borderRadius: containerRadius,
|
|
3356
3751
|
...containerOverrides,
|
|
3357
3752
|
padding: containerPadding,
|
|
3358
|
-
...sharedInputPlaceholderVars
|
|
3753
|
+
...sharedInputPlaceholderVars,
|
|
3754
|
+
// Flex column (BOTH layouts, so default and buttons>card never diverge) so
|
|
3755
|
+
// AVS can be ordered above the vault widget — its submit lives inside the
|
|
3756
|
+
// iframe, so AVS can't sit between fields and button; it goes above the
|
|
3757
|
+
// card form instead of after the button.
|
|
3758
|
+
display: "flex",
|
|
3759
|
+
flexDirection: "column"
|
|
3359
3760
|
}, children: [
|
|
3360
|
-
/* @__PURE__ */ (0,
|
|
3761
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
|
|
3361
3762
|
.flopay-shared-input::placeholder {
|
|
3362
3763
|
color: var(--flopay-input-placeholder-color);
|
|
3363
3764
|
opacity: 1;
|
|
@@ -3366,12 +3767,14 @@ function SplitCardFormInner({
|
|
|
3366
3767
|
font-weight: var(--flopay-input-font-weight);
|
|
3367
3768
|
}
|
|
3368
3769
|
` }),
|
|
3369
|
-
isButtons && showCardForm && /* @__PURE__ */ (0,
|
|
3770
|
+
isButtons && showCardForm && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
|
|
3370
3771
|
display: "flex",
|
|
3371
3772
|
alignItems: "center",
|
|
3372
|
-
padding: "0.75rem 0 0.625rem"
|
|
3773
|
+
padding: "0.75rem 0 0.625rem",
|
|
3774
|
+
// Keep the header on top when AVS is ordered above the card on vault.
|
|
3775
|
+
order: vaultActive ? -2 : 0
|
|
3373
3776
|
}, children: [
|
|
3374
|
-
/* @__PURE__ */ (0,
|
|
3777
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3375
3778
|
"button",
|
|
3376
3779
|
{
|
|
3377
3780
|
type: "button",
|
|
@@ -3393,7 +3796,7 @@ function SplitCardFormInner({
|
|
|
3393
3796
|
},
|
|
3394
3797
|
"aria-label": "Back to payment methods",
|
|
3395
3798
|
children: [
|
|
3396
|
-
/* @__PURE__ */ (0,
|
|
3799
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
|
|
3397
3800
|
display: "inline-flex",
|
|
3398
3801
|
alignItems: "center",
|
|
3399
3802
|
justifyContent: "center",
|
|
@@ -3403,12 +3806,12 @@ function SplitCardFormInner({
|
|
|
3403
3806
|
backgroundColor: "#f3f4f6",
|
|
3404
3807
|
transition: "background-color 0.15s",
|
|
3405
3808
|
...bStyles.backButtonIcon
|
|
3406
|
-
}, children: /* @__PURE__ */ (0,
|
|
3407
|
-
/* @__PURE__ */ (0,
|
|
3809
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
3810
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
3408
3811
|
]
|
|
3409
3812
|
}
|
|
3410
3813
|
),
|
|
3411
|
-
hideTitle ? /* @__PURE__ */ (0,
|
|
3814
|
+
hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3412
3815
|
flex: 1,
|
|
3413
3816
|
textAlign: "center",
|
|
3414
3817
|
fontWeight: 600,
|
|
@@ -3416,58 +3819,65 @@ function SplitCardFormInner({
|
|
|
3416
3819
|
color: "#262833",
|
|
3417
3820
|
paddingRight: 80,
|
|
3418
3821
|
...bStyles.title
|
|
3419
|
-
}, children: /* @__PURE__ */ (0,
|
|
3822
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TitleContentSlot, { content: cardTitleContent }) })
|
|
3420
3823
|
] }),
|
|
3421
|
-
!isButtons && !hideTitle && /* @__PURE__ */ (0,
|
|
3824
|
+
!isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3422
3825
|
textAlign: "center",
|
|
3423
3826
|
fontWeight: 600,
|
|
3424
3827
|
fontSize: "1.1rem",
|
|
3425
3828
|
padding: "0.5rem 0",
|
|
3426
3829
|
color: resolvedTitleColor,
|
|
3830
|
+
// Keep the title at the very top on the vault path. The card-form slot
|
|
3831
|
+
// (-2) and AVS block (-1) are ordered below it but above the card form.
|
|
3832
|
+
order: vaultActive ? -3 : 0,
|
|
3427
3833
|
...bStyles.title
|
|
3428
|
-
}, children: /* @__PURE__ */ (0,
|
|
3429
|
-
/* @__PURE__ */ (0,
|
|
3430
|
-
|
|
3431
|
-
border: `1px solid ${resolvedBorder}`,
|
|
3432
|
-
borderTopLeftRadius: "8px",
|
|
3433
|
-
borderTopRightRadius: "8px",
|
|
3434
|
-
padding: "10px"
|
|
3435
|
-
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
|
|
3436
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex" }, children: [
|
|
3437
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
3438
|
-
flex: 1,
|
|
3439
|
-
backgroundColor: cardInputBg,
|
|
3440
|
-
// Longhand only — mixing `border` shorthand with per-side
|
|
3441
|
-
// overrides triggers React's "shorthand vs longhand" warning
|
|
3442
|
-
// because render order isn't deterministic.
|
|
3443
|
-
borderTop: "none",
|
|
3444
|
-
borderRight: "none",
|
|
3445
|
-
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3446
|
-
borderLeft: `1px solid ${resolvedBorder}`,
|
|
3447
|
-
borderBottomLeftRadius: "8px",
|
|
3448
|
-
padding: "10px"
|
|
3449
|
-
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardExpiryElement, { options: stripeElementStyle }) }),
|
|
3450
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
3451
|
-
flex: 1,
|
|
3834
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TitleContentSlot, { content: cardTitleContent }) }),
|
|
3835
|
+
!vaultActive && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
3836
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3452
3837
|
backgroundColor: cardInputBg,
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
borderLeft: `1px solid ${resolvedBorder}`,
|
|
3457
|
-
borderBottomRightRadius: "8px",
|
|
3838
|
+
border: `1px solid ${resolvedBorder}`,
|
|
3839
|
+
borderTopLeftRadius: resolvedBorderRadius,
|
|
3840
|
+
borderTopRightRadius: resolvedBorderRadius,
|
|
3458
3841
|
padding: "10px"
|
|
3459
|
-
}, children: /* @__PURE__ */ (0,
|
|
3842
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
|
|
3843
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex" }, children: [
|
|
3844
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3845
|
+
flex: 1,
|
|
3846
|
+
backgroundColor: cardInputBg,
|
|
3847
|
+
// Longhand only — mixing `border` shorthand with per-side
|
|
3848
|
+
// overrides triggers React's "shorthand vs longhand" warning
|
|
3849
|
+
// because render order isn't deterministic.
|
|
3850
|
+
borderTop: "none",
|
|
3851
|
+
borderRight: "none",
|
|
3852
|
+
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3853
|
+
borderLeft: `1px solid ${resolvedBorder}`,
|
|
3854
|
+
borderBottomLeftRadius: resolvedBorderRadius,
|
|
3855
|
+
padding: "10px"
|
|
3856
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardExpiryElement, { options: stripeElementStyle }) }),
|
|
3857
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3858
|
+
flex: 1,
|
|
3859
|
+
backgroundColor: cardInputBg,
|
|
3860
|
+
borderTop: "none",
|
|
3861
|
+
borderRight: `1px solid ${resolvedBorder}`,
|
|
3862
|
+
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3863
|
+
borderLeft: `1px solid ${resolvedBorder}`,
|
|
3864
|
+
borderBottomRightRadius: resolvedBorderRadius,
|
|
3865
|
+
padding: "10px"
|
|
3866
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardCvcElement, { options: stripeElementStyle }) })
|
|
3867
|
+
] })
|
|
3460
3868
|
] }),
|
|
3461
|
-
/* @__PURE__ */ (0,
|
|
3869
|
+
!vaultActive && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3462
3870
|
backgroundColor: cardInputBg,
|
|
3463
3871
|
border: `1px solid ${resolvedBorder}`,
|
|
3464
|
-
borderRadius:
|
|
3872
|
+
borderRadius: resolvedBorderRadius,
|
|
3465
3873
|
marginTop: "0.5rem",
|
|
3466
3874
|
padding: "10px"
|
|
3467
|
-
}, children: /* @__PURE__ */ (0,
|
|
3875
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3468
3876
|
"input",
|
|
3469
3877
|
{
|
|
3470
3878
|
className: "flopay-shared-input",
|
|
3879
|
+
id: "flopay-cc-name",
|
|
3880
|
+
name: "cc-name",
|
|
3471
3881
|
placeholder: "Full Name on Card",
|
|
3472
3882
|
autoComplete: "cc-name",
|
|
3473
3883
|
value: fullName,
|
|
@@ -3484,32 +3894,32 @@ function SplitCardFormInner({
|
|
|
3484
3894
|
}
|
|
3485
3895
|
}
|
|
3486
3896
|
) }),
|
|
3487
|
-
avsConfig && (() => {
|
|
3897
|
+
avsConfig && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { order: vaultActive ? -1 : 0 }, "data-testid": "flopay-avs-fields", children: (() => {
|
|
3488
3898
|
const cc = selectedCountry;
|
|
3489
|
-
const inputWrapStyle = (
|
|
3899
|
+
const inputWrapStyle = (invalid = false) => ({
|
|
3490
3900
|
backgroundColor: cardInputBg,
|
|
3491
|
-
border: `1px solid ${
|
|
3492
|
-
borderRadius:
|
|
3901
|
+
border: `1px solid ${avsBorderColor(invalid)}`,
|
|
3902
|
+
borderRadius: resolvedBorderRadius,
|
|
3493
3903
|
marginTop: "0.5rem",
|
|
3494
|
-
padding: "10px"
|
|
3495
|
-
...isButtons && extraStyle ? extraStyle : {}
|
|
3904
|
+
padding: "10px"
|
|
3496
3905
|
});
|
|
3497
3906
|
const inputFieldStyle = () => ({
|
|
3498
3907
|
width: "100%",
|
|
3499
3908
|
border: "none",
|
|
3500
3909
|
outline: "none",
|
|
3501
3910
|
background: "transparent",
|
|
3502
|
-
...sharedInputTypography
|
|
3503
|
-
...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
|
|
3911
|
+
...sharedInputTypography
|
|
3504
3912
|
});
|
|
3505
3913
|
const stateOpts = (0, import_shared5.getStateOptions)(cc);
|
|
3506
|
-
return /* @__PURE__ */ (0,
|
|
3507
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_1, cc) && /* @__PURE__ */ (0,
|
|
3914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
3915
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_1, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: inputWrapStyle(invalidAvsFields.line1), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3508
3916
|
"input",
|
|
3509
3917
|
{
|
|
3510
3918
|
className: "flopay-shared-input",
|
|
3919
|
+
id: "flopay-billing-address-line1",
|
|
3920
|
+
name: "billing-address-line1",
|
|
3511
3921
|
placeholder: "Street Address (e.g. 123 Main St)",
|
|
3512
|
-
autoComplete: "address-line1",
|
|
3922
|
+
autoComplete: "billing address-line1",
|
|
3513
3923
|
value: addressLine1,
|
|
3514
3924
|
onChange: (e) => {
|
|
3515
3925
|
addressLine1Ref.current = e.target.value;
|
|
@@ -3521,12 +3931,14 @@ function SplitCardFormInner({
|
|
|
3521
3931
|
style: inputFieldStyle()
|
|
3522
3932
|
}
|
|
3523
3933
|
) }),
|
|
3524
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_2, cc) && /* @__PURE__ */ (0,
|
|
3934
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_2, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: inputWrapStyle(), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3525
3935
|
"input",
|
|
3526
3936
|
{
|
|
3527
3937
|
className: "flopay-shared-input",
|
|
3938
|
+
id: "flopay-billing-address-line2",
|
|
3939
|
+
name: "billing-address-line2",
|
|
3528
3940
|
placeholder: "Apt, Suite, Unit (optional)",
|
|
3529
|
-
autoComplete: "address-line2",
|
|
3941
|
+
autoComplete: "billing address-line2",
|
|
3530
3942
|
value: addressLine2,
|
|
3531
3943
|
onChange: (e) => {
|
|
3532
3944
|
addressLine2Ref.current = e.target.value;
|
|
@@ -3537,29 +3949,30 @@ function SplitCardFormInner({
|
|
|
3537
3949
|
style: inputFieldStyle()
|
|
3538
3950
|
}
|
|
3539
3951
|
) }),
|
|
3540
|
-
((0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc)) && /* @__PURE__ */ (0,
|
|
3952
|
+
((0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc)) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
|
|
3541
3953
|
display: "flex",
|
|
3542
3954
|
gap: "0",
|
|
3543
3955
|
marginTop: "0.5rem"
|
|
3544
3956
|
}, children: [
|
|
3545
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) && /* @__PURE__ */ (0,
|
|
3957
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3546
3958
|
flex: 1,
|
|
3547
3959
|
backgroundColor: cardInputBg,
|
|
3548
|
-
borderTop: `1px solid ${
|
|
3549
|
-
borderRight: `1px solid ${
|
|
3550
|
-
borderBottom: `1px solid ${
|
|
3551
|
-
borderLeft: `1px solid ${
|
|
3960
|
+
borderTop: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
|
|
3961
|
+
borderRight: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
|
|
3962
|
+
borderBottom: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
|
|
3963
|
+
borderLeft: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
|
|
3552
3964
|
padding: "10px",
|
|
3553
|
-
borderTopLeftRadius:
|
|
3554
|
-
borderBottomLeftRadius:
|
|
3555
|
-
...(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius:
|
|
3556
|
-
|
|
3557
|
-
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3965
|
+
borderTopLeftRadius: resolvedBorderRadius,
|
|
3966
|
+
borderBottomLeftRadius: resolvedBorderRadius,
|
|
3967
|
+
...(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: resolvedBorderRadius }
|
|
3968
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3558
3969
|
"input",
|
|
3559
3970
|
{
|
|
3560
3971
|
className: "flopay-shared-input",
|
|
3972
|
+
id: "flopay-billing-city",
|
|
3973
|
+
name: "billing-city",
|
|
3561
3974
|
placeholder: "City",
|
|
3562
|
-
autoComplete: "address-level2",
|
|
3975
|
+
autoComplete: "billing address-level2",
|
|
3563
3976
|
value: city,
|
|
3564
3977
|
onChange: (e) => {
|
|
3565
3978
|
cityRef.current = e.target.value;
|
|
@@ -3571,39 +3984,42 @@ function SplitCardFormInner({
|
|
|
3571
3984
|
style: inputFieldStyle()
|
|
3572
3985
|
}
|
|
3573
3986
|
) }),
|
|
3574
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) && /* @__PURE__ */ (0,
|
|
3987
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3575
3988
|
flex: 1,
|
|
3576
3989
|
backgroundColor: cardInputBg,
|
|
3577
|
-
border: `1px solid ${
|
|
3990
|
+
border: `1px solid ${avsBorderColor(invalidAvsFields.state)}`,
|
|
3578
3991
|
padding: "10px",
|
|
3579
|
-
borderTopRightRadius:
|
|
3580
|
-
borderBottomRightRadius:
|
|
3581
|
-
...(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius:
|
|
3582
|
-
|
|
3583
|
-
}, children: stateOpts ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
3992
|
+
borderTopRightRadius: resolvedBorderRadius,
|
|
3993
|
+
borderBottomRightRadius: resolvedBorderRadius,
|
|
3994
|
+
...(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: resolvedBorderRadius }
|
|
3995
|
+
}, children: stateOpts ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3584
3996
|
"select",
|
|
3585
3997
|
{
|
|
3998
|
+
id: "flopay-billing-state",
|
|
3999
|
+
name: "billing-state",
|
|
3586
4000
|
value: stateValue,
|
|
3587
4001
|
onChange: (e) => {
|
|
3588
4002
|
stateRef.current = e.target.value;
|
|
3589
4003
|
setStateValue(e.target.value);
|
|
3590
4004
|
},
|
|
3591
4005
|
disabled: isSubmitting,
|
|
3592
|
-
autoComplete: "address-level1",
|
|
4006
|
+
autoComplete: "billing address-level1",
|
|
3593
4007
|
required: true,
|
|
3594
4008
|
"data-testid": "flopay-state",
|
|
3595
4009
|
style: { ...inputFieldStyle(), cursor: "pointer" },
|
|
3596
4010
|
children: [
|
|
3597
|
-
/* @__PURE__ */ (0,
|
|
3598
|
-
stateOpts.map((s) => /* @__PURE__ */ (0,
|
|
4011
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", children: (0, import_shared5.getStateLabel)(cc) }),
|
|
4012
|
+
stateOpts.map((s) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: s.code, children: s.name }, s.code))
|
|
3599
4013
|
]
|
|
3600
4014
|
}
|
|
3601
|
-
) : /* @__PURE__ */ (0,
|
|
4015
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3602
4016
|
"input",
|
|
3603
4017
|
{
|
|
3604
4018
|
className: "flopay-shared-input",
|
|
4019
|
+
id: "flopay-billing-state",
|
|
4020
|
+
name: "billing-state",
|
|
3605
4021
|
placeholder: (0, import_shared5.getStateLabel)(cc),
|
|
3606
|
-
autoComplete: "address-level1",
|
|
4022
|
+
autoComplete: "billing address-level1",
|
|
3607
4023
|
value: stateValue,
|
|
3608
4024
|
onChange: (e) => {
|
|
3609
4025
|
stateRef.current = e.target.value;
|
|
@@ -3616,13 +4032,13 @@ function SplitCardFormInner({
|
|
|
3616
4032
|
}
|
|
3617
4033
|
) })
|
|
3618
4034
|
] }),
|
|
3619
|
-
((0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc)) && /* @__PURE__ */ (0,
|
|
4035
|
+
((0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc)) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
|
|
3620
4036
|
display: "flex",
|
|
3621
4037
|
flexDirection: avsLayoutProp === "column" ? "column" : "row",
|
|
3622
4038
|
gap: avsLayoutProp === "column" ? "0.5rem" : "0",
|
|
3623
4039
|
marginTop: "0.5rem"
|
|
3624
4040
|
}, children: [
|
|
3625
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) && /* @__PURE__ */ (0,
|
|
4041
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3626
4042
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
3627
4043
|
backgroundColor: cardInputBg,
|
|
3628
4044
|
borderTop: `1px solid ${resolvedBorder}`,
|
|
@@ -3630,11 +4046,12 @@ function SplitCardFormInner({
|
|
|
3630
4046
|
borderBottom: `1px solid ${resolvedBorder}`,
|
|
3631
4047
|
borderLeft: `1px solid ${resolvedBorder}`,
|
|
3632
4048
|
padding: "10px",
|
|
3633
|
-
...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius:
|
|
3634
|
-
|
|
3635
|
-
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
4049
|
+
...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: resolvedBorderRadius, borderBottomLeftRadius: resolvedBorderRadius, borderRight: "none" } : { borderRadius: resolvedBorderRadius }
|
|
4050
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3636
4051
|
"select",
|
|
3637
4052
|
{
|
|
4053
|
+
id: "flopay-billing-country",
|
|
4054
|
+
name: "billing-country",
|
|
3638
4055
|
value: selectedCountry,
|
|
3639
4056
|
onChange: (e) => {
|
|
3640
4057
|
selectedCountryRef.current = e.target.value;
|
|
@@ -3644,29 +4061,30 @@ function SplitCardFormInner({
|
|
|
3644
4061
|
setStateValue("");
|
|
3645
4062
|
},
|
|
3646
4063
|
disabled: isSubmitting,
|
|
3647
|
-
autoComplete: "country",
|
|
4064
|
+
autoComplete: "billing country",
|
|
3648
4065
|
"data-testid": "flopay-country",
|
|
3649
4066
|
style: { ...inputFieldStyle(), cursor: "pointer" },
|
|
3650
|
-
children: import_shared5.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0,
|
|
4067
|
+
children: import_shared5.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("option", { value: c.code, children: [
|
|
3651
4068
|
c.flag,
|
|
3652
4069
|
" ",
|
|
3653
4070
|
c.name
|
|
3654
4071
|
] }, c.code))
|
|
3655
4072
|
}
|
|
3656
4073
|
) }),
|
|
3657
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) && /* @__PURE__ */ (0,
|
|
4074
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3658
4075
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
3659
4076
|
backgroundColor: cardInputBg,
|
|
3660
|
-
border: `1px solid ${
|
|
4077
|
+
border: `1px solid ${avsBorderColor(invalidAvsFields.zip)}`,
|
|
3661
4078
|
padding: "10px",
|
|
3662
|
-
...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius:
|
|
3663
|
-
|
|
3664
|
-
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
4079
|
+
...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: resolvedBorderRadius, borderBottomRightRadius: resolvedBorderRadius } : { borderRadius: resolvedBorderRadius }
|
|
4080
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3665
4081
|
"input",
|
|
3666
4082
|
{
|
|
3667
4083
|
className: "flopay-shared-input",
|
|
4084
|
+
id: "flopay-billing-postal-code",
|
|
4085
|
+
name: "billing-postal-code",
|
|
3668
4086
|
placeholder: (0, import_shared5.getPostalCodeLabel)(selectedCountry),
|
|
3669
|
-
autoComplete: "postal-code",
|
|
4087
|
+
autoComplete: "billing postal-code",
|
|
3670
4088
|
value: zipCode,
|
|
3671
4089
|
onChange: (e) => {
|
|
3672
4090
|
zipCodeRef.current = e.target.value;
|
|
@@ -3681,8 +4099,10 @@ function SplitCardFormInner({
|
|
|
3681
4099
|
) })
|
|
3682
4100
|
] })
|
|
3683
4101
|
] });
|
|
3684
|
-
})(),
|
|
3685
|
-
|
|
4102
|
+
})() }),
|
|
4103
|
+
vaultActive && cardPreFormSlot && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { order: -2, width: "100%" }, children: cardPreFormSlot }),
|
|
4104
|
+
vaultActive && vaultCardFieldsNode,
|
|
4105
|
+
displayError && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
3686
4106
|
margin: "0.75rem 0",
|
|
3687
4107
|
padding: "0.625rem 0.875rem",
|
|
3688
4108
|
background: "#FEF2F2",
|
|
@@ -3696,15 +4116,21 @@ function SplitCardFormInner({
|
|
|
3696
4116
|
gap: "0.5rem",
|
|
3697
4117
|
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
3698
4118
|
}, children: [
|
|
3699
|
-
/* @__PURE__ */ (0,
|
|
4119
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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" }) }),
|
|
3700
4120
|
displayError
|
|
3701
4121
|
] }),
|
|
3702
|
-
children ?? /* @__PURE__ */ (0,
|
|
4122
|
+
!vaultActive && (children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3703
4123
|
"button",
|
|
3704
4124
|
{
|
|
3705
4125
|
type: "submit",
|
|
3706
4126
|
disabled: !formReady || isSubmitting,
|
|
3707
4127
|
"data-testid": "flopay-submit",
|
|
4128
|
+
onMouseEnter: (e) => {
|
|
4129
|
+
if (formReady && !isSubmitting) e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
|
|
4130
|
+
},
|
|
4131
|
+
onMouseLeave: (e) => {
|
|
4132
|
+
e.currentTarget.style.backgroundColor = bStyles.submitButton?.backgroundColor ?? resolvedPrimaryColor;
|
|
4133
|
+
},
|
|
3708
4134
|
style: {
|
|
3709
4135
|
width: "100%",
|
|
3710
4136
|
padding: "0.875rem",
|
|
@@ -3717,11 +4143,12 @@ function SplitCardFormInner({
|
|
|
3717
4143
|
fontWeight: 600,
|
|
3718
4144
|
cursor: !formReady || isSubmitting ? "not-allowed" : "pointer",
|
|
3719
4145
|
opacity: !formReady || isSubmitting ? 0.5 : 1,
|
|
4146
|
+
transition: "background-color 0.15s",
|
|
3720
4147
|
...bStyles.submitButton
|
|
3721
4148
|
},
|
|
3722
4149
|
children: isSubmitting ? "PROCESSING..." : submitLabel
|
|
3723
4150
|
}
|
|
3724
|
-
)
|
|
4151
|
+
))
|
|
3725
4152
|
] });
|
|
3726
4153
|
const gateDebugStyle = {
|
|
3727
4154
|
margin: 0,
|
|
@@ -3737,9 +4164,9 @@ function SplitCardFormInner({
|
|
|
3737
4164
|
const renderDirectPaypalGateDebug = (testId) => {
|
|
3738
4165
|
if (!debug) return null;
|
|
3739
4166
|
if (!showPayPal || !directPaypalConfigured) {
|
|
3740
|
-
return /* @__PURE__ */ (0,
|
|
4167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
|
|
3741
4168
|
}
|
|
3742
|
-
return /* @__PURE__ */ (0,
|
|
4169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
|
|
3743
4170
|
"FloPay/DirectPayPal-debug (parent gate)",
|
|
3744
4171
|
` showPayPal=${showPayPal}`,
|
|
3745
4172
|
` directPaypalConfigured=${directPaypalConfigured}`,
|
|
@@ -3752,9 +4179,9 @@ function SplitCardFormInner({
|
|
|
3752
4179
|
const renderStripeGateDebug = (testId) => {
|
|
3753
4180
|
if (!debug) return null;
|
|
3754
4181
|
if (!showStripe || !stripeInstance) {
|
|
3755
|
-
return /* @__PURE__ */ (0,
|
|
4182
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
|
|
3756
4183
|
}
|
|
3757
|
-
return /* @__PURE__ */ (0,
|
|
4184
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
|
|
3758
4185
|
"FloPay/Stripe-debug (parent gate)",
|
|
3759
4186
|
` showStripe=${showStripe}`,
|
|
3760
4187
|
` currency=${currency}`,
|
|
@@ -3783,11 +4210,11 @@ function SplitCardFormInner({
|
|
|
3783
4210
|
const cardButtonSizing = cardButtonContent === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
3784
4211
|
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;
|
|
3785
4212
|
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;
|
|
3786
|
-
return /* @__PURE__ */ (0,
|
|
3787
|
-
/* @__PURE__ */ (0,
|
|
3788
|
-
overlayStatus && /* @__PURE__ */ (0,
|
|
3789
|
-
/* @__PURE__ */ (0,
|
|
3790
|
-
/* @__PURE__ */ (0,
|
|
4213
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
4214
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
|
|
4215
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
4216
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "grid" }, children: [
|
|
4217
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3791
4218
|
"div",
|
|
3792
4219
|
{
|
|
3793
4220
|
"data-testid": "flopay-buttons-panel",
|
|
@@ -3804,8 +4231,8 @@ function SplitCardFormInner({
|
|
|
3804
4231
|
children: [
|
|
3805
4232
|
renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug"),
|
|
3806
4233
|
renderStripeGateDebug("flopay-stripe-gate-debug"),
|
|
3807
|
-
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0,
|
|
3808
|
-
paypalDirectRetry && /* @__PURE__ */ (0,
|
|
4234
|
+
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
4235
|
+
paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3809
4236
|
"div",
|
|
3810
4237
|
{
|
|
3811
4238
|
"data-testid": "flopay-paypal-direct-retry-notice",
|
|
@@ -3821,7 +4248,7 @@ function SplitCardFormInner({
|
|
|
3821
4248
|
children: "Please confirm your PayPal payment to complete checkout."
|
|
3822
4249
|
}
|
|
3823
4250
|
),
|
|
3824
|
-
/* @__PURE__ */ (0,
|
|
4251
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3825
4252
|
DirectPayPalButton,
|
|
3826
4253
|
{
|
|
3827
4254
|
sessionId,
|
|
@@ -3847,7 +4274,7 @@ function SplitCardFormInner({
|
|
|
3847
4274
|
paypalDirectRetry?.orderId ?? "fresh"
|
|
3848
4275
|
)
|
|
3849
4276
|
] }),
|
|
3850
|
-
shouldRenderStripePayPal && /* @__PURE__ */ (0,
|
|
4277
|
+
shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3851
4278
|
PayPalButtonInner,
|
|
3852
4279
|
{
|
|
3853
4280
|
sessionId,
|
|
@@ -3861,10 +4288,10 @@ function SplitCardFormInner({
|
|
|
3861
4288
|
onDecline,
|
|
3862
4289
|
runBeforeButtonClick,
|
|
3863
4290
|
onLoadStateChange: setPaypalLoadState,
|
|
3864
|
-
placeholderBorderRadius:
|
|
4291
|
+
placeholderBorderRadius: buttonBorderRadius
|
|
3865
4292
|
}
|
|
3866
4293
|
) }),
|
|
3867
|
-
shouldRenderWallets ? /* @__PURE__ */ (0,
|
|
4294
|
+
shouldRenderWallets ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3868
4295
|
WalletButtonInner,
|
|
3869
4296
|
{
|
|
3870
4297
|
sessionId,
|
|
@@ -3878,10 +4305,10 @@ function SplitCardFormInner({
|
|
|
3878
4305
|
onDecline,
|
|
3879
4306
|
runBeforeButtonClick,
|
|
3880
4307
|
onLoadStateChange: setWalletLoadState,
|
|
3881
|
-
placeholderBorderRadius:
|
|
4308
|
+
placeholderBorderRadius: buttonBorderRadius
|
|
3882
4309
|
}
|
|
3883
|
-
) }) : shouldShowWallets ? /* @__PURE__ */ (0,
|
|
3884
|
-
shouldRenderPaymentElement && /* @__PURE__ */ (0,
|
|
4310
|
+
) }) : shouldShowWallets ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: buttonBorderRadius, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
|
|
4311
|
+
shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3885
4312
|
StripePaymentElementInner,
|
|
3886
4313
|
{
|
|
3887
4314
|
sessionId,
|
|
@@ -3909,11 +4336,11 @@ function SplitCardFormInner({
|
|
|
3909
4336
|
backgroundColor: bStyles.cardButton?.backgroundColor,
|
|
3910
4337
|
borderColor: bStyles.cardInputBorder,
|
|
3911
4338
|
textColor: bStyles.cardButton?.color,
|
|
3912
|
-
borderRadius:
|
|
4339
|
+
borderRadius: buttonBorderRadius
|
|
3913
4340
|
}
|
|
3914
4341
|
}
|
|
3915
4342
|
),
|
|
3916
|
-
showStripe && /* @__PURE__ */ (0,
|
|
4343
|
+
showStripe && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3917
4344
|
"button",
|
|
3918
4345
|
{
|
|
3919
4346
|
type: "button",
|
|
@@ -3941,7 +4368,8 @@ function SplitCardFormInner({
|
|
|
3941
4368
|
themeBundle,
|
|
3942
4369
|
resolvedPrimaryColor,
|
|
3943
4370
|
resolvedBorderRadius,
|
|
3944
|
-
submitButtonStyle: bStyles.submitButton
|
|
4371
|
+
submitButtonStyle: bStyles.submitButton,
|
|
4372
|
+
explicitPrimaryColor: appearanceVars?.colorPrimary
|
|
3945
4373
|
}),
|
|
3946
4374
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
3947
4375
|
fontWeight: 600,
|
|
@@ -3950,20 +4378,28 @@ function SplitCardFormInner({
|
|
|
3950
4378
|
alignItems: "center",
|
|
3951
4379
|
justifyContent: "center",
|
|
3952
4380
|
gap: "0.625rem",
|
|
3953
|
-
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
4381
|
+
transition: "background-color 0.15s, border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
3954
4382
|
position: "relative",
|
|
3955
4383
|
opacity: isSubmitting ? 0.6 : 1
|
|
3956
4384
|
},
|
|
4385
|
+
onMouseEnter: (e) => {
|
|
4386
|
+
if (!isSubmitting && (themeBundle || appearanceVars?.colorPrimary)) {
|
|
4387
|
+
e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
|
|
4388
|
+
}
|
|
4389
|
+
},
|
|
4390
|
+
onMouseLeave: (e) => {
|
|
4391
|
+
if (themeBundle || appearanceVars?.colorPrimary) e.currentTarget.style.backgroundColor = resolvedPrimaryColor;
|
|
4392
|
+
},
|
|
3957
4393
|
onMouseDown: (e) => {
|
|
3958
4394
|
e.currentTarget.style.transform = "scale(0.985)";
|
|
3959
4395
|
},
|
|
3960
4396
|
onMouseUp: (e) => {
|
|
3961
4397
|
e.currentTarget.style.transform = "scale(1)";
|
|
3962
4398
|
},
|
|
3963
|
-
children: /* @__PURE__ */ (0,
|
|
4399
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardButtonContentSlot, { content: cardButtonContent })
|
|
3964
4400
|
}
|
|
3965
4401
|
),
|
|
3966
|
-
displayError && viewState === "buttons" && /* @__PURE__ */ (0,
|
|
4402
|
+
displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
3967
4403
|
margin: "0.25rem 0",
|
|
3968
4404
|
padding: "0.625rem 0.875rem",
|
|
3969
4405
|
background: "#FEF2F2",
|
|
@@ -3977,33 +4413,33 @@ function SplitCardFormInner({
|
|
|
3977
4413
|
gap: "0.5rem",
|
|
3978
4414
|
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
3979
4415
|
}, children: [
|
|
3980
|
-
/* @__PURE__ */ (0,
|
|
4416
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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" }) }),
|
|
3981
4417
|
displayError
|
|
3982
4418
|
] })
|
|
3983
4419
|
]
|
|
3984
4420
|
}
|
|
3985
4421
|
),
|
|
3986
|
-
showStripe && isCardView && /* @__PURE__ */ (0,
|
|
4422
|
+
showStripe && isCardView && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3987
4423
|
gridArea: "1 / 1",
|
|
3988
4424
|
...cardAnim ? { animation: cardAnim } : {},
|
|
3989
4425
|
...viewState === "collapsing" ? { pointerEvents: "none" } : {}
|
|
3990
4426
|
}, children: cardFormBlock }),
|
|
3991
|
-
showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ (0,
|
|
4427
|
+
showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
3992
4428
|
gridArea: "1 / 1",
|
|
3993
4429
|
...apmAnim ? { animation: apmAnim } : {},
|
|
3994
4430
|
...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
|
|
3995
|
-
}, children: /* @__PURE__ */ (0,
|
|
4431
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
|
|
3996
4432
|
backgroundColor: cardBg,
|
|
3997
4433
|
borderRadius: containerRadius,
|
|
3998
4434
|
...containerOverrides,
|
|
3999
4435
|
padding: containerPadding
|
|
4000
4436
|
}, children: [
|
|
4001
|
-
/* @__PURE__ */ (0,
|
|
4437
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
|
|
4002
4438
|
display: "flex",
|
|
4003
4439
|
alignItems: "center",
|
|
4004
4440
|
padding: "0.75rem 0 0.625rem"
|
|
4005
4441
|
}, children: [
|
|
4006
|
-
/* @__PURE__ */ (0,
|
|
4442
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
4007
4443
|
"button",
|
|
4008
4444
|
{
|
|
4009
4445
|
type: "button",
|
|
@@ -4026,7 +4462,7 @@ function SplitCardFormInner({
|
|
|
4026
4462
|
},
|
|
4027
4463
|
"aria-label": "Back to payment methods",
|
|
4028
4464
|
children: [
|
|
4029
|
-
/* @__PURE__ */ (0,
|
|
4465
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
|
|
4030
4466
|
display: "inline-flex",
|
|
4031
4467
|
alignItems: "center",
|
|
4032
4468
|
justifyContent: "center",
|
|
@@ -4036,12 +4472,12 @@ function SplitCardFormInner({
|
|
|
4036
4472
|
backgroundColor: "#f3f4f6",
|
|
4037
4473
|
transition: "background-color 0.15s",
|
|
4038
4474
|
...bStyles.backButtonIcon
|
|
4039
|
-
}, children: /* @__PURE__ */ (0,
|
|
4040
|
-
/* @__PURE__ */ (0,
|
|
4475
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
4476
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
4041
4477
|
]
|
|
4042
4478
|
}
|
|
4043
4479
|
),
|
|
4044
|
-
/* @__PURE__ */ (0,
|
|
4480
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
4045
4481
|
flex: 1,
|
|
4046
4482
|
textAlign: "center",
|
|
4047
4483
|
fontWeight: 600,
|
|
@@ -4051,12 +4487,12 @@ function SplitCardFormInner({
|
|
|
4051
4487
|
...bStyles.title
|
|
4052
4488
|
}, children: `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(expandedApmMethod)}` })
|
|
4053
4489
|
] }),
|
|
4054
|
-
/* @__PURE__ */ (0,
|
|
4490
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4055
4491
|
import_react_stripe_js.Elements,
|
|
4056
4492
|
{
|
|
4057
4493
|
stripe: stripeInstance,
|
|
4058
4494
|
options: apmInlineOptions,
|
|
4059
|
-
children: /* @__PURE__ */ (0,
|
|
4495
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4060
4496
|
StripeMethodInlineForm,
|
|
4061
4497
|
{
|
|
4062
4498
|
method: expandedApmMethod,
|
|
@@ -4074,7 +4510,8 @@ function SplitCardFormInner({
|
|
|
4074
4510
|
isProcessing: isSubmitting,
|
|
4075
4511
|
submitButtonColor: resolvedPrimaryColor,
|
|
4076
4512
|
submitButtonBorderRadius: resolvedBorderRadius,
|
|
4077
|
-
submitButtonStyle: bStyles.submitButton
|
|
4513
|
+
submitButtonStyle: bStyles.submitButton,
|
|
4514
|
+
errorText: displayError
|
|
4078
4515
|
}
|
|
4079
4516
|
)
|
|
4080
4517
|
},
|
|
@@ -4085,24 +4522,24 @@ function SplitCardFormInner({
|
|
|
4085
4522
|
] });
|
|
4086
4523
|
}
|
|
4087
4524
|
if (isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && showStripe) {
|
|
4088
|
-
return /* @__PURE__ */ (0,
|
|
4089
|
-
/* @__PURE__ */ (0,
|
|
4090
|
-
overlayStatus && /* @__PURE__ */ (0,
|
|
4091
|
-
/* @__PURE__ */ (0,
|
|
4525
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
4526
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
|
|
4527
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
4528
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
4092
4529
|
...apmAnim ? { animation: apmAnim } : {},
|
|
4093
4530
|
...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
|
|
4094
|
-
}, children: /* @__PURE__ */ (0,
|
|
4531
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
|
|
4095
4532
|
backgroundColor: cardBg,
|
|
4096
4533
|
borderRadius: containerRadius,
|
|
4097
4534
|
...containerOverrides,
|
|
4098
4535
|
padding: containerPadding
|
|
4099
4536
|
}, children: [
|
|
4100
|
-
/* @__PURE__ */ (0,
|
|
4537
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
|
|
4101
4538
|
display: "flex",
|
|
4102
4539
|
alignItems: "center",
|
|
4103
4540
|
padding: "0.75rem 0 0.625rem"
|
|
4104
4541
|
}, children: [
|
|
4105
|
-
/* @__PURE__ */ (0,
|
|
4542
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
4106
4543
|
"button",
|
|
4107
4544
|
{
|
|
4108
4545
|
type: "button",
|
|
@@ -4125,7 +4562,7 @@ function SplitCardFormInner({
|
|
|
4125
4562
|
},
|
|
4126
4563
|
"aria-label": "Back to payment methods",
|
|
4127
4564
|
children: [
|
|
4128
|
-
/* @__PURE__ */ (0,
|
|
4565
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
|
|
4129
4566
|
display: "inline-flex",
|
|
4130
4567
|
alignItems: "center",
|
|
4131
4568
|
justifyContent: "center",
|
|
@@ -4135,12 +4572,12 @@ function SplitCardFormInner({
|
|
|
4135
4572
|
backgroundColor: "#f3f4f6",
|
|
4136
4573
|
transition: "background-color 0.15s",
|
|
4137
4574
|
...bStyles.backButtonIcon
|
|
4138
|
-
}, children: /* @__PURE__ */ (0,
|
|
4139
|
-
/* @__PURE__ */ (0,
|
|
4575
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
4576
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
4140
4577
|
]
|
|
4141
4578
|
}
|
|
4142
4579
|
),
|
|
4143
|
-
/* @__PURE__ */ (0,
|
|
4580
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
4144
4581
|
flex: 1,
|
|
4145
4582
|
textAlign: "center",
|
|
4146
4583
|
fontWeight: 600,
|
|
@@ -4150,12 +4587,12 @@ function SplitCardFormInner({
|
|
|
4150
4587
|
...bStyles.title
|
|
4151
4588
|
}, children: `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(expandedApmMethod)}` })
|
|
4152
4589
|
] }),
|
|
4153
|
-
/* @__PURE__ */ (0,
|
|
4590
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4154
4591
|
import_react_stripe_js.Elements,
|
|
4155
4592
|
{
|
|
4156
4593
|
stripe: stripeInstance,
|
|
4157
4594
|
options: apmInlineOptions,
|
|
4158
|
-
children: /* @__PURE__ */ (0,
|
|
4595
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4159
4596
|
StripeMethodInlineForm,
|
|
4160
4597
|
{
|
|
4161
4598
|
method: expandedApmMethod,
|
|
@@ -4173,7 +4610,8 @@ function SplitCardFormInner({
|
|
|
4173
4610
|
isProcessing: isSubmitting,
|
|
4174
4611
|
submitButtonColor: resolvedPrimaryColor,
|
|
4175
4612
|
submitButtonBorderRadius: resolvedBorderRadius,
|
|
4176
|
-
submitButtonStyle: bStyles.submitButton
|
|
4613
|
+
submitButtonStyle: bStyles.submitButton,
|
|
4614
|
+
errorText: displayError
|
|
4177
4615
|
}
|
|
4178
4616
|
)
|
|
4179
4617
|
},
|
|
@@ -4182,14 +4620,14 @@ function SplitCardFormInner({
|
|
|
4182
4620
|
] }) })
|
|
4183
4621
|
] });
|
|
4184
4622
|
}
|
|
4185
|
-
return /* @__PURE__ */ (0,
|
|
4186
|
-
/* @__PURE__ */ (0,
|
|
4187
|
-
overlayStatus && /* @__PURE__ */ (0,
|
|
4188
|
-
/* @__PURE__ */ (0,
|
|
4623
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
4624
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
|
|
4625
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
4626
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
4189
4627
|
renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug-default"),
|
|
4190
4628
|
renderStripeGateDebug("flopay-stripe-gate-debug-default"),
|
|
4191
|
-
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0,
|
|
4192
|
-
paypalDirectRetry && /* @__PURE__ */ (0,
|
|
4629
|
+
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
4630
|
+
paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4193
4631
|
"div",
|
|
4194
4632
|
{
|
|
4195
4633
|
"data-testid": "flopay-paypal-direct-retry-notice-default",
|
|
@@ -4205,7 +4643,7 @@ function SplitCardFormInner({
|
|
|
4205
4643
|
children: "Please confirm your PayPal payment to complete checkout."
|
|
4206
4644
|
}
|
|
4207
4645
|
),
|
|
4208
|
-
/* @__PURE__ */ (0,
|
|
4646
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4209
4647
|
DirectPayPalButton,
|
|
4210
4648
|
{
|
|
4211
4649
|
sessionId,
|
|
@@ -4231,7 +4669,7 @@ function SplitCardFormInner({
|
|
|
4231
4669
|
paypalDirectRetry?.orderId ?? "fresh"
|
|
4232
4670
|
)
|
|
4233
4671
|
] }),
|
|
4234
|
-
shouldRenderStripePayPal && /* @__PURE__ */ (0,
|
|
4672
|
+
shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4235
4673
|
PayPalButtonInner,
|
|
4236
4674
|
{
|
|
4237
4675
|
sessionId,
|
|
@@ -4245,10 +4683,10 @@ function SplitCardFormInner({
|
|
|
4245
4683
|
onDecline,
|
|
4246
4684
|
runBeforeButtonClick,
|
|
4247
4685
|
onLoadStateChange: setPaypalLoadState,
|
|
4248
|
-
placeholderBorderRadius:
|
|
4686
|
+
placeholderBorderRadius: buttonBorderRadius
|
|
4249
4687
|
}
|
|
4250
4688
|
) }),
|
|
4251
|
-
shouldRenderWallets && /* @__PURE__ */ (0,
|
|
4689
|
+
shouldRenderWallets && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4252
4690
|
WalletButtonInner,
|
|
4253
4691
|
{
|
|
4254
4692
|
sessionId,
|
|
@@ -4262,10 +4700,10 @@ function SplitCardFormInner({
|
|
|
4262
4700
|
onDecline,
|
|
4263
4701
|
runBeforeButtonClick,
|
|
4264
4702
|
onLoadStateChange: setWalletLoadState,
|
|
4265
|
-
placeholderBorderRadius:
|
|
4703
|
+
placeholderBorderRadius: buttonBorderRadius
|
|
4266
4704
|
}
|
|
4267
4705
|
) }),
|
|
4268
|
-
shouldRenderPaymentElement && /* @__PURE__ */ (0,
|
|
4706
|
+
shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4269
4707
|
StripePaymentElementInner,
|
|
4270
4708
|
{
|
|
4271
4709
|
sessionId,
|
|
@@ -4293,12 +4731,12 @@ function SplitCardFormInner({
|
|
|
4293
4731
|
backgroundColor: bStyles.cardButton?.backgroundColor,
|
|
4294
4732
|
borderColor: bStyles.cardInputBorder,
|
|
4295
4733
|
textColor: bStyles.cardButton?.color,
|
|
4296
|
-
borderRadius:
|
|
4734
|
+
borderRadius: buttonBorderRadius
|
|
4297
4735
|
}
|
|
4298
4736
|
}
|
|
4299
4737
|
)
|
|
4300
4738
|
] }),
|
|
4301
|
-
showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ (0,
|
|
4739
|
+
showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
|
|
4302
4740
|
display: "flex",
|
|
4303
4741
|
alignItems: "center",
|
|
4304
4742
|
gap: "0.75rem",
|
|
@@ -4306,9 +4744,9 @@ function SplitCardFormInner({
|
|
|
4306
4744
|
color: "#999",
|
|
4307
4745
|
fontSize: "0.85rem"
|
|
4308
4746
|
}, children: [
|
|
4309
|
-
/* @__PURE__ */ (0,
|
|
4310
|
-
/* @__PURE__ */ (0,
|
|
4311
|
-
/* @__PURE__ */ (0,
|
|
4747
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
|
|
4748
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "or pay with card" }),
|
|
4749
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
|
|
4312
4750
|
] }),
|
|
4313
4751
|
showStripe && cardFormBlock
|
|
4314
4752
|
] });
|
|
@@ -4318,6 +4756,26 @@ function SplitCardFormInner({
|
|
|
4318
4756
|
var import_js3 = require("@flopay/js");
|
|
4319
4757
|
var import_shared7 = require("@flopay/shared");
|
|
4320
4758
|
var DEFAULT_SAVED_PAYMENT_DECLINE_METHOD = "card";
|
|
4759
|
+
async function retrieveResumeIntent(stripe, clientSecret, isSetupIntent) {
|
|
4760
|
+
if (isSetupIntent) {
|
|
4761
|
+
if (typeof stripe.retrieveSetupIntent !== "function") return null;
|
|
4762
|
+
const { setupIntent, error: error2 } = await stripe.retrieveSetupIntent(clientSecret);
|
|
4763
|
+
return { error: error2, intent: setupIntent ?? null };
|
|
4764
|
+
}
|
|
4765
|
+
if (typeof stripe.retrievePaymentIntent !== "function") return null;
|
|
4766
|
+
const { paymentIntent, error } = await stripe.retrievePaymentIntent(clientSecret);
|
|
4767
|
+
return { error, intent: paymentIntent ?? null };
|
|
4768
|
+
}
|
|
4769
|
+
async function confirmResumeIntent(stripe, clientSecret, data, isSetupIntent) {
|
|
4770
|
+
if (isSetupIntent) {
|
|
4771
|
+
if (typeof stripe.confirmCardSetup !== "function") return null;
|
|
4772
|
+
const { setupIntent, error: error2 } = await stripe.confirmCardSetup(clientSecret, data);
|
|
4773
|
+
return { error: error2, intent: setupIntent ?? null };
|
|
4774
|
+
}
|
|
4775
|
+
if (typeof stripe.confirmCardPayment !== "function") return null;
|
|
4776
|
+
const { paymentIntent, error } = await stripe.confirmCardPayment(clientSecret, data);
|
|
4777
|
+
return { error, intent: paymentIntent ?? null };
|
|
4778
|
+
}
|
|
4321
4779
|
function getRedirectResultFromCheckoutProcessError(error) {
|
|
4322
4780
|
if (!error?.type || !error.threeDSecureToken) {
|
|
4323
4781
|
return null;
|
|
@@ -4331,6 +4789,210 @@ function getRedirectResultFromCheckoutProcessError(error) {
|
|
|
4331
4789
|
paymentMethodId: error.paymentMethodId
|
|
4332
4790
|
};
|
|
4333
4791
|
}
|
|
4792
|
+
function isTerminalAutoCheckoutThreeDsOutcome(outcome) {
|
|
4793
|
+
return outcome.status === "succeeded" || outcome.status === "declined";
|
|
4794
|
+
}
|
|
4795
|
+
async function runAutoCheckoutThreeDsChallenge(input) {
|
|
4796
|
+
if (typeof document === "undefined" || typeof window === "undefined") {
|
|
4797
|
+
throw new import_shared7.FloPayError("3DS challenge requires a browser environment.", "api_error", {
|
|
4798
|
+
code: "three_ds_no_window"
|
|
4799
|
+
});
|
|
4800
|
+
}
|
|
4801
|
+
if (input.signal?.aborted) {
|
|
4802
|
+
throw new import_shared7.FloPayError("Card authentication was cancelled.", "api_error", {
|
|
4803
|
+
code: "three_ds_aborted"
|
|
4804
|
+
});
|
|
4805
|
+
}
|
|
4806
|
+
const CHALLENGE_TIMEOUT_MS = 3e5;
|
|
4807
|
+
const CHALLENGE_POLL_INTERVAL_MS = 1e3;
|
|
4808
|
+
const COMPLETE_REQUEST_TIMEOUT_MS = 15e3;
|
|
4809
|
+
const completionEndpoint = `${input.billingApiUrl.replace(/\/$/, "")}/v1/checkouts/sessions/${encodeURIComponent(
|
|
4810
|
+
input.sessionId
|
|
4811
|
+
)}/3ds/complete`;
|
|
4812
|
+
const completeThreeDs = async () => {
|
|
4813
|
+
const controller = new AbortController();
|
|
4814
|
+
const onParentAbort = () => controller.abort();
|
|
4815
|
+
if (input.signal?.aborted) {
|
|
4816
|
+
controller.abort();
|
|
4817
|
+
} else {
|
|
4818
|
+
input.signal?.addEventListener("abort", onParentAbort);
|
|
4819
|
+
}
|
|
4820
|
+
const requestTimeout = window.setTimeout(() => controller.abort(), COMPLETE_REQUEST_TIMEOUT_MS);
|
|
4821
|
+
try {
|
|
4822
|
+
const response = await fetch(completionEndpoint, {
|
|
4823
|
+
method: "POST",
|
|
4824
|
+
headers: {
|
|
4825
|
+
"x-checkout-session-token": input.nonce,
|
|
4826
|
+
"content-type": "application/json"
|
|
4827
|
+
},
|
|
4828
|
+
body: "{}",
|
|
4829
|
+
signal: controller.signal
|
|
4830
|
+
});
|
|
4831
|
+
if (!response.ok) {
|
|
4832
|
+
return { status: "unknown" };
|
|
4833
|
+
}
|
|
4834
|
+
const json = await response.json().catch(() => null);
|
|
4835
|
+
return coerceThreeDsOutcome(json);
|
|
4836
|
+
} catch {
|
|
4837
|
+
return { status: "unknown" };
|
|
4838
|
+
} finally {
|
|
4839
|
+
window.clearTimeout(requestTimeout);
|
|
4840
|
+
input.signal?.removeEventListener("abort", onParentAbort);
|
|
4841
|
+
}
|
|
4842
|
+
};
|
|
4843
|
+
const previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
4844
|
+
const backdrop = document.createElement("div");
|
|
4845
|
+
backdrop.setAttribute("data-flopay-auto-3ds-overlay", "1");
|
|
4846
|
+
backdrop.setAttribute("role", "dialog");
|
|
4847
|
+
backdrop.setAttribute("aria-modal", "true");
|
|
4848
|
+
backdrop.setAttribute("aria-label", "Card authentication");
|
|
4849
|
+
backdrop.style.cssText = [
|
|
4850
|
+
"position:fixed",
|
|
4851
|
+
"inset:0",
|
|
4852
|
+
"z-index:2147483647",
|
|
4853
|
+
"background:rgba(15,23,42,0.6)",
|
|
4854
|
+
"display:flex",
|
|
4855
|
+
"align-items:center",
|
|
4856
|
+
"justify-content:center",
|
|
4857
|
+
"padding:16px"
|
|
4858
|
+
].join(";");
|
|
4859
|
+
const frame = document.createElement("iframe");
|
|
4860
|
+
frame.setAttribute("title", "Card authentication");
|
|
4861
|
+
frame.setAttribute("allow", "payment");
|
|
4862
|
+
frame.tabIndex = 0;
|
|
4863
|
+
frame.style.cssText = [
|
|
4864
|
+
"width:min(100%,460px)",
|
|
4865
|
+
"height:min(100%,640px)",
|
|
4866
|
+
"border:0",
|
|
4867
|
+
"border-radius:12px",
|
|
4868
|
+
"background:#fff",
|
|
4869
|
+
"box-shadow:0 12px 30px rgba(0,0,0,0.35)"
|
|
4870
|
+
].join(";");
|
|
4871
|
+
frame.src = input.nextActionRedirectUrl;
|
|
4872
|
+
backdrop.appendChild(frame);
|
|
4873
|
+
document.body.appendChild(backdrop);
|
|
4874
|
+
frame.focus();
|
|
4875
|
+
let expectedReturnOrigin = null;
|
|
4876
|
+
try {
|
|
4877
|
+
expectedReturnOrigin = new URL(input.billingApiUrl, window.location.href).origin;
|
|
4878
|
+
} catch {
|
|
4879
|
+
expectedReturnOrigin = null;
|
|
4880
|
+
}
|
|
4881
|
+
try {
|
|
4882
|
+
const polledOutcome = await new Promise((resolve, reject) => {
|
|
4883
|
+
let settled = false;
|
|
4884
|
+
let timer = 0;
|
|
4885
|
+
let pollTimer = 0;
|
|
4886
|
+
let loadPollTimer = 0;
|
|
4887
|
+
let pollInFlight = false;
|
|
4888
|
+
const cleanup = () => {
|
|
4889
|
+
window.clearTimeout(timer);
|
|
4890
|
+
window.clearInterval(pollTimer);
|
|
4891
|
+
window.clearTimeout(loadPollTimer);
|
|
4892
|
+
window.removeEventListener("message", listener);
|
|
4893
|
+
frame.removeEventListener("load", onFrameLoad);
|
|
4894
|
+
input.signal?.removeEventListener("abort", onAbort);
|
|
4895
|
+
};
|
|
4896
|
+
const maybeResolveFromBackend = async () => {
|
|
4897
|
+
if (settled || pollInFlight) return;
|
|
4898
|
+
pollInFlight = true;
|
|
4899
|
+
try {
|
|
4900
|
+
const outcome = await completeThreeDs();
|
|
4901
|
+
if (settled || !isTerminalAutoCheckoutThreeDsOutcome(outcome)) return;
|
|
4902
|
+
settled = true;
|
|
4903
|
+
cleanup();
|
|
4904
|
+
resolve(outcome);
|
|
4905
|
+
} finally {
|
|
4906
|
+
pollInFlight = false;
|
|
4907
|
+
}
|
|
4908
|
+
};
|
|
4909
|
+
const onFrameLoad = () => {
|
|
4910
|
+
window.clearTimeout(loadPollTimer);
|
|
4911
|
+
loadPollTimer = window.setTimeout(() => {
|
|
4912
|
+
void maybeResolveFromBackend();
|
|
4913
|
+
}, 250);
|
|
4914
|
+
};
|
|
4915
|
+
const onAbort = () => {
|
|
4916
|
+
if (settled) return;
|
|
4917
|
+
settled = true;
|
|
4918
|
+
cleanup();
|
|
4919
|
+
reject(
|
|
4920
|
+
new import_shared7.FloPayError("Card authentication was cancelled.", "api_error", {
|
|
4921
|
+
code: "three_ds_aborted"
|
|
4922
|
+
})
|
|
4923
|
+
);
|
|
4924
|
+
};
|
|
4925
|
+
const listener = (event) => {
|
|
4926
|
+
if (event.source !== frame.contentWindow) return;
|
|
4927
|
+
if (expectedReturnOrigin && event.origin !== expectedReturnOrigin) return;
|
|
4928
|
+
const data = event.data;
|
|
4929
|
+
if (!data || typeof data !== "object") return;
|
|
4930
|
+
const record = data;
|
|
4931
|
+
if (record["source"] !== "flopay-vault-3ds-return") return;
|
|
4932
|
+
if (settled) return;
|
|
4933
|
+
settled = true;
|
|
4934
|
+
cleanup();
|
|
4935
|
+
resolve(null);
|
|
4936
|
+
};
|
|
4937
|
+
timer = window.setTimeout(() => {
|
|
4938
|
+
if (settled) return;
|
|
4939
|
+
settled = true;
|
|
4940
|
+
cleanup();
|
|
4941
|
+
reject(
|
|
4942
|
+
new import_shared7.FloPayError("Card authentication timed out.", "api_error", {
|
|
4943
|
+
code: "three_ds_timeout"
|
|
4944
|
+
})
|
|
4945
|
+
);
|
|
4946
|
+
}, CHALLENGE_TIMEOUT_MS);
|
|
4947
|
+
pollTimer = window.setInterval(() => {
|
|
4948
|
+
void maybeResolveFromBackend();
|
|
4949
|
+
}, CHALLENGE_POLL_INTERVAL_MS);
|
|
4950
|
+
frame.addEventListener("load", onFrameLoad);
|
|
4951
|
+
window.addEventListener("message", listener);
|
|
4952
|
+
input.signal?.addEventListener("abort", onAbort);
|
|
4953
|
+
if (input.signal?.aborted) onAbort();
|
|
4954
|
+
});
|
|
4955
|
+
if (polledOutcome) {
|
|
4956
|
+
return polledOutcome;
|
|
4957
|
+
}
|
|
4958
|
+
return await completeThreeDs();
|
|
4959
|
+
} finally {
|
|
4960
|
+
backdrop.parentNode?.removeChild(backdrop);
|
|
4961
|
+
if (previousFocus?.isConnected) {
|
|
4962
|
+
previousFocus.focus();
|
|
4963
|
+
}
|
|
4964
|
+
}
|
|
4965
|
+
}
|
|
4966
|
+
function coerceThreeDsOutcome(json) {
|
|
4967
|
+
if (!json || typeof json !== "object") return { status: "unknown" };
|
|
4968
|
+
const status = typeof json["status"] === "string" ? json["status"] : "unknown";
|
|
4969
|
+
const providerIntentId = typeof json["providerIntentId"] === "string" ? json["providerIntentId"] : null;
|
|
4970
|
+
switch (status) {
|
|
4971
|
+
case "succeeded":
|
|
4972
|
+
return { status: "succeeded", providerIntentId };
|
|
4973
|
+
case "declined":
|
|
4974
|
+
return {
|
|
4975
|
+
status: "declined",
|
|
4976
|
+
providerIntentId,
|
|
4977
|
+
declineReason: typeof json["declineReason"] === "string" ? json["declineReason"] : null,
|
|
4978
|
+
gatewayDeclineReason: typeof json["gatewayDeclineReason"] === "string" ? json["gatewayDeclineReason"] : null
|
|
4979
|
+
};
|
|
4980
|
+
case "requires_action":
|
|
4981
|
+
return {
|
|
4982
|
+
status: "requires_action",
|
|
4983
|
+
providerIntentId,
|
|
4984
|
+
nextActionRedirectUrl: typeof json["nextActionRedirectUrl"] === "string" ? json["nextActionRedirectUrl"] : null
|
|
4985
|
+
};
|
|
4986
|
+
case "pending":
|
|
4987
|
+
return { status: "pending", providerIntentId };
|
|
4988
|
+
case "timeout":
|
|
4989
|
+
return { status: "timeout", providerIntentId };
|
|
4990
|
+
case "no_attempt":
|
|
4991
|
+
return { status: "no_attempt" };
|
|
4992
|
+
default:
|
|
4993
|
+
return { status: "unknown" };
|
|
4994
|
+
}
|
|
4995
|
+
}
|
|
4334
4996
|
function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment failed. Please try again.", options) {
|
|
4335
4997
|
const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
|
|
4336
4998
|
const rawMessage = error?.message ?? fallbackMessage;
|
|
@@ -4553,64 +5215,66 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
4553
5215
|
{ checkoutMethod: "card" }
|
|
4554
5216
|
);
|
|
4555
5217
|
}
|
|
5218
|
+
const isSetupIntent = (0, import_shared7.isSetupIntentClientSecret)(redirectResult.threeDSecureToken);
|
|
4556
5219
|
let paymentIntent = null;
|
|
4557
5220
|
let savedPaymentMethodId = redirectResult.paymentMethodId;
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
);
|
|
4562
|
-
if (retrieveError) {
|
|
5221
|
+
const retrieved = await retrieveResumeIntent(stripe, redirectResult.threeDSecureToken, isSetupIntent);
|
|
5222
|
+
if (retrieved) {
|
|
5223
|
+
if (retrieved.error) {
|
|
4563
5224
|
throw Object.assign(
|
|
4564
5225
|
new import_shared7.FloPayError(
|
|
4565
|
-
|
|
5226
|
+
retrieved.error.message ?? `Failed to retrieve 3DS ${isSetupIntent ? "setup" : "payment"} status.`,
|
|
4566
5227
|
"api_error",
|
|
4567
|
-
{ code:
|
|
5228
|
+
{ code: retrieved.error.code }
|
|
4568
5229
|
),
|
|
4569
5230
|
{ checkoutMethod: "card" }
|
|
4570
5231
|
);
|
|
4571
5232
|
}
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
5233
|
+
const existingIntent = retrieved.intent;
|
|
5234
|
+
if (!savedPaymentMethodId && existingIntent?.payment_method) {
|
|
5235
|
+
if (typeof existingIntent.payment_method === "string") {
|
|
5236
|
+
savedPaymentMethodId = existingIntent.payment_method;
|
|
5237
|
+
} else if ("id" in existingIntent.payment_method) {
|
|
5238
|
+
savedPaymentMethodId = existingIntent.payment_method.id ?? void 0;
|
|
4577
5239
|
}
|
|
4578
5240
|
}
|
|
4579
5241
|
}
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
5242
|
+
const confirmed = savedPaymentMethodId ? await confirmResumeIntent(
|
|
5243
|
+
stripe,
|
|
5244
|
+
redirectResult.threeDSecureToken,
|
|
5245
|
+
{
|
|
5246
|
+
payment_method: savedPaymentMethodId,
|
|
5247
|
+
return_url: returnUrl ?? resolveSavedPaymentReturnUrl(session) ?? window.location.href
|
|
5248
|
+
},
|
|
5249
|
+
isSetupIntent
|
|
5250
|
+
) : null;
|
|
5251
|
+
if (confirmed) {
|
|
5252
|
+
if (confirmed.error) {
|
|
4589
5253
|
throw Object.assign(
|
|
4590
5254
|
new import_shared7.FloPayError(
|
|
4591
|
-
|
|
5255
|
+
confirmed.error.message ?? "3DS authentication failed.",
|
|
4592
5256
|
"api_error",
|
|
4593
|
-
{ code:
|
|
5257
|
+
{ code: confirmed.error.code }
|
|
4594
5258
|
),
|
|
4595
5259
|
{ checkoutMethod: "card" }
|
|
4596
5260
|
);
|
|
4597
5261
|
}
|
|
4598
|
-
paymentIntent =
|
|
5262
|
+
paymentIntent = confirmed.intent;
|
|
4599
5263
|
} else {
|
|
4600
|
-
const
|
|
5264
|
+
const nextAction = await stripe.handleNextAction({
|
|
4601
5265
|
clientSecret: redirectResult.threeDSecureToken
|
|
4602
5266
|
});
|
|
4603
|
-
if (
|
|
5267
|
+
if (nextAction.error) {
|
|
4604
5268
|
throw Object.assign(
|
|
4605
5269
|
new import_shared7.FloPayError(
|
|
4606
|
-
|
|
5270
|
+
nextAction.error.message ?? "3DS authentication failed.",
|
|
4607
5271
|
"api_error",
|
|
4608
|
-
{ code:
|
|
5272
|
+
{ code: nextAction.error.code }
|
|
4609
5273
|
),
|
|
4610
5274
|
{ checkoutMethod: "card" }
|
|
4611
5275
|
);
|
|
4612
5276
|
}
|
|
4613
|
-
paymentIntent =
|
|
5277
|
+
paymentIntent = (isSetupIntent ? nextAction.setupIntent : nextAction.paymentIntent) ?? null;
|
|
4614
5278
|
}
|
|
4615
5279
|
if (paymentIntent && (paymentIntent.status === "requires_capture" || paymentIntent.status === "succeeded" || paymentIntent.status === "processing")) {
|
|
4616
5280
|
const followUp = await processSavedPaymentForMode({
|
|
@@ -4770,7 +5434,7 @@ async function loadSavedPaymentProviders({
|
|
|
4770
5434
|
}
|
|
4771
5435
|
|
|
4772
5436
|
// src/flopay-checkout.tsx
|
|
4773
|
-
var
|
|
5437
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
4774
5438
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
|
|
4775
5439
|
var PAYPAL_RESUME_STORAGE_KEY = "flopay_checkout_saved_payment_resume";
|
|
4776
5440
|
var sessionInflightMap = /* @__PURE__ */ new Map();
|
|
@@ -4819,6 +5483,36 @@ function clearPayPalResumeState() {
|
|
|
4819
5483
|
console.warn("[FloPayCheckout] Failed to clear PayPal resume state.", error);
|
|
4820
5484
|
}
|
|
4821
5485
|
}
|
|
5486
|
+
function readCachedInlineSession(cacheKey) {
|
|
5487
|
+
if (!canUseStorage()) return null;
|
|
5488
|
+
const raw = window.sessionStorage.getItem(cacheKey);
|
|
5489
|
+
if (!raw) return null;
|
|
5490
|
+
try {
|
|
5491
|
+
const parsed = JSON.parse(raw);
|
|
5492
|
+
if (parsed && typeof parsed.sid === "string" && parsed.sid) {
|
|
5493
|
+
return { sid: parsed.sid, nonce: typeof parsed.nonce === "string" ? parsed.nonce : void 0 };
|
|
5494
|
+
}
|
|
5495
|
+
return null;
|
|
5496
|
+
} catch {
|
|
5497
|
+
return { sid: raw };
|
|
5498
|
+
}
|
|
5499
|
+
}
|
|
5500
|
+
function persistCachedInlineSession(cacheKey, sid, nonce) {
|
|
5501
|
+
if (!canUseStorage()) return;
|
|
5502
|
+
try {
|
|
5503
|
+
window.sessionStorage.setItem(cacheKey, JSON.stringify(nonce ? { sid, nonce } : { sid }));
|
|
5504
|
+
} catch (error) {
|
|
5505
|
+
console.warn("[FloPayCheckout] Failed to persist checkout session cache.", error);
|
|
5506
|
+
}
|
|
5507
|
+
}
|
|
5508
|
+
function clearCachedInlineSession(cacheKey) {
|
|
5509
|
+
if (!canUseStorage()) return;
|
|
5510
|
+
try {
|
|
5511
|
+
window.sessionStorage.removeItem(cacheKey);
|
|
5512
|
+
} catch (error) {
|
|
5513
|
+
console.warn("[FloPayCheckout] Failed to clear checkout session cache.", error);
|
|
5514
|
+
}
|
|
5515
|
+
}
|
|
4822
5516
|
function clearPayPalRedirectParams() {
|
|
4823
5517
|
if (typeof window === "undefined") return;
|
|
4824
5518
|
const url = new URL(window.location.href);
|
|
@@ -4877,6 +5571,8 @@ function FloPayCheckout({
|
|
|
4877
5571
|
onButtonClick,
|
|
4878
5572
|
onBeforeButtonClick,
|
|
4879
5573
|
enableAVS,
|
|
5574
|
+
cardFieldOrder,
|
|
5575
|
+
cardPreFormSlot,
|
|
4880
5576
|
avsLayout,
|
|
4881
5577
|
submitLabel,
|
|
4882
5578
|
className,
|
|
@@ -4888,41 +5584,41 @@ function FloPayCheckout({
|
|
|
4888
5584
|
onSessionCompleted
|
|
4889
5585
|
}) {
|
|
4890
5586
|
const resolvedBillingUrl = (0, import_shared8.resolveBillingApiUrl)(billingApiUrl);
|
|
4891
|
-
const themeBundle = (0,
|
|
5587
|
+
const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
|
|
4892
5588
|
const appearance = appearanceOverride ?? themeBundle?.appearance;
|
|
4893
5589
|
const checkoutType = createSessionParams ? "embedded_checkout" : "standard_checkout";
|
|
4894
5590
|
const checkoutLayout = children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout";
|
|
4895
|
-
const [unified, setUnified] = (0,
|
|
4896
|
-
const [flopay, setFloPay] = (0,
|
|
4897
|
-
const flopayRef = (0,
|
|
4898
|
-
const [paypalFlopay, setPaypalFloPay] = (0,
|
|
4899
|
-
const paypalFlopayRef = (0,
|
|
4900
|
-
const [session, setSession] = (0,
|
|
4901
|
-
const [resolvedSessionId, setResolvedSessionId] = (0,
|
|
5591
|
+
const [unified, setUnified] = (0, import_react10.useState)(null);
|
|
5592
|
+
const [flopay, setFloPay] = (0, import_react10.useState)(null);
|
|
5593
|
+
const flopayRef = (0, import_react10.useRef)(null);
|
|
5594
|
+
const [paypalFlopay, setPaypalFloPay] = (0, import_react10.useState)(null);
|
|
5595
|
+
const paypalFlopayRef = (0, import_react10.useRef)(null);
|
|
5596
|
+
const [session, setSession] = (0, import_react10.useState)(null);
|
|
5597
|
+
const [resolvedSessionId, setResolvedSessionId] = (0, import_react10.useState)(sessionIdProp ?? "");
|
|
4902
5598
|
const activeSessionId = sessionIdProp ?? resolvedSessionId;
|
|
4903
5599
|
const initSessionDependency = createSessionParams ? "" : activeSessionId;
|
|
4904
|
-
const [isLoading, setIsLoading] = (0,
|
|
4905
|
-
const [loadError, setLoadError] = (0,
|
|
4906
|
-
const [currentMode, setCurrentMode] = (0,
|
|
4907
|
-
const [confirmProcessing, setConfirmProcessing] = (0,
|
|
4908
|
-
const [modeError, setModeError] = (0,
|
|
4909
|
-
const [modeOverlayStatus, setModeOverlayStatus] = (0,
|
|
4910
|
-
const [modeOverlayError, setModeOverlayError] = (0,
|
|
4911
|
-
const [createSessionPatch, setCreateSessionPatch] = (0,
|
|
4912
|
-
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0,
|
|
4913
|
-
const [cardBootstrapPending, setCardBootstrapPending] = (0,
|
|
4914
|
-
const autoCheckoutAttempted = (0,
|
|
4915
|
-
const paypalResumeAttempted = (0,
|
|
4916
|
-
const savedPaymentKeysRef = (0,
|
|
4917
|
-
const onCompleteRef = (0,
|
|
5600
|
+
const [isLoading, setIsLoading] = (0, import_react10.useState)(true);
|
|
5601
|
+
const [loadError, setLoadError] = (0, import_react10.useState)(null);
|
|
5602
|
+
const [currentMode, setCurrentMode] = (0, import_react10.useState)("full");
|
|
5603
|
+
const [confirmProcessing, setConfirmProcessing] = (0, import_react10.useState)(false);
|
|
5604
|
+
const [modeError, setModeError] = (0, import_react10.useState)(initialErrorMessage);
|
|
5605
|
+
const [modeOverlayStatus, setModeOverlayStatus] = (0, import_react10.useState)(null);
|
|
5606
|
+
const [modeOverlayError, setModeOverlayError] = (0, import_react10.useState)(null);
|
|
5607
|
+
const [createSessionPatch, setCreateSessionPatch] = (0, import_react10.useState)(void 0);
|
|
5608
|
+
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0, import_react10.useState)("");
|
|
5609
|
+
const [cardBootstrapPending, setCardBootstrapPending] = (0, import_react10.useState)(false);
|
|
5610
|
+
const autoCheckoutAttempted = (0, import_react10.useRef)(false);
|
|
5611
|
+
const paypalResumeAttempted = (0, import_react10.useRef)(false);
|
|
5612
|
+
const savedPaymentKeysRef = (0, import_react10.useRef)(null);
|
|
5613
|
+
const onCompleteRef = (0, import_react10.useRef)(onComplete);
|
|
4918
5614
|
onCompleteRef.current = onComplete;
|
|
4919
|
-
const onErrorRef = (0,
|
|
5615
|
+
const onErrorRef = (0, import_react10.useRef)(onError);
|
|
4920
5616
|
onErrorRef.current = onError;
|
|
4921
|
-
const onDeclineRef = (0,
|
|
5617
|
+
const onDeclineRef = (0, import_react10.useRef)(onDecline);
|
|
4922
5618
|
onDeclineRef.current = onDecline;
|
|
4923
|
-
const onSessionCompletedRef = (0,
|
|
5619
|
+
const onSessionCompletedRef = (0, import_react10.useRef)(onSessionCompleted);
|
|
4924
5620
|
onSessionCompletedRef.current = onSessionCompleted;
|
|
4925
|
-
(0,
|
|
5621
|
+
(0, import_react10.useEffect)(() => {
|
|
4926
5622
|
console.info("[FloPay] Checkout initialized", {
|
|
4927
5623
|
sdk_version: import_shared8.SDK_VERSION,
|
|
4928
5624
|
checkout_type: checkoutType,
|
|
@@ -4930,40 +5626,40 @@ function FloPayCheckout({
|
|
|
4930
5626
|
billing_api_url: resolvedBillingUrl
|
|
4931
5627
|
});
|
|
4932
5628
|
}, [checkoutLayout, checkoutType, resolvedBillingUrl]);
|
|
4933
|
-
const baseCreateSessionHash = (0,
|
|
5629
|
+
const baseCreateSessionHash = (0, import_react10.useMemo)(
|
|
4934
5630
|
() => createSessionParams ? hashCreateParams(createSessionParams) : "",
|
|
4935
5631
|
[createSessionParams]
|
|
4936
5632
|
);
|
|
4937
|
-
const activeCreateSessionPatch = (0,
|
|
5633
|
+
const activeCreateSessionPatch = (0, import_react10.useMemo)(
|
|
4938
5634
|
() => createSessionPatchBaseHash === baseCreateSessionHash ? createSessionPatch : void 0,
|
|
4939
5635
|
[createSessionPatch, createSessionPatchBaseHash, baseCreateSessionHash]
|
|
4940
5636
|
);
|
|
4941
|
-
const effectiveCreateSessionBase = (0,
|
|
5637
|
+
const effectiveCreateSessionBase = (0, import_react10.useMemo)(
|
|
4942
5638
|
() => createSessionParams ? mergeInlineSessionPatch(createSessionParams, activeCreateSessionPatch) : void 0,
|
|
4943
5639
|
[createSessionParams, activeCreateSessionPatch]
|
|
4944
5640
|
);
|
|
4945
5641
|
const effectiveCreateSessionMode = checkoutModeProp ?? effectiveCreateSessionBase?.checkoutMode ?? "full";
|
|
4946
|
-
const effectiveCreateSession = (0,
|
|
5642
|
+
const effectiveCreateSession = (0, import_react10.useMemo)(
|
|
4947
5643
|
() => effectiveCreateSessionBase ? {
|
|
4948
5644
|
...effectiveCreateSessionBase,
|
|
4949
5645
|
checkoutMode: effectiveCreateSessionMode
|
|
4950
5646
|
} : void 0,
|
|
4951
5647
|
[effectiveCreateSessionBase, effectiveCreateSessionMode]
|
|
4952
5648
|
);
|
|
4953
|
-
(0,
|
|
5649
|
+
(0, import_react10.useEffect)(() => {
|
|
4954
5650
|
setCreateSessionPatch(void 0);
|
|
4955
5651
|
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
4956
5652
|
}, [baseCreateSessionHash]);
|
|
4957
|
-
(0,
|
|
5653
|
+
(0, import_react10.useEffect)(() => {
|
|
4958
5654
|
setModeError(initialErrorMessage);
|
|
4959
5655
|
}, [initialErrorMessage]);
|
|
4960
|
-
const emitDecline = (0,
|
|
5656
|
+
const emitDecline = (0, import_react10.useCallback)(
|
|
4961
5657
|
(method, input, overrides) => {
|
|
4962
5658
|
onDeclineRef.current?.(buildDeclineEvent(method, input, overrides));
|
|
4963
5659
|
},
|
|
4964
5660
|
[]
|
|
4965
5661
|
);
|
|
4966
|
-
const runSavedPaymentFlow = (0,
|
|
5662
|
+
const runSavedPaymentFlow = (0, import_react10.useCallback)(
|
|
4967
5663
|
async (sess, options) => {
|
|
4968
5664
|
setModeError(null);
|
|
4969
5665
|
setModeOverlayError(null);
|
|
@@ -5081,7 +5777,7 @@ function FloPayCheckout({
|
|
|
5081
5777
|
resolvedBillingUrl
|
|
5082
5778
|
]
|
|
5083
5779
|
);
|
|
5084
|
-
(0,
|
|
5780
|
+
(0, import_react10.useEffect)(() => {
|
|
5085
5781
|
if (typeof window === "undefined" || paypalResumeAttempted.current) {
|
|
5086
5782
|
return;
|
|
5087
5783
|
}
|
|
@@ -5198,7 +5894,7 @@ function FloPayCheckout({
|
|
|
5198
5894
|
}
|
|
5199
5895
|
})();
|
|
5200
5896
|
}, [emitDecline, locale, normalizeSavedPaymentError, resolvedBillingUrl]);
|
|
5201
|
-
const initializedHashRef = (0,
|
|
5897
|
+
const initializedHashRef = (0, import_react10.useRef)(null);
|
|
5202
5898
|
function hashCreateParams(params) {
|
|
5203
5899
|
const key = JSON.stringify({
|
|
5204
5900
|
c: params?.clientId,
|
|
@@ -5231,16 +5927,16 @@ function FloPayCheckout({
|
|
|
5231
5927
|
}
|
|
5232
5928
|
return `flopay_session_${Math.abs(h).toString(36)}`;
|
|
5233
5929
|
}
|
|
5234
|
-
const createSessionHash = (0,
|
|
5930
|
+
const createSessionHash = (0, import_react10.useMemo)(
|
|
5235
5931
|
() => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
|
|
5236
5932
|
[effectiveCreateSession]
|
|
5237
5933
|
);
|
|
5238
|
-
const createSessionParamsRef = (0,
|
|
5934
|
+
const createSessionParamsRef = (0, import_react10.useRef)(effectiveCreateSession);
|
|
5239
5935
|
createSessionParamsRef.current = effectiveCreateSession;
|
|
5240
|
-
(0,
|
|
5936
|
+
(0, import_react10.useEffect)(() => {
|
|
5241
5937
|
setResolvedSessionId(sessionIdProp ?? "");
|
|
5242
5938
|
}, [sessionIdProp]);
|
|
5243
|
-
(0,
|
|
5939
|
+
(0, import_react10.useEffect)(() => {
|
|
5244
5940
|
autoCheckoutAttempted.current = false;
|
|
5245
5941
|
setModeError(initialErrorMessage);
|
|
5246
5942
|
setModeOverlayError(null);
|
|
@@ -5248,22 +5944,23 @@ function FloPayCheckout({
|
|
|
5248
5944
|
}, [createSessionHash, initialErrorMessage, sessionIdProp]);
|
|
5249
5945
|
async function resolveInlineSession(params, cacheKey) {
|
|
5250
5946
|
const api = new import_js4.PaymentAPI(resolvedBillingUrl);
|
|
5251
|
-
|
|
5947
|
+
const cached = readCachedInlineSession(cacheKey);
|
|
5948
|
+
let sid = cached?.sid ?? null;
|
|
5252
5949
|
let realResult = null;
|
|
5253
5950
|
if (sid) {
|
|
5254
5951
|
try {
|
|
5255
|
-
realResult = await api.getUnifiedCheckoutSession(sid);
|
|
5952
|
+
realResult = await api.getUnifiedCheckoutSession(sid, cached?.nonce);
|
|
5256
5953
|
const status = realResult.data.session?.status;
|
|
5257
5954
|
if (status === "complete") {
|
|
5258
5955
|
if (wasSessionRecentlyCompleted(sid)) {
|
|
5259
5956
|
return { sid, result: realResult };
|
|
5260
5957
|
}
|
|
5261
|
-
|
|
5958
|
+
clearCachedInlineSession(cacheKey);
|
|
5262
5959
|
sid = null;
|
|
5263
5960
|
realResult = null;
|
|
5264
5961
|
}
|
|
5265
5962
|
} catch {
|
|
5266
|
-
|
|
5963
|
+
clearCachedInlineSession(cacheKey);
|
|
5267
5964
|
sid = null;
|
|
5268
5965
|
}
|
|
5269
5966
|
}
|
|
@@ -5277,13 +5974,13 @@ function FloPayCheckout({
|
|
|
5277
5974
|
};
|
|
5278
5975
|
realResult = await api.createAndFetchSession(paramsWithAnalytics);
|
|
5279
5976
|
sid = realResult.data.session?.id ?? "";
|
|
5280
|
-
if (sid
|
|
5281
|
-
|
|
5977
|
+
if (sid) {
|
|
5978
|
+
persistCachedInlineSession(cacheKey, sid, realResult.data.session?.clientSecret);
|
|
5282
5979
|
}
|
|
5283
5980
|
}
|
|
5284
5981
|
return { sid: sid ?? "", result: realResult };
|
|
5285
5982
|
}
|
|
5286
|
-
const bootstrapInlineSession = (0,
|
|
5983
|
+
const bootstrapInlineSession = (0, import_react10.useCallback)(
|
|
5287
5984
|
async (patch) => {
|
|
5288
5985
|
const baseParams = createSessionParamsRef.current;
|
|
5289
5986
|
if (!baseParams) {
|
|
@@ -5344,7 +6041,7 @@ function FloPayCheckout({
|
|
|
5344
6041
|
},
|
|
5345
6042
|
[locale, resolvedBillingUrl]
|
|
5346
6043
|
);
|
|
5347
|
-
const handleInlineSessionPatch = (0,
|
|
6044
|
+
const handleInlineSessionPatch = (0, import_react10.useCallback)(async (patch) => {
|
|
5348
6045
|
if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) {
|
|
5349
6046
|
return {
|
|
5350
6047
|
sessionId: resolvedSessionId,
|
|
@@ -5367,7 +6064,7 @@ function FloPayCheckout({
|
|
|
5367
6064
|
resolvedSessionId,
|
|
5368
6065
|
session
|
|
5369
6066
|
]);
|
|
5370
|
-
(0,
|
|
6067
|
+
(0, import_react10.useEffect)(() => {
|
|
5371
6068
|
let cancelled = false;
|
|
5372
6069
|
setLoadError(null);
|
|
5373
6070
|
if (createSessionHash) {
|
|
@@ -5533,7 +6230,7 @@ function FloPayCheckout({
|
|
|
5533
6230
|
nonceProp,
|
|
5534
6231
|
runSavedPaymentFlow
|
|
5535
6232
|
]);
|
|
5536
|
-
const handleConfirmCheckout = (0,
|
|
6233
|
+
const handleConfirmCheckout = (0, import_react10.useCallback)(async () => {
|
|
5537
6234
|
if (confirmProcessing || !session) return;
|
|
5538
6235
|
setConfirmProcessing(true);
|
|
5539
6236
|
setModeError(null);
|
|
@@ -5548,7 +6245,7 @@ function FloPayCheckout({
|
|
|
5548
6245
|
}, [activeSessionId, confirmProcessing, runSavedPaymentFlow, session]);
|
|
5549
6246
|
const directPaypalConfig = resolveDirectPaypalConfig(unified);
|
|
5550
6247
|
const isPaypalOnlySession = isPayPalOnlyUnified(unified);
|
|
5551
|
-
const providerOptions = (0,
|
|
6248
|
+
const providerOptions = (0, import_react10.useMemo)(() => {
|
|
5552
6249
|
if (!unified || !session || !unified.data.stripe?.publishableKey) return void 0;
|
|
5553
6250
|
const opts = {
|
|
5554
6251
|
appearance,
|
|
@@ -5567,7 +6264,7 @@ function FloPayCheckout({
|
|
|
5567
6264
|
const shouldHandleInlineSessionPatch = Boolean(
|
|
5568
6265
|
createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && effectiveCreateSessionMode === "full"
|
|
5569
6266
|
);
|
|
5570
|
-
const checkoutValue = (0,
|
|
6267
|
+
const checkoutValue = (0, import_react10.useMemo)(
|
|
5571
6268
|
() => ({
|
|
5572
6269
|
session,
|
|
5573
6270
|
loading: isLoading,
|
|
@@ -5589,7 +6286,7 @@ function FloPayCheckout({
|
|
|
5589
6286
|
]
|
|
5590
6287
|
);
|
|
5591
6288
|
const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && !isPaypalOnlySession && (!flopay || !providerOptions);
|
|
5592
|
-
const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0,
|
|
6289
|
+
const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5593
6290
|
ProcessingOverlay,
|
|
5594
6291
|
{
|
|
5595
6292
|
status: modeOverlayStatus,
|
|
@@ -5598,32 +6295,32 @@ function FloPayCheckout({
|
|
|
5598
6295
|
) : null;
|
|
5599
6296
|
if (isLoading) {
|
|
5600
6297
|
if (loadingNode) {
|
|
5601
|
-
return /* @__PURE__ */ (0,
|
|
6298
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
5602
6299
|
loadingNode,
|
|
5603
6300
|
modeOverlay
|
|
5604
6301
|
] });
|
|
5605
6302
|
}
|
|
5606
6303
|
if (layout === "buttons") {
|
|
5607
6304
|
const bundleRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
5608
|
-
const skeletonBar = (h) => /* @__PURE__ */ (0,
|
|
6305
|
+
const skeletonBar = (h) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5609
6306
|
height: h,
|
|
5610
6307
|
borderRadius: bundleRadius,
|
|
5611
6308
|
background: "#e5e7eb",
|
|
5612
6309
|
animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
|
|
5613
6310
|
} });
|
|
5614
|
-
return /* @__PURE__ */ (0,
|
|
5615
|
-
/* @__PURE__ */ (0,
|
|
6311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
6312
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
5616
6313
|
showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
5617
6314
|
showStripe && (showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
5618
6315
|
showStripe && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
5619
|
-
/* @__PURE__ */ (0,
|
|
6316
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
5620
6317
|
] }),
|
|
5621
6318
|
modeOverlay
|
|
5622
6319
|
] });
|
|
5623
6320
|
}
|
|
5624
|
-
return /* @__PURE__ */ (0,
|
|
5625
|
-
/* @__PURE__ */ (0,
|
|
5626
|
-
/* @__PURE__ */ (0,
|
|
6321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
6322
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
|
|
6323
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5627
6324
|
width: 24,
|
|
5628
6325
|
height: 24,
|
|
5629
6326
|
border: "2px solid #e5e7eb",
|
|
@@ -5631,16 +6328,16 @@ function FloPayCheckout({
|
|
|
5631
6328
|
borderRadius: "50%",
|
|
5632
6329
|
animation: "spin 0.6s linear infinite"
|
|
5633
6330
|
} }),
|
|
5634
|
-
/* @__PURE__ */ (0,
|
|
6331
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
5635
6332
|
] }),
|
|
5636
6333
|
modeOverlay
|
|
5637
6334
|
] });
|
|
5638
6335
|
}
|
|
5639
6336
|
if (loadError) {
|
|
5640
6337
|
if (errorNode) {
|
|
5641
|
-
return /* @__PURE__ */ (0,
|
|
6338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
|
|
5642
6339
|
}
|
|
5643
|
-
return /* @__PURE__ */ (0,
|
|
6340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5644
6341
|
"div",
|
|
5645
6342
|
{
|
|
5646
6343
|
role: "alert",
|
|
@@ -5656,8 +6353,8 @@ function FloPayCheckout({
|
|
|
5656
6353
|
) });
|
|
5657
6354
|
}
|
|
5658
6355
|
if (shouldShowInterimButtons) {
|
|
5659
|
-
return /* @__PURE__ */ (0,
|
|
5660
|
-
/* @__PURE__ */ (0,
|
|
6356
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
6357
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5661
6358
|
InterimButtonsView,
|
|
5662
6359
|
{
|
|
5663
6360
|
onButtonClick,
|
|
@@ -5677,9 +6374,9 @@ function FloPayCheckout({
|
|
|
5677
6374
|
] });
|
|
5678
6375
|
}
|
|
5679
6376
|
if (isPaypalOnlySession && session && directPaypalConfig) {
|
|
5680
|
-
return /* @__PURE__ */ (0,
|
|
5681
|
-
/* @__PURE__ */ (0,
|
|
5682
|
-
modeError && /* @__PURE__ */ (0,
|
|
6377
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
6378
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className, style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
6379
|
+
modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5683
6380
|
"div",
|
|
5684
6381
|
{
|
|
5685
6382
|
role: "alert",
|
|
@@ -5696,7 +6393,7 @@ function FloPayCheckout({
|
|
|
5696
6393
|
children: modeError
|
|
5697
6394
|
}
|
|
5698
6395
|
),
|
|
5699
|
-
/* @__PURE__ */ (0,
|
|
6396
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5700
6397
|
DirectPayPalButton,
|
|
5701
6398
|
{
|
|
5702
6399
|
sessionId: activeSessionId,
|
|
@@ -5720,12 +6417,12 @@ function FloPayCheckout({
|
|
|
5720
6417
|
] });
|
|
5721
6418
|
}
|
|
5722
6419
|
if (!flopay || !providerOptions) {
|
|
5723
|
-
return /* @__PURE__ */ (0,
|
|
6420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: modeOverlay });
|
|
5724
6421
|
}
|
|
5725
6422
|
if (currentMode === "confirm") {
|
|
5726
|
-
return /* @__PURE__ */ (0,
|
|
5727
|
-
/* @__PURE__ */ (0,
|
|
5728
|
-
modeError && /* @__PURE__ */ (0,
|
|
6423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
6424
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className, children: [
|
|
6425
|
+
modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5729
6426
|
"div",
|
|
5730
6427
|
{
|
|
5731
6428
|
style: {
|
|
@@ -5740,7 +6437,7 @@ function FloPayCheckout({
|
|
|
5740
6437
|
renderConfirmButton ? renderConfirmButton({
|
|
5741
6438
|
onConfirm: handleConfirmCheckout,
|
|
5742
6439
|
isProcessing: confirmProcessing
|
|
5743
|
-
}) : /* @__PURE__ */ (0,
|
|
6440
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5744
6441
|
"button",
|
|
5745
6442
|
{
|
|
5746
6443
|
type: "button",
|
|
@@ -5765,9 +6462,9 @@ function FloPayCheckout({
|
|
|
5765
6462
|
modeOverlay
|
|
5766
6463
|
] });
|
|
5767
6464
|
}
|
|
5768
|
-
return /* @__PURE__ */ (0,
|
|
5769
|
-
/* @__PURE__ */ (0,
|
|
5770
|
-
modeError && /* @__PURE__ */ (0,
|
|
6465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
6466
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
6467
|
+
modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5771
6468
|
"div",
|
|
5772
6469
|
{
|
|
5773
6470
|
style: {
|
|
@@ -5782,7 +6479,7 @@ function FloPayCheckout({
|
|
|
5782
6479
|
children: modeError
|
|
5783
6480
|
}
|
|
5784
6481
|
),
|
|
5785
|
-
/* @__PURE__ */ (0,
|
|
6482
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5786
6483
|
SessionInjector,
|
|
5787
6484
|
{
|
|
5788
6485
|
sessionId: activeSessionId,
|
|
@@ -5792,7 +6489,7 @@ function FloPayCheckout({
|
|
|
5792
6489
|
children
|
|
5793
6490
|
}
|
|
5794
6491
|
)
|
|
5795
|
-
] }) : /* @__PURE__ */ (0,
|
|
6492
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5796
6493
|
SplitCardForm,
|
|
5797
6494
|
{
|
|
5798
6495
|
sessionId: activeSessionId,
|
|
@@ -5812,6 +6509,7 @@ function FloPayCheckout({
|
|
|
5812
6509
|
showPayPal,
|
|
5813
6510
|
showStripe,
|
|
5814
6511
|
enabledPaymentMethods: unified?.data.stripe?.enabledPaymentMethods,
|
|
6512
|
+
enabledPaymentMethodCountries: unified?.data.stripe?.enabledPaymentMethodCountries,
|
|
5815
6513
|
showApplePay,
|
|
5816
6514
|
showGooglePay,
|
|
5817
6515
|
layout,
|
|
@@ -5825,6 +6523,8 @@ function FloPayCheckout({
|
|
|
5825
6523
|
onButtonClick,
|
|
5826
6524
|
onBeforeButtonClick,
|
|
5827
6525
|
enableAVS,
|
|
6526
|
+
...cardFieldOrder ? { cardFieldOrder } : {},
|
|
6527
|
+
...cardPreFormSlot ? { cardPreFormSlot } : {},
|
|
5828
6528
|
avsLayout,
|
|
5829
6529
|
country: session?.customer?.country,
|
|
5830
6530
|
city: session?.customer?.city,
|
|
@@ -5852,8 +6552,8 @@ function SessionInjector({
|
|
|
5852
6552
|
session,
|
|
5853
6553
|
children
|
|
5854
6554
|
}) {
|
|
5855
|
-
return /* @__PURE__ */ (0,
|
|
5856
|
-
if (!
|
|
6555
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: import_react10.default.Children.map(children, (child) => {
|
|
6556
|
+
if (!import_react10.default.isValidElement(child)) return child;
|
|
5857
6557
|
const existing = child.props;
|
|
5858
6558
|
const injected = {};
|
|
5859
6559
|
if (!existing.sessionId) injected.sessionId = sessionId;
|
|
@@ -5868,7 +6568,7 @@ function SessionInjector({
|
|
|
5868
6568
|
injected.lastName = session.customer.lastName;
|
|
5869
6569
|
}
|
|
5870
6570
|
if (Object.keys(injected).length === 0) return child;
|
|
5871
|
-
return
|
|
6571
|
+
return import_react10.default.cloneElement(child, injected);
|
|
5872
6572
|
}) });
|
|
5873
6573
|
}
|
|
5874
6574
|
function InterimButtonsView({
|
|
@@ -5888,15 +6588,15 @@ function InterimButtonsView({
|
|
|
5888
6588
|
cardBackButtonContent,
|
|
5889
6589
|
cardTitleContent
|
|
5890
6590
|
}) {
|
|
5891
|
-
const [showCardForm, setShowCardForm] = (0,
|
|
6591
|
+
const [showCardForm, setShowCardForm] = (0, import_react10.useState)(false);
|
|
5892
6592
|
const isCardOpenControlled = typeof cardOpen === "boolean";
|
|
5893
|
-
(0,
|
|
6593
|
+
(0, import_react10.useEffect)(() => {
|
|
5894
6594
|
if (isCardOpenControlled) {
|
|
5895
6595
|
setShowCardForm(cardOpen);
|
|
5896
6596
|
}
|
|
5897
6597
|
}, [cardOpen, isCardOpenControlled]);
|
|
5898
|
-
const themeBundle = (0,
|
|
5899
|
-
const bStyles = (0,
|
|
6598
|
+
const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
|
|
6599
|
+
const bStyles = (0, import_react10.useMemo)(() => {
|
|
5900
6600
|
const base = themeBundle?.buttonsLayout ?? (0, import_shared8.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
5901
6601
|
if (!stylesOverride) return base;
|
|
5902
6602
|
return {
|
|
@@ -5911,7 +6611,7 @@ function InterimButtonsView({
|
|
|
5911
6611
|
};
|
|
5912
6612
|
}, [themeBundle, buttonsTheme, stylesOverride]);
|
|
5913
6613
|
const skeletonRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
5914
|
-
const skeleton = (h) => /* @__PURE__ */ (0,
|
|
6614
|
+
const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5915
6615
|
height: h,
|
|
5916
6616
|
borderRadius: skeletonRadius,
|
|
5917
6617
|
background: "#e5e7eb",
|
|
@@ -5923,15 +6623,15 @@ function InterimButtonsView({
|
|
|
5923
6623
|
const inputBg = bStyles.cardInputBackground ?? "white";
|
|
5924
6624
|
const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
|
|
5925
6625
|
const hideTitle = isEmptySlotContent(cardTitleContent);
|
|
5926
|
-
return /* @__PURE__ */ (0,
|
|
6626
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
5927
6627
|
backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
|
|
5928
6628
|
borderRadius: "8px",
|
|
5929
6629
|
animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
|
|
5930
6630
|
overflow: "hidden",
|
|
5931
6631
|
...bStyles.cardFormContainer
|
|
5932
6632
|
}, children: [
|
|
5933
|
-
/* @__PURE__ */ (0,
|
|
5934
|
-
/* @__PURE__ */ (0,
|
|
6633
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
|
|
6634
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
5935
6635
|
"button",
|
|
5936
6636
|
{
|
|
5937
6637
|
type: "button",
|
|
@@ -5958,7 +6658,7 @@ function InterimButtonsView({
|
|
|
5958
6658
|
...bStyles.backButton
|
|
5959
6659
|
},
|
|
5960
6660
|
children: [
|
|
5961
|
-
/* @__PURE__ */ (0,
|
|
6661
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
|
|
5962
6662
|
display: "inline-flex",
|
|
5963
6663
|
alignItems: "center",
|
|
5964
6664
|
justifyContent: "center",
|
|
@@ -5967,12 +6667,12 @@ function InterimButtonsView({
|
|
|
5967
6667
|
borderRadius: "50%",
|
|
5968
6668
|
backgroundColor: "#f3f4f6",
|
|
5969
6669
|
...bStyles.backButtonIcon
|
|
5970
|
-
}, children: /* @__PURE__ */ (0,
|
|
5971
|
-
/* @__PURE__ */ (0,
|
|
6670
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
6671
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
5972
6672
|
]
|
|
5973
6673
|
}
|
|
5974
6674
|
),
|
|
5975
|
-
hideTitle ? /* @__PURE__ */ (0,
|
|
6675
|
+
hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5976
6676
|
flex: 1,
|
|
5977
6677
|
textAlign: "center",
|
|
5978
6678
|
fontWeight: 600,
|
|
@@ -5980,11 +6680,11 @@ function InterimButtonsView({
|
|
|
5980
6680
|
color: "#262833",
|
|
5981
6681
|
paddingRight: 80,
|
|
5982
6682
|
...bStyles.title
|
|
5983
|
-
}, children: /* @__PURE__ */ (0,
|
|
6683
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TitleContentSlot, { content: cardTitleContent }) })
|
|
5984
6684
|
] }),
|
|
5985
|
-
/* @__PURE__ */ (0,
|
|
5986
|
-
/* @__PURE__ */ (0,
|
|
5987
|
-
/* @__PURE__ */ (0,
|
|
6685
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
6686
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex" }, children: [
|
|
6687
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5988
6688
|
flex: 1,
|
|
5989
6689
|
backgroundColor: inputBg,
|
|
5990
6690
|
borderTop: "none",
|
|
@@ -5994,8 +6694,8 @@ function InterimButtonsView({
|
|
|
5994
6694
|
borderBottomLeftRadius: 8,
|
|
5995
6695
|
padding: 12,
|
|
5996
6696
|
height: 45
|
|
5997
|
-
}, children: /* @__PURE__ */ (0,
|
|
5998
|
-
/* @__PURE__ */ (0,
|
|
6697
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
6698
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5999
6699
|
flex: 1,
|
|
6000
6700
|
backgroundColor: inputBg,
|
|
6001
6701
|
borderTop: "none",
|
|
@@ -6005,10 +6705,10 @@ function InterimButtonsView({
|
|
|
6005
6705
|
borderBottomRightRadius: 8,
|
|
6006
6706
|
padding: 12,
|
|
6007
6707
|
height: 45
|
|
6008
|
-
}, children: /* @__PURE__ */ (0,
|
|
6708
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
|
|
6009
6709
|
] }),
|
|
6010
|
-
/* @__PURE__ */ (0,
|
|
6011
|
-
/* @__PURE__ */ (0,
|
|
6710
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
6711
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
6012
6712
|
height: 50,
|
|
6013
6713
|
borderRadius: 8,
|
|
6014
6714
|
marginTop: 16,
|
|
@@ -6017,7 +6717,7 @@ function InterimButtonsView({
|
|
|
6017
6717
|
...bStyles.submitButton,
|
|
6018
6718
|
opacity: 0.5
|
|
6019
6719
|
} }),
|
|
6020
|
-
/* @__PURE__ */ (0,
|
|
6720
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
|
|
6021
6721
|
@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
6022
6722
|
@keyframes flopay-interim-expand {
|
|
6023
6723
|
0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
|
|
@@ -6027,10 +6727,10 @@ function InterimButtonsView({
|
|
|
6027
6727
|
` })
|
|
6028
6728
|
] });
|
|
6029
6729
|
}
|
|
6030
|
-
return /* @__PURE__ */ (0,
|
|
6730
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
6031
6731
|
showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
6032
6732
|
showStripe && (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
6033
|
-
showStripe && /* @__PURE__ */ (0,
|
|
6733
|
+
showStripe && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
6034
6734
|
"button",
|
|
6035
6735
|
{
|
|
6036
6736
|
type: "button",
|
|
@@ -6070,10 +6770,10 @@ function InterimButtonsView({
|
|
|
6070
6770
|
onMouseUp: (e) => {
|
|
6071
6771
|
e.currentTarget.style.transform = "scale(1)";
|
|
6072
6772
|
},
|
|
6073
|
-
children: /* @__PURE__ */ (0,
|
|
6773
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardButtonContentSlot, { content: cardButtonContent })
|
|
6074
6774
|
}
|
|
6075
6775
|
),
|
|
6076
|
-
errorMessage && /* @__PURE__ */ (0,
|
|
6776
|
+
errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
6077
6777
|
margin: "0.25rem 0",
|
|
6078
6778
|
padding: "0.625rem 0.875rem",
|
|
6079
6779
|
background: "#FEF2F2",
|
|
@@ -6087,22 +6787,22 @@ function InterimButtonsView({
|
|
|
6087
6787
|
gap: "0.5rem",
|
|
6088
6788
|
...bStyles.errorBanner
|
|
6089
6789
|
}, children: [
|
|
6090
|
-
/* @__PURE__ */ (0,
|
|
6790
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("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" }) }),
|
|
6091
6791
|
errorMessage
|
|
6092
6792
|
] }),
|
|
6093
|
-
/* @__PURE__ */ (0,
|
|
6793
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
6094
6794
|
] });
|
|
6095
6795
|
}
|
|
6096
6796
|
|
|
6097
6797
|
// src/checkout-form.tsx
|
|
6098
6798
|
var import_js5 = require("@flopay/js");
|
|
6099
6799
|
var import_shared9 = require("@flopay/shared");
|
|
6100
|
-
var
|
|
6101
|
-
var
|
|
6800
|
+
var import_react11 = require("react");
|
|
6801
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
6102
6802
|
var WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
6103
|
-
var CheckoutForm = (0,
|
|
6803
|
+
var CheckoutForm = (0, import_react11.forwardRef)(
|
|
6104
6804
|
function CheckoutForm2(props, ref) {
|
|
6105
|
-
return /* @__PURE__ */ (0,
|
|
6805
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutFormInner, { ...props, innerRef: ref });
|
|
6106
6806
|
}
|
|
6107
6807
|
);
|
|
6108
6808
|
function CheckoutFormInner({
|
|
@@ -6132,27 +6832,27 @@ function CheckoutFormInner({
|
|
|
6132
6832
|
const paypalFlopay = usePayPalFloPay();
|
|
6133
6833
|
const elements = useElements();
|
|
6134
6834
|
const contextBillingUrl = useBillingApiUrl();
|
|
6135
|
-
const [processing, setProcessing] = (0,
|
|
6136
|
-
const [error, setError] = (0,
|
|
6137
|
-
const [is3DSActive, setIs3DSActive] = (0,
|
|
6835
|
+
const [processing, setProcessing] = (0, import_react11.useState)(false);
|
|
6836
|
+
const [error, setError] = (0, import_react11.useState)(null);
|
|
6837
|
+
const [is3DSActive, setIs3DSActive] = (0, import_react11.useState)(false);
|
|
6138
6838
|
const displayError = externalError ?? error;
|
|
6139
6839
|
const isSubmitting = externalProcessing ?? processing;
|
|
6140
6840
|
const isSelfContained = !onTokenizedBody;
|
|
6141
6841
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
6142
|
-
const updateError = (0,
|
|
6842
|
+
const updateError = (0, import_react11.useCallback)(
|
|
6143
6843
|
(err) => {
|
|
6144
6844
|
setError(err);
|
|
6145
6845
|
onErrorChange?.(err);
|
|
6146
6846
|
},
|
|
6147
6847
|
[onErrorChange]
|
|
6148
6848
|
);
|
|
6149
|
-
const emitDecline = (0,
|
|
6849
|
+
const emitDecline = (0, import_react11.useCallback)(
|
|
6150
6850
|
(input, overrides) => {
|
|
6151
6851
|
onDecline?.(buildDeclineEvent("card", input, overrides));
|
|
6152
6852
|
},
|
|
6153
6853
|
[onDecline]
|
|
6154
6854
|
);
|
|
6155
|
-
const processPaymentInternal = (0,
|
|
6855
|
+
const processPaymentInternal = (0, import_react11.useCallback)(
|
|
6156
6856
|
async (tokenizedBody, completionPaymentMethodId) => {
|
|
6157
6857
|
setProcessing(true);
|
|
6158
6858
|
updateError(null);
|
|
@@ -6264,7 +6964,7 @@ function CheckoutFormInner({
|
|
|
6264
6964
|
},
|
|
6265
6965
|
[baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, flopay, paypalFlopay, onComplete, onError, onDecline, updateError, emitDecline]
|
|
6266
6966
|
);
|
|
6267
|
-
const dispatchTokenizedBody = (0,
|
|
6967
|
+
const dispatchTokenizedBody = (0, import_react11.useCallback)(
|
|
6268
6968
|
(tokenizedBody) => {
|
|
6269
6969
|
if (onTokenizedBody) {
|
|
6270
6970
|
onTokenizedBody(tokenizedBody);
|
|
@@ -6274,7 +6974,7 @@ function CheckoutFormInner({
|
|
|
6274
6974
|
},
|
|
6275
6975
|
[onTokenizedBody, processPaymentInternal]
|
|
6276
6976
|
);
|
|
6277
|
-
(0,
|
|
6977
|
+
(0, import_react11.useImperativeHandle)(innerRef, () => ({
|
|
6278
6978
|
async handleNextAction(secret) {
|
|
6279
6979
|
if (!flopay) return;
|
|
6280
6980
|
setIs3DSActive(true);
|
|
@@ -6301,7 +7001,7 @@ function CheckoutFormInner({
|
|
|
6301
7001
|
}
|
|
6302
7002
|
}
|
|
6303
7003
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
6304
|
-
(0,
|
|
7004
|
+
(0, import_react11.useEffect)(() => {
|
|
6305
7005
|
if (typeof window === "undefined") return;
|
|
6306
7006
|
const stored = localStorage.getItem(WALLET_RESUME_KEY);
|
|
6307
7007
|
if (!stored) return;
|
|
@@ -6319,7 +7019,7 @@ function CheckoutFormInner({
|
|
|
6319
7019
|
localStorage.removeItem(WALLET_RESUME_KEY);
|
|
6320
7020
|
}
|
|
6321
7021
|
}, [sessionId, dispatchTokenizedBody]);
|
|
6322
|
-
const handleSubmit = (0,
|
|
7022
|
+
const handleSubmit = (0, import_react11.useCallback)(
|
|
6323
7023
|
async (e) => {
|
|
6324
7024
|
e.preventDefault();
|
|
6325
7025
|
if (!flopay || !elements || isSubmitting) return;
|
|
@@ -6411,8 +7111,8 @@ function CheckoutFormInner({
|
|
|
6411
7111
|
[flopay, elements, isSubmitting, sessionId, nonce, email, firstName, lastName, baseUrl, isSelfContained, dispatchTokenizedBody, onError, updateError, emitDecline]
|
|
6412
7112
|
);
|
|
6413
7113
|
const isReady = flopay !== null && elements !== null;
|
|
6414
|
-
return /* @__PURE__ */ (0,
|
|
6415
|
-
(is3DSActive || isSubmitting) && /* @__PURE__ */ (0,
|
|
7114
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
7115
|
+
(is3DSActive || isSubmitting) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-testid": "flopay-overlay", style: {
|
|
6416
7116
|
position: "absolute",
|
|
6417
7117
|
inset: 0,
|
|
6418
7118
|
background: "rgba(255,255,255,0.7)",
|
|
@@ -6421,12 +7121,12 @@ function CheckoutFormInner({
|
|
|
6421
7121
|
justifyContent: "center",
|
|
6422
7122
|
zIndex: 10
|
|
6423
7123
|
}, children: is3DSActive ? "Verifying payment..." : "Processing..." }),
|
|
6424
|
-
!isReady && /* @__PURE__ */ (0,
|
|
6425
|
-
isReady && /* @__PURE__ */ (0,
|
|
6426
|
-
/* @__PURE__ */ (0,
|
|
6427
|
-
showAddress && /* @__PURE__ */ (0,
|
|
6428
|
-
displayError && /* @__PURE__ */ (0,
|
|
6429
|
-
children ?? /* @__PURE__ */ (0,
|
|
7124
|
+
!isReady && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
|
|
7125
|
+
isReady && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
7126
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PaymentElement, { options: { layout } }),
|
|
7127
|
+
showAddress && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
|
|
7128
|
+
displayError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
|
|
7129
|
+
children ?? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
6430
7130
|
"button",
|
|
6431
7131
|
{
|
|
6432
7132
|
type: "submit",
|
|
@@ -6442,8 +7142,8 @@ function CheckoutFormInner({
|
|
|
6442
7142
|
// src/paypal-button.tsx
|
|
6443
7143
|
var import_js6 = require("@flopay/js");
|
|
6444
7144
|
var import_shared10 = require("@flopay/shared");
|
|
6445
|
-
var
|
|
6446
|
-
var
|
|
7145
|
+
var import_react12 = require("react");
|
|
7146
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
6447
7147
|
function PayPalButton({
|
|
6448
7148
|
sessionId,
|
|
6449
7149
|
nonce,
|
|
@@ -6461,11 +7161,11 @@ function PayPalButton({
|
|
|
6461
7161
|
const flopay = useFloPay();
|
|
6462
7162
|
const elements = useElements();
|
|
6463
7163
|
const contextBillingUrl = useBillingApiUrl();
|
|
6464
|
-
const [ready, setReady] = (0,
|
|
6465
|
-
const [submitting, setSubmitting] = (0,
|
|
6466
|
-
const paypalResumeAttempted = (0,
|
|
7164
|
+
const [ready, setReady] = (0, import_react12.useState)(false);
|
|
7165
|
+
const [submitting, setSubmitting] = (0, import_react12.useState)(false);
|
|
7166
|
+
const paypalResumeAttempted = (0, import_react12.useRef)(false);
|
|
6467
7167
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
6468
|
-
const processPaymentInternal = (0,
|
|
7168
|
+
const processPaymentInternal = (0, import_react12.useCallback)(
|
|
6469
7169
|
async (tokenizedBody) => {
|
|
6470
7170
|
try {
|
|
6471
7171
|
const api = new import_js6.PaymentAPI(baseUrl);
|
|
@@ -6493,7 +7193,7 @@ function PayPalButton({
|
|
|
6493
7193
|
},
|
|
6494
7194
|
[baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, onComplete, onErrorChange]
|
|
6495
7195
|
);
|
|
6496
|
-
const dispatchTokenizedBody = (0,
|
|
7196
|
+
const dispatchTokenizedBody = (0, import_react12.useCallback)(
|
|
6497
7197
|
(body) => {
|
|
6498
7198
|
if (onTokenizedBody) {
|
|
6499
7199
|
onTokenizedBody(body);
|
|
@@ -6503,7 +7203,7 @@ function PayPalButton({
|
|
|
6503
7203
|
},
|
|
6504
7204
|
[onTokenizedBody, processPaymentInternal]
|
|
6505
7205
|
);
|
|
6506
|
-
(0,
|
|
7206
|
+
(0, import_react12.useEffect)(() => {
|
|
6507
7207
|
if (!flopay || paypalResumeAttempted.current) return;
|
|
6508
7208
|
const params = new URLSearchParams(window.location.search);
|
|
6509
7209
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -6551,7 +7251,7 @@ function PayPalButton({
|
|
|
6551
7251
|
}
|
|
6552
7252
|
})();
|
|
6553
7253
|
}, [flopay, dispatchTokenizedBody, onErrorChange]);
|
|
6554
|
-
const handlePayPalConfirm = (0,
|
|
7254
|
+
const handlePayPalConfirm = (0, import_react12.useCallback)(async () => {
|
|
6555
7255
|
if (!flopay || !elements) return;
|
|
6556
7256
|
try {
|
|
6557
7257
|
setSubmitting(true);
|
|
@@ -6585,11 +7285,11 @@ function PayPalButton({
|
|
|
6585
7285
|
}
|
|
6586
7286
|
}, [flopay, elements, sessionId, nonce, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
|
|
6587
7287
|
if (!flopay || !elements) {
|
|
6588
|
-
return /* @__PURE__ */ (0,
|
|
7288
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
|
|
6589
7289
|
}
|
|
6590
|
-
return /* @__PURE__ */ (0,
|
|
6591
|
-
!ready && /* @__PURE__ */ (0,
|
|
6592
|
-
/* @__PURE__ */ (0,
|
|
7290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
7291
|
+
!ready && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
|
|
7292
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
6593
7293
|
"button",
|
|
6594
7294
|
{
|
|
6595
7295
|
type: "button",
|
|
@@ -6611,7 +7311,7 @@ function PayPalButton({
|
|
|
6611
7311
|
children: submitting ? "Processing..." : "PayPal"
|
|
6612
7312
|
}
|
|
6613
7313
|
) }),
|
|
6614
|
-
(submitting || isProcessing) && /* @__PURE__ */ (0,
|
|
7314
|
+
(submitting || isProcessing) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: {
|
|
6615
7315
|
position: "fixed",
|
|
6616
7316
|
inset: 0,
|
|
6617
7317
|
background: "rgba(0,0,0,0.4)",
|
|
@@ -6619,7 +7319,7 @@ function PayPalButton({
|
|
|
6619
7319
|
alignItems: "center",
|
|
6620
7320
|
justifyContent: "center",
|
|
6621
7321
|
zIndex: 1e3
|
|
6622
|
-
}, children: /* @__PURE__ */ (0,
|
|
7322
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: {
|
|
6623
7323
|
background: "white",
|
|
6624
7324
|
borderRadius: 8,
|
|
6625
7325
|
padding: "1.5rem",
|
|
@@ -6631,10 +7331,10 @@ function PayPalButton({
|
|
|
6631
7331
|
}
|
|
6632
7332
|
|
|
6633
7333
|
// src/automatic-payment-button.tsx
|
|
6634
|
-
var
|
|
7334
|
+
var import_react13 = require("react");
|
|
6635
7335
|
var import_js7 = require("@flopay/js");
|
|
6636
7336
|
var import_shared11 = require("@flopay/shared");
|
|
6637
|
-
var
|
|
7337
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
6638
7338
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
|
|
6639
7339
|
function sleep2(ms) {
|
|
6640
7340
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -6702,6 +7402,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
6702
7402
|
billingApiUrl,
|
|
6703
7403
|
locale,
|
|
6704
7404
|
theme,
|
|
7405
|
+
appearance,
|
|
6705
7406
|
buttonsTheme,
|
|
6706
7407
|
buttonsStyles: stylesOverride,
|
|
6707
7408
|
onSuccess,
|
|
@@ -6713,11 +7414,11 @@ function FloPayAutomaticPaymentButton({
|
|
|
6713
7414
|
style,
|
|
6714
7415
|
...buttonProps
|
|
6715
7416
|
}) {
|
|
6716
|
-
const resolvedBillingUrl = (0,
|
|
7417
|
+
const resolvedBillingUrl = (0, import_react13.useMemo)(
|
|
6717
7418
|
() => (0, import_shared11.resolveBillingApiUrl)(billingApiUrl),
|
|
6718
7419
|
[billingApiUrl]
|
|
6719
7420
|
);
|
|
6720
|
-
const createSessionDraft = (0,
|
|
7421
|
+
const createSessionDraft = (0, import_react13.useMemo)(
|
|
6721
7422
|
() => resolveCreateSessionDraft({
|
|
6722
7423
|
createSession,
|
|
6723
7424
|
clientId,
|
|
@@ -6745,34 +7446,36 @@ function FloPayAutomaticPaymentButton({
|
|
|
6745
7446
|
utmMetadata
|
|
6746
7447
|
]
|
|
6747
7448
|
);
|
|
6748
|
-
const [isProcessing, setIsProcessing] = (0,
|
|
6749
|
-
const [overlayStatus, setOverlayStatus] = (0,
|
|
6750
|
-
const [overlayError, setOverlayError] = (0,
|
|
6751
|
-
const [fallbackSession, setFallbackSession] = (0,
|
|
6752
|
-
const isMountedRef = (0,
|
|
6753
|
-
const
|
|
6754
|
-
const
|
|
6755
|
-
const
|
|
6756
|
-
const
|
|
6757
|
-
(0,
|
|
7449
|
+
const [isProcessing, setIsProcessing] = (0, import_react13.useState)(false);
|
|
7450
|
+
const [overlayStatus, setOverlayStatus] = (0, import_react13.useState)(null);
|
|
7451
|
+
const [overlayError, setOverlayError] = (0, import_react13.useState)(null);
|
|
7452
|
+
const [fallbackSession, setFallbackSession] = (0, import_react13.useState)(null);
|
|
7453
|
+
const isMountedRef = (0, import_react13.useRef)(true);
|
|
7454
|
+
const threeDsAbortRef = (0, import_react13.useRef)(null);
|
|
7455
|
+
const fallbackSessionRef = (0, import_react13.useRef)(fallbackSession);
|
|
7456
|
+
const onSuccessRef = (0, import_react13.useRef)(onSuccess);
|
|
7457
|
+
const onErrorRef = (0, import_react13.useRef)(onError);
|
|
7458
|
+
const onDeclineRef = (0, import_react13.useRef)(onDecline);
|
|
7459
|
+
(0, import_react13.useEffect)(() => {
|
|
6758
7460
|
fallbackSessionRef.current = fallbackSession;
|
|
6759
7461
|
}, [fallbackSession]);
|
|
6760
|
-
(0,
|
|
7462
|
+
(0, import_react13.useEffect)(() => {
|
|
6761
7463
|
onSuccessRef.current = onSuccess;
|
|
6762
7464
|
}, [onSuccess]);
|
|
6763
|
-
(0,
|
|
7465
|
+
(0, import_react13.useEffect)(() => {
|
|
6764
7466
|
onErrorRef.current = onError;
|
|
6765
7467
|
}, [onError]);
|
|
6766
|
-
(0,
|
|
7468
|
+
(0, import_react13.useEffect)(() => {
|
|
6767
7469
|
onDeclineRef.current = onDecline;
|
|
6768
7470
|
}, [onDecline]);
|
|
6769
|
-
(0,
|
|
7471
|
+
(0, import_react13.useEffect)(() => {
|
|
6770
7472
|
isMountedRef.current = true;
|
|
6771
7473
|
return () => {
|
|
6772
7474
|
isMountedRef.current = false;
|
|
7475
|
+
threeDsAbortRef.current?.abort();
|
|
6773
7476
|
};
|
|
6774
7477
|
}, []);
|
|
6775
|
-
(0,
|
|
7478
|
+
(0, import_react13.useEffect)(() => {
|
|
6776
7479
|
if (!fallbackSession || typeof window === "undefined") {
|
|
6777
7480
|
return;
|
|
6778
7481
|
}
|
|
@@ -6786,13 +7489,13 @@ function FloPayAutomaticPaymentButton({
|
|
|
6786
7489
|
window.removeEventListener("keydown", handleKeyDown);
|
|
6787
7490
|
};
|
|
6788
7491
|
}, [fallbackSession]);
|
|
6789
|
-
const emitDecline = (0,
|
|
7492
|
+
const emitDecline = (0, import_react13.useCallback)((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
|
|
6790
7493
|
onDeclineRef.current?.(buildDeclineEvent(method, error, {
|
|
6791
7494
|
code: error.code,
|
|
6792
7495
|
declineCode: error.declineCode
|
|
6793
7496
|
}));
|
|
6794
7497
|
}, []);
|
|
6795
|
-
const showSuccess = (0,
|
|
7498
|
+
const showSuccess = (0, import_react13.useCallback)(async (event) => {
|
|
6796
7499
|
if (!isMountedRef.current) return;
|
|
6797
7500
|
setOverlayError(null);
|
|
6798
7501
|
setOverlayStatus("success");
|
|
@@ -6800,7 +7503,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
6800
7503
|
if (!isMountedRef.current) return;
|
|
6801
7504
|
onSuccessRef.current?.(event);
|
|
6802
7505
|
}, []);
|
|
6803
|
-
const showError = (0,
|
|
7506
|
+
const showError = (0, import_react13.useCallback)(async (error, options) => {
|
|
6804
7507
|
if (!isMountedRef.current) return;
|
|
6805
7508
|
onErrorRef.current?.(error);
|
|
6806
7509
|
if (options?.emitDecline) {
|
|
@@ -6810,7 +7513,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
6810
7513
|
setOverlayStatus("error");
|
|
6811
7514
|
await sleep2(PROCESSING_OVERLAY_ERROR_DELAY_MS);
|
|
6812
7515
|
}, [emitDecline]);
|
|
6813
|
-
const processResolvedSession = (0,
|
|
7516
|
+
const processResolvedSession = (0, import_react13.useCallback)(async (apiResult, resolvedSessionId, options) => {
|
|
6814
7517
|
const session = apiResult.data.session ?? null;
|
|
6815
7518
|
if (!session) {
|
|
6816
7519
|
throw new import_shared11.FloPayError("No session data returned", "api_error");
|
|
@@ -6851,6 +7554,62 @@ function FloPayAutomaticPaymentButton({
|
|
|
6851
7554
|
return;
|
|
6852
7555
|
}
|
|
6853
7556
|
if (apiResult.autoProcessingError) {
|
|
7557
|
+
if (apiResult.autoProcessingError.type === "3ds_required" && apiResult.autoProcessingError.nextActionRedirectUrl && resolvedSessionId && effectiveNonce) {
|
|
7558
|
+
const threeDsAbort = new AbortController();
|
|
7559
|
+
threeDsAbortRef.current = threeDsAbort;
|
|
7560
|
+
let outcome;
|
|
7561
|
+
try {
|
|
7562
|
+
outcome = await runAutoCheckoutThreeDsChallenge({
|
|
7563
|
+
billingApiUrl: resolvedBillingUrl,
|
|
7564
|
+
sessionId: resolvedSessionId,
|
|
7565
|
+
nonce: effectiveNonce,
|
|
7566
|
+
nextActionRedirectUrl: apiResult.autoProcessingError.nextActionRedirectUrl,
|
|
7567
|
+
signal: threeDsAbort.signal
|
|
7568
|
+
});
|
|
7569
|
+
} finally {
|
|
7570
|
+
if (threeDsAbortRef.current === threeDsAbort) {
|
|
7571
|
+
threeDsAbortRef.current = null;
|
|
7572
|
+
}
|
|
7573
|
+
}
|
|
7574
|
+
if (outcome.status === "declined") {
|
|
7575
|
+
throw checkoutProcessErrorToFloPayError(
|
|
7576
|
+
{
|
|
7577
|
+
type: outcome.declineReason ?? "decline",
|
|
7578
|
+
message: "Card was declined.",
|
|
7579
|
+
gatewayErrorCode: outcome.gatewayDeclineReason ?? void 0
|
|
7580
|
+
},
|
|
7581
|
+
"Card was declined.",
|
|
7582
|
+
{
|
|
7583
|
+
checkoutMethod: apiResult.autoProcessingError.checkoutMethod
|
|
7584
|
+
}
|
|
7585
|
+
);
|
|
7586
|
+
}
|
|
7587
|
+
const api = new import_js7.PaymentAPI(resolvedBillingUrl);
|
|
7588
|
+
const completed = await api.waitForCheckoutSessionCompletion(resolvedSessionId, {
|
|
7589
|
+
initialDelayMs: 0,
|
|
7590
|
+
nonce: effectiveNonce
|
|
7591
|
+
});
|
|
7592
|
+
const completedSession = completed.data.session;
|
|
7593
|
+
if (!completedSession || completedSession.status !== "complete") {
|
|
7594
|
+
throw checkoutProcessErrorToFloPayError(
|
|
7595
|
+
{
|
|
7596
|
+
type: "unknown",
|
|
7597
|
+
message: "Card authentication was not completed."
|
|
7598
|
+
},
|
|
7599
|
+
"Card authentication was not completed.",
|
|
7600
|
+
{
|
|
7601
|
+
checkoutMethod: apiResult.autoProcessingError.checkoutMethod
|
|
7602
|
+
}
|
|
7603
|
+
);
|
|
7604
|
+
}
|
|
7605
|
+
await showSuccess({
|
|
7606
|
+
result: { status: "succeeded" },
|
|
7607
|
+
session: completedSession,
|
|
7608
|
+
sessionId: completedSession.id || resolvedSessionId,
|
|
7609
|
+
autoCompleted: false
|
|
7610
|
+
});
|
|
7611
|
+
return;
|
|
7612
|
+
}
|
|
6854
7613
|
throw checkoutProcessErrorToFloPayError(
|
|
6855
7614
|
apiResult.autoProcessingError,
|
|
6856
7615
|
"Automatic payment failed. Please try again.",
|
|
@@ -6910,7 +7669,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
6910
7669
|
showError,
|
|
6911
7670
|
showSuccess
|
|
6912
7671
|
]);
|
|
6913
|
-
const handleButtonClick = (0,
|
|
7672
|
+
const handleButtonClick = (0, import_react13.useCallback)(async (event) => {
|
|
6914
7673
|
buttonProps.onClick?.(event);
|
|
6915
7674
|
if (event.defaultPrevented || disabled || isProcessing) {
|
|
6916
7675
|
return;
|
|
@@ -6992,7 +7751,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
6992
7751
|
showError,
|
|
6993
7752
|
showSuccess
|
|
6994
7753
|
]);
|
|
6995
|
-
const handleFallbackComplete = (0,
|
|
7754
|
+
const handleFallbackComplete = (0, import_react13.useCallback)((result) => {
|
|
6996
7755
|
const activeFallback = fallbackSessionRef.current;
|
|
6997
7756
|
setFallbackSession(null);
|
|
6998
7757
|
onSuccessRef.current?.({
|
|
@@ -7002,14 +7761,14 @@ function FloPayAutomaticPaymentButton({
|
|
|
7002
7761
|
autoCompleted: false
|
|
7003
7762
|
});
|
|
7004
7763
|
}, []);
|
|
7005
|
-
const handleFallbackError = (0,
|
|
7764
|
+
const handleFallbackError = (0, import_react13.useCallback)((error) => {
|
|
7006
7765
|
onErrorRef.current?.(error);
|
|
7007
7766
|
}, []);
|
|
7008
|
-
const handleFallbackDecline = (0,
|
|
7767
|
+
const handleFallbackDecline = (0, import_react13.useCallback)((decline) => {
|
|
7009
7768
|
onDeclineRef.current?.(decline);
|
|
7010
7769
|
}, []);
|
|
7011
|
-
const themeBundle = (0,
|
|
7012
|
-
const bStyles = (0,
|
|
7770
|
+
const themeBundle = (0, import_react13.useMemo)(() => (0, import_shared11.resolveTheme)(theme), [theme]);
|
|
7771
|
+
const bStyles = (0, import_react13.useMemo)(() => {
|
|
7013
7772
|
const base = themeBundle?.buttonsLayout ?? (0, import_shared11.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
7014
7773
|
if (!stylesOverride) return base;
|
|
7015
7774
|
return {
|
|
@@ -7018,9 +7777,26 @@ function FloPayAutomaticPaymentButton({
|
|
|
7018
7777
|
cardButton: { ...base.cardButton, ...stylesOverride.cardButton }
|
|
7019
7778
|
};
|
|
7020
7779
|
}, [themeBundle, buttonsTheme, stylesOverride]);
|
|
7780
|
+
const resolvedAppearance = (0, import_react13.useMemo)(() => {
|
|
7781
|
+
const bundleAppearance = themeBundle?.appearance;
|
|
7782
|
+
if (!appearance) return bundleAppearance;
|
|
7783
|
+
if (!bundleAppearance) return appearance;
|
|
7784
|
+
return {
|
|
7785
|
+
...bundleAppearance,
|
|
7786
|
+
...appearance,
|
|
7787
|
+
variables: {
|
|
7788
|
+
...bundleAppearance.variables,
|
|
7789
|
+
...appearance.variables
|
|
7790
|
+
}
|
|
7791
|
+
};
|
|
7792
|
+
}, [appearance, themeBundle]);
|
|
7793
|
+
const resolvedAppearanceVars = resolvedAppearance?.variables;
|
|
7794
|
+
const resolvedPrimaryColor = resolvedAppearanceVars?.colorPrimary ?? "#4A49FF";
|
|
7795
|
+
const resolvedPrimaryHoverColor = resolvedAppearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
|
|
7796
|
+
const resolvedButtonBorderRadius = resolvedAppearanceVars?.borderRadius ?? "8px";
|
|
7021
7797
|
const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
7022
|
-
return /* @__PURE__ */ (0,
|
|
7023
|
-
/* @__PURE__ */ (0,
|
|
7798
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
7799
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7024
7800
|
"button",
|
|
7025
7801
|
{
|
|
7026
7802
|
...buttonProps,
|
|
@@ -7036,14 +7812,17 @@ function FloPayAutomaticPaymentButton({
|
|
|
7036
7812
|
// on top so the auto-pay button carries the *submit* button's
|
|
7037
7813
|
// background and text colours — making it visually identical to
|
|
7038
7814
|
// the "Confirm Payment" / "Pay with X" actions it stands in for.
|
|
7815
|
+
// `resolvedPrimaryColor` is the *merged* appearance value, so a
|
|
7816
|
+
// per-checkout `colorPrimary` override re-skins this button too.
|
|
7039
7817
|
// Inline `style` consumer override stays at the end so explicit
|
|
7040
7818
|
// per-button overrides still win.
|
|
7041
7819
|
...bStyles.cardButton,
|
|
7042
7820
|
...derivePrimaryTileStyle({
|
|
7043
7821
|
themeBundle,
|
|
7044
|
-
resolvedPrimaryColor
|
|
7045
|
-
resolvedBorderRadius:
|
|
7046
|
-
submitButtonStyle: bStyles.submitButton
|
|
7822
|
+
resolvedPrimaryColor,
|
|
7823
|
+
resolvedBorderRadius: resolvedButtonBorderRadius,
|
|
7824
|
+
submitButtonStyle: bStyles.submitButton,
|
|
7825
|
+
explicitPrimaryColor: resolvedAppearanceVars?.colorPrimary
|
|
7047
7826
|
}),
|
|
7048
7827
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
7049
7828
|
fontWeight: 600,
|
|
@@ -7052,11 +7831,23 @@ function FloPayAutomaticPaymentButton({
|
|
|
7052
7831
|
alignItems: "center",
|
|
7053
7832
|
justifyContent: "center",
|
|
7054
7833
|
gap: "0.625rem",
|
|
7055
|
-
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
7834
|
+
transition: "background-color 0.15s, border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
7056
7835
|
position: "relative",
|
|
7057
7836
|
opacity: disabled || isProcessing ? 0.6 : 1,
|
|
7058
7837
|
...style
|
|
7059
7838
|
},
|
|
7839
|
+
onMouseEnter: (e) => {
|
|
7840
|
+
buttonProps.onMouseEnter?.(e);
|
|
7841
|
+
if (!e.defaultPrevented && !disabled && !isProcessing && (themeBundle || resolvedAppearanceVars?.colorPrimary)) {
|
|
7842
|
+
e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
|
|
7843
|
+
}
|
|
7844
|
+
},
|
|
7845
|
+
onMouseLeave: (e) => {
|
|
7846
|
+
buttonProps.onMouseLeave?.(e);
|
|
7847
|
+
if (!e.defaultPrevented && (themeBundle || resolvedAppearanceVars?.colorPrimary)) {
|
|
7848
|
+
e.currentTarget.style.backgroundColor = resolvedPrimaryColor;
|
|
7849
|
+
}
|
|
7850
|
+
},
|
|
7060
7851
|
onMouseDown: (e) => {
|
|
7061
7852
|
buttonProps.onMouseDown?.(e);
|
|
7062
7853
|
if (!e.defaultPrevented) {
|
|
@@ -7069,17 +7860,17 @@ function FloPayAutomaticPaymentButton({
|
|
|
7069
7860
|
e.currentTarget.style.transform = "scale(1)";
|
|
7070
7861
|
}
|
|
7071
7862
|
},
|
|
7072
|
-
children: /* @__PURE__ */ (0,
|
|
7863
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CardButtonContentSlot, { content: children })
|
|
7073
7864
|
}
|
|
7074
7865
|
),
|
|
7075
|
-
overlayStatus && /* @__PURE__ */ (0,
|
|
7866
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7076
7867
|
ProcessingOverlay,
|
|
7077
7868
|
{
|
|
7078
7869
|
status: overlayStatus,
|
|
7079
7870
|
errorMessage: overlayError
|
|
7080
7871
|
}
|
|
7081
7872
|
),
|
|
7082
|
-
fallbackSession && /* @__PURE__ */ (0,
|
|
7873
|
+
fallbackSession && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7083
7874
|
"div",
|
|
7084
7875
|
{
|
|
7085
7876
|
"data-testid": "flopay-automatic-payment-fallback",
|
|
@@ -7100,7 +7891,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
7100
7891
|
padding: "1.5rem",
|
|
7101
7892
|
zIndex: 1100
|
|
7102
7893
|
},
|
|
7103
|
-
children: /* @__PURE__ */ (0,
|
|
7894
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7104
7895
|
"div",
|
|
7105
7896
|
{
|
|
7106
7897
|
style: {
|
|
@@ -7116,7 +7907,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
7116
7907
|
flexDirection: "column",
|
|
7117
7908
|
gap: "1rem"
|
|
7118
7909
|
},
|
|
7119
|
-
children: /* @__PURE__ */ (0,
|
|
7910
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7120
7911
|
FloPayCheckout,
|
|
7121
7912
|
{
|
|
7122
7913
|
sessionId: fallbackSession.sessionId,
|
|
@@ -7125,6 +7916,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
7125
7916
|
billingApiUrl: resolvedBillingUrl,
|
|
7126
7917
|
locale,
|
|
7127
7918
|
theme,
|
|
7919
|
+
...resolvedAppearance ? { appearance: resolvedAppearance } : {},
|
|
7128
7920
|
buttonsTheme,
|
|
7129
7921
|
buttonsStyles: stylesOverride,
|
|
7130
7922
|
initialErrorMessage: fallbackSession.errorMessage,
|
|
@@ -7155,6 +7947,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
7155
7947
|
PayPalButton,
|
|
7156
7948
|
PaymentElement,
|
|
7157
7949
|
SplitCardForm,
|
|
7950
|
+
VaultCardFields,
|
|
7158
7951
|
useCheckout,
|
|
7159
7952
|
useElements,
|
|
7160
7953
|
useFloPay,
|