@flopay/react 0.4.3 → 0.4.4
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 +64 -1
- package/dist/index.cjs +1859 -640
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -3
- package/dist/index.d.ts +39 -3
- package/dist/index.mjs +1747 -529
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
CardExpiryElement: () => CardExpiryElement,
|
|
37
37
|
CardNumberElement: () => CardNumberElement,
|
|
38
38
|
CheckoutForm: () => CheckoutForm,
|
|
39
|
+
FloPayAutomaticPaymentButton: () => FloPayAutomaticPaymentButton,
|
|
39
40
|
FloPayCheckout: () => FloPayCheckout,
|
|
40
41
|
FloPayProvider: () => FloPayProvider,
|
|
41
42
|
PayPalButton: () => PayPalButton,
|
|
@@ -141,9 +142,9 @@ function FloPayProvider({
|
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
// src/flopay-checkout.tsx
|
|
144
|
-
var
|
|
145
|
-
var
|
|
146
|
-
var
|
|
145
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
146
|
+
var import_js2 = require("@flopay/js");
|
|
147
|
+
var import_shared7 = require("@flopay/shared");
|
|
147
148
|
|
|
148
149
|
// src/card-button-content.tsx
|
|
149
150
|
var import_react3 = require("react");
|
|
@@ -275,7 +276,7 @@ var AddressElement = createElementComponent("address", "AddressElement");
|
|
|
275
276
|
// src/split-card-form.tsx
|
|
276
277
|
var import_react_stripe_js = require("@stripe/react-stripe-js");
|
|
277
278
|
var import_shared4 = require("@flopay/shared");
|
|
278
|
-
var
|
|
279
|
+
var import_react7 = require("react");
|
|
279
280
|
|
|
280
281
|
// src/hooks.ts
|
|
281
282
|
var import_react5 = require("react");
|
|
@@ -300,6 +301,157 @@ function useBillingApiUrl() {
|
|
|
300
301
|
return ctx.billingApiUrl || (0, import_shared2.resolveBillingApiUrl)();
|
|
301
302
|
}
|
|
302
303
|
|
|
304
|
+
// src/processing-overlay.tsx
|
|
305
|
+
var import_react6 = require("react");
|
|
306
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
307
|
+
var PROCESSING_OVERLAY_SUCCESS_DELAY_MS = 1200;
|
|
308
|
+
var PROCESSING_OVERLAY_ERROR_DELAY_MS = 1500;
|
|
309
|
+
function ProcessingOverlay({
|
|
310
|
+
status,
|
|
311
|
+
errorMessage
|
|
312
|
+
}) {
|
|
313
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
314
|
+
"div",
|
|
315
|
+
{
|
|
316
|
+
"data-testid": "flopay-processing-overlay",
|
|
317
|
+
"data-status": status,
|
|
318
|
+
role: "dialog",
|
|
319
|
+
"aria-modal": "true",
|
|
320
|
+
style: {
|
|
321
|
+
position: "fixed",
|
|
322
|
+
inset: 0,
|
|
323
|
+
background: "rgba(0,0,0,0.35)",
|
|
324
|
+
display: "flex",
|
|
325
|
+
alignItems: "center",
|
|
326
|
+
justifyContent: "center",
|
|
327
|
+
zIndex: 1e3,
|
|
328
|
+
backdropFilter: "blur(2px)"
|
|
329
|
+
},
|
|
330
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
331
|
+
"div",
|
|
332
|
+
{
|
|
333
|
+
style: {
|
|
334
|
+
background: "white",
|
|
335
|
+
borderRadius: 12,
|
|
336
|
+
padding: "2rem 2.5rem",
|
|
337
|
+
textAlign: "center",
|
|
338
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.18)",
|
|
339
|
+
minWidth: 240,
|
|
340
|
+
display: "flex",
|
|
341
|
+
flexDirection: "column",
|
|
342
|
+
alignItems: "center",
|
|
343
|
+
gap: 16
|
|
344
|
+
},
|
|
345
|
+
children: [
|
|
346
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { width: 48, height: 48, position: "relative" }, children: [
|
|
347
|
+
status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
348
|
+
"svg",
|
|
349
|
+
{
|
|
350
|
+
width: "48",
|
|
351
|
+
height: "48",
|
|
352
|
+
viewBox: "0 0 24 24",
|
|
353
|
+
fill: "none",
|
|
354
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
355
|
+
style: { animation: "flopay-spin 0.8s linear infinite" },
|
|
356
|
+
children: [
|
|
357
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
|
|
358
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
),
|
|
362
|
+
status === "success" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
363
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
|
|
364
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
365
|
+
"path",
|
|
366
|
+
{
|
|
367
|
+
d: "M7 12.5l3 3 7-7",
|
|
368
|
+
stroke: "white",
|
|
369
|
+
strokeWidth: "2.5",
|
|
370
|
+
strokeLinecap: "round",
|
|
371
|
+
strokeLinejoin: "round",
|
|
372
|
+
style: {
|
|
373
|
+
strokeDasharray: 20,
|
|
374
|
+
strokeDashoffset: 20,
|
|
375
|
+
animation: "flopay-draw 0.4s 0.15s ease forwards"
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
)
|
|
379
|
+
] }) }),
|
|
380
|
+
status === "error" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
381
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
|
|
382
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
383
|
+
"path",
|
|
384
|
+
{
|
|
385
|
+
d: "M8 8l8 8M16 8l-8 8",
|
|
386
|
+
stroke: "white",
|
|
387
|
+
strokeWidth: "2.5",
|
|
388
|
+
strokeLinecap: "round",
|
|
389
|
+
style: {
|
|
390
|
+
strokeDasharray: 12,
|
|
391
|
+
strokeDashoffset: 12,
|
|
392
|
+
animation: "flopay-draw 0.3s 0.1s ease forwards"
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
)
|
|
396
|
+
] }) })
|
|
397
|
+
] }),
|
|
398
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
399
|
+
"span",
|
|
400
|
+
{
|
|
401
|
+
style: {
|
|
402
|
+
fontSize: 14,
|
|
403
|
+
fontWeight: 600,
|
|
404
|
+
letterSpacing: "0.05em",
|
|
405
|
+
color: status === "success" ? "#16a34a" : status === "error" ? "#dc2626" : "#374151"
|
|
406
|
+
},
|
|
407
|
+
children: [
|
|
408
|
+
status === "processing" && "PROCESSING...",
|
|
409
|
+
status === "success" && "PAYMENT SUCCESSFUL",
|
|
410
|
+
status === "error" && "PAYMENT FAILED"
|
|
411
|
+
]
|
|
412
|
+
}
|
|
413
|
+
),
|
|
414
|
+
status === "success" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
415
|
+
"p",
|
|
416
|
+
{
|
|
417
|
+
style: {
|
|
418
|
+
fontSize: 13,
|
|
419
|
+
color: "#6b7280",
|
|
420
|
+
fontWeight: 400,
|
|
421
|
+
maxWidth: 260,
|
|
422
|
+
lineHeight: 1.4,
|
|
423
|
+
margin: 0
|
|
424
|
+
},
|
|
425
|
+
children: "You will be automatically redirected, do not close or navigate away from this window."
|
|
426
|
+
}
|
|
427
|
+
),
|
|
428
|
+
status === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
429
|
+
"p",
|
|
430
|
+
{
|
|
431
|
+
style: {
|
|
432
|
+
fontSize: 13,
|
|
433
|
+
color: "#6b7280",
|
|
434
|
+
fontWeight: 400,
|
|
435
|
+
maxWidth: 260,
|
|
436
|
+
lineHeight: 1.4,
|
|
437
|
+
margin: 0
|
|
438
|
+
},
|
|
439
|
+
children: errorMessage
|
|
440
|
+
}
|
|
441
|
+
),
|
|
442
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: `
|
|
443
|
+
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
444
|
+
@keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
|
|
445
|
+
@keyframes flopay-draw { to { stroke-dashoffset: 0; } }
|
|
446
|
+
@keyframes flopay-shake { 0%,100% { transform: translateX(0); } 20%,60% { transform: translateX(-4px); } 40%,80% { transform: translateX(4px); } }
|
|
447
|
+
` })
|
|
448
|
+
]
|
|
449
|
+
}
|
|
450
|
+
)
|
|
451
|
+
}
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
|
|
303
455
|
// src/checkout-utils.ts
|
|
304
456
|
var import_shared3 = require("@flopay/shared");
|
|
305
457
|
function mergeInlineSessionPatches(base, patch) {
|
|
@@ -357,7 +509,7 @@ function buildSyntheticSession(params, checkoutModeOverride) {
|
|
|
357
509
|
},
|
|
358
510
|
successUrl: params.successUrl,
|
|
359
511
|
cancelUrl: params.cancelUrl,
|
|
360
|
-
checkoutMode: params.checkoutMode ??
|
|
512
|
+
checkoutMode: checkoutModeOverride ?? params.checkoutMode ?? "full",
|
|
361
513
|
items: (params.items ?? []).map((item, idx) => ({
|
|
362
514
|
uuid: `synthetic-item-${idx}`,
|
|
363
515
|
checkoutSessionId: "",
|
|
@@ -398,10 +550,22 @@ function buildDeclineEvent(method, input, overrides) {
|
|
|
398
550
|
...declineCode ? { declineCode } : {}
|
|
399
551
|
};
|
|
400
552
|
}
|
|
553
|
+
function resolveTokenizedPaymentMethodId(tokenizedBody) {
|
|
554
|
+
const candidates = [
|
|
555
|
+
tokenizedBody?.id,
|
|
556
|
+
tokenizedBody?.originalPaymentMethodId
|
|
557
|
+
];
|
|
558
|
+
for (const candidate of candidates) {
|
|
559
|
+
if (typeof candidate === "string" && candidate.startsWith("pm_")) {
|
|
560
|
+
return candidate;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
return void 0;
|
|
564
|
+
}
|
|
401
565
|
|
|
402
566
|
// src/split-card-form.tsx
|
|
403
567
|
var import_shared5 = require("@flopay/shared");
|
|
404
|
-
var
|
|
568
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
405
569
|
var WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
406
570
|
var FLOPAY_KEYFRAMES = `
|
|
407
571
|
@keyframes flopay-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
@@ -443,7 +607,7 @@ function normalizeBeforeButtonClickError(method, err) {
|
|
|
443
607
|
);
|
|
444
608
|
}
|
|
445
609
|
function FloPayKeyframes() {
|
|
446
|
-
return /* @__PURE__ */ (0,
|
|
610
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: FLOPAY_KEYFRAMES });
|
|
447
611
|
}
|
|
448
612
|
function toCssSize(value) {
|
|
449
613
|
if (typeof value === "number") return `${value}px`;
|
|
@@ -464,8 +628,8 @@ function ExpressCheckoutReadySwap({
|
|
|
464
628
|
children
|
|
465
629
|
}) {
|
|
466
630
|
if (state === "unavailable") return null;
|
|
467
|
-
return /* @__PURE__ */ (0,
|
|
468
|
-
/* @__PURE__ */ (0,
|
|
631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { position: "relative", minHeight: 44 }, children: [
|
|
632
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
469
633
|
"div",
|
|
470
634
|
{
|
|
471
635
|
"data-testid": placeholderTestId,
|
|
@@ -484,7 +648,7 @@ function ExpressCheckoutReadySwap({
|
|
|
484
648
|
}
|
|
485
649
|
}
|
|
486
650
|
),
|
|
487
|
-
/* @__PURE__ */ (0,
|
|
651
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
488
652
|
"div",
|
|
489
653
|
{
|
|
490
654
|
style: {
|
|
@@ -499,109 +663,9 @@ function ExpressCheckoutReadySwap({
|
|
|
499
663
|
)
|
|
500
664
|
] });
|
|
501
665
|
}
|
|
502
|
-
|
|
503
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: {
|
|
504
|
-
position: "fixed",
|
|
505
|
-
inset: 0,
|
|
506
|
-
background: "rgba(0,0,0,0.35)",
|
|
507
|
-
display: "flex",
|
|
508
|
-
alignItems: "center",
|
|
509
|
-
justifyContent: "center",
|
|
510
|
-
zIndex: 1e3,
|
|
511
|
-
backdropFilter: "blur(2px)"
|
|
512
|
-
}, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: {
|
|
513
|
-
background: "white",
|
|
514
|
-
borderRadius: 12,
|
|
515
|
-
padding: "2rem 2.5rem",
|
|
516
|
-
textAlign: "center",
|
|
517
|
-
boxShadow: "0 8px 32px rgba(0,0,0,0.18)",
|
|
518
|
-
minWidth: 240,
|
|
519
|
-
display: "flex",
|
|
520
|
-
flexDirection: "column",
|
|
521
|
-
alignItems: "center",
|
|
522
|
-
gap: 16
|
|
523
|
-
}, children: [
|
|
524
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { width: 48, height: 48, position: "relative" }, children: [
|
|
525
|
-
status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
526
|
-
"svg",
|
|
527
|
-
{
|
|
528
|
-
width: "48",
|
|
529
|
-
height: "48",
|
|
530
|
-
viewBox: "0 0 24 24",
|
|
531
|
-
fill: "none",
|
|
532
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
533
|
-
style: { animation: "flopay-spin 0.8s linear infinite" },
|
|
534
|
-
children: [
|
|
535
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
|
|
536
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
|
|
537
|
-
]
|
|
538
|
-
}
|
|
539
|
-
),
|
|
540
|
-
status === "success" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
541
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
|
|
542
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
543
|
-
"path",
|
|
544
|
-
{
|
|
545
|
-
d: "M7 12.5l3 3 7-7",
|
|
546
|
-
stroke: "white",
|
|
547
|
-
strokeWidth: "2.5",
|
|
548
|
-
strokeLinecap: "round",
|
|
549
|
-
strokeLinejoin: "round",
|
|
550
|
-
style: { strokeDasharray: 20, strokeDashoffset: 20, animation: "flopay-draw 0.4s 0.15s ease forwards" }
|
|
551
|
-
}
|
|
552
|
-
)
|
|
553
|
-
] }) }),
|
|
554
|
-
status === "error" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
555
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
|
|
556
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
557
|
-
"path",
|
|
558
|
-
{
|
|
559
|
-
d: "M8 8l8 8M16 8l-8 8",
|
|
560
|
-
stroke: "white",
|
|
561
|
-
strokeWidth: "2.5",
|
|
562
|
-
strokeLinecap: "round",
|
|
563
|
-
style: { strokeDasharray: 12, strokeDashoffset: 12, animation: "flopay-draw 0.3s 0.1s ease forwards" }
|
|
564
|
-
}
|
|
565
|
-
)
|
|
566
|
-
] }) })
|
|
567
|
-
] }),
|
|
568
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: {
|
|
569
|
-
fontSize: 14,
|
|
570
|
-
fontWeight: 600,
|
|
571
|
-
letterSpacing: "0.05em",
|
|
572
|
-
color: status === "success" ? "#16a34a" : status === "error" ? "#dc2626" : "#374151"
|
|
573
|
-
}, children: [
|
|
574
|
-
status === "processing" && "PROCESSING...",
|
|
575
|
-
status === "success" && "PAYMENT SUCCESSFUL",
|
|
576
|
-
status === "error" && "PAYMENT FAILED"
|
|
577
|
-
] }),
|
|
578
|
-
status === "success" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: {
|
|
579
|
-
fontSize: 13,
|
|
580
|
-
color: "#6b7280",
|
|
581
|
-
fontWeight: 400,
|
|
582
|
-
maxWidth: 260,
|
|
583
|
-
lineHeight: 1.4,
|
|
584
|
-
margin: 0
|
|
585
|
-
}, children: "You will be automatically redirected, do not close or navigate away from this window." }),
|
|
586
|
-
status === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: {
|
|
587
|
-
fontSize: 13,
|
|
588
|
-
color: "#6b7280",
|
|
589
|
-
fontWeight: 400,
|
|
590
|
-
maxWidth: 260,
|
|
591
|
-
lineHeight: 1.4,
|
|
592
|
-
margin: 0
|
|
593
|
-
}, children: errorMessage }),
|
|
594
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: `
|
|
595
|
-
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
596
|
-
@keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
|
|
597
|
-
@keyframes flopay-draw { to { stroke-dashoffset: 0; } }
|
|
598
|
-
@keyframes flopay-shake { 0%,100% { transform: translateX(0); } 20%,60% { transform: translateX(-4px); } 40%,80% { transform: translateX(4px); } }
|
|
599
|
-
` })
|
|
600
|
-
] }) });
|
|
601
|
-
}
|
|
602
|
-
var SplitCardForm = (0, import_react6.forwardRef)(
|
|
666
|
+
var SplitCardForm = (0, import_react7.forwardRef)(
|
|
603
667
|
function SplitCardForm2(props, ref) {
|
|
604
|
-
return /* @__PURE__ */ (0,
|
|
668
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SplitCardFormInner, { ...props, innerRef: ref });
|
|
605
669
|
}
|
|
606
670
|
);
|
|
607
671
|
function PayPalButtonInner({
|
|
@@ -617,12 +681,12 @@ function PayPalButtonInner({
|
|
|
617
681
|
}) {
|
|
618
682
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
619
683
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
620
|
-
const [loadState, setLoadState] = (0,
|
|
621
|
-
const [submitting, setSubmitting] = (0,
|
|
622
|
-
const paypalResumeAttempted = (0,
|
|
623
|
-
const beforeClickRef = (0,
|
|
684
|
+
const [loadState, setLoadState] = (0, import_react7.useState)("loading");
|
|
685
|
+
const [submitting, setSubmitting] = (0, import_react7.useState)(false);
|
|
686
|
+
const paypalResumeAttempted = (0, import_react7.useRef)(false);
|
|
687
|
+
const beforeClickRef = (0, import_react7.useRef)(null);
|
|
624
688
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
625
|
-
(0,
|
|
689
|
+
(0, import_react7.useEffect)(() => {
|
|
626
690
|
if (!stripe || paypalResumeAttempted.current) return;
|
|
627
691
|
const params = new URLSearchParams(window.location.search);
|
|
628
692
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -669,7 +733,7 @@ function PayPalButtonInner({
|
|
|
669
733
|
}
|
|
670
734
|
})();
|
|
671
735
|
}, [stripe, onTokenizedBody, onErrorChange, onDecline]);
|
|
672
|
-
const handlePayPalClick = (0,
|
|
736
|
+
const handlePayPalClick = (0, import_react7.useCallback)(async (event) => {
|
|
673
737
|
if (isProcessing || submitting) {
|
|
674
738
|
event.reject();
|
|
675
739
|
return;
|
|
@@ -686,7 +750,7 @@ function PayPalButtonInner({
|
|
|
686
750
|
};
|
|
687
751
|
event.resolve();
|
|
688
752
|
}, [isProcessing, runBeforeButtonClick, submitting]);
|
|
689
|
-
const handlePayPalConfirm = (0,
|
|
753
|
+
const handlePayPalConfirm = (0, import_react7.useCallback)(async (event) => {
|
|
690
754
|
if (!stripe || !elements) return;
|
|
691
755
|
let prepared = beforeClickRef.current;
|
|
692
756
|
beforeClickRef.current = null;
|
|
@@ -764,8 +828,8 @@ function PayPalButtonInner({
|
|
|
764
828
|
setSubmitting(false);
|
|
765
829
|
}
|
|
766
830
|
}, [stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, onButtonClick, runBeforeButtonClick]);
|
|
767
|
-
return /* @__PURE__ */ (0,
|
|
768
|
-
/* @__PURE__ */ (0,
|
|
831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
832
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-paypal-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
769
833
|
import_react_stripe_js.ExpressCheckoutElement,
|
|
770
834
|
{
|
|
771
835
|
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
|
|
@@ -787,7 +851,7 @@ function PayPalButtonInner({
|
|
|
787
851
|
}
|
|
788
852
|
}
|
|
789
853
|
) }),
|
|
790
|
-
submitting && /* @__PURE__ */ (0,
|
|
854
|
+
submitting && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ProcessingOverlay, { status: "processing" })
|
|
791
855
|
] });
|
|
792
856
|
}
|
|
793
857
|
function WalletButtonInner({
|
|
@@ -804,12 +868,12 @@ function WalletButtonInner({
|
|
|
804
868
|
}) {
|
|
805
869
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
806
870
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
807
|
-
const [loadState, setLoadState] = (0,
|
|
808
|
-
const [submitting, setSubmitting] = (0,
|
|
871
|
+
const [loadState, setLoadState] = (0, import_react7.useState)("loading");
|
|
872
|
+
const [submitting, setSubmitting] = (0, import_react7.useState)(false);
|
|
809
873
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
810
|
-
const lastWalletMethodRef = (0,
|
|
811
|
-
const beforeClickRef = (0,
|
|
812
|
-
const handleWalletConfirm = (0,
|
|
874
|
+
const lastWalletMethodRef = (0, import_react7.useRef)("card");
|
|
875
|
+
const beforeClickRef = (0, import_react7.useRef)(null);
|
|
876
|
+
const handleWalletConfirm = (0, import_react7.useCallback)(
|
|
813
877
|
async (event) => {
|
|
814
878
|
if (!stripe || !elements) return;
|
|
815
879
|
const walletType = event.expressPaymentType;
|
|
@@ -890,8 +954,8 @@ function WalletButtonInner({
|
|
|
890
954
|
},
|
|
891
955
|
[stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, onButtonClick, runBeforeButtonClick]
|
|
892
956
|
);
|
|
893
|
-
return /* @__PURE__ */ (0,
|
|
894
|
-
/* @__PURE__ */ (0,
|
|
957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
958
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-wallet-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
895
959
|
import_react_stripe_js.ExpressCheckoutElement,
|
|
896
960
|
{
|
|
897
961
|
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["applePay", "googlePay"])),
|
|
@@ -929,7 +993,7 @@ function WalletButtonInner({
|
|
|
929
993
|
}
|
|
930
994
|
}
|
|
931
995
|
) }),
|
|
932
|
-
submitting && /* @__PURE__ */ (0,
|
|
996
|
+
submitting && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ProcessingOverlay, { status: "processing" })
|
|
933
997
|
] });
|
|
934
998
|
}
|
|
935
999
|
function SplitCardFormInner({
|
|
@@ -962,6 +1026,7 @@ function SplitCardFormInner({
|
|
|
962
1026
|
cardButtonContent,
|
|
963
1027
|
cardBackButtonContent,
|
|
964
1028
|
cardTitleContent,
|
|
1029
|
+
showSecurityFooter = true,
|
|
965
1030
|
onButtonClick,
|
|
966
1031
|
onBeforeButtonClick,
|
|
967
1032
|
enableAVS = false,
|
|
@@ -978,39 +1043,39 @@ function SplitCardFormInner({
|
|
|
978
1043
|
const flopay = useFloPay();
|
|
979
1044
|
const paypalFlopay = usePayPalFloPay();
|
|
980
1045
|
const elements = useElements();
|
|
981
|
-
const checkout = (0,
|
|
1046
|
+
const checkout = (0, import_react7.useContext)(CheckoutContext);
|
|
982
1047
|
const contextBillingUrl = useBillingApiUrl();
|
|
983
|
-
const [processing, setProcessing] = (0,
|
|
984
|
-
const [error, setError] = (0,
|
|
985
|
-
const [is3DSActive, setIs3DSActive] = (0,
|
|
986
|
-
const [selectedCountry, setSelectedCountry] = (0,
|
|
987
|
-
const [zipCode, setZipCode] = (0,
|
|
988
|
-
const [accountPatch, setAccountPatch] = (0,
|
|
989
|
-
const zipCodeRef = (0,
|
|
990
|
-
const selectedCountryRef = (0,
|
|
991
|
-
const [viewState, setViewState] = (0,
|
|
1048
|
+
const [processing, setProcessing] = (0, import_react7.useState)(false);
|
|
1049
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
1050
|
+
const [is3DSActive, setIs3DSActive] = (0, import_react7.useState)(false);
|
|
1051
|
+
const [selectedCountry, setSelectedCountry] = (0, import_react7.useState)(countryProp ?? "US");
|
|
1052
|
+
const [zipCode, setZipCode] = (0, import_react7.useState)(zipProp ?? "");
|
|
1053
|
+
const [accountPatch, setAccountPatch] = (0, import_react7.useState)({});
|
|
1054
|
+
const zipCodeRef = (0, import_react7.useRef)(zipProp ?? "");
|
|
1055
|
+
const selectedCountryRef = (0, import_react7.useRef)(countryProp ?? "US");
|
|
1056
|
+
const [viewState, setViewState] = (0, import_react7.useState)(initialCardOpen ? "card" : "buttons");
|
|
992
1057
|
const showCardForm = viewState === "expanding" || viewState === "card";
|
|
993
1058
|
const TRANSITION_MS = 280;
|
|
994
|
-
const expandToCard = (0,
|
|
1059
|
+
const expandToCard = (0, import_react7.useCallback)(() => {
|
|
995
1060
|
setViewState("expanding");
|
|
996
1061
|
setTimeout(() => setViewState("card"), TRANSITION_MS);
|
|
997
1062
|
}, []);
|
|
998
|
-
const collapseToButtons = (0,
|
|
1063
|
+
const collapseToButtons = (0, import_react7.useCallback)(() => {
|
|
999
1064
|
setViewState("collapsing");
|
|
1000
1065
|
setTimeout(() => setViewState("buttons"), TRANSITION_MS);
|
|
1001
1066
|
}, []);
|
|
1002
|
-
(0,
|
|
1067
|
+
(0, import_react7.useEffect)(() => {
|
|
1003
1068
|
if (layout === "buttons" && initialCardOpen) {
|
|
1004
1069
|
setViewState("card");
|
|
1005
1070
|
}
|
|
1006
1071
|
}, [layout, initialCardOpen]);
|
|
1007
|
-
const [fullName, setFullName] = (0,
|
|
1008
|
-
const [formReady, setFormReady] = (0,
|
|
1009
|
-
const [overlayStatus, setOverlayStatus] = (0,
|
|
1010
|
-
const processingRef = (0,
|
|
1072
|
+
const [fullName, setFullName] = (0, import_react7.useState)("");
|
|
1073
|
+
const [formReady, setFormReady] = (0, import_react7.useState)(false);
|
|
1074
|
+
const [overlayStatus, setOverlayStatus] = (0, import_react7.useState)(null);
|
|
1075
|
+
const processingRef = (0, import_react7.useRef)(false);
|
|
1011
1076
|
const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
|
|
1012
1077
|
const displayError = externalError ?? error;
|
|
1013
|
-
const bStyles = (0,
|
|
1078
|
+
const bStyles = (0, import_react7.useMemo)(() => {
|
|
1014
1079
|
const base = (0, import_shared4.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
1015
1080
|
if (!buttonsStylesOverride) return base;
|
|
1016
1081
|
return {
|
|
@@ -1028,7 +1093,7 @@ function SplitCardFormInner({
|
|
|
1028
1093
|
const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
|
|
1029
1094
|
const isSelfContained = !onTokenizedBody;
|
|
1030
1095
|
const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
|
|
1031
|
-
const resolvedAccount = (0,
|
|
1096
|
+
const resolvedAccount = (0, import_react7.useMemo)(() => mergeAccountPatch({
|
|
1032
1097
|
userId,
|
|
1033
1098
|
email,
|
|
1034
1099
|
firstName,
|
|
@@ -1036,50 +1101,50 @@ function SplitCardFormInner({
|
|
|
1036
1101
|
country: countryProp,
|
|
1037
1102
|
zip: zipProp
|
|
1038
1103
|
}, accountPatch), [userId, email, firstName, lastName, countryProp, zipProp, accountPatch]);
|
|
1039
|
-
const stripeInstance = (0,
|
|
1104
|
+
const stripeInstance = (0, import_react7.useMemo)(() => {
|
|
1040
1105
|
if (!flopay) return null;
|
|
1041
1106
|
return flopay.getRawProvider();
|
|
1042
1107
|
}, [flopay]);
|
|
1043
|
-
const paypalStripeInstance = (0,
|
|
1108
|
+
const paypalStripeInstance = (0, import_react7.useMemo)(() => {
|
|
1044
1109
|
if (!paypalFlopay) return null;
|
|
1045
1110
|
return paypalFlopay.getRawProvider();
|
|
1046
1111
|
}, [paypalFlopay]);
|
|
1047
1112
|
const amountInCents = totalAmount || 100;
|
|
1048
|
-
const walletOptions = (0,
|
|
1113
|
+
const walletOptions = (0, import_react7.useMemo)(() => ({
|
|
1049
1114
|
mode: "payment",
|
|
1050
1115
|
amount: amountInCents,
|
|
1051
1116
|
currency: currency.toLowerCase(),
|
|
1052
1117
|
paymentMethodCreation: "manual",
|
|
1053
1118
|
captureMethod: "manual"
|
|
1054
1119
|
}), [amountInCents, currency]);
|
|
1055
|
-
const paypalOptions = (0,
|
|
1120
|
+
const paypalOptions = (0, import_react7.useMemo)(() => ({
|
|
1056
1121
|
mode: "payment",
|
|
1057
1122
|
amount: amountInCents,
|
|
1058
1123
|
currency: currency.toLowerCase(),
|
|
1059
1124
|
captureMethod: "manual"
|
|
1060
1125
|
}), [amountInCents, currency]);
|
|
1061
|
-
const updateError = (0,
|
|
1126
|
+
const updateError = (0, import_react7.useCallback)(
|
|
1062
1127
|
(err) => {
|
|
1063
1128
|
setError(err);
|
|
1064
1129
|
onErrorChange?.(err);
|
|
1065
1130
|
},
|
|
1066
1131
|
[onErrorChange]
|
|
1067
1132
|
);
|
|
1068
|
-
const emitDecline = (0,
|
|
1133
|
+
const emitDecline = (0, import_react7.useCallback)(
|
|
1069
1134
|
(method, input, overrides) => {
|
|
1070
1135
|
onDecline?.(buildDeclineEvent(method, input, overrides));
|
|
1071
1136
|
},
|
|
1072
1137
|
[onDecline]
|
|
1073
1138
|
);
|
|
1074
1139
|
const showWallets = showApplePay || showGooglePay;
|
|
1075
|
-
const handleNameChange = (0,
|
|
1140
|
+
const handleNameChange = (0, import_react7.useCallback)((value) => {
|
|
1076
1141
|
setFullName(value);
|
|
1077
1142
|
onFullNameChange?.(value);
|
|
1078
1143
|
const parts = value.trim().split(/\s+/);
|
|
1079
1144
|
onFirstNameChange?.(parts[0] ?? "");
|
|
1080
1145
|
onLastNameChange?.(parts.length > 1 ? parts.slice(1).join(" ") : "");
|
|
1081
1146
|
}, [onFullNameChange, onFirstNameChange, onLastNameChange]);
|
|
1082
|
-
const applyInlineSessionPatch = (0,
|
|
1147
|
+
const applyInlineSessionPatch = (0, import_react7.useCallback)(
|
|
1083
1148
|
(patch, method) => {
|
|
1084
1149
|
if (!checkout.applyInlineSessionPatch) {
|
|
1085
1150
|
return Promise.resolve({ error: null, sessionId });
|
|
@@ -1096,7 +1161,7 @@ function SplitCardFormInner({
|
|
|
1096
1161
|
},
|
|
1097
1162
|
[checkout.applyInlineSessionPatch, onError, sessionId, updateError]
|
|
1098
1163
|
);
|
|
1099
|
-
const runBeforeButtonClick = (0,
|
|
1164
|
+
const runBeforeButtonClick = (0, import_react7.useCallback)(async (method) => {
|
|
1100
1165
|
if (!onBeforeButtonClick) return { proceed: true };
|
|
1101
1166
|
try {
|
|
1102
1167
|
const result = await onBeforeButtonClick({
|
|
@@ -1132,7 +1197,7 @@ function SplitCardFormInner({
|
|
|
1132
1197
|
return { proceed: false };
|
|
1133
1198
|
}
|
|
1134
1199
|
}, [applyInlineSessionPatch, checkout.inlineSessionDraft, onBeforeButtonClick, onError, sessionId, updateError]);
|
|
1135
|
-
const processPaymentInternal = (0,
|
|
1200
|
+
const processPaymentInternal = (0, import_react7.useCallback)(
|
|
1136
1201
|
async (tokenizedBody, overrides) => {
|
|
1137
1202
|
if (processingRef.current) return;
|
|
1138
1203
|
processingRef.current = true;
|
|
@@ -1163,10 +1228,11 @@ function SplitCardFormInner({
|
|
|
1163
1228
|
});
|
|
1164
1229
|
if (response.ok) {
|
|
1165
1230
|
setOverlayStatus("success");
|
|
1166
|
-
await new Promise((r) => setTimeout(r,
|
|
1231
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_SUCCESS_DELAY_MS));
|
|
1167
1232
|
onComplete?.({
|
|
1168
1233
|
status: "succeeded",
|
|
1169
|
-
paymentIntentId: tokenizedBody.threeDSecureActionResultTokenId
|
|
1234
|
+
paymentIntentId: tokenizedBody.threeDSecureActionResultTokenId,
|
|
1235
|
+
paymentMethodId: resolveTokenizedPaymentMethodId(tokenizedBody)
|
|
1170
1236
|
});
|
|
1171
1237
|
return;
|
|
1172
1238
|
}
|
|
@@ -1196,7 +1262,8 @@ function SplitCardFormInner({
|
|
|
1196
1262
|
await processPaymentInternal({
|
|
1197
1263
|
id: result.paymentIntentId,
|
|
1198
1264
|
type: "card",
|
|
1199
|
-
threeDSecureActionResultTokenId: result.paymentIntentId
|
|
1265
|
+
threeDSecureActionResultTokenId: result.paymentIntentId,
|
|
1266
|
+
originalPaymentMethodId: resolveTokenizedPaymentMethodId(tokenizedBody)
|
|
1200
1267
|
});
|
|
1201
1268
|
}
|
|
1202
1269
|
} finally {
|
|
@@ -1250,11 +1317,11 @@ function SplitCardFormInner({
|
|
|
1250
1317
|
code: json?.code ?? json?.gatewayErrorCode,
|
|
1251
1318
|
declineCode: json?.declineCode ?? json?.gatewayDeclineReason
|
|
1252
1319
|
});
|
|
1253
|
-
await new Promise((r) => setTimeout(r,
|
|
1320
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
1254
1321
|
} catch (err) {
|
|
1255
1322
|
setOverlayStatus("error");
|
|
1256
1323
|
updateError(err instanceof Error ? err.message : "An unexpected error occurred");
|
|
1257
|
-
await new Promise((r) => setTimeout(r,
|
|
1324
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
1258
1325
|
} finally {
|
|
1259
1326
|
setProcessing(false);
|
|
1260
1327
|
setOverlayStatus(null);
|
|
@@ -1263,7 +1330,7 @@ function SplitCardFormInner({
|
|
|
1263
1330
|
},
|
|
1264
1331
|
[baseUrl, sessionId, resolvedAccount, fullName, chv, flopay, paypalFlopay, onComplete, onError, updateError, emitDecline]
|
|
1265
1332
|
);
|
|
1266
|
-
const dispatchTokenizedBody = (0,
|
|
1333
|
+
const dispatchTokenizedBody = (0, import_react7.useCallback)(
|
|
1267
1334
|
(tokenizedBody, overrides) => {
|
|
1268
1335
|
if (onTokenizedBody) {
|
|
1269
1336
|
onTokenizedBody(tokenizedBody);
|
|
@@ -1273,7 +1340,7 @@ function SplitCardFormInner({
|
|
|
1273
1340
|
},
|
|
1274
1341
|
[onTokenizedBody, processPaymentInternal]
|
|
1275
1342
|
);
|
|
1276
|
-
(0,
|
|
1343
|
+
(0, import_react7.useImperativeHandle)(innerRef, () => ({
|
|
1277
1344
|
async handleNextAction(secret) {
|
|
1278
1345
|
if (!flopay) return;
|
|
1279
1346
|
setIs3DSActive(true);
|
|
@@ -1300,7 +1367,7 @@ function SplitCardFormInner({
|
|
|
1300
1367
|
}
|
|
1301
1368
|
}
|
|
1302
1369
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
1303
|
-
(0,
|
|
1370
|
+
(0, import_react7.useEffect)(() => {
|
|
1304
1371
|
if (typeof window === "undefined") return;
|
|
1305
1372
|
const stored = localStorage.getItem(WALLET_RESUME_KEY);
|
|
1306
1373
|
if (!stored) return;
|
|
@@ -1318,7 +1385,7 @@ function SplitCardFormInner({
|
|
|
1318
1385
|
localStorage.removeItem(WALLET_RESUME_KEY);
|
|
1319
1386
|
}
|
|
1320
1387
|
}, [sessionId, dispatchTokenizedBody]);
|
|
1321
|
-
const handleSubmit = (0,
|
|
1388
|
+
const handleSubmit = (0, import_react7.useCallback)(
|
|
1322
1389
|
async (e) => {
|
|
1323
1390
|
e.preventDefault();
|
|
1324
1391
|
if (!flopay || !elements || isSubmitting || processingRef.current) return;
|
|
@@ -1378,19 +1445,20 @@ function SplitCardFormInner({
|
|
|
1378
1445
|
updateError(confirmResult.error.message);
|
|
1379
1446
|
onError?.(confirmResult.error);
|
|
1380
1447
|
emitDecline("card", confirmResult.error);
|
|
1381
|
-
await new Promise((r) => setTimeout(r,
|
|
1448
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
1382
1449
|
return;
|
|
1383
1450
|
}
|
|
1384
1451
|
handedOff = isSelfContained;
|
|
1385
1452
|
dispatchTokenizedBody({
|
|
1386
1453
|
id: pmResult.paymentMethodId,
|
|
1387
1454
|
type: "card",
|
|
1388
|
-
threeDSecureActionResultTokenId: confirmResult.paymentIntentId
|
|
1455
|
+
threeDSecureActionResultTokenId: confirmResult.paymentIntentId,
|
|
1456
|
+
originalPaymentMethodId: pmResult.paymentMethodId
|
|
1389
1457
|
});
|
|
1390
1458
|
} catch (err) {
|
|
1391
1459
|
setOverlayStatus("error");
|
|
1392
1460
|
updateError(err instanceof Error ? err.message : "An unexpected error occurred");
|
|
1393
|
-
await new Promise((r) => setTimeout(r,
|
|
1461
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
1394
1462
|
} finally {
|
|
1395
1463
|
if (!handedOff) {
|
|
1396
1464
|
setProcessing(false);
|
|
@@ -1402,7 +1470,7 @@ function SplitCardFormInner({
|
|
|
1402
1470
|
);
|
|
1403
1471
|
const isReady = flopay !== null && elements !== null;
|
|
1404
1472
|
if (!isReady) {
|
|
1405
|
-
return /* @__PURE__ */ (0,
|
|
1473
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
|
|
1406
1474
|
}
|
|
1407
1475
|
const isButtons = layout === "buttons";
|
|
1408
1476
|
const resolvedBorder = isButtons ? bStyles.cardInputBorder ?? "#e5e7eb" : "#A4A4FF";
|
|
@@ -1445,7 +1513,7 @@ function SplitCardFormInner({
|
|
|
1445
1513
|
invalid: { color: "#ef4444" }
|
|
1446
1514
|
}
|
|
1447
1515
|
};
|
|
1448
|
-
const cardFormBlock = /* @__PURE__ */ (0,
|
|
1516
|
+
const cardFormBlock = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: {
|
|
1449
1517
|
backgroundColor: cardBg,
|
|
1450
1518
|
borderRadius: "8px",
|
|
1451
1519
|
padding: isButtons ? "0" : "1rem",
|
|
@@ -1453,7 +1521,7 @@ function SplitCardFormInner({
|
|
|
1453
1521
|
...isButtons ? { padding: bStyles.cardFormContainer?.padding ?? "0" } : {},
|
|
1454
1522
|
...sharedInputPlaceholderVars
|
|
1455
1523
|
}, children: [
|
|
1456
|
-
/* @__PURE__ */ (0,
|
|
1524
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
|
|
1457
1525
|
.flopay-shared-input::placeholder {
|
|
1458
1526
|
color: var(--flopay-input-placeholder-color);
|
|
1459
1527
|
opacity: 1;
|
|
@@ -1462,12 +1530,12 @@ function SplitCardFormInner({
|
|
|
1462
1530
|
font-weight: var(--flopay-input-font-weight);
|
|
1463
1531
|
}
|
|
1464
1532
|
` }),
|
|
1465
|
-
isButtons && showCardForm && /* @__PURE__ */ (0,
|
|
1533
|
+
isButtons && showCardForm && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: {
|
|
1466
1534
|
display: "flex",
|
|
1467
1535
|
alignItems: "center",
|
|
1468
1536
|
padding: "0.75rem 0 0.625rem"
|
|
1469
1537
|
}, children: [
|
|
1470
|
-
/* @__PURE__ */ (0,
|
|
1538
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1471
1539
|
"button",
|
|
1472
1540
|
{
|
|
1473
1541
|
type: "button",
|
|
@@ -1489,7 +1557,7 @@ function SplitCardFormInner({
|
|
|
1489
1557
|
},
|
|
1490
1558
|
"aria-label": "Back to payment methods",
|
|
1491
1559
|
children: [
|
|
1492
|
-
/* @__PURE__ */ (0,
|
|
1560
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: {
|
|
1493
1561
|
display: "inline-flex",
|
|
1494
1562
|
alignItems: "center",
|
|
1495
1563
|
justifyContent: "center",
|
|
@@ -1499,12 +1567,12 @@ function SplitCardFormInner({
|
|
|
1499
1567
|
backgroundColor: "#f3f4f6",
|
|
1500
1568
|
transition: "background-color 0.15s",
|
|
1501
1569
|
...bStyles.backButtonIcon
|
|
1502
|
-
}, children: /* @__PURE__ */ (0,
|
|
1503
|
-
/* @__PURE__ */ (0,
|
|
1570
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime5.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_runtime5.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
1571
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
1504
1572
|
]
|
|
1505
1573
|
}
|
|
1506
1574
|
),
|
|
1507
|
-
hideTitle ? /* @__PURE__ */ (0,
|
|
1575
|
+
hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
|
|
1508
1576
|
flex: 1,
|
|
1509
1577
|
textAlign: "center",
|
|
1510
1578
|
fontWeight: 600,
|
|
@@ -1512,18 +1580,18 @@ function SplitCardFormInner({
|
|
|
1512
1580
|
color: "#262833",
|
|
1513
1581
|
paddingRight: 80,
|
|
1514
1582
|
...bStyles.title
|
|
1515
|
-
}, children: /* @__PURE__ */ (0,
|
|
1583
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TitleContentSlot, { content: cardTitleContent }) })
|
|
1516
1584
|
] }),
|
|
1517
|
-
!isButtons && !hideTitle && /* @__PURE__ */ (0,
|
|
1518
|
-
/* @__PURE__ */ (0,
|
|
1585
|
+
!isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { textAlign: "center", fontWeight: 600, fontSize: "1.1rem", padding: "0.5rem 0", color: "#262833" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TitleContentSlot, { content: cardTitleContent }) }),
|
|
1586
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
|
|
1519
1587
|
backgroundColor: cardInputBg,
|
|
1520
1588
|
border: `1px solid ${resolvedBorder}`,
|
|
1521
1589
|
borderTopLeftRadius: "8px",
|
|
1522
1590
|
borderTopRightRadius: "8px",
|
|
1523
1591
|
padding: "10px"
|
|
1524
|
-
}, children: /* @__PURE__ */ (0,
|
|
1525
|
-
/* @__PURE__ */ (0,
|
|
1526
|
-
/* @__PURE__ */ (0,
|
|
1592
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
|
|
1593
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex" }, children: [
|
|
1594
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
|
|
1527
1595
|
flex: 1,
|
|
1528
1596
|
backgroundColor: cardInputBg,
|
|
1529
1597
|
border: `1px solid ${resolvedBorder}`,
|
|
@@ -1531,23 +1599,23 @@ function SplitCardFormInner({
|
|
|
1531
1599
|
borderRight: "none",
|
|
1532
1600
|
borderBottomLeftRadius: "8px",
|
|
1533
1601
|
padding: "10px"
|
|
1534
|
-
}, children: /* @__PURE__ */ (0,
|
|
1535
|
-
/* @__PURE__ */ (0,
|
|
1602
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CardExpiryElement, { options: stripeElementStyle }) }),
|
|
1603
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
|
|
1536
1604
|
flex: 1,
|
|
1537
1605
|
backgroundColor: cardInputBg,
|
|
1538
1606
|
border: `1px solid ${resolvedBorder}`,
|
|
1539
1607
|
borderTop: "none",
|
|
1540
1608
|
borderBottomRightRadius: "8px",
|
|
1541
1609
|
padding: "10px"
|
|
1542
|
-
}, children: /* @__PURE__ */ (0,
|
|
1610
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CardCvcElement, { options: stripeElementStyle }) })
|
|
1543
1611
|
] }),
|
|
1544
|
-
/* @__PURE__ */ (0,
|
|
1612
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
|
|
1545
1613
|
backgroundColor: cardInputBg,
|
|
1546
1614
|
border: `1px solid ${resolvedBorder}`,
|
|
1547
1615
|
borderRadius: "8px",
|
|
1548
1616
|
marginTop: "0.5rem",
|
|
1549
1617
|
padding: "10px"
|
|
1550
|
-
}, children: /* @__PURE__ */ (0,
|
|
1618
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1551
1619
|
"input",
|
|
1552
1620
|
{
|
|
1553
1621
|
className: "flopay-shared-input",
|
|
@@ -1567,20 +1635,20 @@ function SplitCardFormInner({
|
|
|
1567
1635
|
}
|
|
1568
1636
|
}
|
|
1569
1637
|
) }),
|
|
1570
|
-
enableAVS && /* @__PURE__ */ (0,
|
|
1638
|
+
enableAVS && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: {
|
|
1571
1639
|
display: "flex",
|
|
1572
1640
|
flexDirection: avsLayoutProp === "column" ? "column" : "row",
|
|
1573
1641
|
gap: avsLayoutProp === "column" ? "0.5rem" : "0",
|
|
1574
1642
|
marginTop: "0.5rem"
|
|
1575
1643
|
}, children: [
|
|
1576
|
-
/* @__PURE__ */ (0,
|
|
1644
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
|
|
1577
1645
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
1578
1646
|
backgroundColor: cardInputBg,
|
|
1579
1647
|
border: `1px solid ${resolvedBorder}`,
|
|
1580
1648
|
padding: "10px",
|
|
1581
1649
|
...avsLayoutProp === "row" ? { borderRadius: "0", borderTopLeftRadius: "8px", borderBottomLeftRadius: "8px", borderRight: "none" } : { borderRadius: "8px" },
|
|
1582
1650
|
...isButtons && bStyles.countrySelect ? bStyles.countrySelect : {}
|
|
1583
|
-
}, children: /* @__PURE__ */ (0,
|
|
1651
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1584
1652
|
"select",
|
|
1585
1653
|
{
|
|
1586
1654
|
value: selectedCountry,
|
|
@@ -1601,21 +1669,21 @@ function SplitCardFormInner({
|
|
|
1601
1669
|
cursor: "pointer",
|
|
1602
1670
|
...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
|
|
1603
1671
|
},
|
|
1604
|
-
children: import_shared4.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0,
|
|
1672
|
+
children: import_shared4.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("option", { value: c.code, children: [
|
|
1605
1673
|
c.flag,
|
|
1606
1674
|
" ",
|
|
1607
1675
|
c.name
|
|
1608
1676
|
] }, c.code))
|
|
1609
1677
|
}
|
|
1610
1678
|
) }),
|
|
1611
|
-
/* @__PURE__ */ (0,
|
|
1679
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
|
|
1612
1680
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
1613
1681
|
backgroundColor: cardInputBg,
|
|
1614
1682
|
border: `1px solid ${resolvedBorder}`,
|
|
1615
1683
|
padding: "10px",
|
|
1616
1684
|
...avsLayoutProp === "row" ? { borderRadius: "0", borderTopRightRadius: "8px", borderBottomRightRadius: "8px" } : { borderRadius: "8px" },
|
|
1617
1685
|
...isButtons && bStyles.zipInput ? bStyles.zipInput : {}
|
|
1618
|
-
}, children: /* @__PURE__ */ (0,
|
|
1686
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1619
1687
|
"input",
|
|
1620
1688
|
{
|
|
1621
1689
|
className: "flopay-shared-input",
|
|
@@ -1641,7 +1709,7 @@ function SplitCardFormInner({
|
|
|
1641
1709
|
}
|
|
1642
1710
|
) })
|
|
1643
1711
|
] }),
|
|
1644
|
-
displayError && /* @__PURE__ */ (0,
|
|
1712
|
+
displayError && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
1645
1713
|
margin: "0.75rem 0",
|
|
1646
1714
|
padding: "0.625rem 0.875rem",
|
|
1647
1715
|
background: "#FEF2F2",
|
|
@@ -1655,10 +1723,10 @@ function SplitCardFormInner({
|
|
|
1655
1723
|
gap: "0.5rem",
|
|
1656
1724
|
...isButtons && bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
1657
1725
|
}, children: [
|
|
1658
|
-
/* @__PURE__ */ (0,
|
|
1726
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.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" }) }),
|
|
1659
1727
|
displayError
|
|
1660
1728
|
] }),
|
|
1661
|
-
children ?? /* @__PURE__ */ (0,
|
|
1729
|
+
children ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1662
1730
|
"button",
|
|
1663
1731
|
{
|
|
1664
1732
|
type: "submit",
|
|
@@ -1681,7 +1749,7 @@ function SplitCardFormInner({
|
|
|
1681
1749
|
children: isSubmitting ? "PROCESSING..." : submitLabel
|
|
1682
1750
|
}
|
|
1683
1751
|
),
|
|
1684
|
-
!isButtons && /* @__PURE__ */ (0,
|
|
1752
|
+
!isButtons && showSecurityFooter && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
|
|
1685
1753
|
backgroundColor: "#EFF9F0",
|
|
1686
1754
|
borderRadius: "8px",
|
|
1687
1755
|
padding: "0.75rem",
|
|
@@ -1698,11 +1766,11 @@ function SplitCardFormInner({
|
|
|
1698
1766
|
const cardButtonSizing = cardButtonContent === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
1699
1767
|
const buttonsAnim = viewState === "expanding" ? `flopay-buttons-exit ${TRANSITION_MS}ms cubic-bezier(0.4, 0, 0.2, 1) both` : viewState === "collapsing" ? `flopay-buttons-enter ${TRANSITION_MS}ms cubic-bezier(0, 0, 0.2, 1) both` : void 0;
|
|
1700
1768
|
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;
|
|
1701
|
-
return /* @__PURE__ */ (0,
|
|
1702
|
-
/* @__PURE__ */ (0,
|
|
1703
|
-
overlayStatus && /* @__PURE__ */ (0,
|
|
1704
|
-
/* @__PURE__ */ (0,
|
|
1705
|
-
/* @__PURE__ */ (0,
|
|
1769
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
1770
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FloPayKeyframes, {}),
|
|
1771
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
1772
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "grid" }, children: [
|
|
1773
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: {
|
|
1706
1774
|
gridArea: "1 / 1",
|
|
1707
1775
|
display: "flex",
|
|
1708
1776
|
flexDirection: "column",
|
|
@@ -1711,7 +1779,7 @@ function SplitCardFormInner({
|
|
|
1711
1779
|
...!isButtonsView && !buttonsAnim ? { visibility: "hidden", position: "absolute", pointerEvents: "none", width: "100%" } : {},
|
|
1712
1780
|
...buttonsAnim ? { animation: buttonsAnim, pointerEvents: "none" } : {}
|
|
1713
1781
|
}, children: [
|
|
1714
|
-
showPayPal && paypalStripeInstance && /* @__PURE__ */ (0,
|
|
1782
|
+
showPayPal && paypalStripeInstance && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1715
1783
|
PayPalButtonInner,
|
|
1716
1784
|
{
|
|
1717
1785
|
sessionId,
|
|
@@ -1725,7 +1793,7 @@ function SplitCardFormInner({
|
|
|
1725
1793
|
runBeforeButtonClick
|
|
1726
1794
|
}
|
|
1727
1795
|
) }),
|
|
1728
|
-
showWallets && stripeInstance ? /* @__PURE__ */ (0,
|
|
1796
|
+
showWallets && stripeInstance ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1729
1797
|
WalletButtonInner,
|
|
1730
1798
|
{
|
|
1731
1799
|
sessionId,
|
|
@@ -1739,8 +1807,8 @@ function SplitCardFormInner({
|
|
|
1739
1807
|
onDecline,
|
|
1740
1808
|
runBeforeButtonClick
|
|
1741
1809
|
}
|
|
1742
|
-
) }) : showWallets ? /* @__PURE__ */ (0,
|
|
1743
|
-
/* @__PURE__ */ (0,
|
|
1810
|
+
) }) : showWallets ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: 8, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
|
|
1811
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1744
1812
|
"button",
|
|
1745
1813
|
{
|
|
1746
1814
|
type: "button",
|
|
@@ -1778,10 +1846,10 @@ function SplitCardFormInner({
|
|
|
1778
1846
|
onMouseUp: (e) => {
|
|
1779
1847
|
e.currentTarget.style.transform = "scale(1)";
|
|
1780
1848
|
},
|
|
1781
|
-
children: /* @__PURE__ */ (0,
|
|
1849
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CardButtonContentSlot, { content: cardButtonContent })
|
|
1782
1850
|
}
|
|
1783
1851
|
),
|
|
1784
|
-
displayError && viewState === "buttons" && /* @__PURE__ */ (0,
|
|
1852
|
+
displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
1785
1853
|
margin: "0.25rem 0",
|
|
1786
1854
|
padding: "0.625rem 0.875rem",
|
|
1787
1855
|
background: "#FEF2F2",
|
|
@@ -1795,11 +1863,11 @@ function SplitCardFormInner({
|
|
|
1795
1863
|
gap: "0.5rem",
|
|
1796
1864
|
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
1797
1865
|
}, children: [
|
|
1798
|
-
/* @__PURE__ */ (0,
|
|
1866
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.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" }) }),
|
|
1799
1867
|
displayError
|
|
1800
1868
|
] })
|
|
1801
1869
|
] }),
|
|
1802
|
-
isCardView && /* @__PURE__ */ (0,
|
|
1870
|
+
isCardView && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
|
|
1803
1871
|
gridArea: "1 / 1",
|
|
1804
1872
|
...cardAnim ? { animation: cardAnim } : {},
|
|
1805
1873
|
...viewState === "collapsing" ? { pointerEvents: "none" } : {}
|
|
@@ -1807,10 +1875,10 @@ function SplitCardFormInner({
|
|
|
1807
1875
|
] })
|
|
1808
1876
|
] });
|
|
1809
1877
|
}
|
|
1810
|
-
return /* @__PURE__ */ (0,
|
|
1811
|
-
/* @__PURE__ */ (0,
|
|
1812
|
-
overlayStatus && /* @__PURE__ */ (0,
|
|
1813
|
-
showWallets && stripeInstance && /* @__PURE__ */ (0,
|
|
1878
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
1879
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FloPayKeyframes, {}),
|
|
1880
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
1881
|
+
showWallets && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1814
1882
|
WalletButtonInner,
|
|
1815
1883
|
{
|
|
1816
1884
|
sessionId,
|
|
@@ -1823,7 +1891,7 @@ function SplitCardFormInner({
|
|
|
1823
1891
|
onDecline
|
|
1824
1892
|
}
|
|
1825
1893
|
) }),
|
|
1826
|
-
showPayPal && paypalStripeInstance && /* @__PURE__ */ (0,
|
|
1894
|
+
showPayPal && paypalStripeInstance && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1827
1895
|
PayPalButtonInner,
|
|
1828
1896
|
{
|
|
1829
1897
|
sessionId,
|
|
@@ -1835,7 +1903,7 @@ function SplitCardFormInner({
|
|
|
1835
1903
|
onDecline
|
|
1836
1904
|
}
|
|
1837
1905
|
) }),
|
|
1838
|
-
(showWallets && stripeInstance || showPayPal && paypalStripeInstance) && /* @__PURE__ */ (0,
|
|
1906
|
+
(showWallets && stripeInstance || showPayPal && paypalStripeInstance) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: {
|
|
1839
1907
|
display: "flex",
|
|
1840
1908
|
alignItems: "center",
|
|
1841
1909
|
gap: "0.75rem",
|
|
@@ -1843,17 +1911,503 @@ function SplitCardFormInner({
|
|
|
1843
1911
|
color: "#999",
|
|
1844
1912
|
fontSize: "0.85rem"
|
|
1845
1913
|
}, children: [
|
|
1846
|
-
/* @__PURE__ */ (0,
|
|
1847
|
-
/* @__PURE__ */ (0,
|
|
1848
|
-
/* @__PURE__ */ (0,
|
|
1914
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
|
|
1915
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "or pay with card" }),
|
|
1916
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
|
|
1849
1917
|
] }),
|
|
1850
1918
|
cardFormBlock
|
|
1851
1919
|
] });
|
|
1852
1920
|
}
|
|
1853
1921
|
|
|
1922
|
+
// src/saved-payment-flow.ts
|
|
1923
|
+
var import_js = require("@flopay/js");
|
|
1924
|
+
var import_shared6 = require("@flopay/shared");
|
|
1925
|
+
var DEFAULT_SAVED_PAYMENT_DECLINE_METHOD = "card";
|
|
1926
|
+
function resolveSavedPaymentReturnUrl(session) {
|
|
1927
|
+
if (typeof window !== "undefined" && window.location.href) {
|
|
1928
|
+
return window.location.href;
|
|
1929
|
+
}
|
|
1930
|
+
return session.successUrl || session.cancelUrl || void 0;
|
|
1931
|
+
}
|
|
1932
|
+
function isStripePaymentIntentClientSecret(value) {
|
|
1933
|
+
return typeof value === "string" && value.startsWith("pi_") && value.includes("_secret_");
|
|
1934
|
+
}
|
|
1935
|
+
async function retryOnceOnFetchFailure(action) {
|
|
1936
|
+
try {
|
|
1937
|
+
return await action();
|
|
1938
|
+
} catch (err) {
|
|
1939
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1940
|
+
if (!/failed to fetch|fetch failed/i.test(message)) {
|
|
1941
|
+
throw err;
|
|
1942
|
+
}
|
|
1943
|
+
return action();
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
function getRedirectTokenFromProcessResponse(json, options) {
|
|
1947
|
+
const directCandidates = [
|
|
1948
|
+
json?.threeDSecureToken,
|
|
1949
|
+
json?.clientSecret,
|
|
1950
|
+
json?.stripeClientSecret
|
|
1951
|
+
];
|
|
1952
|
+
for (const candidate of directCandidates) {
|
|
1953
|
+
if (typeof candidate === "string" && candidate.length > 0 && (!options?.requirePaymentIntentClientSecret || isStripePaymentIntentClientSecret(candidate))) {
|
|
1954
|
+
return candidate;
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
const nested = json?.data;
|
|
1958
|
+
if (nested && typeof nested === "object") {
|
|
1959
|
+
const nestedRecord = nested;
|
|
1960
|
+
const nestedCandidates = [
|
|
1961
|
+
nestedRecord.threeDSecureToken,
|
|
1962
|
+
nestedRecord.clientSecret,
|
|
1963
|
+
nestedRecord.stripeClientSecret,
|
|
1964
|
+
nestedRecord.id
|
|
1965
|
+
];
|
|
1966
|
+
for (const candidate of nestedCandidates) {
|
|
1967
|
+
if (typeof candidate === "string" && candidate.length > 0 && (!options?.requirePaymentIntentClientSecret || isStripePaymentIntentClientSecret(candidate))) {
|
|
1968
|
+
return candidate;
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
const nestedGatewayData = nestedRecord.gatewayData;
|
|
1972
|
+
if (nestedGatewayData && typeof nestedGatewayData === "object") {
|
|
1973
|
+
const nestedGatewayDataRecord = nestedGatewayData;
|
|
1974
|
+
const gatewayCandidates = [
|
|
1975
|
+
nestedGatewayDataRecord.stripeClientSecret,
|
|
1976
|
+
nestedGatewayDataRecord.clientSecret
|
|
1977
|
+
];
|
|
1978
|
+
for (const candidate of gatewayCandidates) {
|
|
1979
|
+
if (typeof candidate === "string" && candidate.length > 0 && (!options?.requirePaymentIntentClientSecret || isStripePaymentIntentClientSecret(candidate))) {
|
|
1980
|
+
return candidate;
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
return void 0;
|
|
1986
|
+
}
|
|
1987
|
+
async function recover3DSRedirectResult({
|
|
1988
|
+
billingApiUrl,
|
|
1989
|
+
sessionId,
|
|
1990
|
+
responseJson
|
|
1991
|
+
}) {
|
|
1992
|
+
const directToken = getRedirectTokenFromProcessResponse(responseJson, {
|
|
1993
|
+
requirePaymentIntentClientSecret: true
|
|
1994
|
+
});
|
|
1995
|
+
if (typeof directToken === "string" && directToken.length > 0) {
|
|
1996
|
+
return {
|
|
1997
|
+
type: "3ds_required",
|
|
1998
|
+
threeDSecureToken: directToken
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
if (!sessionId) {
|
|
2002
|
+
return null;
|
|
2003
|
+
}
|
|
2004
|
+
try {
|
|
2005
|
+
const api = new import_js.PaymentAPI(billingApiUrl);
|
|
2006
|
+
const unified = await api.getUnifiedCheckoutSession(sessionId);
|
|
2007
|
+
const refreshedToken = unified.provider === "stripe" ? unified.data.stripe?.clientSecret : void 0;
|
|
2008
|
+
if (isStripePaymentIntentClientSecret(refreshedToken)) {
|
|
2009
|
+
return {
|
|
2010
|
+
type: "3ds_required",
|
|
2011
|
+
threeDSecureToken: refreshedToken
|
|
2012
|
+
};
|
|
2013
|
+
}
|
|
2014
|
+
} catch {
|
|
2015
|
+
}
|
|
2016
|
+
return null;
|
|
2017
|
+
}
|
|
2018
|
+
async function processSavedPaymentForMode({
|
|
2019
|
+
billingApiUrl,
|
|
2020
|
+
sessionId,
|
|
2021
|
+
session,
|
|
2022
|
+
tokenizedData,
|
|
2023
|
+
returnUrl
|
|
2024
|
+
}) {
|
|
2025
|
+
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2026
|
+
const resolvedSessionId = sessionId ?? session.id;
|
|
2027
|
+
const customerId = session.customer?.id ?? session.accountData?.userId ?? "";
|
|
2028
|
+
const customerEmail = session.customer?.email ?? session.accountData?.email ?? "";
|
|
2029
|
+
const firstName = session.customer?.firstName ?? session.accountData?.firstName ?? "";
|
|
2030
|
+
const lastName = session.customer?.lastName ?? session.accountData?.lastName ?? "";
|
|
2031
|
+
const country = session.customer?.country ?? session.accountData?.country ?? void 0;
|
|
2032
|
+
const zip = session.customer?.zip ?? session.accountData?.zip ?? void 0;
|
|
2033
|
+
const response = await retryOnceOnFetchFailure(() => fetch(`${baseUrl}/v1/checkouts/sessions/process`, {
|
|
2034
|
+
method: "POST",
|
|
2035
|
+
headers: {
|
|
2036
|
+
"Content-Type": "application/json",
|
|
2037
|
+
"x-user-id": customerId
|
|
2038
|
+
},
|
|
2039
|
+
body: JSON.stringify({
|
|
2040
|
+
sessionId: resolvedSessionId,
|
|
2041
|
+
tokenizedData,
|
|
2042
|
+
accountData: {
|
|
2043
|
+
userId: customerId,
|
|
2044
|
+
email: customerEmail,
|
|
2045
|
+
firstName,
|
|
2046
|
+
lastName,
|
|
2047
|
+
country,
|
|
2048
|
+
zip
|
|
2049
|
+
},
|
|
2050
|
+
returnUrl: returnUrl ?? resolveSavedPaymentReturnUrl(session)
|
|
2051
|
+
})
|
|
2052
|
+
}));
|
|
2053
|
+
if (response.ok) {
|
|
2054
|
+
return {
|
|
2055
|
+
type: "success",
|
|
2056
|
+
result: {
|
|
2057
|
+
status: "succeeded",
|
|
2058
|
+
paymentIntentId: tokenizedData?.threeDSecureActionResultTokenId,
|
|
2059
|
+
paymentMethodId: resolveTokenizedPaymentMethodId(tokenizedData)
|
|
2060
|
+
}
|
|
2061
|
+
};
|
|
2062
|
+
}
|
|
2063
|
+
const json = await response.json().catch(() => null);
|
|
2064
|
+
if (json?.type === "paypal_redirect_required" || json?.type === "3ds_required") {
|
|
2065
|
+
const redirectToken = getRedirectTokenFromProcessResponse(json);
|
|
2066
|
+
if (!redirectToken) {
|
|
2067
|
+
throw new import_shared6.FloPayError(
|
|
2068
|
+
"Authentication is required but no redirect token was provided.",
|
|
2069
|
+
"api_error",
|
|
2070
|
+
{ code: "authentication_required" }
|
|
2071
|
+
);
|
|
2072
|
+
}
|
|
2073
|
+
return {
|
|
2074
|
+
type: json.type,
|
|
2075
|
+
threeDSecureToken: redirectToken,
|
|
2076
|
+
paymentMethodId: json.paymentMethodId
|
|
2077
|
+
};
|
|
2078
|
+
}
|
|
2079
|
+
if (json?.gatewayErrorCode === "authentication_required") {
|
|
2080
|
+
const recoveredRedirect = await recover3DSRedirectResult({
|
|
2081
|
+
billingApiUrl: baseUrl,
|
|
2082
|
+
sessionId: resolvedSessionId,
|
|
2083
|
+
responseJson: json
|
|
2084
|
+
});
|
|
2085
|
+
if (recoveredRedirect) {
|
|
2086
|
+
return recoveredRedirect;
|
|
2087
|
+
}
|
|
2088
|
+
throw Object.assign(
|
|
2089
|
+
new import_shared6.FloPayError(
|
|
2090
|
+
"Your card requires authentication. Please enter your payment details below.",
|
|
2091
|
+
"api_error",
|
|
2092
|
+
{ code: "authentication_required" }
|
|
2093
|
+
),
|
|
2094
|
+
{ checkoutMethod: "card" }
|
|
2095
|
+
);
|
|
2096
|
+
}
|
|
2097
|
+
throw new import_shared6.FloPayError(
|
|
2098
|
+
json?.message ?? "Payment failed. Please try again.",
|
|
2099
|
+
"api_error",
|
|
2100
|
+
{
|
|
2101
|
+
code: json?.code ?? json?.gatewayErrorCode,
|
|
2102
|
+
declineCode: json?.declineCode ?? json?.gatewayDeclineReason
|
|
2103
|
+
}
|
|
2104
|
+
);
|
|
2105
|
+
}
|
|
2106
|
+
async function processSavedPaymentWithIntent({
|
|
2107
|
+
billingApiUrl,
|
|
2108
|
+
sessionId,
|
|
2109
|
+
session,
|
|
2110
|
+
paymentMethodId,
|
|
2111
|
+
flopay,
|
|
2112
|
+
returnUrl
|
|
2113
|
+
}) {
|
|
2114
|
+
const customerEmail = session.customer?.email ?? session.accountData?.email ?? "";
|
|
2115
|
+
if (!customerEmail) {
|
|
2116
|
+
throw Object.assign(
|
|
2117
|
+
new import_shared6.FloPayError("Customer email is required to create a payment intent.", "validation_error", {
|
|
2118
|
+
param: "email"
|
|
2119
|
+
}),
|
|
2120
|
+
{ checkoutMethod: "card" }
|
|
2121
|
+
);
|
|
2122
|
+
}
|
|
2123
|
+
const api = new import_js.PaymentAPI(billingApiUrl);
|
|
2124
|
+
const intentResponse = await retryOnceOnFetchFailure(() => api.createPaymentIntent(
|
|
2125
|
+
sessionId,
|
|
2126
|
+
customerEmail,
|
|
2127
|
+
paymentMethodId
|
|
2128
|
+
));
|
|
2129
|
+
const intentJson = await intentResponse.json().catch(() => null);
|
|
2130
|
+
if (!intentResponse.ok) {
|
|
2131
|
+
throw Object.assign(
|
|
2132
|
+
new import_shared6.FloPayError(
|
|
2133
|
+
intentJson?.message ?? "Failed to create payment intent.",
|
|
2134
|
+
"api_error",
|
|
2135
|
+
{ code: intentJson?.code ?? intentJson?.gatewayErrorCode }
|
|
2136
|
+
),
|
|
2137
|
+
{ checkoutMethod: "card" }
|
|
2138
|
+
);
|
|
2139
|
+
}
|
|
2140
|
+
const intentClientSecret = getRedirectTokenFromProcessResponse(intentJson, {
|
|
2141
|
+
requirePaymentIntentClientSecret: true
|
|
2142
|
+
});
|
|
2143
|
+
if (!intentClientSecret) {
|
|
2144
|
+
throw Object.assign(
|
|
2145
|
+
new import_shared6.FloPayError("No client secret in payment intent response.", "api_error"),
|
|
2146
|
+
{ checkoutMethod: "card" }
|
|
2147
|
+
);
|
|
2148
|
+
}
|
|
2149
|
+
const confirmResult = await flopay.confirmCardPayment({
|
|
2150
|
+
clientSecret: intentClientSecret,
|
|
2151
|
+
paymentMethodId
|
|
2152
|
+
});
|
|
2153
|
+
if (confirmResult.error) {
|
|
2154
|
+
throw Object.assign(
|
|
2155
|
+
confirmResult.error,
|
|
2156
|
+
{ checkoutMethod: "card" }
|
|
2157
|
+
);
|
|
2158
|
+
}
|
|
2159
|
+
if (!confirmResult.paymentIntentId || confirmResult.status !== "succeeded" && confirmResult.status !== "processing" && confirmResult.status !== "requires_capture") {
|
|
2160
|
+
throw Object.assign(
|
|
2161
|
+
new import_shared6.FloPayError(
|
|
2162
|
+
`Payment intent in unexpected status: ${confirmResult.status}`,
|
|
2163
|
+
"api_error",
|
|
2164
|
+
{
|
|
2165
|
+
code: confirmResult.status === "requires_action" ? "authentication_required" : void 0
|
|
2166
|
+
}
|
|
2167
|
+
),
|
|
2168
|
+
{ checkoutMethod: "card" }
|
|
2169
|
+
);
|
|
2170
|
+
}
|
|
2171
|
+
const followUp = await processSavedPaymentForMode({
|
|
2172
|
+
billingApiUrl,
|
|
2173
|
+
sessionId,
|
|
2174
|
+
session,
|
|
2175
|
+
tokenizedData: {
|
|
2176
|
+
id: paymentMethodId,
|
|
2177
|
+
type: "card",
|
|
2178
|
+
threeDSecureActionResultTokenId: confirmResult.paymentIntentId,
|
|
2179
|
+
originalPaymentMethodId: paymentMethodId
|
|
2180
|
+
},
|
|
2181
|
+
returnUrl
|
|
2182
|
+
});
|
|
2183
|
+
const finalResult = followUp.type === "success" ? followUp.result : await handleSavedPaymentRedirectResult(followUp, {
|
|
2184
|
+
flopay,
|
|
2185
|
+
paypalFlopay: null,
|
|
2186
|
+
attempt3DS: true,
|
|
2187
|
+
billingApiUrl,
|
|
2188
|
+
sessionId,
|
|
2189
|
+
session,
|
|
2190
|
+
returnUrl
|
|
2191
|
+
});
|
|
2192
|
+
return {
|
|
2193
|
+
...finalResult,
|
|
2194
|
+
paymentIntentId: finalResult.paymentIntentId ?? confirmResult.paymentIntentId,
|
|
2195
|
+
paymentMethodId: finalResult.paymentMethodId ?? paymentMethodId
|
|
2196
|
+
};
|
|
2197
|
+
}
|
|
2198
|
+
async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
2199
|
+
flopay,
|
|
2200
|
+
paypalFlopay,
|
|
2201
|
+
attempt3DS,
|
|
2202
|
+
billingApiUrl,
|
|
2203
|
+
sessionId,
|
|
2204
|
+
session,
|
|
2205
|
+
returnUrl
|
|
2206
|
+
}) {
|
|
2207
|
+
const stripe = flopay?.getRawProvider();
|
|
2208
|
+
if (!stripe) {
|
|
2209
|
+
throw new import_shared6.FloPayError("Payment provider is not available.", "api_error");
|
|
2210
|
+
}
|
|
2211
|
+
if (redirectResult.type === "3ds_required") {
|
|
2212
|
+
if (!attempt3DS || !redirectResult.threeDSecureToken) {
|
|
2213
|
+
throw Object.assign(
|
|
2214
|
+
new import_shared6.FloPayError(
|
|
2215
|
+
"Your card requires authentication. Please enter your payment details below.",
|
|
2216
|
+
"api_error",
|
|
2217
|
+
{ code: "authentication_required" }
|
|
2218
|
+
),
|
|
2219
|
+
{ checkoutMethod: "card" }
|
|
2220
|
+
);
|
|
2221
|
+
}
|
|
2222
|
+
let paymentIntent = null;
|
|
2223
|
+
let savedPaymentMethodId = redirectResult.paymentMethodId;
|
|
2224
|
+
if (typeof stripe.retrievePaymentIntent === "function") {
|
|
2225
|
+
const { paymentIntent: existingPaymentIntent, error: retrieveError } = await stripe.retrievePaymentIntent(
|
|
2226
|
+
redirectResult.threeDSecureToken
|
|
2227
|
+
);
|
|
2228
|
+
if (retrieveError) {
|
|
2229
|
+
throw Object.assign(
|
|
2230
|
+
new import_shared6.FloPayError(
|
|
2231
|
+
retrieveError.message ?? "Failed to retrieve 3DS payment status.",
|
|
2232
|
+
"api_error",
|
|
2233
|
+
{ code: retrieveError.code }
|
|
2234
|
+
),
|
|
2235
|
+
{ checkoutMethod: "card" }
|
|
2236
|
+
);
|
|
2237
|
+
}
|
|
2238
|
+
if (!savedPaymentMethodId && existingPaymentIntent?.payment_method) {
|
|
2239
|
+
if (typeof existingPaymentIntent.payment_method === "string") {
|
|
2240
|
+
savedPaymentMethodId = existingPaymentIntent.payment_method;
|
|
2241
|
+
} else if ("id" in existingPaymentIntent.payment_method) {
|
|
2242
|
+
savedPaymentMethodId = existingPaymentIntent.payment_method.id;
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
if (savedPaymentMethodId && typeof stripe.confirmCardPayment === "function") {
|
|
2247
|
+
const { error: confirmError, paymentIntent: confirmedPaymentIntent } = await stripe.confirmCardPayment(
|
|
2248
|
+
redirectResult.threeDSecureToken,
|
|
2249
|
+
{
|
|
2250
|
+
payment_method: savedPaymentMethodId,
|
|
2251
|
+
return_url: returnUrl ?? resolveSavedPaymentReturnUrl(session) ?? window.location.href
|
|
2252
|
+
}
|
|
2253
|
+
);
|
|
2254
|
+
if (confirmError) {
|
|
2255
|
+
throw Object.assign(
|
|
2256
|
+
new import_shared6.FloPayError(
|
|
2257
|
+
confirmError.message ?? "3DS authentication failed.",
|
|
2258
|
+
"api_error",
|
|
2259
|
+
{ code: confirmError.code }
|
|
2260
|
+
),
|
|
2261
|
+
{ checkoutMethod: "card" }
|
|
2262
|
+
);
|
|
2263
|
+
}
|
|
2264
|
+
paymentIntent = confirmedPaymentIntent ?? null;
|
|
2265
|
+
} else {
|
|
2266
|
+
const { error: nextActionError, paymentIntent: nextActionPaymentIntent } = await stripe.handleNextAction({
|
|
2267
|
+
clientSecret: redirectResult.threeDSecureToken
|
|
2268
|
+
});
|
|
2269
|
+
if (nextActionError) {
|
|
2270
|
+
throw Object.assign(
|
|
2271
|
+
new import_shared6.FloPayError(
|
|
2272
|
+
nextActionError.message ?? "3DS authentication failed.",
|
|
2273
|
+
"api_error",
|
|
2274
|
+
{ code: nextActionError.code }
|
|
2275
|
+
),
|
|
2276
|
+
{ checkoutMethod: "card" }
|
|
2277
|
+
);
|
|
2278
|
+
}
|
|
2279
|
+
paymentIntent = nextActionPaymentIntent ?? null;
|
|
2280
|
+
}
|
|
2281
|
+
if (paymentIntent && (paymentIntent.status === "requires_capture" || paymentIntent.status === "succeeded" || paymentIntent.status === "processing")) {
|
|
2282
|
+
const followUp = await processSavedPaymentForMode({
|
|
2283
|
+
billingApiUrl,
|
|
2284
|
+
sessionId,
|
|
2285
|
+
session,
|
|
2286
|
+
tokenizedData: {
|
|
2287
|
+
id: paymentIntent.id,
|
|
2288
|
+
type: "card",
|
|
2289
|
+
threeDSecureActionResultTokenId: paymentIntent.id,
|
|
2290
|
+
originalPaymentMethodId: savedPaymentMethodId
|
|
2291
|
+
},
|
|
2292
|
+
returnUrl
|
|
2293
|
+
});
|
|
2294
|
+
if (followUp.type === "success") {
|
|
2295
|
+
return {
|
|
2296
|
+
...followUp.result,
|
|
2297
|
+
paymentIntentId: followUp.result.paymentIntentId ?? paymentIntent.id,
|
|
2298
|
+
paymentMethodId: followUp.result.paymentMethodId ?? savedPaymentMethodId
|
|
2299
|
+
};
|
|
2300
|
+
}
|
|
2301
|
+
return handleSavedPaymentRedirectResult(followUp, {
|
|
2302
|
+
flopay,
|
|
2303
|
+
paypalFlopay,
|
|
2304
|
+
attempt3DS,
|
|
2305
|
+
billingApiUrl,
|
|
2306
|
+
sessionId,
|
|
2307
|
+
session,
|
|
2308
|
+
returnUrl
|
|
2309
|
+
});
|
|
2310
|
+
}
|
|
2311
|
+
throw Object.assign(
|
|
2312
|
+
new import_shared6.FloPayError("3DS authentication did not complete successfully.", "api_error"),
|
|
2313
|
+
{ checkoutMethod: "card" }
|
|
2314
|
+
);
|
|
2315
|
+
}
|
|
2316
|
+
if (redirectResult.type === "paypal_redirect_required") {
|
|
2317
|
+
const paypalStripe = (paypalFlopay ?? flopay)?.getRawProvider();
|
|
2318
|
+
if (!paypalStripe) {
|
|
2319
|
+
throw Object.assign(
|
|
2320
|
+
new import_shared6.FloPayError("PayPal is not available.", "api_error"),
|
|
2321
|
+
{ checkoutMethod: "paypal" }
|
|
2322
|
+
);
|
|
2323
|
+
}
|
|
2324
|
+
const confirmParams = {
|
|
2325
|
+
return_url: returnUrl ?? resolveSavedPaymentReturnUrl(session) ?? window.location.href
|
|
2326
|
+
};
|
|
2327
|
+
if (redirectResult.paymentMethodId) {
|
|
2328
|
+
confirmParams["payment_method"] = redirectResult.paymentMethodId;
|
|
2329
|
+
}
|
|
2330
|
+
const { error } = await paypalStripe.confirmPayment({
|
|
2331
|
+
clientSecret: redirectResult.threeDSecureToken,
|
|
2332
|
+
confirmParams,
|
|
2333
|
+
redirect: "if_required"
|
|
2334
|
+
});
|
|
2335
|
+
if (error) {
|
|
2336
|
+
throw Object.assign(
|
|
2337
|
+
new import_shared6.FloPayError(
|
|
2338
|
+
error.message ?? "PayPal authorization failed.",
|
|
2339
|
+
"api_error",
|
|
2340
|
+
{ code: error.code }
|
|
2341
|
+
),
|
|
2342
|
+
{ checkoutMethod: "paypal" }
|
|
2343
|
+
);
|
|
2344
|
+
}
|
|
2345
|
+
return { status: "succeeded" };
|
|
2346
|
+
}
|
|
2347
|
+
throw new import_shared6.FloPayError("Unsupported payment redirect state.", "api_error");
|
|
2348
|
+
}
|
|
2349
|
+
function normalizeSavedPaymentError(err) {
|
|
2350
|
+
if (err instanceof import_shared6.FloPayError) {
|
|
2351
|
+
return err;
|
|
2352
|
+
}
|
|
2353
|
+
return new import_shared6.FloPayError(
|
|
2354
|
+
err instanceof Error ? err.message : "Payment failed. Please try again.",
|
|
2355
|
+
"api_error"
|
|
2356
|
+
);
|
|
2357
|
+
}
|
|
2358
|
+
function resolveSavedPaymentPublishableKeys(unified, fallbackPublishableKey) {
|
|
2359
|
+
let publishableKey;
|
|
2360
|
+
let paypalPublishableKey;
|
|
2361
|
+
if (unified.provider === "stripe") {
|
|
2362
|
+
publishableKey = unified.data.stripe?.publishableKey;
|
|
2363
|
+
paypalPublishableKey = unified.data.stripe?.paypalPublishableKey ?? void 0;
|
|
2364
|
+
}
|
|
2365
|
+
if (!publishableKey) {
|
|
2366
|
+
publishableKey = fallbackPublishableKey;
|
|
2367
|
+
}
|
|
2368
|
+
if (!publishableKey) {
|
|
2369
|
+
throw new import_shared6.FloPayError(
|
|
2370
|
+
"No publishable key found. Provide fallbackPublishableKey or ensure the session includes gatewayData.publishableKey.",
|
|
2371
|
+
"validation_error"
|
|
2372
|
+
);
|
|
2373
|
+
}
|
|
2374
|
+
return {
|
|
2375
|
+
publishableKey,
|
|
2376
|
+
paypalPublishableKey
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2379
|
+
async function loadSavedPaymentProviders({
|
|
2380
|
+
publishableKey,
|
|
2381
|
+
paypalPublishableKey,
|
|
2382
|
+
billingApiUrl,
|
|
2383
|
+
locale
|
|
2384
|
+
}) {
|
|
2385
|
+
const needsSeparatePaypal = Boolean(paypalPublishableKey) && paypalPublishableKey !== publishableKey;
|
|
2386
|
+
const [instance, paypalInstanceOrError] = await Promise.all([
|
|
2387
|
+
(0, import_js.loadFloPay)(publishableKey, {
|
|
2388
|
+
billingApiUrl,
|
|
2389
|
+
locale
|
|
2390
|
+
}),
|
|
2391
|
+
needsSeparatePaypal ? (0, import_js.loadFloPay)(paypalPublishableKey, {
|
|
2392
|
+
billingApiUrl,
|
|
2393
|
+
locale
|
|
2394
|
+
}).catch((err) => {
|
|
2395
|
+
console.warn("[FloPay] Failed to load PayPal Stripe instance:", err);
|
|
2396
|
+
return null;
|
|
2397
|
+
}) : Promise.resolve(null)
|
|
2398
|
+
]);
|
|
2399
|
+
return {
|
|
2400
|
+
flopay: instance,
|
|
2401
|
+
paypalFlopay: paypalPublishableKey ? needsSeparatePaypal ? paypalInstanceOrError : instance : null
|
|
2402
|
+
};
|
|
2403
|
+
}
|
|
2404
|
+
|
|
1854
2405
|
// src/flopay-checkout.tsx
|
|
1855
|
-
var
|
|
2406
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1856
2407
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
|
|
2408
|
+
function sleep(ms) {
|
|
2409
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2410
|
+
}
|
|
1857
2411
|
function hasInlineSessionPatchData(patch) {
|
|
1858
2412
|
if (!patch) return false;
|
|
1859
2413
|
return Boolean(
|
|
@@ -1884,6 +2438,7 @@ function FloPayCheckout({
|
|
|
1884
2438
|
cardButtonContent,
|
|
1885
2439
|
cardBackButtonContent,
|
|
1886
2440
|
cardTitleContent,
|
|
2441
|
+
showSecurityFooter = true,
|
|
1887
2442
|
onButtonClick,
|
|
1888
2443
|
onBeforeButtonClick,
|
|
1889
2444
|
enableAVS,
|
|
@@ -1896,171 +2451,131 @@ function FloPayCheckout({
|
|
|
1896
2451
|
renderConfirmButton,
|
|
1897
2452
|
onSessionCompleted
|
|
1898
2453
|
}) {
|
|
1899
|
-
const resolvedBillingUrl = (0,
|
|
2454
|
+
const resolvedBillingUrl = (0, import_shared7.resolveBillingApiUrl)(billingApiUrl);
|
|
1900
2455
|
const checkoutType = createSessionParams ? "embedded_checkout" : "standard_checkout";
|
|
1901
2456
|
const checkoutLayout = children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout";
|
|
1902
|
-
const [unified, setUnified] = (0,
|
|
1903
|
-
const [flopay, setFloPay] = (0,
|
|
1904
|
-
const flopayRef = (0,
|
|
1905
|
-
const [paypalFlopay, setPaypalFloPay] = (0,
|
|
1906
|
-
const paypalFlopayRef = (0,
|
|
1907
|
-
const [session, setSession] = (0,
|
|
1908
|
-
const [resolvedSessionId, setResolvedSessionId] = (0,
|
|
1909
|
-
const
|
|
1910
|
-
const
|
|
1911
|
-
const [
|
|
1912
|
-
const [
|
|
1913
|
-
const [
|
|
1914
|
-
const [
|
|
1915
|
-
const [
|
|
1916
|
-
const [
|
|
1917
|
-
const
|
|
1918
|
-
const
|
|
2457
|
+
const [unified, setUnified] = (0, import_react8.useState)(null);
|
|
2458
|
+
const [flopay, setFloPay] = (0, import_react8.useState)(null);
|
|
2459
|
+
const flopayRef = (0, import_react8.useRef)(null);
|
|
2460
|
+
const [paypalFlopay, setPaypalFloPay] = (0, import_react8.useState)(null);
|
|
2461
|
+
const paypalFlopayRef = (0, import_react8.useRef)(null);
|
|
2462
|
+
const [session, setSession] = (0, import_react8.useState)(null);
|
|
2463
|
+
const [resolvedSessionId, setResolvedSessionId] = (0, import_react8.useState)(sessionIdProp ?? "");
|
|
2464
|
+
const activeSessionId = sessionIdProp ?? resolvedSessionId;
|
|
2465
|
+
const initSessionDependency = createSessionParams ? "" : activeSessionId;
|
|
2466
|
+
const [isLoading, setIsLoading] = (0, import_react8.useState)(true);
|
|
2467
|
+
const [loadError, setLoadError] = (0, import_react8.useState)(null);
|
|
2468
|
+
const [currentMode, setCurrentMode] = (0, import_react8.useState)("full");
|
|
2469
|
+
const [confirmProcessing, setConfirmProcessing] = (0, import_react8.useState)(false);
|
|
2470
|
+
const [modeError, setModeError] = (0, import_react8.useState)(null);
|
|
2471
|
+
const [modeOverlayStatus, setModeOverlayStatus] = (0, import_react8.useState)(null);
|
|
2472
|
+
const [modeOverlayError, setModeOverlayError] = (0, import_react8.useState)(null);
|
|
2473
|
+
const [createSessionPatch, setCreateSessionPatch] = (0, import_react8.useState)(void 0);
|
|
2474
|
+
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0, import_react8.useState)("");
|
|
2475
|
+
const [cardBootstrapPending, setCardBootstrapPending] = (0, import_react8.useState)(false);
|
|
2476
|
+
const autoCheckoutAttempted = (0, import_react8.useRef)(false);
|
|
2477
|
+
const onCompleteRef = (0, import_react8.useRef)(onComplete);
|
|
1919
2478
|
onCompleteRef.current = onComplete;
|
|
1920
|
-
const onErrorRef = (0,
|
|
2479
|
+
const onErrorRef = (0, import_react8.useRef)(onError);
|
|
1921
2480
|
onErrorRef.current = onError;
|
|
1922
|
-
const onDeclineRef = (0,
|
|
2481
|
+
const onDeclineRef = (0, import_react8.useRef)(onDecline);
|
|
1923
2482
|
onDeclineRef.current = onDecline;
|
|
1924
|
-
const onSessionCompletedRef = (0,
|
|
2483
|
+
const onSessionCompletedRef = (0, import_react8.useRef)(onSessionCompleted);
|
|
1925
2484
|
onSessionCompletedRef.current = onSessionCompleted;
|
|
1926
|
-
(0,
|
|
2485
|
+
(0, import_react8.useEffect)(() => {
|
|
1927
2486
|
console.info("[FloPay] Checkout initialized", {
|
|
1928
|
-
sdk_version:
|
|
2487
|
+
sdk_version: import_shared7.SDK_VERSION,
|
|
1929
2488
|
checkout_type: checkoutType,
|
|
1930
2489
|
checkout_layout: checkoutLayout,
|
|
1931
2490
|
billing_api_url: resolvedBillingUrl
|
|
1932
2491
|
});
|
|
1933
2492
|
}, [checkoutLayout, checkoutType, resolvedBillingUrl]);
|
|
1934
|
-
const baseCreateSessionHash = (0,
|
|
2493
|
+
const baseCreateSessionHash = (0, import_react8.useMemo)(
|
|
1935
2494
|
() => createSessionParams ? hashCreateParams(createSessionParams) : "",
|
|
1936
2495
|
[createSessionParams]
|
|
1937
2496
|
);
|
|
1938
|
-
const activeCreateSessionPatch = (0,
|
|
2497
|
+
const activeCreateSessionPatch = (0, import_react8.useMemo)(
|
|
1939
2498
|
() => createSessionPatchBaseHash === baseCreateSessionHash ? createSessionPatch : void 0,
|
|
1940
2499
|
[createSessionPatch, createSessionPatchBaseHash, baseCreateSessionHash]
|
|
1941
2500
|
);
|
|
1942
|
-
const
|
|
2501
|
+
const effectiveCreateSessionBase = (0, import_react8.useMemo)(
|
|
1943
2502
|
() => createSessionParams ? mergeInlineSessionPatch(createSessionParams, activeCreateSessionPatch) : void 0,
|
|
1944
2503
|
[createSessionParams, activeCreateSessionPatch]
|
|
1945
2504
|
);
|
|
1946
|
-
|
|
2505
|
+
const effectiveCreateSessionMode = checkoutModeProp ?? effectiveCreateSessionBase?.checkoutMode ?? "full";
|
|
2506
|
+
const effectiveCreateSession = (0, import_react8.useMemo)(
|
|
2507
|
+
() => effectiveCreateSessionBase ? {
|
|
2508
|
+
...effectiveCreateSessionBase,
|
|
2509
|
+
checkoutMode: effectiveCreateSessionMode
|
|
2510
|
+
} : void 0,
|
|
2511
|
+
[effectiveCreateSessionBase, effectiveCreateSessionMode]
|
|
2512
|
+
);
|
|
2513
|
+
(0, import_react8.useEffect)(() => {
|
|
1947
2514
|
setCreateSessionPatch(void 0);
|
|
1948
2515
|
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
1949
2516
|
}, [baseCreateSessionHash]);
|
|
1950
|
-
const emitDecline = (0,
|
|
2517
|
+
const emitDecline = (0, import_react8.useCallback)(
|
|
1951
2518
|
(method, input, overrides) => {
|
|
1952
2519
|
onDeclineRef.current?.(buildDeclineEvent(method, input, overrides));
|
|
1953
2520
|
},
|
|
1954
2521
|
[]
|
|
1955
2522
|
);
|
|
1956
|
-
const
|
|
1957
|
-
async (sess) => {
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
tokenizedData: { id: void 0 },
|
|
1968
|
-
accountData: {
|
|
1969
|
-
userId: sess.customer?.id ?? "",
|
|
1970
|
-
email: sess.customer?.email ?? "",
|
|
1971
|
-
firstName: sess.customer?.firstName ?? "",
|
|
1972
|
-
lastName: sess.customer?.lastName ?? ""
|
|
1973
|
-
}
|
|
1974
|
-
})
|
|
1975
|
-
});
|
|
1976
|
-
if (response.ok) {
|
|
1977
|
-
onCompleteRef.current?.({ status: "succeeded" });
|
|
1978
|
-
return null;
|
|
1979
|
-
}
|
|
1980
|
-
const json = await response.json().catch(() => null);
|
|
1981
|
-
if ((json?.type === "paypal_redirect_required" || json?.type === "3ds_required") && json?.threeDSecureToken) {
|
|
1982
|
-
return {
|
|
1983
|
-
type: json.type,
|
|
1984
|
-
threeDSecureToken: json.threeDSecureToken,
|
|
1985
|
-
paymentMethodId: json.paymentMethodId
|
|
1986
|
-
};
|
|
1987
|
-
}
|
|
1988
|
-
if (json?.gatewayErrorCode === "authentication_required") {
|
|
1989
|
-
return {
|
|
1990
|
-
type: "3ds_required",
|
|
1991
|
-
threeDSecureToken: ""
|
|
1992
|
-
// No client secret available
|
|
1993
|
-
};
|
|
1994
|
-
}
|
|
1995
|
-
throw new import_shared6.FloPayError(
|
|
1996
|
-
json?.message ?? "Payment failed. Please try again.",
|
|
1997
|
-
"api_error",
|
|
1998
|
-
{
|
|
1999
|
-
code: json?.code ?? json?.gatewayErrorCode,
|
|
2000
|
-
declineCode: json?.declineCode ?? json?.gatewayDeclineReason
|
|
2001
|
-
}
|
|
2002
|
-
);
|
|
2003
|
-
},
|
|
2004
|
-
[resolvedBillingUrl, resolvedSessionId]
|
|
2005
|
-
);
|
|
2006
|
-
const handleRedirectResult = (0, import_react7.useCallback)(
|
|
2007
|
-
async (redirectResult, sess, options) => {
|
|
2008
|
-
const stripe = flopayRef.current?.getRawProvider();
|
|
2009
|
-
if (!stripe) return false;
|
|
2010
|
-
if (redirectResult.type === "3ds_required") {
|
|
2011
|
-
if (!options?.attempt3DS || !redirectResult.threeDSecureToken) {
|
|
2012
|
-
setModeError("Your card requires authentication. Please enter your payment details below.");
|
|
2013
|
-
return false;
|
|
2014
|
-
}
|
|
2015
|
-
const { error: nextActionError, paymentIntent } = await stripe.handleNextAction({
|
|
2016
|
-
clientSecret: redirectResult.threeDSecureToken
|
|
2523
|
+
const runSavedPaymentFlow = (0, import_react8.useCallback)(
|
|
2524
|
+
async (sess, options) => {
|
|
2525
|
+
setModeError(null);
|
|
2526
|
+
setModeOverlayError(null);
|
|
2527
|
+
setModeOverlayStatus("processing");
|
|
2528
|
+
const activeSessionId2 = options?.sessionId ?? sess.id;
|
|
2529
|
+
try {
|
|
2530
|
+
const result = await processSavedPaymentForMode({
|
|
2531
|
+
billingApiUrl: resolvedBillingUrl,
|
|
2532
|
+
sessionId: activeSessionId2,
|
|
2533
|
+
session: sess
|
|
2017
2534
|
});
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
if (paymentIntent && (paymentIntent.status === "requires_capture" || paymentIntent.status === "succeeded")) {
|
|
2026
|
-
onCompleteRef.current?.({ status: "succeeded", paymentIntentId: paymentIntent.id });
|
|
2027
|
-
return true;
|
|
2028
|
-
}
|
|
2029
|
-
return false;
|
|
2030
|
-
}
|
|
2031
|
-
if (redirectResult.type === "paypal_redirect_required") {
|
|
2032
|
-
const paypalStripe = paypalFlopayRef.current?.getRawProvider();
|
|
2033
|
-
if (!paypalStripe) {
|
|
2034
|
-
setModeError("PayPal is not available.");
|
|
2035
|
-
return false;
|
|
2036
|
-
}
|
|
2037
|
-
const confirmParams = {
|
|
2038
|
-
return_url: window.location.href
|
|
2039
|
-
};
|
|
2040
|
-
if (redirectResult.paymentMethodId) {
|
|
2041
|
-
confirmParams["payment_method"] = redirectResult.paymentMethodId;
|
|
2042
|
-
}
|
|
2043
|
-
const { error } = await paypalStripe.confirmPayment({
|
|
2044
|
-
clientSecret: redirectResult.threeDSecureToken,
|
|
2045
|
-
confirmParams,
|
|
2046
|
-
redirect: "if_required"
|
|
2535
|
+
const paymentResult = result.type === "success" ? result.result : await handleSavedPaymentRedirectResult(result, {
|
|
2536
|
+
flopay: flopayRef.current,
|
|
2537
|
+
paypalFlopay: paypalFlopayRef.current,
|
|
2538
|
+
attempt3DS: options?.attempt3DS,
|
|
2539
|
+
billingApiUrl: resolvedBillingUrl,
|
|
2540
|
+
sessionId: activeSessionId2,
|
|
2541
|
+
session: sess
|
|
2047
2542
|
});
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
code: error.code
|
|
2052
|
-
});
|
|
2053
|
-
return false;
|
|
2054
|
-
}
|
|
2055
|
-
onCompleteRef.current?.({ status: "succeeded" });
|
|
2543
|
+
setModeOverlayStatus("success");
|
|
2544
|
+
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
2545
|
+
onCompleteRef.current?.(paymentResult);
|
|
2056
2546
|
return true;
|
|
2547
|
+
} catch (err) {
|
|
2548
|
+
const floPayErr = normalizeSavedPaymentError(err);
|
|
2549
|
+
const method = floPayErr.checkoutMethod ?? DEFAULT_SAVED_PAYMENT_DECLINE_METHOD;
|
|
2550
|
+
setModeError(floPayErr.message);
|
|
2551
|
+
setModeOverlayError(floPayErr.message);
|
|
2552
|
+
if (options?.fallbackToFull) {
|
|
2553
|
+
setCurrentMode("full");
|
|
2554
|
+
}
|
|
2555
|
+
onErrorRef.current?.(floPayErr);
|
|
2556
|
+
emitDecline(method, floPayErr, {
|
|
2557
|
+
code: floPayErr.code,
|
|
2558
|
+
declineCode: floPayErr.declineCode
|
|
2559
|
+
});
|
|
2560
|
+
setModeOverlayStatus("error");
|
|
2561
|
+
await Promise.allSettled([
|
|
2562
|
+
sleep(PROCESSING_OVERLAY_ERROR_DELAY_MS),
|
|
2563
|
+
options?.ensureProvidersReady ? options.ensureProvidersReady() : Promise.resolve()
|
|
2564
|
+
]);
|
|
2565
|
+
return false;
|
|
2566
|
+
} finally {
|
|
2567
|
+
setModeOverlayStatus(null);
|
|
2568
|
+
setModeOverlayError(null);
|
|
2057
2569
|
}
|
|
2058
|
-
return false;
|
|
2059
2570
|
},
|
|
2060
|
-
[
|
|
2571
|
+
[
|
|
2572
|
+
emitDecline,
|
|
2573
|
+
normalizeSavedPaymentError,
|
|
2574
|
+
resolvedBillingUrl
|
|
2575
|
+
]
|
|
2061
2576
|
);
|
|
2062
|
-
const inflightRef = (0,
|
|
2063
|
-
const initializedHashRef = (0,
|
|
2577
|
+
const inflightRef = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
|
|
2578
|
+
const initializedHashRef = (0, import_react8.useRef)(null);
|
|
2064
2579
|
function hashCreateParams(params) {
|
|
2065
2580
|
const key = JSON.stringify({
|
|
2066
2581
|
c: params?.clientId,
|
|
@@ -2080,17 +2595,23 @@ function FloPayCheckout({
|
|
|
2080
2595
|
}
|
|
2081
2596
|
return `flopay_session_${Math.abs(h).toString(36)}`;
|
|
2082
2597
|
}
|
|
2083
|
-
const createSessionHash = (0,
|
|
2598
|
+
const createSessionHash = (0, import_react8.useMemo)(
|
|
2084
2599
|
() => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
|
|
2085
2600
|
[effectiveCreateSession]
|
|
2086
2601
|
);
|
|
2087
|
-
const createSessionParamsRef = (0,
|
|
2602
|
+
const createSessionParamsRef = (0, import_react8.useRef)(effectiveCreateSession);
|
|
2088
2603
|
createSessionParamsRef.current = effectiveCreateSession;
|
|
2089
|
-
(0,
|
|
2604
|
+
(0, import_react8.useEffect)(() => {
|
|
2090
2605
|
setResolvedSessionId(sessionIdProp ?? "");
|
|
2091
2606
|
}, [sessionIdProp]);
|
|
2607
|
+
(0, import_react8.useEffect)(() => {
|
|
2608
|
+
autoCheckoutAttempted.current = false;
|
|
2609
|
+
setModeError(null);
|
|
2610
|
+
setModeOverlayError(null);
|
|
2611
|
+
setModeOverlayStatus(null);
|
|
2612
|
+
}, [sessionIdProp, createSessionHash]);
|
|
2092
2613
|
async function resolveInlineSession(params, cacheKey) {
|
|
2093
|
-
const api = new
|
|
2614
|
+
const api = new import_js2.PaymentAPI(resolvedBillingUrl);
|
|
2094
2615
|
let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
|
|
2095
2616
|
let realResult = null;
|
|
2096
2617
|
if (sid) {
|
|
@@ -2115,11 +2636,11 @@ function FloPayCheckout({
|
|
|
2115
2636
|
}
|
|
2116
2637
|
return { sid: sid ?? "", result: realResult };
|
|
2117
2638
|
}
|
|
2118
|
-
const bootstrapInlineSession = (0,
|
|
2639
|
+
const bootstrapInlineSession = (0, import_react8.useCallback)(
|
|
2119
2640
|
async (patch) => {
|
|
2120
2641
|
const baseParams = createSessionParamsRef.current;
|
|
2121
2642
|
if (!baseParams) {
|
|
2122
|
-
throw new
|
|
2643
|
+
throw new import_shared7.FloPayError("createSession is required to bootstrap checkout.", "validation_error");
|
|
2123
2644
|
}
|
|
2124
2645
|
const mergedParams = mergeInlineSessionPatch(baseParams, patch);
|
|
2125
2646
|
const cacheKey = hashCreateParams(mergedParams);
|
|
@@ -2148,43 +2669,23 @@ function FloPayCheckout({
|
|
|
2148
2669
|
if (sid) {
|
|
2149
2670
|
setResolvedSessionId(sid);
|
|
2150
2671
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
}
|
|
2164
|
-
const needsSeparatePaypal = Boolean(paypalPublishableKey) && paypalPublishableKey !== publishableKey;
|
|
2165
|
-
const [instance, paypalInstanceOrError] = await Promise.all([
|
|
2166
|
-
(0, import_js.loadFloPay)(publishableKey, {
|
|
2167
|
-
billingApiUrl: resolvedBillingUrl,
|
|
2168
|
-
locale
|
|
2169
|
-
}),
|
|
2170
|
-
needsSeparatePaypal ? (0, import_js.loadFloPay)(paypalPublishableKey, {
|
|
2171
|
-
billingApiUrl: resolvedBillingUrl,
|
|
2172
|
-
locale
|
|
2173
|
-
}).catch((err) => {
|
|
2174
|
-
console.warn("[FloPay] Failed to load PayPal Stripe instance:", err);
|
|
2175
|
-
return null;
|
|
2176
|
-
}) : Promise.resolve(null)
|
|
2177
|
-
]);
|
|
2672
|
+
const {
|
|
2673
|
+
publishableKey,
|
|
2674
|
+
paypalPublishableKey
|
|
2675
|
+
} = resolveSavedPaymentPublishableKeys(realResult, fallbackPublishableKey);
|
|
2676
|
+
const {
|
|
2677
|
+
flopay: instance,
|
|
2678
|
+
paypalFlopay: paypalInstance
|
|
2679
|
+
} = await loadSavedPaymentProviders({
|
|
2680
|
+
publishableKey,
|
|
2681
|
+
paypalPublishableKey,
|
|
2682
|
+
billingApiUrl: resolvedBillingUrl,
|
|
2683
|
+
locale
|
|
2684
|
+
});
|
|
2178
2685
|
flopayRef.current = instance;
|
|
2179
2686
|
setFloPay(instance);
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
paypalFlopayRef.current = paypalInstance;
|
|
2183
|
-
setPaypalFloPay(paypalInstance);
|
|
2184
|
-
} else {
|
|
2185
|
-
paypalFlopayRef.current = null;
|
|
2186
|
-
setPaypalFloPay(null);
|
|
2187
|
-
}
|
|
2687
|
+
paypalFlopayRef.current = paypalInstance;
|
|
2688
|
+
setPaypalFloPay(paypalInstance);
|
|
2188
2689
|
setIsLoading(false);
|
|
2189
2690
|
} catch (err) {
|
|
2190
2691
|
if (initializedHashRef.current === cacheKey) {
|
|
@@ -2196,7 +2697,7 @@ function FloPayCheckout({
|
|
|
2196
2697
|
},
|
|
2197
2698
|
[fallbackPublishableKey, locale, resolvedBillingUrl]
|
|
2198
2699
|
);
|
|
2199
|
-
const handleInlineSessionPatch = (0,
|
|
2700
|
+
const handleInlineSessionPatch = (0, import_react8.useCallback)(async (patch) => {
|
|
2200
2701
|
if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) {
|
|
2201
2702
|
return {
|
|
2202
2703
|
sessionId: resolvedSessionId,
|
|
@@ -2219,21 +2720,61 @@ function FloPayCheckout({
|
|
|
2219
2720
|
resolvedSessionId,
|
|
2220
2721
|
session
|
|
2221
2722
|
]);
|
|
2222
|
-
(0,
|
|
2723
|
+
(0, import_react8.useEffect)(() => {
|
|
2223
2724
|
let cancelled = false;
|
|
2224
2725
|
setLoadError(null);
|
|
2225
2726
|
if (createSessionHash) {
|
|
2226
|
-
if (initializedHashRef.current === createSessionHash) return;
|
|
2227
2727
|
const params = createSessionParamsRef.current;
|
|
2228
2728
|
setSession(buildSyntheticSession(params, checkoutModeProp));
|
|
2229
|
-
setCurrentMode(
|
|
2729
|
+
setCurrentMode(effectiveCreateSessionMode);
|
|
2230
2730
|
setIsLoading(false);
|
|
2731
|
+
if (initializedHashRef.current === createSessionHash) {
|
|
2732
|
+
return () => {
|
|
2733
|
+
cancelled = true;
|
|
2734
|
+
};
|
|
2735
|
+
}
|
|
2231
2736
|
(async () => {
|
|
2737
|
+
const shouldAutoProcessInlineSession = effectiveCreateSessionMode === "auto" && !autoCheckoutAttempted.current;
|
|
2738
|
+
if (shouldAutoProcessInlineSession) {
|
|
2739
|
+
setModeError(null);
|
|
2740
|
+
setModeOverlayError(null);
|
|
2741
|
+
setModeOverlayStatus("processing");
|
|
2742
|
+
}
|
|
2232
2743
|
try {
|
|
2233
|
-
await bootstrapInlineSession();
|
|
2744
|
+
const resolved = await bootstrapInlineSession();
|
|
2745
|
+
const resolvedSession = resolved.result.data.session ?? null;
|
|
2746
|
+
if (!cancelled && shouldAutoProcessInlineSession && resolvedSession) {
|
|
2747
|
+
autoCheckoutAttempted.current = true;
|
|
2748
|
+
await runSavedPaymentFlow(resolvedSession, {
|
|
2749
|
+
attempt3DS: true,
|
|
2750
|
+
fallbackToFull: true,
|
|
2751
|
+
sessionId: resolved.sid || resolvedSession.id
|
|
2752
|
+
});
|
|
2753
|
+
return;
|
|
2754
|
+
}
|
|
2755
|
+
if (!cancelled && shouldAutoProcessInlineSession) {
|
|
2756
|
+
setModeOverlayStatus(null);
|
|
2757
|
+
setModeOverlayError(null);
|
|
2758
|
+
}
|
|
2234
2759
|
} catch (err) {
|
|
2235
2760
|
if (cancelled) return;
|
|
2236
|
-
const
|
|
2761
|
+
const errorCode = err instanceof import_shared7.FloPayError ? err.code : typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
|
|
2762
|
+
if (shouldAutoProcessInlineSession && errorCode === "session_auto_completed") {
|
|
2763
|
+
autoCheckoutAttempted.current = true;
|
|
2764
|
+
setModeOverlayStatus("success");
|
|
2765
|
+
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
2766
|
+
if (!cancelled) {
|
|
2767
|
+
onCompleteRef.current?.({ status: "succeeded" });
|
|
2768
|
+
setModeOverlayStatus(null);
|
|
2769
|
+
setModeOverlayError(null);
|
|
2770
|
+
}
|
|
2771
|
+
return;
|
|
2772
|
+
}
|
|
2773
|
+
if (shouldAutoProcessInlineSession) {
|
|
2774
|
+
setModeOverlayStatus(null);
|
|
2775
|
+
setModeOverlayError(null);
|
|
2776
|
+
}
|
|
2777
|
+
const floPayErr = err instanceof import_shared7.FloPayError ? err : new import_shared7.FloPayError(err instanceof Error ? err.message : "Failed to create session", "api_error");
|
|
2237
2778
|
setLoadError(floPayErr);
|
|
2238
2779
|
}
|
|
2239
2780
|
})();
|
|
@@ -2244,14 +2785,14 @@ function FloPayCheckout({
|
|
|
2244
2785
|
setIsLoading(true);
|
|
2245
2786
|
async function init() {
|
|
2246
2787
|
try {
|
|
2247
|
-
const api = new
|
|
2248
|
-
const result = await api.getUnifiedCheckoutSession(
|
|
2788
|
+
const api = new import_js2.PaymentAPI(resolvedBillingUrl);
|
|
2789
|
+
const result = await api.getUnifiedCheckoutSession(activeSessionId);
|
|
2249
2790
|
if (cancelled) return;
|
|
2250
2791
|
setUnified(result);
|
|
2251
2792
|
const sess = result.data.session ?? null;
|
|
2252
2793
|
setSession(sess);
|
|
2253
2794
|
if (!sess) {
|
|
2254
|
-
throw new
|
|
2795
|
+
throw new import_shared7.FloPayError("No session data returned", "api_error");
|
|
2255
2796
|
}
|
|
2256
2797
|
if (sess.status === "complete") {
|
|
2257
2798
|
setIsLoading(false);
|
|
@@ -2265,22 +2806,20 @@ function FloPayCheckout({
|
|
|
2265
2806
|
autoCheckoutAttempted.current = true;
|
|
2266
2807
|
const stripeInitPromise = initStripe(result);
|
|
2267
2808
|
try {
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2809
|
+
await runSavedPaymentFlow(sess, {
|
|
2810
|
+
attempt3DS: true,
|
|
2811
|
+
fallbackToFull: true,
|
|
2812
|
+
ensureProvidersReady: () => stripeInitPromise,
|
|
2813
|
+
sessionId: activeSessionId || sess.id
|
|
2814
|
+
});
|
|
2273
2815
|
if (cancelled) return;
|
|
2274
2816
|
await stripeInitPromise;
|
|
2275
|
-
const handled = await handleRedirectResult(redirectResult, sess, { attempt3DS: true });
|
|
2276
2817
|
if (!cancelled) {
|
|
2277
|
-
if (!handled) setCurrentMode("full");
|
|
2278
2818
|
setIsLoading(false);
|
|
2279
2819
|
}
|
|
2280
2820
|
return;
|
|
2281
2821
|
} catch {
|
|
2282
2822
|
if (cancelled) return;
|
|
2283
|
-
setCurrentMode("full");
|
|
2284
2823
|
await stripeInitPromise;
|
|
2285
2824
|
if (!cancelled) setIsLoading(false);
|
|
2286
2825
|
return;
|
|
@@ -2290,82 +2829,56 @@ function FloPayCheckout({
|
|
|
2290
2829
|
if (!cancelled) setIsLoading(false);
|
|
2291
2830
|
} catch (err) {
|
|
2292
2831
|
if (cancelled) return;
|
|
2293
|
-
const floPayErr = err instanceof
|
|
2832
|
+
const floPayErr = err instanceof import_shared7.FloPayError ? err : new import_shared7.FloPayError(err instanceof Error ? err.message : "Failed to initialize checkout", "api_error");
|
|
2294
2833
|
setLoadError(floPayErr);
|
|
2295
2834
|
setIsLoading(false);
|
|
2296
2835
|
}
|
|
2297
2836
|
}
|
|
2298
2837
|
async function initStripe(result) {
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
}
|
|
2312
|
-
const needsSeparatePaypal = Boolean(paypalPublishableKey) && paypalPublishableKey !== publishableKey;
|
|
2313
|
-
const [instance, paypalInstanceOrError] = await Promise.all([
|
|
2314
|
-
(0, import_js.loadFloPay)(publishableKey, {
|
|
2315
|
-
billingApiUrl: resolvedBillingUrl,
|
|
2316
|
-
locale
|
|
2317
|
-
}),
|
|
2318
|
-
needsSeparatePaypal ? (0, import_js.loadFloPay)(paypalPublishableKey, {
|
|
2319
|
-
billingApiUrl: resolvedBillingUrl,
|
|
2320
|
-
locale
|
|
2321
|
-
}).catch((err) => {
|
|
2322
|
-
console.warn("[FloPay] Failed to load PayPal Stripe instance:", err);
|
|
2323
|
-
return null;
|
|
2324
|
-
}) : Promise.resolve(null)
|
|
2325
|
-
]);
|
|
2838
|
+
const {
|
|
2839
|
+
publishableKey,
|
|
2840
|
+
paypalPublishableKey
|
|
2841
|
+
} = resolveSavedPaymentPublishableKeys(result, fallbackPublishableKey);
|
|
2842
|
+
const {
|
|
2843
|
+
flopay: instance,
|
|
2844
|
+
paypalFlopay: paypalInstance
|
|
2845
|
+
} = await loadSavedPaymentProviders({
|
|
2846
|
+
publishableKey,
|
|
2847
|
+
paypalPublishableKey,
|
|
2848
|
+
billingApiUrl: resolvedBillingUrl,
|
|
2849
|
+
locale
|
|
2850
|
+
});
|
|
2326
2851
|
flopayRef.current = instance;
|
|
2327
2852
|
setFloPay(instance);
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
paypalFlopayRef.current = paypalInstance;
|
|
2331
|
-
setPaypalFloPay(paypalInstance);
|
|
2332
|
-
} else {
|
|
2333
|
-
paypalFlopayRef.current = null;
|
|
2334
|
-
setPaypalFloPay(null);
|
|
2335
|
-
}
|
|
2853
|
+
paypalFlopayRef.current = paypalInstance;
|
|
2854
|
+
setPaypalFloPay(paypalInstance);
|
|
2336
2855
|
}
|
|
2337
2856
|
init();
|
|
2338
2857
|
return () => {
|
|
2339
2858
|
cancelled = true;
|
|
2340
2859
|
};
|
|
2341
|
-
}, [
|
|
2342
|
-
|
|
2860
|
+
}, [
|
|
2861
|
+
bootstrapInlineSession,
|
|
2862
|
+
checkoutModeProp,
|
|
2863
|
+
createSessionHash,
|
|
2864
|
+
effectiveCreateSessionMode,
|
|
2865
|
+
initSessionDependency,
|
|
2866
|
+
runSavedPaymentFlow
|
|
2867
|
+
]);
|
|
2868
|
+
const handleConfirmCheckout = (0, import_react8.useCallback)(async () => {
|
|
2343
2869
|
if (confirmProcessing || !session) return;
|
|
2344
2870
|
setConfirmProcessing(true);
|
|
2345
2871
|
setModeError(null);
|
|
2346
2872
|
try {
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
}
|
|
2351
|
-
const handled = await handleRedirectResult(redirectResult, session);
|
|
2352
|
-
if (!handled) {
|
|
2353
|
-
setCurrentMode("full");
|
|
2354
|
-
}
|
|
2355
|
-
} catch (err) {
|
|
2356
|
-
const floPayErr = err instanceof import_shared6.FloPayError ? err : new import_shared6.FloPayError(
|
|
2357
|
-
err instanceof Error ? err.message : "Payment failed",
|
|
2358
|
-
"api_error"
|
|
2359
|
-
);
|
|
2360
|
-
setModeError(floPayErr.message);
|
|
2361
|
-
onError?.(floPayErr);
|
|
2362
|
-
emitDecline("card", floPayErr);
|
|
2363
|
-
setCurrentMode("full");
|
|
2873
|
+
await runSavedPaymentFlow(session, {
|
|
2874
|
+
fallbackToFull: true,
|
|
2875
|
+
sessionId: activeSessionId || session.id
|
|
2876
|
+
});
|
|
2364
2877
|
} finally {
|
|
2365
2878
|
setConfirmProcessing(false);
|
|
2366
2879
|
}
|
|
2367
|
-
}, [
|
|
2368
|
-
const providerOptions = (0,
|
|
2880
|
+
}, [activeSessionId, confirmProcessing, runSavedPaymentFlow, session]);
|
|
2881
|
+
const providerOptions = (0, import_react8.useMemo)(() => {
|
|
2369
2882
|
if (!unified || !session) return void 0;
|
|
2370
2883
|
const opts = {
|
|
2371
2884
|
appearance,
|
|
@@ -2375,16 +2888,16 @@ function FloPayCheckout({
|
|
|
2375
2888
|
if (unified.provider === "stripe" && unified.data.stripe?.clientSecret) {
|
|
2376
2889
|
opts.clientSecret = unified.data.stripe.clientSecret;
|
|
2377
2890
|
} else {
|
|
2378
|
-
const displayTotal = (0,
|
|
2891
|
+
const displayTotal = (0, import_shared7.buildCheckoutDisplayData)(session).total;
|
|
2379
2892
|
opts.amount = Math.round(displayTotal * 100) || session.amount;
|
|
2380
2893
|
opts.currency = session.currency?.toLowerCase();
|
|
2381
2894
|
}
|
|
2382
2895
|
return opts;
|
|
2383
2896
|
}, [unified, session, appearance, resolvedBillingUrl]);
|
|
2384
2897
|
const shouldHandleInlineSessionPatch = Boolean(
|
|
2385
|
-
createSessionParams && !children && layout === "buttons" && onBeforeButtonClick &&
|
|
2898
|
+
createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && effectiveCreateSessionMode === "full"
|
|
2386
2899
|
);
|
|
2387
|
-
const checkoutValue = (0,
|
|
2900
|
+
const checkoutValue = (0, import_react8.useMemo)(
|
|
2388
2901
|
() => ({
|
|
2389
2902
|
session,
|
|
2390
2903
|
loading: isLoading,
|
|
@@ -2406,37 +2919,55 @@ function FloPayCheckout({
|
|
|
2406
2919
|
]
|
|
2407
2920
|
);
|
|
2408
2921
|
const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && (!flopay || !providerOptions);
|
|
2922
|
+
const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2923
|
+
ProcessingOverlay,
|
|
2924
|
+
{
|
|
2925
|
+
status: modeOverlayStatus,
|
|
2926
|
+
errorMessage: modeOverlayError
|
|
2927
|
+
}
|
|
2928
|
+
) : null;
|
|
2409
2929
|
if (isLoading) {
|
|
2410
|
-
if (loadingNode)
|
|
2930
|
+
if (loadingNode) {
|
|
2931
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2932
|
+
loadingNode,
|
|
2933
|
+
modeOverlay
|
|
2934
|
+
] });
|
|
2935
|
+
}
|
|
2411
2936
|
if (layout === "buttons") {
|
|
2412
|
-
const skeletonBar = (h) => /* @__PURE__ */ (0,
|
|
2937
|
+
const skeletonBar = (h) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2413
2938
|
height: h,
|
|
2414
2939
|
borderRadius: 8,
|
|
2415
2940
|
background: "#e5e7eb",
|
|
2416
2941
|
animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
|
|
2417
2942
|
} });
|
|
2418
|
-
return /* @__PURE__ */ (0,
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2944
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
2945
|
+
showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
2946
|
+
(showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
2947
|
+
skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
2948
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
2949
|
+
] }),
|
|
2950
|
+
modeOverlay
|
|
2423
2951
|
] });
|
|
2424
2952
|
}
|
|
2425
|
-
return /* @__PURE__ */ (0,
|
|
2426
|
-
/* @__PURE__ */ (0,
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2953
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2954
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
|
|
2955
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2956
|
+
width: 24,
|
|
2957
|
+
height: 24,
|
|
2958
|
+
border: "2px solid #e5e7eb",
|
|
2959
|
+
borderTopColor: "#6b7280",
|
|
2960
|
+
borderRadius: "50%",
|
|
2961
|
+
animation: "spin 0.6s linear infinite"
|
|
2962
|
+
} }),
|
|
2963
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
2964
|
+
] }),
|
|
2965
|
+
modeOverlay
|
|
2435
2966
|
] });
|
|
2436
2967
|
}
|
|
2437
2968
|
if (loadError) {
|
|
2438
|
-
if (errorNode) return /* @__PURE__ */ (0,
|
|
2439
|
-
return /* @__PURE__ */ (0,
|
|
2969
|
+
if (errorNode) return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: errorNode(loadError) });
|
|
2970
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2440
2971
|
"div",
|
|
2441
2972
|
{
|
|
2442
2973
|
style: {
|
|
@@ -2450,99 +2981,111 @@ function FloPayCheckout({
|
|
|
2450
2981
|
);
|
|
2451
2982
|
}
|
|
2452
2983
|
if (shouldShowInterimButtons) {
|
|
2453
|
-
return /* @__PURE__ */ (0,
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2984
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2985
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2986
|
+
InterimButtonsView,
|
|
2987
|
+
{
|
|
2988
|
+
onButtonClick,
|
|
2989
|
+
showPayPal,
|
|
2990
|
+
showApplePay,
|
|
2991
|
+
showGooglePay,
|
|
2992
|
+
buttonsTheme,
|
|
2993
|
+
buttonsStyles,
|
|
2994
|
+
cardButtonContent,
|
|
2995
|
+
cardBackButtonContent,
|
|
2996
|
+
cardTitleContent
|
|
2997
|
+
}
|
|
2998
|
+
) }),
|
|
2999
|
+
modeOverlay
|
|
3000
|
+
] });
|
|
3001
|
+
}
|
|
3002
|
+
if (!flopay || !providerOptions) {
|
|
3003
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: modeOverlay });
|
|
2467
3004
|
}
|
|
2468
|
-
if (!flopay || !providerOptions) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, {});
|
|
2469
3005
|
if (currentMode === "confirm") {
|
|
2470
|
-
return /* @__PURE__ */ (0,
|
|
2471
|
-
|
|
3006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
3007
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className, children: [
|
|
3008
|
+
modeError && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3009
|
+
"div",
|
|
3010
|
+
{
|
|
3011
|
+
style: {
|
|
3012
|
+
color: "#dc2626",
|
|
3013
|
+
fontSize: "0.875rem",
|
|
3014
|
+
marginBottom: "0.75rem",
|
|
3015
|
+
textAlign: "center"
|
|
3016
|
+
},
|
|
3017
|
+
children: modeError
|
|
3018
|
+
}
|
|
3019
|
+
),
|
|
3020
|
+
renderConfirmButton ? renderConfirmButton({
|
|
3021
|
+
onConfirm: handleConfirmCheckout,
|
|
3022
|
+
isProcessing: confirmProcessing
|
|
3023
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3024
|
+
"button",
|
|
3025
|
+
{
|
|
3026
|
+
type: "button",
|
|
3027
|
+
onClick: handleConfirmCheckout,
|
|
3028
|
+
disabled: confirmProcessing,
|
|
3029
|
+
style: {
|
|
3030
|
+
width: "100%",
|
|
3031
|
+
padding: "0.875rem",
|
|
3032
|
+
backgroundColor: "#4A49FF",
|
|
3033
|
+
color: "white",
|
|
3034
|
+
border: "none",
|
|
3035
|
+
borderRadius: "8px",
|
|
3036
|
+
fontSize: "1rem",
|
|
3037
|
+
fontWeight: 600,
|
|
3038
|
+
cursor: confirmProcessing ? "not-allowed" : "pointer",
|
|
3039
|
+
opacity: confirmProcessing ? 0.6 : 1
|
|
3040
|
+
},
|
|
3041
|
+
children: confirmProcessing ? "Processing..." : confirmLabel ?? "Confirm Purchase"
|
|
3042
|
+
}
|
|
3043
|
+
)
|
|
3044
|
+
] }) }) }),
|
|
3045
|
+
modeOverlay
|
|
3046
|
+
] });
|
|
3047
|
+
}
|
|
3048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
3049
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
3050
|
+
modeError && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2472
3051
|
"div",
|
|
2473
3052
|
{
|
|
2474
3053
|
style: {
|
|
2475
|
-
|
|
2476
|
-
fontSize: "0.875rem",
|
|
3054
|
+
padding: "0.75rem 1rem",
|
|
2477
3055
|
marginBottom: "0.75rem",
|
|
2478
|
-
|
|
3056
|
+
backgroundColor: "#FEF3C7",
|
|
3057
|
+
border: "1px solid #F59E0B",
|
|
3058
|
+
borderRadius: "8px",
|
|
3059
|
+
color: "#92400E",
|
|
3060
|
+
fontSize: "0.875rem"
|
|
2479
3061
|
},
|
|
2480
3062
|
children: modeError
|
|
2481
3063
|
}
|
|
2482
3064
|
),
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
isProcessing: confirmProcessing
|
|
2486
|
-
}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2487
|
-
"button",
|
|
3065
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3066
|
+
SessionInjector,
|
|
2488
3067
|
{
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
width: "100%",
|
|
2494
|
-
padding: "0.875rem",
|
|
2495
|
-
backgroundColor: "#4A49FF",
|
|
2496
|
-
color: "white",
|
|
2497
|
-
border: "none",
|
|
2498
|
-
borderRadius: "8px",
|
|
2499
|
-
fontSize: "1rem",
|
|
2500
|
-
fontWeight: 600,
|
|
2501
|
-
cursor: confirmProcessing ? "not-allowed" : "pointer",
|
|
2502
|
-
opacity: confirmProcessing ? 0.6 : 1
|
|
2503
|
-
},
|
|
2504
|
-
children: confirmProcessing ? "Processing..." : confirmLabel ?? "Confirm Purchase"
|
|
3068
|
+
sessionId: activeSessionId,
|
|
3069
|
+
billingApiUrl: resolvedBillingUrl,
|
|
3070
|
+
session,
|
|
3071
|
+
children
|
|
2505
3072
|
}
|
|
2506
3073
|
)
|
|
2507
|
-
] })
|
|
2508
|
-
}
|
|
2509
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: [
|
|
2510
|
-
modeError && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2511
|
-
"div",
|
|
2512
|
-
{
|
|
2513
|
-
style: {
|
|
2514
|
-
padding: "0.75rem 1rem",
|
|
2515
|
-
marginBottom: "0.75rem",
|
|
2516
|
-
backgroundColor: "#FEF3C7",
|
|
2517
|
-
border: "1px solid #F59E0B",
|
|
2518
|
-
borderRadius: "8px",
|
|
2519
|
-
color: "#92400E",
|
|
2520
|
-
fontSize: "0.875rem"
|
|
2521
|
-
},
|
|
2522
|
-
children: modeError
|
|
2523
|
-
}
|
|
2524
|
-
),
|
|
2525
|
-
children ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2526
|
-
SessionInjector,
|
|
2527
|
-
{
|
|
2528
|
-
sessionId: resolvedSessionId,
|
|
2529
|
-
billingApiUrl: resolvedBillingUrl,
|
|
2530
|
-
session,
|
|
2531
|
-
children
|
|
2532
|
-
}
|
|
2533
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3074
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2534
3075
|
SplitCardForm,
|
|
2535
3076
|
{
|
|
2536
|
-
sessionId:
|
|
3077
|
+
sessionId: activeSessionId,
|
|
2537
3078
|
email: session?.customer?.email,
|
|
2538
3079
|
userId: session?.customer?.id,
|
|
2539
3080
|
firstName: session?.customer?.firstName,
|
|
2540
3081
|
lastName: session?.customer?.lastName,
|
|
2541
|
-
totalAmount: session ? Math.round((0,
|
|
3082
|
+
totalAmount: session ? Math.round((0, import_shared7.buildCheckoutDisplayData)(session).total * 100) : 0,
|
|
2542
3083
|
currency: session?.currency?.toLowerCase() ?? "usd",
|
|
2543
3084
|
onComplete,
|
|
2544
3085
|
onError,
|
|
2545
3086
|
onDecline,
|
|
3087
|
+
error: modeError,
|
|
3088
|
+
onErrorChange: setModeError,
|
|
2546
3089
|
onFullNameChange,
|
|
2547
3090
|
showPayPal,
|
|
2548
3091
|
showApplePay,
|
|
@@ -2553,6 +3096,7 @@ function FloPayCheckout({
|
|
|
2553
3096
|
cardButtonContent,
|
|
2554
3097
|
cardBackButtonContent,
|
|
2555
3098
|
cardTitleContent,
|
|
3099
|
+
showSecurityFooter,
|
|
2556
3100
|
onButtonClick,
|
|
2557
3101
|
onBeforeButtonClick,
|
|
2558
3102
|
enableAVS,
|
|
@@ -2563,8 +3107,9 @@ function FloPayCheckout({
|
|
|
2563
3107
|
submitLabel,
|
|
2564
3108
|
className
|
|
2565
3109
|
}
|
|
2566
|
-
)
|
|
2567
|
-
|
|
3110
|
+
) }) }),
|
|
3111
|
+
modeOverlay
|
|
3112
|
+
] });
|
|
2568
3113
|
}
|
|
2569
3114
|
function SessionInjector({
|
|
2570
3115
|
sessionId,
|
|
@@ -2572,8 +3117,8 @@ function SessionInjector({
|
|
|
2572
3117
|
session,
|
|
2573
3118
|
children
|
|
2574
3119
|
}) {
|
|
2575
|
-
return /* @__PURE__ */ (0,
|
|
2576
|
-
if (!
|
|
3120
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: import_react8.default.Children.map(children, (child) => {
|
|
3121
|
+
if (!import_react8.default.isValidElement(child)) return child;
|
|
2577
3122
|
const existing = child.props;
|
|
2578
3123
|
const injected = {};
|
|
2579
3124
|
if (!existing.sessionId) injected.sessionId = sessionId;
|
|
@@ -2587,7 +3132,7 @@ function SessionInjector({
|
|
|
2587
3132
|
injected.lastName = session.customer.lastName;
|
|
2588
3133
|
}
|
|
2589
3134
|
if (Object.keys(injected).length === 0) return child;
|
|
2590
|
-
return
|
|
3135
|
+
return import_react8.default.cloneElement(child, injected);
|
|
2591
3136
|
}) });
|
|
2592
3137
|
}
|
|
2593
3138
|
function InterimButtonsView({
|
|
@@ -2605,15 +3150,15 @@ function InterimButtonsView({
|
|
|
2605
3150
|
cardBackButtonContent,
|
|
2606
3151
|
cardTitleContent
|
|
2607
3152
|
}) {
|
|
2608
|
-
const [showCardForm, setShowCardForm] = (0,
|
|
3153
|
+
const [showCardForm, setShowCardForm] = (0, import_react8.useState)(false);
|
|
2609
3154
|
const isCardOpenControlled = typeof cardOpen === "boolean";
|
|
2610
|
-
(0,
|
|
3155
|
+
(0, import_react8.useEffect)(() => {
|
|
2611
3156
|
if (isCardOpenControlled) {
|
|
2612
3157
|
setShowCardForm(cardOpen);
|
|
2613
3158
|
}
|
|
2614
3159
|
}, [cardOpen, isCardOpenControlled]);
|
|
2615
|
-
const bStyles = (0,
|
|
2616
|
-
const base = (0,
|
|
3160
|
+
const bStyles = (0, import_react8.useMemo)(() => {
|
|
3161
|
+
const base = (0, import_shared7.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
2617
3162
|
if (!stylesOverride) return base;
|
|
2618
3163
|
return {
|
|
2619
3164
|
...base,
|
|
@@ -2626,7 +3171,7 @@ function InterimButtonsView({
|
|
|
2626
3171
|
title: { ...base.title, ...stylesOverride.title }
|
|
2627
3172
|
};
|
|
2628
3173
|
}, [buttonsTheme, stylesOverride]);
|
|
2629
|
-
const skeleton = (h) => /* @__PURE__ */ (0,
|
|
3174
|
+
const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2630
3175
|
height: h,
|
|
2631
3176
|
borderRadius: 8,
|
|
2632
3177
|
background: "#e5e7eb",
|
|
@@ -2638,15 +3183,15 @@ function InterimButtonsView({
|
|
|
2638
3183
|
const inputBg = bStyles.cardInputBackground ?? "white";
|
|
2639
3184
|
const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
|
|
2640
3185
|
const hideTitle = isEmptySlotContent(cardTitleContent);
|
|
2641
|
-
return /* @__PURE__ */ (0,
|
|
3186
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
|
|
2642
3187
|
backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
|
|
2643
3188
|
borderRadius: "8px",
|
|
2644
3189
|
animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
|
|
2645
3190
|
overflow: "hidden",
|
|
2646
3191
|
...bStyles.cardFormContainer
|
|
2647
3192
|
}, children: [
|
|
2648
|
-
/* @__PURE__ */ (0,
|
|
2649
|
-
/* @__PURE__ */ (0,
|
|
3193
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
|
|
3194
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2650
3195
|
"button",
|
|
2651
3196
|
{
|
|
2652
3197
|
type: "button",
|
|
@@ -2673,7 +3218,7 @@ function InterimButtonsView({
|
|
|
2673
3218
|
...bStyles.backButton
|
|
2674
3219
|
},
|
|
2675
3220
|
children: [
|
|
2676
|
-
/* @__PURE__ */ (0,
|
|
3221
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: {
|
|
2677
3222
|
display: "inline-flex",
|
|
2678
3223
|
alignItems: "center",
|
|
2679
3224
|
justifyContent: "center",
|
|
@@ -2682,12 +3227,12 @@ function InterimButtonsView({
|
|
|
2682
3227
|
borderRadius: "50%",
|
|
2683
3228
|
backgroundColor: "#f3f4f6",
|
|
2684
3229
|
...bStyles.backButtonIcon
|
|
2685
|
-
}, children: /* @__PURE__ */ (0,
|
|
2686
|
-
/* @__PURE__ */ (0,
|
|
3230
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.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_runtime6.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
3231
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
2687
3232
|
]
|
|
2688
3233
|
}
|
|
2689
3234
|
),
|
|
2690
|
-
hideTitle ? /* @__PURE__ */ (0,
|
|
3235
|
+
hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2691
3236
|
flex: 1,
|
|
2692
3237
|
textAlign: "center",
|
|
2693
3238
|
fontWeight: 600,
|
|
@@ -2695,15 +3240,15 @@ function InterimButtonsView({
|
|
|
2695
3240
|
color: "#262833",
|
|
2696
3241
|
paddingRight: 80,
|
|
2697
3242
|
...bStyles.title
|
|
2698
|
-
}, children: /* @__PURE__ */ (0,
|
|
3243
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TitleContentSlot, { content: cardTitleContent }) })
|
|
2699
3244
|
] }),
|
|
2700
|
-
/* @__PURE__ */ (0,
|
|
2701
|
-
/* @__PURE__ */ (0,
|
|
2702
|
-
/* @__PURE__ */ (0,
|
|
2703
|
-
/* @__PURE__ */ (0,
|
|
3245
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
3246
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex" }, children: [
|
|
3247
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1, backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTop: "none", borderRight: "none", borderBottomLeftRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
3248
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1, backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTop: "none", borderBottomRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
|
|
2704
3249
|
] }),
|
|
2705
|
-
/* @__PURE__ */ (0,
|
|
2706
|
-
/* @__PURE__ */ (0,
|
|
3250
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
3251
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2707
3252
|
height: 50,
|
|
2708
3253
|
borderRadius: 8,
|
|
2709
3254
|
marginTop: 16,
|
|
@@ -2712,7 +3257,7 @@ function InterimButtonsView({
|
|
|
2712
3257
|
...bStyles.submitButton,
|
|
2713
3258
|
opacity: 0.5
|
|
2714
3259
|
} }),
|
|
2715
|
-
/* @__PURE__ */ (0,
|
|
3260
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `
|
|
2716
3261
|
@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
2717
3262
|
@keyframes flopay-interim-expand {
|
|
2718
3263
|
0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
|
|
@@ -2722,10 +3267,10 @@ function InterimButtonsView({
|
|
|
2722
3267
|
` })
|
|
2723
3268
|
] });
|
|
2724
3269
|
}
|
|
2725
|
-
return /* @__PURE__ */ (0,
|
|
3270
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
2726
3271
|
showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
2727
3272
|
(showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
2728
|
-
/* @__PURE__ */ (0,
|
|
3273
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2729
3274
|
"button",
|
|
2730
3275
|
{
|
|
2731
3276
|
type: "button",
|
|
@@ -2765,10 +3310,10 @@ function InterimButtonsView({
|
|
|
2765
3310
|
onMouseUp: (e) => {
|
|
2766
3311
|
e.currentTarget.style.transform = "scale(1)";
|
|
2767
3312
|
},
|
|
2768
|
-
children: /* @__PURE__ */ (0,
|
|
3313
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardButtonContentSlot, { content: cardButtonContent })
|
|
2769
3314
|
}
|
|
2770
3315
|
),
|
|
2771
|
-
errorMessage && /* @__PURE__ */ (0,
|
|
3316
|
+
errorMessage && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
|
|
2772
3317
|
margin: "0.25rem 0",
|
|
2773
3318
|
padding: "0.625rem 0.875rem",
|
|
2774
3319
|
background: "#FEF2F2",
|
|
@@ -2782,21 +3327,21 @@ function InterimButtonsView({
|
|
|
2782
3327
|
gap: "0.5rem",
|
|
2783
3328
|
...bStyles.errorBanner
|
|
2784
3329
|
}, children: [
|
|
2785
|
-
/* @__PURE__ */ (0,
|
|
3330
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.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" }) }),
|
|
2786
3331
|
errorMessage
|
|
2787
3332
|
] }),
|
|
2788
|
-
/* @__PURE__ */ (0,
|
|
3333
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
2789
3334
|
] });
|
|
2790
3335
|
}
|
|
2791
3336
|
|
|
2792
3337
|
// src/checkout-form.tsx
|
|
2793
|
-
var
|
|
2794
|
-
var
|
|
2795
|
-
var
|
|
3338
|
+
var import_shared8 = require("@flopay/shared");
|
|
3339
|
+
var import_react9 = require("react");
|
|
3340
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2796
3341
|
var WALLET_RESUME_KEY2 = "flopay_wallet_resume";
|
|
2797
|
-
var CheckoutForm = (0,
|
|
3342
|
+
var CheckoutForm = (0, import_react9.forwardRef)(
|
|
2798
3343
|
function CheckoutForm2(props, ref) {
|
|
2799
|
-
return /* @__PURE__ */ (0,
|
|
3344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutFormInner, { ...props, innerRef: ref });
|
|
2800
3345
|
}
|
|
2801
3346
|
);
|
|
2802
3347
|
function CheckoutFormInner({
|
|
@@ -2825,27 +3370,27 @@ function CheckoutFormInner({
|
|
|
2825
3370
|
const paypalFlopay = usePayPalFloPay();
|
|
2826
3371
|
const elements = useElements();
|
|
2827
3372
|
const contextBillingUrl = useBillingApiUrl();
|
|
2828
|
-
const [processing, setProcessing] = (0,
|
|
2829
|
-
const [error, setError] = (0,
|
|
2830
|
-
const [is3DSActive, setIs3DSActive] = (0,
|
|
3373
|
+
const [processing, setProcessing] = (0, import_react9.useState)(false);
|
|
3374
|
+
const [error, setError] = (0, import_react9.useState)(null);
|
|
3375
|
+
const [is3DSActive, setIs3DSActive] = (0, import_react9.useState)(false);
|
|
2831
3376
|
const displayError = externalError ?? error;
|
|
2832
3377
|
const isSubmitting = externalProcessing ?? processing;
|
|
2833
3378
|
const isSelfContained = !onTokenizedBody;
|
|
2834
3379
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
2835
|
-
const updateError = (0,
|
|
3380
|
+
const updateError = (0, import_react9.useCallback)(
|
|
2836
3381
|
(err) => {
|
|
2837
3382
|
setError(err);
|
|
2838
3383
|
onErrorChange?.(err);
|
|
2839
3384
|
},
|
|
2840
3385
|
[onErrorChange]
|
|
2841
3386
|
);
|
|
2842
|
-
const emitDecline = (0,
|
|
3387
|
+
const emitDecline = (0, import_react9.useCallback)(
|
|
2843
3388
|
(input, overrides) => {
|
|
2844
3389
|
onDecline?.(buildDeclineEvent("card", input, overrides));
|
|
2845
3390
|
},
|
|
2846
3391
|
[onDecline]
|
|
2847
3392
|
);
|
|
2848
|
-
const processPaymentInternal = (0,
|
|
3393
|
+
const processPaymentInternal = (0, import_react9.useCallback)(
|
|
2849
3394
|
async (tokenizedBody) => {
|
|
2850
3395
|
setProcessing(true);
|
|
2851
3396
|
updateError(null);
|
|
@@ -2871,7 +3416,8 @@ function CheckoutFormInner({
|
|
|
2871
3416
|
if (response.ok) {
|
|
2872
3417
|
onComplete?.({
|
|
2873
3418
|
status: "succeeded",
|
|
2874
|
-
paymentIntentId: tokenizedBody.threeDSecureActionResultTokenId
|
|
3419
|
+
paymentIntentId: tokenizedBody.threeDSecureActionResultTokenId,
|
|
3420
|
+
paymentMethodId: resolveTokenizedPaymentMethodId(tokenizedBody)
|
|
2875
3421
|
});
|
|
2876
3422
|
return;
|
|
2877
3423
|
}
|
|
@@ -2898,7 +3444,8 @@ function CheckoutFormInner({
|
|
|
2898
3444
|
await processPaymentInternal({
|
|
2899
3445
|
id: result.paymentIntentId,
|
|
2900
3446
|
type: "card",
|
|
2901
|
-
threeDSecureActionResultTokenId: result.paymentIntentId
|
|
3447
|
+
threeDSecureActionResultTokenId: result.paymentIntentId,
|
|
3448
|
+
originalPaymentMethodId: resolveTokenizedPaymentMethodId(tokenizedBody)
|
|
2902
3449
|
});
|
|
2903
3450
|
}
|
|
2904
3451
|
} finally {
|
|
@@ -2953,7 +3500,7 @@ function CheckoutFormInner({
|
|
|
2953
3500
|
},
|
|
2954
3501
|
[baseUrl, sessionId, userId, email, firstName, lastName, chv, flopay, paypalFlopay, onComplete, onError, onDecline, updateError, emitDecline]
|
|
2955
3502
|
);
|
|
2956
|
-
const dispatchTokenizedBody = (0,
|
|
3503
|
+
const dispatchTokenizedBody = (0, import_react9.useCallback)(
|
|
2957
3504
|
(tokenizedBody) => {
|
|
2958
3505
|
if (onTokenizedBody) {
|
|
2959
3506
|
onTokenizedBody(tokenizedBody);
|
|
@@ -2963,7 +3510,7 @@ function CheckoutFormInner({
|
|
|
2963
3510
|
},
|
|
2964
3511
|
[onTokenizedBody, processPaymentInternal]
|
|
2965
3512
|
);
|
|
2966
|
-
(0,
|
|
3513
|
+
(0, import_react9.useImperativeHandle)(innerRef, () => ({
|
|
2967
3514
|
async handleNextAction(secret) {
|
|
2968
3515
|
if (!flopay) return;
|
|
2969
3516
|
setIs3DSActive(true);
|
|
@@ -2990,7 +3537,7 @@ function CheckoutFormInner({
|
|
|
2990
3537
|
}
|
|
2991
3538
|
}
|
|
2992
3539
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
2993
|
-
(0,
|
|
3540
|
+
(0, import_react9.useEffect)(() => {
|
|
2994
3541
|
if (typeof window === "undefined") return;
|
|
2995
3542
|
const stored = localStorage.getItem(WALLET_RESUME_KEY2);
|
|
2996
3543
|
if (!stored) return;
|
|
@@ -3008,7 +3555,7 @@ function CheckoutFormInner({
|
|
|
3008
3555
|
localStorage.removeItem(WALLET_RESUME_KEY2);
|
|
3009
3556
|
}
|
|
3010
3557
|
}, [sessionId, dispatchTokenizedBody]);
|
|
3011
|
-
const handleSubmit = (0,
|
|
3558
|
+
const handleSubmit = (0, import_react9.useCallback)(
|
|
3012
3559
|
async (e) => {
|
|
3013
3560
|
e.preventDefault();
|
|
3014
3561
|
if (!flopay || !elements || isSubmitting) return;
|
|
@@ -3027,7 +3574,7 @@ function CheckoutFormInner({
|
|
|
3027
3574
|
return;
|
|
3028
3575
|
}
|
|
3029
3576
|
if (!sessionId || !email) {
|
|
3030
|
-
throw new
|
|
3577
|
+
throw new import_shared8.FloPayError("Missing sessionId or email", "validation_error");
|
|
3031
3578
|
}
|
|
3032
3579
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
3033
3580
|
method: "POST",
|
|
@@ -3039,10 +3586,10 @@ function CheckoutFormInner({
|
|
|
3039
3586
|
isPaypal: false
|
|
3040
3587
|
})
|
|
3041
3588
|
});
|
|
3042
|
-
if (!intentResponse.ok) throw new
|
|
3589
|
+
if (!intentResponse.ok) throw new import_shared8.FloPayError("Failed to create payment intent", "api_error");
|
|
3043
3590
|
const intentJson = await intentResponse.json();
|
|
3044
3591
|
const intentClientSecret = intentJson.data?.id;
|
|
3045
|
-
if (!intentClientSecret) throw new
|
|
3592
|
+
if (!intentClientSecret) throw new import_shared8.FloPayError("No client_secret in payment intent response", "api_error");
|
|
3046
3593
|
const confirmResult = await flopay.confirmCardPayment({
|
|
3047
3594
|
clientSecret: intentClientSecret,
|
|
3048
3595
|
paymentMethodId: pmResult.paymentMethodId
|
|
@@ -3056,7 +3603,8 @@ function CheckoutFormInner({
|
|
|
3056
3603
|
dispatchTokenizedBody({
|
|
3057
3604
|
id: pmResult.paymentMethodId,
|
|
3058
3605
|
type: "card",
|
|
3059
|
-
threeDSecureActionResultTokenId: confirmResult.paymentIntentId
|
|
3606
|
+
threeDSecureActionResultTokenId: confirmResult.paymentIntentId,
|
|
3607
|
+
originalPaymentMethodId: pmResult.paymentMethodId
|
|
3060
3608
|
});
|
|
3061
3609
|
} catch (err) {
|
|
3062
3610
|
updateError(err instanceof Error ? err.message : "An unexpected error occurred");
|
|
@@ -3070,8 +3618,8 @@ function CheckoutFormInner({
|
|
|
3070
3618
|
[flopay, elements, isSubmitting, sessionId, email, baseUrl, isSelfContained, dispatchTokenizedBody, onError, updateError, emitDecline]
|
|
3071
3619
|
);
|
|
3072
3620
|
const isReady = flopay !== null && elements !== null;
|
|
3073
|
-
return /* @__PURE__ */ (0,
|
|
3074
|
-
(is3DSActive || isSubmitting) && /* @__PURE__ */ (0,
|
|
3621
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
3622
|
+
(is3DSActive || isSubmitting) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-testid": "flopay-overlay", style: {
|
|
3075
3623
|
position: "absolute",
|
|
3076
3624
|
inset: 0,
|
|
3077
3625
|
background: "rgba(255,255,255,0.7)",
|
|
@@ -3080,12 +3628,12 @@ function CheckoutFormInner({
|
|
|
3080
3628
|
justifyContent: "center",
|
|
3081
3629
|
zIndex: 10
|
|
3082
3630
|
}, children: is3DSActive ? "Verifying payment..." : "Processing..." }),
|
|
3083
|
-
!isReady && /* @__PURE__ */ (0,
|
|
3084
|
-
isReady && /* @__PURE__ */ (0,
|
|
3085
|
-
/* @__PURE__ */ (0,
|
|
3086
|
-
showAddress && /* @__PURE__ */ (0,
|
|
3087
|
-
displayError && /* @__PURE__ */ (0,
|
|
3088
|
-
children ?? /* @__PURE__ */ (0,
|
|
3631
|
+
!isReady && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
|
|
3632
|
+
isReady && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
3633
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PaymentElement, { options: { layout } }),
|
|
3634
|
+
showAddress && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
|
|
3635
|
+
displayError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
|
|
3636
|
+
children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3089
3637
|
"button",
|
|
3090
3638
|
{
|
|
3091
3639
|
type: "submit",
|
|
@@ -3099,9 +3647,9 @@ function CheckoutFormInner({
|
|
|
3099
3647
|
}
|
|
3100
3648
|
|
|
3101
3649
|
// src/paypal-button.tsx
|
|
3102
|
-
var
|
|
3103
|
-
var
|
|
3104
|
-
var
|
|
3650
|
+
var import_shared9 = require("@flopay/shared");
|
|
3651
|
+
var import_react10 = require("react");
|
|
3652
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
3105
3653
|
function PayPalButton({
|
|
3106
3654
|
sessionId,
|
|
3107
3655
|
billingApiUrl,
|
|
@@ -3118,11 +3666,11 @@ function PayPalButton({
|
|
|
3118
3666
|
const flopay = useFloPay();
|
|
3119
3667
|
const elements = useElements();
|
|
3120
3668
|
const contextBillingUrl = useBillingApiUrl();
|
|
3121
|
-
const [ready, setReady] = (0,
|
|
3122
|
-
const [submitting, setSubmitting] = (0,
|
|
3123
|
-
const paypalResumeAttempted = (0,
|
|
3669
|
+
const [ready, setReady] = (0, import_react10.useState)(false);
|
|
3670
|
+
const [submitting, setSubmitting] = (0, import_react10.useState)(false);
|
|
3671
|
+
const paypalResumeAttempted = (0, import_react10.useRef)(false);
|
|
3124
3672
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
3125
|
-
const processPaymentInternal = (0,
|
|
3673
|
+
const processPaymentInternal = (0, import_react10.useCallback)(
|
|
3126
3674
|
async (tokenizedBody) => {
|
|
3127
3675
|
try {
|
|
3128
3676
|
const response = await fetch(`${baseUrl}/v1/checkouts/sessions/process`, {
|
|
@@ -3155,7 +3703,7 @@ function PayPalButton({
|
|
|
3155
3703
|
},
|
|
3156
3704
|
[baseUrl, sessionId, userId, email, firstName, lastName, chv, onComplete, onErrorChange]
|
|
3157
3705
|
);
|
|
3158
|
-
const dispatchTokenizedBody = (0,
|
|
3706
|
+
const dispatchTokenizedBody = (0, import_react10.useCallback)(
|
|
3159
3707
|
(body) => {
|
|
3160
3708
|
if (onTokenizedBody) {
|
|
3161
3709
|
onTokenizedBody(body);
|
|
@@ -3165,7 +3713,7 @@ function PayPalButton({
|
|
|
3165
3713
|
},
|
|
3166
3714
|
[onTokenizedBody, processPaymentInternal]
|
|
3167
3715
|
);
|
|
3168
|
-
(0,
|
|
3716
|
+
(0, import_react10.useEffect)(() => {
|
|
3169
3717
|
if (!flopay || paypalResumeAttempted.current) return;
|
|
3170
3718
|
const params = new URLSearchParams(window.location.search);
|
|
3171
3719
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -3213,13 +3761,13 @@ function PayPalButton({
|
|
|
3213
3761
|
}
|
|
3214
3762
|
})();
|
|
3215
3763
|
}, [flopay, dispatchTokenizedBody, onErrorChange]);
|
|
3216
|
-
const handlePayPalConfirm = (0,
|
|
3764
|
+
const handlePayPalConfirm = (0, import_react10.useCallback)(async () => {
|
|
3217
3765
|
if (!flopay || !elements) return;
|
|
3218
3766
|
try {
|
|
3219
3767
|
setSubmitting(true);
|
|
3220
3768
|
onErrorChange?.(null);
|
|
3221
3769
|
if (!sessionId || !email) {
|
|
3222
|
-
throw new
|
|
3770
|
+
throw new import_shared9.FloPayError("Missing sessionId or email for PayPal payment", "validation_error");
|
|
3223
3771
|
}
|
|
3224
3772
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
3225
3773
|
method: "POST",
|
|
@@ -3231,10 +3779,10 @@ function PayPalButton({
|
|
|
3231
3779
|
isPaypal: "true"
|
|
3232
3780
|
})
|
|
3233
3781
|
});
|
|
3234
|
-
if (!intentResponse.ok) throw new
|
|
3782
|
+
if (!intentResponse.ok) throw new import_shared9.FloPayError("Failed to create payment intent", "api_error");
|
|
3235
3783
|
const intentJson = await intentResponse.json();
|
|
3236
3784
|
const intentClientSecret = intentJson.data?.id;
|
|
3237
|
-
if (!intentClientSecret) throw new
|
|
3785
|
+
if (!intentClientSecret) throw new import_shared9.FloPayError("No client_secret in response", "api_error");
|
|
3238
3786
|
const result = await flopay.confirmPayment({
|
|
3239
3787
|
clientSecret: intentClientSecret,
|
|
3240
3788
|
returnUrl: window.location.href
|
|
@@ -3256,11 +3804,11 @@ function PayPalButton({
|
|
|
3256
3804
|
}
|
|
3257
3805
|
}, [flopay, elements, sessionId, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
|
|
3258
3806
|
if (!flopay || !elements) {
|
|
3259
|
-
return /* @__PURE__ */ (0,
|
|
3807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
|
|
3260
3808
|
}
|
|
3261
|
-
return /* @__PURE__ */ (0,
|
|
3262
|
-
!ready && /* @__PURE__ */ (0,
|
|
3263
|
-
/* @__PURE__ */ (0,
|
|
3809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3810
|
+
!ready && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
|
|
3811
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3264
3812
|
"button",
|
|
3265
3813
|
{
|
|
3266
3814
|
type: "button",
|
|
@@ -3282,7 +3830,7 @@ function PayPalButton({
|
|
|
3282
3830
|
children: submitting ? "Processing..." : "PayPal"
|
|
3283
3831
|
}
|
|
3284
3832
|
) }),
|
|
3285
|
-
(submitting || isProcessing) && /* @__PURE__ */ (0,
|
|
3833
|
+
(submitting || isProcessing) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
3286
3834
|
position: "fixed",
|
|
3287
3835
|
inset: 0,
|
|
3288
3836
|
background: "rgba(0,0,0,0.4)",
|
|
@@ -3290,7 +3838,7 @@ function PayPalButton({
|
|
|
3290
3838
|
alignItems: "center",
|
|
3291
3839
|
justifyContent: "center",
|
|
3292
3840
|
zIndex: 1e3
|
|
3293
|
-
}, children: /* @__PURE__ */ (0,
|
|
3841
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
3294
3842
|
background: "white",
|
|
3295
3843
|
borderRadius: 8,
|
|
3296
3844
|
padding: "1.5rem",
|
|
@@ -3300,6 +3848,676 @@ function PayPalButton({
|
|
|
3300
3848
|
}, children: "Processing PayPal payment..." }) })
|
|
3301
3849
|
] });
|
|
3302
3850
|
}
|
|
3851
|
+
|
|
3852
|
+
// src/automatic-payment-button.tsx
|
|
3853
|
+
var import_react11 = require("react");
|
|
3854
|
+
var import_js3 = require("@flopay/js");
|
|
3855
|
+
var import_shared10 = require("@flopay/shared");
|
|
3856
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
3857
|
+
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
|
|
3858
|
+
var PAYPAL_RESUME_STORAGE_KEY = "flopay_automatic_payment_button_resume";
|
|
3859
|
+
function sleep2(ms) {
|
|
3860
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3861
|
+
}
|
|
3862
|
+
function coerceError(err, fallbackMessage) {
|
|
3863
|
+
if (err instanceof import_shared10.FloPayError) {
|
|
3864
|
+
return err;
|
|
3865
|
+
}
|
|
3866
|
+
return new import_shared10.FloPayError(
|
|
3867
|
+
err instanceof Error ? err.message : fallbackMessage,
|
|
3868
|
+
"api_error"
|
|
3869
|
+
);
|
|
3870
|
+
}
|
|
3871
|
+
function canUseStorage() {
|
|
3872
|
+
return typeof window !== "undefined" && typeof window.sessionStorage !== "undefined";
|
|
3873
|
+
}
|
|
3874
|
+
function shouldShowFallbackCheckout(error, sessionId) {
|
|
3875
|
+
if (!sessionId) return false;
|
|
3876
|
+
if (error.type === "validation_error") return false;
|
|
3877
|
+
if (error.checkoutMethod && error.checkoutMethod !== "card") return false;
|
|
3878
|
+
return true;
|
|
3879
|
+
}
|
|
3880
|
+
function readPayPalResumeState() {
|
|
3881
|
+
if (!canUseStorage()) return null;
|
|
3882
|
+
try {
|
|
3883
|
+
const raw = window.sessionStorage.getItem(PAYPAL_RESUME_STORAGE_KEY);
|
|
3884
|
+
if (!raw) return null;
|
|
3885
|
+
return JSON.parse(raw);
|
|
3886
|
+
} catch {
|
|
3887
|
+
return null;
|
|
3888
|
+
}
|
|
3889
|
+
}
|
|
3890
|
+
function persistPayPalResumeState(state) {
|
|
3891
|
+
if (!canUseStorage()) return;
|
|
3892
|
+
try {
|
|
3893
|
+
window.sessionStorage.setItem(PAYPAL_RESUME_STORAGE_KEY, JSON.stringify(state));
|
|
3894
|
+
} catch (error) {
|
|
3895
|
+
console.warn("[FloPayAutomaticPaymentButton] Failed to persist PayPal resume state.", error);
|
|
3896
|
+
}
|
|
3897
|
+
}
|
|
3898
|
+
function clearPayPalResumeState() {
|
|
3899
|
+
if (!canUseStorage()) return;
|
|
3900
|
+
try {
|
|
3901
|
+
window.sessionStorage.removeItem(PAYPAL_RESUME_STORAGE_KEY);
|
|
3902
|
+
} catch (error) {
|
|
3903
|
+
console.warn("[FloPayAutomaticPaymentButton] Failed to clear PayPal resume state.", error);
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3906
|
+
function clearPayPalRedirectParams() {
|
|
3907
|
+
if (typeof window === "undefined") return;
|
|
3908
|
+
const url = new URL(window.location.href);
|
|
3909
|
+
const keys = ["payment_intent", "payment_intent_client_secret", "redirect_status"];
|
|
3910
|
+
let changed = false;
|
|
3911
|
+
for (const key of keys) {
|
|
3912
|
+
if (url.searchParams.has(key)) {
|
|
3913
|
+
url.searchParams.delete(key);
|
|
3914
|
+
changed = true;
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3917
|
+
if (changed) {
|
|
3918
|
+
window.history.replaceState({}, "", url.toString());
|
|
3919
|
+
}
|
|
3920
|
+
}
|
|
3921
|
+
function resolveCreateSessionDraft(props) {
|
|
3922
|
+
if (props.createSession) {
|
|
3923
|
+
return {
|
|
3924
|
+
...props.createSession,
|
|
3925
|
+
checkoutMode: "auto"
|
|
3926
|
+
};
|
|
3927
|
+
}
|
|
3928
|
+
if (!props.clientId || !props.account || !props.successUrl || !props.cancelUrl) {
|
|
3929
|
+
return null;
|
|
3930
|
+
}
|
|
3931
|
+
return {
|
|
3932
|
+
clientId: props.clientId,
|
|
3933
|
+
items: props.items,
|
|
3934
|
+
subscriptions: props.subscriptions,
|
|
3935
|
+
account: props.account,
|
|
3936
|
+
successUrl: props.successUrl,
|
|
3937
|
+
cancelUrl: props.cancelUrl,
|
|
3938
|
+
couponCodes: props.couponCodes,
|
|
3939
|
+
tagsData: props.tagsData,
|
|
3940
|
+
utmMetadata: props.utmMetadata,
|
|
3941
|
+
checkoutMode: "auto"
|
|
3942
|
+
};
|
|
3943
|
+
}
|
|
3944
|
+
function FloPayAutomaticPaymentButton({
|
|
3945
|
+
sessionId,
|
|
3946
|
+
createSession,
|
|
3947
|
+
paymentMethodId,
|
|
3948
|
+
clientId,
|
|
3949
|
+
items,
|
|
3950
|
+
subscriptions,
|
|
3951
|
+
account,
|
|
3952
|
+
successUrl,
|
|
3953
|
+
cancelUrl,
|
|
3954
|
+
couponCodes,
|
|
3955
|
+
tagsData,
|
|
3956
|
+
utmMetadata,
|
|
3957
|
+
billingApiUrl,
|
|
3958
|
+
locale,
|
|
3959
|
+
fallbackPublishableKey,
|
|
3960
|
+
buttonsTheme,
|
|
3961
|
+
buttonsStyles: stylesOverride,
|
|
3962
|
+
onSuccess,
|
|
3963
|
+
onError,
|
|
3964
|
+
onDecline,
|
|
3965
|
+
children,
|
|
3966
|
+
disabled = false,
|
|
3967
|
+
type = "button",
|
|
3968
|
+
style,
|
|
3969
|
+
...buttonProps
|
|
3970
|
+
}) {
|
|
3971
|
+
const resolvedBillingUrl = (0, import_react11.useMemo)(
|
|
3972
|
+
() => (0, import_shared10.resolveBillingApiUrl)(billingApiUrl),
|
|
3973
|
+
[billingApiUrl]
|
|
3974
|
+
);
|
|
3975
|
+
const createSessionDraft = (0, import_react11.useMemo)(
|
|
3976
|
+
() => resolveCreateSessionDraft({
|
|
3977
|
+
createSession,
|
|
3978
|
+
clientId,
|
|
3979
|
+
items,
|
|
3980
|
+
subscriptions,
|
|
3981
|
+
account,
|
|
3982
|
+
successUrl,
|
|
3983
|
+
cancelUrl,
|
|
3984
|
+
couponCodes,
|
|
3985
|
+
tagsData,
|
|
3986
|
+
utmMetadata
|
|
3987
|
+
}),
|
|
3988
|
+
[
|
|
3989
|
+
account,
|
|
3990
|
+
cancelUrl,
|
|
3991
|
+
clientId,
|
|
3992
|
+
couponCodes,
|
|
3993
|
+
createSession,
|
|
3994
|
+
items,
|
|
3995
|
+
subscriptions,
|
|
3996
|
+
successUrl,
|
|
3997
|
+
tagsData,
|
|
3998
|
+
utmMetadata
|
|
3999
|
+
]
|
|
4000
|
+
);
|
|
4001
|
+
const [isProcessing, setIsProcessing] = (0, import_react11.useState)(false);
|
|
4002
|
+
const [overlayStatus, setOverlayStatus] = (0, import_react11.useState)(null);
|
|
4003
|
+
const [overlayError, setOverlayError] = (0, import_react11.useState)(null);
|
|
4004
|
+
const [fallbackSession, setFallbackSession] = (0, import_react11.useState)(null);
|
|
4005
|
+
const automaticPaymentToken = (0, import_react11.useMemo)(
|
|
4006
|
+
() => paymentMethodId ? {
|
|
4007
|
+
id: paymentMethodId,
|
|
4008
|
+
type: "card"
|
|
4009
|
+
} : void 0,
|
|
4010
|
+
[paymentMethodId]
|
|
4011
|
+
);
|
|
4012
|
+
const isMountedRef = (0, import_react11.useRef)(true);
|
|
4013
|
+
const resumeAttemptedRef = (0, import_react11.useRef)(false);
|
|
4014
|
+
const fallbackSessionRef = (0, import_react11.useRef)(fallbackSession);
|
|
4015
|
+
const onSuccessRef = (0, import_react11.useRef)(onSuccess);
|
|
4016
|
+
const onErrorRef = (0, import_react11.useRef)(onError);
|
|
4017
|
+
const onDeclineRef = (0, import_react11.useRef)(onDecline);
|
|
4018
|
+
(0, import_react11.useEffect)(() => {
|
|
4019
|
+
fallbackSessionRef.current = fallbackSession;
|
|
4020
|
+
}, [fallbackSession]);
|
|
4021
|
+
(0, import_react11.useEffect)(() => {
|
|
4022
|
+
onSuccessRef.current = onSuccess;
|
|
4023
|
+
}, [onSuccess]);
|
|
4024
|
+
(0, import_react11.useEffect)(() => {
|
|
4025
|
+
onErrorRef.current = onError;
|
|
4026
|
+
}, [onError]);
|
|
4027
|
+
(0, import_react11.useEffect)(() => {
|
|
4028
|
+
onDeclineRef.current = onDecline;
|
|
4029
|
+
}, [onDecline]);
|
|
4030
|
+
(0, import_react11.useEffect)(() => {
|
|
4031
|
+
isMountedRef.current = true;
|
|
4032
|
+
return () => {
|
|
4033
|
+
isMountedRef.current = false;
|
|
4034
|
+
};
|
|
4035
|
+
}, []);
|
|
4036
|
+
(0, import_react11.useEffect)(() => {
|
|
4037
|
+
if (!fallbackSession || typeof window === "undefined") {
|
|
4038
|
+
return;
|
|
4039
|
+
}
|
|
4040
|
+
const handleKeyDown = (event) => {
|
|
4041
|
+
if (event.key === "Escape") {
|
|
4042
|
+
setFallbackSession(null);
|
|
4043
|
+
}
|
|
4044
|
+
};
|
|
4045
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4046
|
+
return () => {
|
|
4047
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
4048
|
+
};
|
|
4049
|
+
}, [fallbackSession]);
|
|
4050
|
+
const emitDecline = (0, import_react11.useCallback)((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
|
|
4051
|
+
onDeclineRef.current?.(buildDeclineEvent(method, error, {
|
|
4052
|
+
code: error.code,
|
|
4053
|
+
declineCode: error.declineCode
|
|
4054
|
+
}));
|
|
4055
|
+
}, []);
|
|
4056
|
+
const showSuccess = (0, import_react11.useCallback)(async (event) => {
|
|
4057
|
+
if (!isMountedRef.current) return;
|
|
4058
|
+
setOverlayError(null);
|
|
4059
|
+
setOverlayStatus("success");
|
|
4060
|
+
await sleep2(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
4061
|
+
if (!isMountedRef.current) return;
|
|
4062
|
+
onSuccessRef.current?.(event);
|
|
4063
|
+
}, []);
|
|
4064
|
+
const showError = (0, import_react11.useCallback)(async (error, options) => {
|
|
4065
|
+
if (!isMountedRef.current) return;
|
|
4066
|
+
onErrorRef.current?.(error);
|
|
4067
|
+
if (options?.emitDecline) {
|
|
4068
|
+
emitDecline(error, options.method);
|
|
4069
|
+
}
|
|
4070
|
+
setOverlayError(error.message);
|
|
4071
|
+
setOverlayStatus("error");
|
|
4072
|
+
await sleep2(PROCESSING_OVERLAY_ERROR_DELAY_MS);
|
|
4073
|
+
}, [emitDecline]);
|
|
4074
|
+
const processResolvedSession = (0, import_react11.useCallback)(async (apiResult, resolvedSessionId) => {
|
|
4075
|
+
const session = apiResult.data.session ?? null;
|
|
4076
|
+
if (!session) {
|
|
4077
|
+
throw new import_shared10.FloPayError("No session data returned", "api_error");
|
|
4078
|
+
}
|
|
4079
|
+
if (session.status === "complete") {
|
|
4080
|
+
await showSuccess({
|
|
4081
|
+
result: { status: "succeeded" },
|
|
4082
|
+
session,
|
|
4083
|
+
sessionId: session.id || resolvedSessionId,
|
|
4084
|
+
autoCompleted: false
|
|
4085
|
+
});
|
|
4086
|
+
return;
|
|
4087
|
+
}
|
|
4088
|
+
try {
|
|
4089
|
+
const result = await processSavedPaymentForMode({
|
|
4090
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4091
|
+
sessionId: resolvedSessionId ?? session.id,
|
|
4092
|
+
session,
|
|
4093
|
+
tokenizedData: automaticPaymentToken
|
|
4094
|
+
});
|
|
4095
|
+
let paymentResult = result.type === "success" ? result.result : null;
|
|
4096
|
+
if (result.type !== "success") {
|
|
4097
|
+
const {
|
|
4098
|
+
publishableKey,
|
|
4099
|
+
paypalPublishableKey
|
|
4100
|
+
} = resolveSavedPaymentPublishableKeys(apiResult, fallbackPublishableKey);
|
|
4101
|
+
if (result.type === "paypal_redirect_required") {
|
|
4102
|
+
persistPayPalResumeState({
|
|
4103
|
+
sessionId: session.id || resolvedSessionId,
|
|
4104
|
+
publishableKey,
|
|
4105
|
+
paypalPublishableKey
|
|
4106
|
+
});
|
|
4107
|
+
}
|
|
4108
|
+
const {
|
|
4109
|
+
flopay,
|
|
4110
|
+
paypalFlopay
|
|
4111
|
+
} = await loadSavedPaymentProviders({
|
|
4112
|
+
publishableKey,
|
|
4113
|
+
paypalPublishableKey,
|
|
4114
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4115
|
+
locale
|
|
4116
|
+
});
|
|
4117
|
+
paymentResult = await handleSavedPaymentRedirectResult(result, {
|
|
4118
|
+
flopay,
|
|
4119
|
+
paypalFlopay,
|
|
4120
|
+
attempt3DS: true,
|
|
4121
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4122
|
+
sessionId: session.id || resolvedSessionId,
|
|
4123
|
+
session
|
|
4124
|
+
});
|
|
4125
|
+
if (result.type === "paypal_redirect_required") {
|
|
4126
|
+
clearPayPalResumeState();
|
|
4127
|
+
}
|
|
4128
|
+
}
|
|
4129
|
+
await showSuccess({
|
|
4130
|
+
result: paymentResult ? {
|
|
4131
|
+
...paymentResult,
|
|
4132
|
+
paymentMethodId: paymentResult.paymentMethodId ?? paymentMethodId
|
|
4133
|
+
} : {
|
|
4134
|
+
status: "succeeded",
|
|
4135
|
+
paymentMethodId: paymentMethodId ?? void 0
|
|
4136
|
+
},
|
|
4137
|
+
session,
|
|
4138
|
+
sessionId: session.id || resolvedSessionId,
|
|
4139
|
+
autoCompleted: false
|
|
4140
|
+
});
|
|
4141
|
+
} catch (err) {
|
|
4142
|
+
let floPayErr = normalizeSavedPaymentError(err);
|
|
4143
|
+
const fallbackSessionId = session.id || resolvedSessionId;
|
|
4144
|
+
if (floPayErr.code === "authentication_required" && fallbackSessionId && automaticPaymentToken?.id && automaticPaymentToken.id.startsWith("pm_")) {
|
|
4145
|
+
try {
|
|
4146
|
+
const {
|
|
4147
|
+
publishableKey,
|
|
4148
|
+
paypalPublishableKey
|
|
4149
|
+
} = resolveSavedPaymentPublishableKeys(apiResult, fallbackPublishableKey);
|
|
4150
|
+
const {
|
|
4151
|
+
flopay
|
|
4152
|
+
} = await loadSavedPaymentProviders({
|
|
4153
|
+
publishableKey,
|
|
4154
|
+
paypalPublishableKey,
|
|
4155
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4156
|
+
locale
|
|
4157
|
+
});
|
|
4158
|
+
const paymentResult = await processSavedPaymentWithIntent({
|
|
4159
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4160
|
+
sessionId: fallbackSessionId,
|
|
4161
|
+
session,
|
|
4162
|
+
paymentMethodId: automaticPaymentToken.id,
|
|
4163
|
+
flopay
|
|
4164
|
+
});
|
|
4165
|
+
await showSuccess({
|
|
4166
|
+
result: {
|
|
4167
|
+
...paymentResult,
|
|
4168
|
+
paymentMethodId: paymentResult.paymentMethodId ?? paymentMethodId
|
|
4169
|
+
},
|
|
4170
|
+
session,
|
|
4171
|
+
sessionId: fallbackSessionId,
|
|
4172
|
+
autoCompleted: false
|
|
4173
|
+
});
|
|
4174
|
+
return;
|
|
4175
|
+
} catch (intentRecoveryErr) {
|
|
4176
|
+
floPayErr = normalizeSavedPaymentError(intentRecoveryErr);
|
|
4177
|
+
}
|
|
4178
|
+
}
|
|
4179
|
+
await showError(floPayErr, {
|
|
4180
|
+
emitDecline: true,
|
|
4181
|
+
method: floPayErr.checkoutMethod ?? DEFAULT_SAVED_PAYMENT_DECLINE_METHOD
|
|
4182
|
+
});
|
|
4183
|
+
if (shouldShowFallbackCheckout(floPayErr, fallbackSessionId) && fallbackSessionId && isMountedRef.current) {
|
|
4184
|
+
setFallbackSession({
|
|
4185
|
+
sessionId: fallbackSessionId,
|
|
4186
|
+
errorMessage: floPayErr.message
|
|
4187
|
+
});
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
}, [
|
|
4191
|
+
fallbackPublishableKey,
|
|
4192
|
+
locale,
|
|
4193
|
+
automaticPaymentToken,
|
|
4194
|
+
paymentMethodId,
|
|
4195
|
+
resolvedBillingUrl,
|
|
4196
|
+
showError,
|
|
4197
|
+
showSuccess
|
|
4198
|
+
]);
|
|
4199
|
+
const handleButtonClick = (0, import_react11.useCallback)(async (event) => {
|
|
4200
|
+
buttonProps.onClick?.(event);
|
|
4201
|
+
if (event.defaultPrevented || disabled || isProcessing) {
|
|
4202
|
+
return;
|
|
4203
|
+
}
|
|
4204
|
+
setFallbackSession(null);
|
|
4205
|
+
if (sessionId && createSessionDraft) {
|
|
4206
|
+
const error = new import_shared10.FloPayError(
|
|
4207
|
+
"Provide either sessionId or create-session props, not both.",
|
|
4208
|
+
"validation_error"
|
|
4209
|
+
);
|
|
4210
|
+
await showError(error);
|
|
4211
|
+
if (isMountedRef.current) {
|
|
4212
|
+
setOverlayStatus(null);
|
|
4213
|
+
setOverlayError(null);
|
|
4214
|
+
}
|
|
4215
|
+
return;
|
|
4216
|
+
}
|
|
4217
|
+
if (!sessionId && !createSessionDraft) {
|
|
4218
|
+
const error = new import_shared10.FloPayError(
|
|
4219
|
+
"Provide a sessionId or the props required to create an automatic payment session.",
|
|
4220
|
+
"validation_error"
|
|
4221
|
+
);
|
|
4222
|
+
await showError(error);
|
|
4223
|
+
if (isMountedRef.current) {
|
|
4224
|
+
setOverlayStatus(null);
|
|
4225
|
+
setOverlayError(null);
|
|
4226
|
+
}
|
|
4227
|
+
return;
|
|
4228
|
+
}
|
|
4229
|
+
setIsProcessing(true);
|
|
4230
|
+
setOverlayError(null);
|
|
4231
|
+
setOverlayStatus("processing");
|
|
4232
|
+
try {
|
|
4233
|
+
const api = new import_js3.PaymentAPI(resolvedBillingUrl);
|
|
4234
|
+
if (sessionId) {
|
|
4235
|
+
const result = await api.getUnifiedCheckoutSession(sessionId);
|
|
4236
|
+
await processResolvedSession(result, sessionId);
|
|
4237
|
+
return;
|
|
4238
|
+
}
|
|
4239
|
+
try {
|
|
4240
|
+
const result = await api.createAndFetchSession(createSessionDraft);
|
|
4241
|
+
await processResolvedSession(result, result.data.session?.id ?? null);
|
|
4242
|
+
} catch (err) {
|
|
4243
|
+
if (err instanceof import_shared10.FloPayError && err.code === "session_auto_completed") {
|
|
4244
|
+
await showSuccess({
|
|
4245
|
+
result: { status: "succeeded" },
|
|
4246
|
+
session: null,
|
|
4247
|
+
sessionId: null,
|
|
4248
|
+
autoCompleted: true
|
|
4249
|
+
});
|
|
4250
|
+
return;
|
|
4251
|
+
}
|
|
4252
|
+
throw err;
|
|
4253
|
+
}
|
|
4254
|
+
} catch (err) {
|
|
4255
|
+
await showError(
|
|
4256
|
+
coerceError(err, "Automatic payment failed. Please try again.")
|
|
4257
|
+
);
|
|
4258
|
+
} finally {
|
|
4259
|
+
if (isMountedRef.current) {
|
|
4260
|
+
setOverlayStatus(null);
|
|
4261
|
+
setOverlayError(null);
|
|
4262
|
+
setIsProcessing(false);
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4265
|
+
}, [
|
|
4266
|
+
buttonProps,
|
|
4267
|
+
createSessionDraft,
|
|
4268
|
+
disabled,
|
|
4269
|
+
isProcessing,
|
|
4270
|
+
processResolvedSession,
|
|
4271
|
+
resolvedBillingUrl,
|
|
4272
|
+
sessionId,
|
|
4273
|
+
showError,
|
|
4274
|
+
showSuccess
|
|
4275
|
+
]);
|
|
4276
|
+
const handleFallbackComplete = (0, import_react11.useCallback)((result) => {
|
|
4277
|
+
const activeFallback = fallbackSessionRef.current;
|
|
4278
|
+
setFallbackSession(null);
|
|
4279
|
+
onSuccessRef.current?.({
|
|
4280
|
+
result,
|
|
4281
|
+
session: null,
|
|
4282
|
+
sessionId: activeFallback?.sessionId ?? null,
|
|
4283
|
+
autoCompleted: false
|
|
4284
|
+
});
|
|
4285
|
+
}, []);
|
|
4286
|
+
const handleFallbackError = (0, import_react11.useCallback)((error) => {
|
|
4287
|
+
onErrorRef.current?.(error);
|
|
4288
|
+
}, []);
|
|
4289
|
+
const handleFallbackDecline = (0, import_react11.useCallback)((decline) => {
|
|
4290
|
+
onDeclineRef.current?.(decline);
|
|
4291
|
+
}, []);
|
|
4292
|
+
(0, import_react11.useEffect)(() => {
|
|
4293
|
+
if (typeof window === "undefined" || resumeAttemptedRef.current) {
|
|
4294
|
+
return;
|
|
4295
|
+
}
|
|
4296
|
+
const params = new URLSearchParams(window.location.search);
|
|
4297
|
+
const clientSecret = params.get("payment_intent_client_secret");
|
|
4298
|
+
if (!clientSecret) {
|
|
4299
|
+
return;
|
|
4300
|
+
}
|
|
4301
|
+
const resumeState = readPayPalResumeState();
|
|
4302
|
+
if (!resumeState) {
|
|
4303
|
+
return;
|
|
4304
|
+
}
|
|
4305
|
+
resumeAttemptedRef.current = true;
|
|
4306
|
+
void (async () => {
|
|
4307
|
+
setIsProcessing(true);
|
|
4308
|
+
setOverlayError(null);
|
|
4309
|
+
setOverlayStatus("processing");
|
|
4310
|
+
try {
|
|
4311
|
+
if (params.get("redirect_status") === "failed") {
|
|
4312
|
+
throw Object.assign(
|
|
4313
|
+
new import_shared10.FloPayError("PayPal payment was declined. Please try again.", "api_error"),
|
|
4314
|
+
{ checkoutMethod: "paypal" }
|
|
4315
|
+
);
|
|
4316
|
+
}
|
|
4317
|
+
const {
|
|
4318
|
+
flopay,
|
|
4319
|
+
paypalFlopay
|
|
4320
|
+
} = await loadSavedPaymentProviders({
|
|
4321
|
+
publishableKey: resumeState.publishableKey,
|
|
4322
|
+
paypalPublishableKey: resumeState.paypalPublishableKey,
|
|
4323
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4324
|
+
locale
|
|
4325
|
+
});
|
|
4326
|
+
const paypalStripe = (paypalFlopay ?? flopay).getRawProvider();
|
|
4327
|
+
if (!paypalStripe) {
|
|
4328
|
+
throw Object.assign(
|
|
4329
|
+
new import_shared10.FloPayError("PayPal is not available.", "api_error"),
|
|
4330
|
+
{ checkoutMethod: "paypal" }
|
|
4331
|
+
);
|
|
4332
|
+
}
|
|
4333
|
+
const { paymentIntent, error } = await paypalStripe.retrievePaymentIntent(clientSecret);
|
|
4334
|
+
if (error) {
|
|
4335
|
+
throw Object.assign(
|
|
4336
|
+
new import_shared10.FloPayError(
|
|
4337
|
+
error.message ?? "Failed to retrieve PayPal payment status.",
|
|
4338
|
+
"api_error",
|
|
4339
|
+
{ code: error.code }
|
|
4340
|
+
),
|
|
4341
|
+
{ checkoutMethod: "paypal" }
|
|
4342
|
+
);
|
|
4343
|
+
}
|
|
4344
|
+
if (paymentIntent && (paymentIntent.status === "requires_capture" || paymentIntent.status === "succeeded" || paymentIntent.status === "processing")) {
|
|
4345
|
+
await showSuccess({
|
|
4346
|
+
result: { status: "succeeded", paymentIntentId: paymentIntent.id },
|
|
4347
|
+
session: null,
|
|
4348
|
+
sessionId: resumeState.sessionId,
|
|
4349
|
+
autoCompleted: false
|
|
4350
|
+
});
|
|
4351
|
+
} else {
|
|
4352
|
+
throw Object.assign(
|
|
4353
|
+
new import_shared10.FloPayError("PayPal payment was not completed. Please try again.", "api_error"),
|
|
4354
|
+
{ checkoutMethod: "paypal" }
|
|
4355
|
+
);
|
|
4356
|
+
}
|
|
4357
|
+
} catch (err) {
|
|
4358
|
+
const floPayErr = normalizeSavedPaymentError(err);
|
|
4359
|
+
await showError(floPayErr, {
|
|
4360
|
+
emitDecline: true,
|
|
4361
|
+
method: floPayErr.checkoutMethod ?? "paypal"
|
|
4362
|
+
});
|
|
4363
|
+
} finally {
|
|
4364
|
+
clearPayPalResumeState();
|
|
4365
|
+
clearPayPalRedirectParams();
|
|
4366
|
+
if (isMountedRef.current) {
|
|
4367
|
+
setOverlayStatus(null);
|
|
4368
|
+
setOverlayError(null);
|
|
4369
|
+
setIsProcessing(false);
|
|
4370
|
+
}
|
|
4371
|
+
}
|
|
4372
|
+
})();
|
|
4373
|
+
}, [locale, resolvedBillingUrl, showError, showSuccess]);
|
|
4374
|
+
const bStyles = (0, import_react11.useMemo)(() => {
|
|
4375
|
+
const base = (0, import_shared10.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
4376
|
+
if (!stylesOverride) return base;
|
|
4377
|
+
return {
|
|
4378
|
+
...base,
|
|
4379
|
+
...stylesOverride,
|
|
4380
|
+
cardButton: { ...base.cardButton, ...stylesOverride.cardButton }
|
|
4381
|
+
};
|
|
4382
|
+
}, [buttonsTheme, stylesOverride]);
|
|
4383
|
+
const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
4384
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
4385
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4386
|
+
"button",
|
|
4387
|
+
{
|
|
4388
|
+
...buttonProps,
|
|
4389
|
+
type,
|
|
4390
|
+
onClick: handleButtonClick,
|
|
4391
|
+
disabled: disabled || isProcessing,
|
|
4392
|
+
"aria-busy": isProcessing,
|
|
4393
|
+
style: {
|
|
4394
|
+
width: "100%",
|
|
4395
|
+
...cardButtonSizing,
|
|
4396
|
+
backgroundColor: "white",
|
|
4397
|
+
color: "#262833",
|
|
4398
|
+
border: "1px solid #d1d5db",
|
|
4399
|
+
borderRadius: "8px",
|
|
4400
|
+
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
4401
|
+
fontWeight: 600,
|
|
4402
|
+
cursor: disabled || isProcessing ? "not-allowed" : "pointer",
|
|
4403
|
+
display: "flex",
|
|
4404
|
+
alignItems: "center",
|
|
4405
|
+
justifyContent: "center",
|
|
4406
|
+
gap: "0.625rem",
|
|
4407
|
+
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
4408
|
+
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
4409
|
+
position: "relative",
|
|
4410
|
+
opacity: disabled || isProcessing ? 0.6 : 1,
|
|
4411
|
+
...bStyles.cardButton,
|
|
4412
|
+
...style
|
|
4413
|
+
},
|
|
4414
|
+
onMouseDown: (e) => {
|
|
4415
|
+
buttonProps.onMouseDown?.(e);
|
|
4416
|
+
if (!e.defaultPrevented) {
|
|
4417
|
+
e.currentTarget.style.transform = "scale(0.985)";
|
|
4418
|
+
}
|
|
4419
|
+
},
|
|
4420
|
+
onMouseUp: (e) => {
|
|
4421
|
+
buttonProps.onMouseUp?.(e);
|
|
4422
|
+
if (!e.defaultPrevented) {
|
|
4423
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
4424
|
+
}
|
|
4425
|
+
},
|
|
4426
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CardButtonContentSlot, { content: children })
|
|
4427
|
+
}
|
|
4428
|
+
),
|
|
4429
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4430
|
+
ProcessingOverlay,
|
|
4431
|
+
{
|
|
4432
|
+
status: overlayStatus,
|
|
4433
|
+
errorMessage: overlayError
|
|
4434
|
+
}
|
|
4435
|
+
),
|
|
4436
|
+
fallbackSession && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4437
|
+
"div",
|
|
4438
|
+
{
|
|
4439
|
+
"data-testid": "flopay-automatic-payment-fallback",
|
|
4440
|
+
role: "dialog",
|
|
4441
|
+
"aria-modal": "true",
|
|
4442
|
+
onClick: (event) => {
|
|
4443
|
+
if (event.target === event.currentTarget) {
|
|
4444
|
+
setFallbackSession(null);
|
|
4445
|
+
}
|
|
4446
|
+
},
|
|
4447
|
+
style: {
|
|
4448
|
+
position: "fixed",
|
|
4449
|
+
inset: 0,
|
|
4450
|
+
background: "rgba(0, 0, 0, 0.45)",
|
|
4451
|
+
display: "flex",
|
|
4452
|
+
alignItems: "center",
|
|
4453
|
+
justifyContent: "center",
|
|
4454
|
+
padding: "1.5rem",
|
|
4455
|
+
zIndex: 1100
|
|
4456
|
+
},
|
|
4457
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
4458
|
+
"div",
|
|
4459
|
+
{
|
|
4460
|
+
style: {
|
|
4461
|
+
width: "100%",
|
|
4462
|
+
maxWidth: 520,
|
|
4463
|
+
maxHeight: "90vh",
|
|
4464
|
+
overflowY: "auto",
|
|
4465
|
+
background: "white",
|
|
4466
|
+
borderRadius: 20,
|
|
4467
|
+
padding: "1.5rem",
|
|
4468
|
+
boxShadow: "0 24px 80px rgba(15, 23, 42, 0.28)",
|
|
4469
|
+
display: "flex",
|
|
4470
|
+
flexDirection: "column",
|
|
4471
|
+
gap: "1rem"
|
|
4472
|
+
},
|
|
4473
|
+
children: [
|
|
4474
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4475
|
+
"div",
|
|
4476
|
+
{
|
|
4477
|
+
style: {
|
|
4478
|
+
display: "flex",
|
|
4479
|
+
gap: "1rem",
|
|
4480
|
+
alignItems: "flex-start"
|
|
4481
|
+
},
|
|
4482
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4483
|
+
"div",
|
|
4484
|
+
{
|
|
4485
|
+
style: {
|
|
4486
|
+
flex: 1,
|
|
4487
|
+
background: "#fef2f2",
|
|
4488
|
+
color: "#b91c1c",
|
|
4489
|
+
border: "1px solid #fecaca",
|
|
4490
|
+
borderRadius: "12px",
|
|
4491
|
+
padding: "0.75rem 1rem",
|
|
4492
|
+
fontSize: "0.9rem",
|
|
4493
|
+
lineHeight: 1.5
|
|
4494
|
+
},
|
|
4495
|
+
children: fallbackSession.errorMessage
|
|
4496
|
+
}
|
|
4497
|
+
)
|
|
4498
|
+
}
|
|
4499
|
+
),
|
|
4500
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4501
|
+
FloPayCheckout,
|
|
4502
|
+
{
|
|
4503
|
+
sessionId: fallbackSession.sessionId,
|
|
4504
|
+
checkoutMode: "full",
|
|
4505
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4506
|
+
fallbackPublishableKey,
|
|
4507
|
+
cardTitleContent: null,
|
|
4508
|
+
showSecurityFooter: false,
|
|
4509
|
+
onComplete: handleFallbackComplete,
|
|
4510
|
+
onError: handleFallbackError,
|
|
4511
|
+
onDecline: handleFallbackDecline
|
|
4512
|
+
}
|
|
4513
|
+
)
|
|
4514
|
+
]
|
|
4515
|
+
}
|
|
4516
|
+
)
|
|
4517
|
+
}
|
|
4518
|
+
)
|
|
4519
|
+
] });
|
|
4520
|
+
}
|
|
3303
4521
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3304
4522
|
0 && (module.exports = {
|
|
3305
4523
|
AddressElement,
|
|
@@ -3308,6 +4526,7 @@ function PayPalButton({
|
|
|
3308
4526
|
CardExpiryElement,
|
|
3309
4527
|
CardNumberElement,
|
|
3310
4528
|
CheckoutForm,
|
|
4529
|
+
FloPayAutomaticPaymentButton,
|
|
3311
4530
|
FloPayCheckout,
|
|
3312
4531
|
FloPayProvider,
|
|
3313
4532
|
PayPalButton,
|