@flopay/react 0.4.3 → 0.4.5
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 +1836 -640
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -3
- package/dist/index.d.ts +41 -3
- package/dist/index.mjs +1725 -530
- 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,183 +2438,148 @@ function FloPayCheckout({
|
|
|
1884
2438
|
cardButtonContent,
|
|
1885
2439
|
cardBackButtonContent,
|
|
1886
2440
|
cardTitleContent,
|
|
2441
|
+
showSecurityFooter = true,
|
|
1887
2442
|
onButtonClick,
|
|
1888
2443
|
onBeforeButtonClick,
|
|
1889
2444
|
enableAVS,
|
|
1890
2445
|
avsLayout,
|
|
1891
2446
|
submitLabel,
|
|
1892
2447
|
className,
|
|
2448
|
+
initialErrorMessage = null,
|
|
1893
2449
|
children,
|
|
1894
2450
|
checkoutMode: checkoutModeProp,
|
|
1895
2451
|
confirmLabel,
|
|
1896
2452
|
renderConfirmButton,
|
|
1897
2453
|
onSessionCompleted
|
|
1898
2454
|
}) {
|
|
1899
|
-
const resolvedBillingUrl = (0,
|
|
2455
|
+
const resolvedBillingUrl = (0, import_shared7.resolveBillingApiUrl)(billingApiUrl);
|
|
1900
2456
|
const checkoutType = createSessionParams ? "embedded_checkout" : "standard_checkout";
|
|
1901
2457
|
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
|
|
2458
|
+
const [unified, setUnified] = (0, import_react8.useState)(null);
|
|
2459
|
+
const [flopay, setFloPay] = (0, import_react8.useState)(null);
|
|
2460
|
+
const flopayRef = (0, import_react8.useRef)(null);
|
|
2461
|
+
const [paypalFlopay, setPaypalFloPay] = (0, import_react8.useState)(null);
|
|
2462
|
+
const paypalFlopayRef = (0, import_react8.useRef)(null);
|
|
2463
|
+
const [session, setSession] = (0, import_react8.useState)(null);
|
|
2464
|
+
const [resolvedSessionId, setResolvedSessionId] = (0, import_react8.useState)(sessionIdProp ?? "");
|
|
2465
|
+
const activeSessionId = sessionIdProp ?? resolvedSessionId;
|
|
2466
|
+
const initSessionDependency = createSessionParams ? "" : activeSessionId;
|
|
2467
|
+
const [isLoading, setIsLoading] = (0, import_react8.useState)(true);
|
|
2468
|
+
const [loadError, setLoadError] = (0, import_react8.useState)(null);
|
|
2469
|
+
const [currentMode, setCurrentMode] = (0, import_react8.useState)("full");
|
|
2470
|
+
const [confirmProcessing, setConfirmProcessing] = (0, import_react8.useState)(false);
|
|
2471
|
+
const [modeError, setModeError] = (0, import_react8.useState)(initialErrorMessage);
|
|
2472
|
+
const [modeOverlayStatus, setModeOverlayStatus] = (0, import_react8.useState)(null);
|
|
2473
|
+
const [modeOverlayError, setModeOverlayError] = (0, import_react8.useState)(null);
|
|
2474
|
+
const [createSessionPatch, setCreateSessionPatch] = (0, import_react8.useState)(void 0);
|
|
2475
|
+
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0, import_react8.useState)("");
|
|
2476
|
+
const [cardBootstrapPending, setCardBootstrapPending] = (0, import_react8.useState)(false);
|
|
2477
|
+
const autoCheckoutAttempted = (0, import_react8.useRef)(false);
|
|
2478
|
+
const onCompleteRef = (0, import_react8.useRef)(onComplete);
|
|
1919
2479
|
onCompleteRef.current = onComplete;
|
|
1920
|
-
const onErrorRef = (0,
|
|
2480
|
+
const onErrorRef = (0, import_react8.useRef)(onError);
|
|
1921
2481
|
onErrorRef.current = onError;
|
|
1922
|
-
const onDeclineRef = (0,
|
|
2482
|
+
const onDeclineRef = (0, import_react8.useRef)(onDecline);
|
|
1923
2483
|
onDeclineRef.current = onDecline;
|
|
1924
|
-
const onSessionCompletedRef = (0,
|
|
2484
|
+
const onSessionCompletedRef = (0, import_react8.useRef)(onSessionCompleted);
|
|
1925
2485
|
onSessionCompletedRef.current = onSessionCompleted;
|
|
1926
|
-
(0,
|
|
2486
|
+
(0, import_react8.useEffect)(() => {
|
|
1927
2487
|
console.info("[FloPay] Checkout initialized", {
|
|
1928
|
-
sdk_version:
|
|
2488
|
+
sdk_version: import_shared7.SDK_VERSION,
|
|
1929
2489
|
checkout_type: checkoutType,
|
|
1930
2490
|
checkout_layout: checkoutLayout,
|
|
1931
2491
|
billing_api_url: resolvedBillingUrl
|
|
1932
2492
|
});
|
|
1933
2493
|
}, [checkoutLayout, checkoutType, resolvedBillingUrl]);
|
|
1934
|
-
const baseCreateSessionHash = (0,
|
|
2494
|
+
const baseCreateSessionHash = (0, import_react8.useMemo)(
|
|
1935
2495
|
() => createSessionParams ? hashCreateParams(createSessionParams) : "",
|
|
1936
2496
|
[createSessionParams]
|
|
1937
2497
|
);
|
|
1938
|
-
const activeCreateSessionPatch = (0,
|
|
2498
|
+
const activeCreateSessionPatch = (0, import_react8.useMemo)(
|
|
1939
2499
|
() => createSessionPatchBaseHash === baseCreateSessionHash ? createSessionPatch : void 0,
|
|
1940
2500
|
[createSessionPatch, createSessionPatchBaseHash, baseCreateSessionHash]
|
|
1941
2501
|
);
|
|
1942
|
-
const
|
|
2502
|
+
const effectiveCreateSessionBase = (0, import_react8.useMemo)(
|
|
1943
2503
|
() => createSessionParams ? mergeInlineSessionPatch(createSessionParams, activeCreateSessionPatch) : void 0,
|
|
1944
2504
|
[createSessionParams, activeCreateSessionPatch]
|
|
1945
2505
|
);
|
|
1946
|
-
|
|
2506
|
+
const effectiveCreateSessionMode = checkoutModeProp ?? effectiveCreateSessionBase?.checkoutMode ?? "full";
|
|
2507
|
+
const effectiveCreateSession = (0, import_react8.useMemo)(
|
|
2508
|
+
() => effectiveCreateSessionBase ? {
|
|
2509
|
+
...effectiveCreateSessionBase,
|
|
2510
|
+
checkoutMode: effectiveCreateSessionMode
|
|
2511
|
+
} : void 0,
|
|
2512
|
+
[effectiveCreateSessionBase, effectiveCreateSessionMode]
|
|
2513
|
+
);
|
|
2514
|
+
(0, import_react8.useEffect)(() => {
|
|
1947
2515
|
setCreateSessionPatch(void 0);
|
|
1948
2516
|
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
1949
2517
|
}, [baseCreateSessionHash]);
|
|
1950
|
-
|
|
2518
|
+
(0, import_react8.useEffect)(() => {
|
|
2519
|
+
setModeError(initialErrorMessage);
|
|
2520
|
+
}, [initialErrorMessage]);
|
|
2521
|
+
const emitDecline = (0, import_react8.useCallback)(
|
|
1951
2522
|
(method, input, overrides) => {
|
|
1952
2523
|
onDeclineRef.current?.(buildDeclineEvent(method, input, overrides));
|
|
1953
2524
|
},
|
|
1954
2525
|
[]
|
|
1955
2526
|
);
|
|
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
|
|
2527
|
+
const runSavedPaymentFlow = (0, import_react8.useCallback)(
|
|
2528
|
+
async (sess, options) => {
|
|
2529
|
+
setModeError(null);
|
|
2530
|
+
setModeOverlayError(null);
|
|
2531
|
+
setModeOverlayStatus("processing");
|
|
2532
|
+
const activeSessionId2 = options?.sessionId ?? sess.id;
|
|
2533
|
+
try {
|
|
2534
|
+
const result = await processSavedPaymentForMode({
|
|
2535
|
+
billingApiUrl: resolvedBillingUrl,
|
|
2536
|
+
sessionId: activeSessionId2,
|
|
2537
|
+
session: sess
|
|
2017
2538
|
});
|
|
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"
|
|
2539
|
+
const paymentResult = result.type === "success" ? result.result : await handleSavedPaymentRedirectResult(result, {
|
|
2540
|
+
flopay: flopayRef.current,
|
|
2541
|
+
paypalFlopay: paypalFlopayRef.current,
|
|
2542
|
+
attempt3DS: options?.attempt3DS,
|
|
2543
|
+
billingApiUrl: resolvedBillingUrl,
|
|
2544
|
+
sessionId: activeSessionId2,
|
|
2545
|
+
session: sess
|
|
2047
2546
|
});
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
code: error.code
|
|
2052
|
-
});
|
|
2053
|
-
return false;
|
|
2054
|
-
}
|
|
2055
|
-
onCompleteRef.current?.({ status: "succeeded" });
|
|
2547
|
+
setModeOverlayStatus("success");
|
|
2548
|
+
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
2549
|
+
onCompleteRef.current?.(paymentResult);
|
|
2056
2550
|
return true;
|
|
2551
|
+
} catch (err) {
|
|
2552
|
+
const floPayErr = normalizeSavedPaymentError(err);
|
|
2553
|
+
const method = floPayErr.checkoutMethod ?? DEFAULT_SAVED_PAYMENT_DECLINE_METHOD;
|
|
2554
|
+
setModeError(floPayErr.message);
|
|
2555
|
+
setModeOverlayError(floPayErr.message);
|
|
2556
|
+
if (options?.fallbackToFull) {
|
|
2557
|
+
setCurrentMode("full");
|
|
2558
|
+
}
|
|
2559
|
+
onErrorRef.current?.(floPayErr);
|
|
2560
|
+
emitDecline(method, floPayErr, {
|
|
2561
|
+
code: floPayErr.code,
|
|
2562
|
+
declineCode: floPayErr.declineCode
|
|
2563
|
+
});
|
|
2564
|
+
setModeOverlayStatus("error");
|
|
2565
|
+
await Promise.allSettled([
|
|
2566
|
+
sleep(PROCESSING_OVERLAY_ERROR_DELAY_MS),
|
|
2567
|
+
options?.ensureProvidersReady ? options.ensureProvidersReady() : Promise.resolve()
|
|
2568
|
+
]);
|
|
2569
|
+
return false;
|
|
2570
|
+
} finally {
|
|
2571
|
+
setModeOverlayStatus(null);
|
|
2572
|
+
setModeOverlayError(null);
|
|
2057
2573
|
}
|
|
2058
|
-
return false;
|
|
2059
2574
|
},
|
|
2060
|
-
[
|
|
2575
|
+
[
|
|
2576
|
+
emitDecline,
|
|
2577
|
+
normalizeSavedPaymentError,
|
|
2578
|
+
resolvedBillingUrl
|
|
2579
|
+
]
|
|
2061
2580
|
);
|
|
2062
|
-
const inflightRef = (0,
|
|
2063
|
-
const initializedHashRef = (0,
|
|
2581
|
+
const inflightRef = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
|
|
2582
|
+
const initializedHashRef = (0, import_react8.useRef)(null);
|
|
2064
2583
|
function hashCreateParams(params) {
|
|
2065
2584
|
const key = JSON.stringify({
|
|
2066
2585
|
c: params?.clientId,
|
|
@@ -2080,17 +2599,23 @@ function FloPayCheckout({
|
|
|
2080
2599
|
}
|
|
2081
2600
|
return `flopay_session_${Math.abs(h).toString(36)}`;
|
|
2082
2601
|
}
|
|
2083
|
-
const createSessionHash = (0,
|
|
2602
|
+
const createSessionHash = (0, import_react8.useMemo)(
|
|
2084
2603
|
() => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
|
|
2085
2604
|
[effectiveCreateSession]
|
|
2086
2605
|
);
|
|
2087
|
-
const createSessionParamsRef = (0,
|
|
2606
|
+
const createSessionParamsRef = (0, import_react8.useRef)(effectiveCreateSession);
|
|
2088
2607
|
createSessionParamsRef.current = effectiveCreateSession;
|
|
2089
|
-
(0,
|
|
2608
|
+
(0, import_react8.useEffect)(() => {
|
|
2090
2609
|
setResolvedSessionId(sessionIdProp ?? "");
|
|
2091
2610
|
}, [sessionIdProp]);
|
|
2611
|
+
(0, import_react8.useEffect)(() => {
|
|
2612
|
+
autoCheckoutAttempted.current = false;
|
|
2613
|
+
setModeError(initialErrorMessage);
|
|
2614
|
+
setModeOverlayError(null);
|
|
2615
|
+
setModeOverlayStatus(null);
|
|
2616
|
+
}, [createSessionHash, initialErrorMessage, sessionIdProp]);
|
|
2092
2617
|
async function resolveInlineSession(params, cacheKey) {
|
|
2093
|
-
const api = new
|
|
2618
|
+
const api = new import_js2.PaymentAPI(resolvedBillingUrl);
|
|
2094
2619
|
let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
|
|
2095
2620
|
let realResult = null;
|
|
2096
2621
|
if (sid) {
|
|
@@ -2115,11 +2640,11 @@ function FloPayCheckout({
|
|
|
2115
2640
|
}
|
|
2116
2641
|
return { sid: sid ?? "", result: realResult };
|
|
2117
2642
|
}
|
|
2118
|
-
const bootstrapInlineSession = (0,
|
|
2643
|
+
const bootstrapInlineSession = (0, import_react8.useCallback)(
|
|
2119
2644
|
async (patch) => {
|
|
2120
2645
|
const baseParams = createSessionParamsRef.current;
|
|
2121
2646
|
if (!baseParams) {
|
|
2122
|
-
throw new
|
|
2647
|
+
throw new import_shared7.FloPayError("createSession is required to bootstrap checkout.", "validation_error");
|
|
2123
2648
|
}
|
|
2124
2649
|
const mergedParams = mergeInlineSessionPatch(baseParams, patch);
|
|
2125
2650
|
const cacheKey = hashCreateParams(mergedParams);
|
|
@@ -2148,43 +2673,23 @@ function FloPayCheckout({
|
|
|
2148
2673
|
if (sid) {
|
|
2149
2674
|
setResolvedSessionId(sid);
|
|
2150
2675
|
}
|
|
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
|
-
]);
|
|
2676
|
+
const {
|
|
2677
|
+
publishableKey,
|
|
2678
|
+
paypalPublishableKey
|
|
2679
|
+
} = resolveSavedPaymentPublishableKeys(realResult, fallbackPublishableKey);
|
|
2680
|
+
const {
|
|
2681
|
+
flopay: instance,
|
|
2682
|
+
paypalFlopay: paypalInstance
|
|
2683
|
+
} = await loadSavedPaymentProviders({
|
|
2684
|
+
publishableKey,
|
|
2685
|
+
paypalPublishableKey,
|
|
2686
|
+
billingApiUrl: resolvedBillingUrl,
|
|
2687
|
+
locale
|
|
2688
|
+
});
|
|
2178
2689
|
flopayRef.current = instance;
|
|
2179
2690
|
setFloPay(instance);
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
paypalFlopayRef.current = paypalInstance;
|
|
2183
|
-
setPaypalFloPay(paypalInstance);
|
|
2184
|
-
} else {
|
|
2185
|
-
paypalFlopayRef.current = null;
|
|
2186
|
-
setPaypalFloPay(null);
|
|
2187
|
-
}
|
|
2691
|
+
paypalFlopayRef.current = paypalInstance;
|
|
2692
|
+
setPaypalFloPay(paypalInstance);
|
|
2188
2693
|
setIsLoading(false);
|
|
2189
2694
|
} catch (err) {
|
|
2190
2695
|
if (initializedHashRef.current === cacheKey) {
|
|
@@ -2196,7 +2701,7 @@ function FloPayCheckout({
|
|
|
2196
2701
|
},
|
|
2197
2702
|
[fallbackPublishableKey, locale, resolvedBillingUrl]
|
|
2198
2703
|
);
|
|
2199
|
-
const handleInlineSessionPatch = (0,
|
|
2704
|
+
const handleInlineSessionPatch = (0, import_react8.useCallback)(async (patch) => {
|
|
2200
2705
|
if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) {
|
|
2201
2706
|
return {
|
|
2202
2707
|
sessionId: resolvedSessionId,
|
|
@@ -2219,21 +2724,61 @@ function FloPayCheckout({
|
|
|
2219
2724
|
resolvedSessionId,
|
|
2220
2725
|
session
|
|
2221
2726
|
]);
|
|
2222
|
-
(0,
|
|
2727
|
+
(0, import_react8.useEffect)(() => {
|
|
2223
2728
|
let cancelled = false;
|
|
2224
2729
|
setLoadError(null);
|
|
2225
2730
|
if (createSessionHash) {
|
|
2226
|
-
if (initializedHashRef.current === createSessionHash) return;
|
|
2227
2731
|
const params = createSessionParamsRef.current;
|
|
2228
2732
|
setSession(buildSyntheticSession(params, checkoutModeProp));
|
|
2229
|
-
setCurrentMode(
|
|
2733
|
+
setCurrentMode(effectiveCreateSessionMode);
|
|
2230
2734
|
setIsLoading(false);
|
|
2735
|
+
if (initializedHashRef.current === createSessionHash) {
|
|
2736
|
+
return () => {
|
|
2737
|
+
cancelled = true;
|
|
2738
|
+
};
|
|
2739
|
+
}
|
|
2231
2740
|
(async () => {
|
|
2741
|
+
const shouldAutoProcessInlineSession = effectiveCreateSessionMode === "auto" && !autoCheckoutAttempted.current;
|
|
2742
|
+
if (shouldAutoProcessInlineSession) {
|
|
2743
|
+
setModeError(null);
|
|
2744
|
+
setModeOverlayError(null);
|
|
2745
|
+
setModeOverlayStatus("processing");
|
|
2746
|
+
}
|
|
2232
2747
|
try {
|
|
2233
|
-
await bootstrapInlineSession();
|
|
2748
|
+
const resolved = await bootstrapInlineSession();
|
|
2749
|
+
const resolvedSession = resolved.result.data.session ?? null;
|
|
2750
|
+
if (!cancelled && shouldAutoProcessInlineSession && resolvedSession) {
|
|
2751
|
+
autoCheckoutAttempted.current = true;
|
|
2752
|
+
await runSavedPaymentFlow(resolvedSession, {
|
|
2753
|
+
attempt3DS: true,
|
|
2754
|
+
fallbackToFull: true,
|
|
2755
|
+
sessionId: resolved.sid || resolvedSession.id
|
|
2756
|
+
});
|
|
2757
|
+
return;
|
|
2758
|
+
}
|
|
2759
|
+
if (!cancelled && shouldAutoProcessInlineSession) {
|
|
2760
|
+
setModeOverlayStatus(null);
|
|
2761
|
+
setModeOverlayError(null);
|
|
2762
|
+
}
|
|
2234
2763
|
} catch (err) {
|
|
2235
2764
|
if (cancelled) return;
|
|
2236
|
-
const
|
|
2765
|
+
const errorCode = err instanceof import_shared7.FloPayError ? err.code : typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
|
|
2766
|
+
if (shouldAutoProcessInlineSession && errorCode === "session_auto_completed") {
|
|
2767
|
+
autoCheckoutAttempted.current = true;
|
|
2768
|
+
setModeOverlayStatus("success");
|
|
2769
|
+
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
2770
|
+
if (!cancelled) {
|
|
2771
|
+
onCompleteRef.current?.({ status: "succeeded" });
|
|
2772
|
+
setModeOverlayStatus(null);
|
|
2773
|
+
setModeOverlayError(null);
|
|
2774
|
+
}
|
|
2775
|
+
return;
|
|
2776
|
+
}
|
|
2777
|
+
if (shouldAutoProcessInlineSession) {
|
|
2778
|
+
setModeOverlayStatus(null);
|
|
2779
|
+
setModeOverlayError(null);
|
|
2780
|
+
}
|
|
2781
|
+
const floPayErr = err instanceof import_shared7.FloPayError ? err : new import_shared7.FloPayError(err instanceof Error ? err.message : "Failed to create session", "api_error");
|
|
2237
2782
|
setLoadError(floPayErr);
|
|
2238
2783
|
}
|
|
2239
2784
|
})();
|
|
@@ -2244,14 +2789,14 @@ function FloPayCheckout({
|
|
|
2244
2789
|
setIsLoading(true);
|
|
2245
2790
|
async function init() {
|
|
2246
2791
|
try {
|
|
2247
|
-
const api = new
|
|
2248
|
-
const result = await api.getUnifiedCheckoutSession(
|
|
2792
|
+
const api = new import_js2.PaymentAPI(resolvedBillingUrl);
|
|
2793
|
+
const result = await api.getUnifiedCheckoutSession(activeSessionId);
|
|
2249
2794
|
if (cancelled) return;
|
|
2250
2795
|
setUnified(result);
|
|
2251
2796
|
const sess = result.data.session ?? null;
|
|
2252
2797
|
setSession(sess);
|
|
2253
2798
|
if (!sess) {
|
|
2254
|
-
throw new
|
|
2799
|
+
throw new import_shared7.FloPayError("No session data returned", "api_error");
|
|
2255
2800
|
}
|
|
2256
2801
|
if (sess.status === "complete") {
|
|
2257
2802
|
setIsLoading(false);
|
|
@@ -2265,22 +2810,20 @@ function FloPayCheckout({
|
|
|
2265
2810
|
autoCheckoutAttempted.current = true;
|
|
2266
2811
|
const stripeInitPromise = initStripe(result);
|
|
2267
2812
|
try {
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2813
|
+
await runSavedPaymentFlow(sess, {
|
|
2814
|
+
attempt3DS: true,
|
|
2815
|
+
fallbackToFull: true,
|
|
2816
|
+
ensureProvidersReady: () => stripeInitPromise,
|
|
2817
|
+
sessionId: activeSessionId || sess.id
|
|
2818
|
+
});
|
|
2273
2819
|
if (cancelled) return;
|
|
2274
2820
|
await stripeInitPromise;
|
|
2275
|
-
const handled = await handleRedirectResult(redirectResult, sess, { attempt3DS: true });
|
|
2276
2821
|
if (!cancelled) {
|
|
2277
|
-
if (!handled) setCurrentMode("full");
|
|
2278
2822
|
setIsLoading(false);
|
|
2279
2823
|
}
|
|
2280
2824
|
return;
|
|
2281
2825
|
} catch {
|
|
2282
2826
|
if (cancelled) return;
|
|
2283
|
-
setCurrentMode("full");
|
|
2284
2827
|
await stripeInitPromise;
|
|
2285
2828
|
if (!cancelled) setIsLoading(false);
|
|
2286
2829
|
return;
|
|
@@ -2290,82 +2833,56 @@ function FloPayCheckout({
|
|
|
2290
2833
|
if (!cancelled) setIsLoading(false);
|
|
2291
2834
|
} catch (err) {
|
|
2292
2835
|
if (cancelled) return;
|
|
2293
|
-
const floPayErr = err instanceof
|
|
2836
|
+
const floPayErr = err instanceof import_shared7.FloPayError ? err : new import_shared7.FloPayError(err instanceof Error ? err.message : "Failed to initialize checkout", "api_error");
|
|
2294
2837
|
setLoadError(floPayErr);
|
|
2295
2838
|
setIsLoading(false);
|
|
2296
2839
|
}
|
|
2297
2840
|
}
|
|
2298
2841
|
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
|
-
]);
|
|
2842
|
+
const {
|
|
2843
|
+
publishableKey,
|
|
2844
|
+
paypalPublishableKey
|
|
2845
|
+
} = resolveSavedPaymentPublishableKeys(result, fallbackPublishableKey);
|
|
2846
|
+
const {
|
|
2847
|
+
flopay: instance,
|
|
2848
|
+
paypalFlopay: paypalInstance
|
|
2849
|
+
} = await loadSavedPaymentProviders({
|
|
2850
|
+
publishableKey,
|
|
2851
|
+
paypalPublishableKey,
|
|
2852
|
+
billingApiUrl: resolvedBillingUrl,
|
|
2853
|
+
locale
|
|
2854
|
+
});
|
|
2326
2855
|
flopayRef.current = instance;
|
|
2327
2856
|
setFloPay(instance);
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
paypalFlopayRef.current = paypalInstance;
|
|
2331
|
-
setPaypalFloPay(paypalInstance);
|
|
2332
|
-
} else {
|
|
2333
|
-
paypalFlopayRef.current = null;
|
|
2334
|
-
setPaypalFloPay(null);
|
|
2335
|
-
}
|
|
2857
|
+
paypalFlopayRef.current = paypalInstance;
|
|
2858
|
+
setPaypalFloPay(paypalInstance);
|
|
2336
2859
|
}
|
|
2337
2860
|
init();
|
|
2338
2861
|
return () => {
|
|
2339
2862
|
cancelled = true;
|
|
2340
2863
|
};
|
|
2341
|
-
}, [
|
|
2342
|
-
|
|
2864
|
+
}, [
|
|
2865
|
+
bootstrapInlineSession,
|
|
2866
|
+
checkoutModeProp,
|
|
2867
|
+
createSessionHash,
|
|
2868
|
+
effectiveCreateSessionMode,
|
|
2869
|
+
initSessionDependency,
|
|
2870
|
+
runSavedPaymentFlow
|
|
2871
|
+
]);
|
|
2872
|
+
const handleConfirmCheckout = (0, import_react8.useCallback)(async () => {
|
|
2343
2873
|
if (confirmProcessing || !session) return;
|
|
2344
2874
|
setConfirmProcessing(true);
|
|
2345
2875
|
setModeError(null);
|
|
2346
2876
|
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");
|
|
2877
|
+
await runSavedPaymentFlow(session, {
|
|
2878
|
+
fallbackToFull: true,
|
|
2879
|
+
sessionId: activeSessionId || session.id
|
|
2880
|
+
});
|
|
2364
2881
|
} finally {
|
|
2365
2882
|
setConfirmProcessing(false);
|
|
2366
2883
|
}
|
|
2367
|
-
}, [
|
|
2368
|
-
const providerOptions = (0,
|
|
2884
|
+
}, [activeSessionId, confirmProcessing, runSavedPaymentFlow, session]);
|
|
2885
|
+
const providerOptions = (0, import_react8.useMemo)(() => {
|
|
2369
2886
|
if (!unified || !session) return void 0;
|
|
2370
2887
|
const opts = {
|
|
2371
2888
|
appearance,
|
|
@@ -2375,16 +2892,16 @@ function FloPayCheckout({
|
|
|
2375
2892
|
if (unified.provider === "stripe" && unified.data.stripe?.clientSecret) {
|
|
2376
2893
|
opts.clientSecret = unified.data.stripe.clientSecret;
|
|
2377
2894
|
} else {
|
|
2378
|
-
const displayTotal = (0,
|
|
2895
|
+
const displayTotal = (0, import_shared7.buildCheckoutDisplayData)(session).total;
|
|
2379
2896
|
opts.amount = Math.round(displayTotal * 100) || session.amount;
|
|
2380
2897
|
opts.currency = session.currency?.toLowerCase();
|
|
2381
2898
|
}
|
|
2382
2899
|
return opts;
|
|
2383
2900
|
}, [unified, session, appearance, resolvedBillingUrl]);
|
|
2384
2901
|
const shouldHandleInlineSessionPatch = Boolean(
|
|
2385
|
-
createSessionParams && !children && layout === "buttons" && onBeforeButtonClick &&
|
|
2902
|
+
createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && effectiveCreateSessionMode === "full"
|
|
2386
2903
|
);
|
|
2387
|
-
const checkoutValue = (0,
|
|
2904
|
+
const checkoutValue = (0, import_react8.useMemo)(
|
|
2388
2905
|
() => ({
|
|
2389
2906
|
session,
|
|
2390
2907
|
loading: isLoading,
|
|
@@ -2406,37 +2923,55 @@ function FloPayCheckout({
|
|
|
2406
2923
|
]
|
|
2407
2924
|
);
|
|
2408
2925
|
const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && (!flopay || !providerOptions);
|
|
2926
|
+
const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2927
|
+
ProcessingOverlay,
|
|
2928
|
+
{
|
|
2929
|
+
status: modeOverlayStatus,
|
|
2930
|
+
errorMessage: modeOverlayError
|
|
2931
|
+
}
|
|
2932
|
+
) : null;
|
|
2409
2933
|
if (isLoading) {
|
|
2410
|
-
if (loadingNode)
|
|
2934
|
+
if (loadingNode) {
|
|
2935
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2936
|
+
loadingNode,
|
|
2937
|
+
modeOverlay
|
|
2938
|
+
] });
|
|
2939
|
+
}
|
|
2411
2940
|
if (layout === "buttons") {
|
|
2412
|
-
const skeletonBar = (h) => /* @__PURE__ */ (0,
|
|
2941
|
+
const skeletonBar = (h) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2413
2942
|
height: h,
|
|
2414
2943
|
borderRadius: 8,
|
|
2415
2944
|
background: "#e5e7eb",
|
|
2416
2945
|
animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
|
|
2417
2946
|
} });
|
|
2418
|
-
return /* @__PURE__ */ (0,
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2947
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2948
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
2949
|
+
showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
2950
|
+
(showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
2951
|
+
skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
2952
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
2953
|
+
] }),
|
|
2954
|
+
modeOverlay
|
|
2423
2955
|
] });
|
|
2424
2956
|
}
|
|
2425
|
-
return /* @__PURE__ */ (0,
|
|
2426
|
-
/* @__PURE__ */ (0,
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2958
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
|
|
2959
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2960
|
+
width: 24,
|
|
2961
|
+
height: 24,
|
|
2962
|
+
border: "2px solid #e5e7eb",
|
|
2963
|
+
borderTopColor: "#6b7280",
|
|
2964
|
+
borderRadius: "50%",
|
|
2965
|
+
animation: "spin 0.6s linear infinite"
|
|
2966
|
+
} }),
|
|
2967
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
2968
|
+
] }),
|
|
2969
|
+
modeOverlay
|
|
2435
2970
|
] });
|
|
2436
2971
|
}
|
|
2437
2972
|
if (loadError) {
|
|
2438
|
-
if (errorNode) return /* @__PURE__ */ (0,
|
|
2439
|
-
return /* @__PURE__ */ (0,
|
|
2973
|
+
if (errorNode) return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: errorNode(loadError) });
|
|
2974
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2440
2975
|
"div",
|
|
2441
2976
|
{
|
|
2442
2977
|
style: {
|
|
@@ -2450,99 +2985,111 @@ function FloPayCheckout({
|
|
|
2450
2985
|
);
|
|
2451
2986
|
}
|
|
2452
2987
|
if (shouldShowInterimButtons) {
|
|
2453
|
-
return /* @__PURE__ */ (0,
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2988
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2989
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2990
|
+
InterimButtonsView,
|
|
2991
|
+
{
|
|
2992
|
+
onButtonClick,
|
|
2993
|
+
showPayPal,
|
|
2994
|
+
showApplePay,
|
|
2995
|
+
showGooglePay,
|
|
2996
|
+
buttonsTheme,
|
|
2997
|
+
buttonsStyles,
|
|
2998
|
+
cardButtonContent,
|
|
2999
|
+
cardBackButtonContent,
|
|
3000
|
+
cardTitleContent
|
|
3001
|
+
}
|
|
3002
|
+
) }),
|
|
3003
|
+
modeOverlay
|
|
3004
|
+
] });
|
|
3005
|
+
}
|
|
3006
|
+
if (!flopay || !providerOptions) {
|
|
3007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: modeOverlay });
|
|
2467
3008
|
}
|
|
2468
|
-
if (!flopay || !providerOptions) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, {});
|
|
2469
3009
|
if (currentMode === "confirm") {
|
|
2470
|
-
return /* @__PURE__ */ (0,
|
|
2471
|
-
|
|
3010
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
3011
|
+
/* @__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: [
|
|
3012
|
+
modeError && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3013
|
+
"div",
|
|
3014
|
+
{
|
|
3015
|
+
style: {
|
|
3016
|
+
color: "#dc2626",
|
|
3017
|
+
fontSize: "0.875rem",
|
|
3018
|
+
marginBottom: "0.75rem",
|
|
3019
|
+
textAlign: "center"
|
|
3020
|
+
},
|
|
3021
|
+
children: modeError
|
|
3022
|
+
}
|
|
3023
|
+
),
|
|
3024
|
+
renderConfirmButton ? renderConfirmButton({
|
|
3025
|
+
onConfirm: handleConfirmCheckout,
|
|
3026
|
+
isProcessing: confirmProcessing
|
|
3027
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3028
|
+
"button",
|
|
3029
|
+
{
|
|
3030
|
+
type: "button",
|
|
3031
|
+
onClick: handleConfirmCheckout,
|
|
3032
|
+
disabled: confirmProcessing,
|
|
3033
|
+
style: {
|
|
3034
|
+
width: "100%",
|
|
3035
|
+
padding: "0.875rem",
|
|
3036
|
+
backgroundColor: "#4A49FF",
|
|
3037
|
+
color: "white",
|
|
3038
|
+
border: "none",
|
|
3039
|
+
borderRadius: "8px",
|
|
3040
|
+
fontSize: "1rem",
|
|
3041
|
+
fontWeight: 600,
|
|
3042
|
+
cursor: confirmProcessing ? "not-allowed" : "pointer",
|
|
3043
|
+
opacity: confirmProcessing ? 0.6 : 1
|
|
3044
|
+
},
|
|
3045
|
+
children: confirmProcessing ? "Processing..." : confirmLabel ?? "Confirm Purchase"
|
|
3046
|
+
}
|
|
3047
|
+
)
|
|
3048
|
+
] }) }) }),
|
|
3049
|
+
modeOverlay
|
|
3050
|
+
] });
|
|
3051
|
+
}
|
|
3052
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
3053
|
+
/* @__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: [
|
|
3054
|
+
modeError && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2472
3055
|
"div",
|
|
2473
3056
|
{
|
|
2474
3057
|
style: {
|
|
2475
|
-
|
|
2476
|
-
fontSize: "0.875rem",
|
|
3058
|
+
padding: "0.75rem 1rem",
|
|
2477
3059
|
marginBottom: "0.75rem",
|
|
2478
|
-
|
|
3060
|
+
backgroundColor: "#FEF3C7",
|
|
3061
|
+
border: "1px solid #F59E0B",
|
|
3062
|
+
borderRadius: "8px",
|
|
3063
|
+
color: "#92400E",
|
|
3064
|
+
fontSize: "0.875rem"
|
|
2479
3065
|
},
|
|
2480
3066
|
children: modeError
|
|
2481
3067
|
}
|
|
2482
3068
|
),
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
isProcessing: confirmProcessing
|
|
2486
|
-
}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2487
|
-
"button",
|
|
3069
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3070
|
+
SessionInjector,
|
|
2488
3071
|
{
|
|
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"
|
|
3072
|
+
sessionId: activeSessionId,
|
|
3073
|
+
billingApiUrl: resolvedBillingUrl,
|
|
3074
|
+
session,
|
|
3075
|
+
children
|
|
2505
3076
|
}
|
|
2506
3077
|
)
|
|
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)(
|
|
3078
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2534
3079
|
SplitCardForm,
|
|
2535
3080
|
{
|
|
2536
|
-
sessionId:
|
|
3081
|
+
sessionId: activeSessionId,
|
|
2537
3082
|
email: session?.customer?.email,
|
|
2538
3083
|
userId: session?.customer?.id,
|
|
2539
3084
|
firstName: session?.customer?.firstName,
|
|
2540
3085
|
lastName: session?.customer?.lastName,
|
|
2541
|
-
totalAmount: session ? Math.round((0,
|
|
3086
|
+
totalAmount: session ? Math.round((0, import_shared7.buildCheckoutDisplayData)(session).total * 100) : 0,
|
|
2542
3087
|
currency: session?.currency?.toLowerCase() ?? "usd",
|
|
2543
3088
|
onComplete,
|
|
2544
3089
|
onError,
|
|
2545
3090
|
onDecline,
|
|
3091
|
+
error: modeError,
|
|
3092
|
+
onErrorChange: setModeError,
|
|
2546
3093
|
onFullNameChange,
|
|
2547
3094
|
showPayPal,
|
|
2548
3095
|
showApplePay,
|
|
@@ -2553,6 +3100,7 @@ function FloPayCheckout({
|
|
|
2553
3100
|
cardButtonContent,
|
|
2554
3101
|
cardBackButtonContent,
|
|
2555
3102
|
cardTitleContent,
|
|
3103
|
+
showSecurityFooter,
|
|
2556
3104
|
onButtonClick,
|
|
2557
3105
|
onBeforeButtonClick,
|
|
2558
3106
|
enableAVS,
|
|
@@ -2563,8 +3111,9 @@ function FloPayCheckout({
|
|
|
2563
3111
|
submitLabel,
|
|
2564
3112
|
className
|
|
2565
3113
|
}
|
|
2566
|
-
)
|
|
2567
|
-
|
|
3114
|
+
) }) }),
|
|
3115
|
+
modeOverlay
|
|
3116
|
+
] });
|
|
2568
3117
|
}
|
|
2569
3118
|
function SessionInjector({
|
|
2570
3119
|
sessionId,
|
|
@@ -2572,8 +3121,8 @@ function SessionInjector({
|
|
|
2572
3121
|
session,
|
|
2573
3122
|
children
|
|
2574
3123
|
}) {
|
|
2575
|
-
return /* @__PURE__ */ (0,
|
|
2576
|
-
if (!
|
|
3124
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: import_react8.default.Children.map(children, (child) => {
|
|
3125
|
+
if (!import_react8.default.isValidElement(child)) return child;
|
|
2577
3126
|
const existing = child.props;
|
|
2578
3127
|
const injected = {};
|
|
2579
3128
|
if (!existing.sessionId) injected.sessionId = sessionId;
|
|
@@ -2587,7 +3136,7 @@ function SessionInjector({
|
|
|
2587
3136
|
injected.lastName = session.customer.lastName;
|
|
2588
3137
|
}
|
|
2589
3138
|
if (Object.keys(injected).length === 0) return child;
|
|
2590
|
-
return
|
|
3139
|
+
return import_react8.default.cloneElement(child, injected);
|
|
2591
3140
|
}) });
|
|
2592
3141
|
}
|
|
2593
3142
|
function InterimButtonsView({
|
|
@@ -2605,15 +3154,15 @@ function InterimButtonsView({
|
|
|
2605
3154
|
cardBackButtonContent,
|
|
2606
3155
|
cardTitleContent
|
|
2607
3156
|
}) {
|
|
2608
|
-
const [showCardForm, setShowCardForm] = (0,
|
|
3157
|
+
const [showCardForm, setShowCardForm] = (0, import_react8.useState)(false);
|
|
2609
3158
|
const isCardOpenControlled = typeof cardOpen === "boolean";
|
|
2610
|
-
(0,
|
|
3159
|
+
(0, import_react8.useEffect)(() => {
|
|
2611
3160
|
if (isCardOpenControlled) {
|
|
2612
3161
|
setShowCardForm(cardOpen);
|
|
2613
3162
|
}
|
|
2614
3163
|
}, [cardOpen, isCardOpenControlled]);
|
|
2615
|
-
const bStyles = (0,
|
|
2616
|
-
const base = (0,
|
|
3164
|
+
const bStyles = (0, import_react8.useMemo)(() => {
|
|
3165
|
+
const base = (0, import_shared7.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
2617
3166
|
if (!stylesOverride) return base;
|
|
2618
3167
|
return {
|
|
2619
3168
|
...base,
|
|
@@ -2626,7 +3175,7 @@ function InterimButtonsView({
|
|
|
2626
3175
|
title: { ...base.title, ...stylesOverride.title }
|
|
2627
3176
|
};
|
|
2628
3177
|
}, [buttonsTheme, stylesOverride]);
|
|
2629
|
-
const skeleton = (h) => /* @__PURE__ */ (0,
|
|
3178
|
+
const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2630
3179
|
height: h,
|
|
2631
3180
|
borderRadius: 8,
|
|
2632
3181
|
background: "#e5e7eb",
|
|
@@ -2638,15 +3187,15 @@ function InterimButtonsView({
|
|
|
2638
3187
|
const inputBg = bStyles.cardInputBackground ?? "white";
|
|
2639
3188
|
const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
|
|
2640
3189
|
const hideTitle = isEmptySlotContent(cardTitleContent);
|
|
2641
|
-
return /* @__PURE__ */ (0,
|
|
3190
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
|
|
2642
3191
|
backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
|
|
2643
3192
|
borderRadius: "8px",
|
|
2644
3193
|
animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
|
|
2645
3194
|
overflow: "hidden",
|
|
2646
3195
|
...bStyles.cardFormContainer
|
|
2647
3196
|
}, children: [
|
|
2648
|
-
/* @__PURE__ */ (0,
|
|
2649
|
-
/* @__PURE__ */ (0,
|
|
3197
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
|
|
3198
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2650
3199
|
"button",
|
|
2651
3200
|
{
|
|
2652
3201
|
type: "button",
|
|
@@ -2673,7 +3222,7 @@ function InterimButtonsView({
|
|
|
2673
3222
|
...bStyles.backButton
|
|
2674
3223
|
},
|
|
2675
3224
|
children: [
|
|
2676
|
-
/* @__PURE__ */ (0,
|
|
3225
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: {
|
|
2677
3226
|
display: "inline-flex",
|
|
2678
3227
|
alignItems: "center",
|
|
2679
3228
|
justifyContent: "center",
|
|
@@ -2682,12 +3231,12 @@ function InterimButtonsView({
|
|
|
2682
3231
|
borderRadius: "50%",
|
|
2683
3232
|
backgroundColor: "#f3f4f6",
|
|
2684
3233
|
...bStyles.backButtonIcon
|
|
2685
|
-
}, children: /* @__PURE__ */ (0,
|
|
2686
|
-
/* @__PURE__ */ (0,
|
|
3234
|
+
}, 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" }) }) }),
|
|
3235
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
2687
3236
|
]
|
|
2688
3237
|
}
|
|
2689
3238
|
),
|
|
2690
|
-
hideTitle ? /* @__PURE__ */ (0,
|
|
3239
|
+
hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2691
3240
|
flex: 1,
|
|
2692
3241
|
textAlign: "center",
|
|
2693
3242
|
fontWeight: 600,
|
|
@@ -2695,15 +3244,15 @@ function InterimButtonsView({
|
|
|
2695
3244
|
color: "#262833",
|
|
2696
3245
|
paddingRight: 80,
|
|
2697
3246
|
...bStyles.title
|
|
2698
|
-
}, children: /* @__PURE__ */ (0,
|
|
3247
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TitleContentSlot, { content: cardTitleContent }) })
|
|
2699
3248
|
] }),
|
|
2700
|
-
/* @__PURE__ */ (0,
|
|
2701
|
-
/* @__PURE__ */ (0,
|
|
2702
|
-
/* @__PURE__ */ (0,
|
|
2703
|
-
/* @__PURE__ */ (0,
|
|
3249
|
+
/* @__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" } }) }),
|
|
3250
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex" }, children: [
|
|
3251
|
+
/* @__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" } }) }),
|
|
3252
|
+
/* @__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
3253
|
] }),
|
|
2705
|
-
/* @__PURE__ */ (0,
|
|
2706
|
-
/* @__PURE__ */ (0,
|
|
3254
|
+
/* @__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" } }) }),
|
|
3255
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2707
3256
|
height: 50,
|
|
2708
3257
|
borderRadius: 8,
|
|
2709
3258
|
marginTop: 16,
|
|
@@ -2712,7 +3261,7 @@ function InterimButtonsView({
|
|
|
2712
3261
|
...bStyles.submitButton,
|
|
2713
3262
|
opacity: 0.5
|
|
2714
3263
|
} }),
|
|
2715
|
-
/* @__PURE__ */ (0,
|
|
3264
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `
|
|
2716
3265
|
@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
2717
3266
|
@keyframes flopay-interim-expand {
|
|
2718
3267
|
0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
|
|
@@ -2722,10 +3271,10 @@ function InterimButtonsView({
|
|
|
2722
3271
|
` })
|
|
2723
3272
|
] });
|
|
2724
3273
|
}
|
|
2725
|
-
return /* @__PURE__ */ (0,
|
|
3274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
2726
3275
|
showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
2727
3276
|
(showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
2728
|
-
/* @__PURE__ */ (0,
|
|
3277
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2729
3278
|
"button",
|
|
2730
3279
|
{
|
|
2731
3280
|
type: "button",
|
|
@@ -2765,10 +3314,10 @@ function InterimButtonsView({
|
|
|
2765
3314
|
onMouseUp: (e) => {
|
|
2766
3315
|
e.currentTarget.style.transform = "scale(1)";
|
|
2767
3316
|
},
|
|
2768
|
-
children: /* @__PURE__ */ (0,
|
|
3317
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardButtonContentSlot, { content: cardButtonContent })
|
|
2769
3318
|
}
|
|
2770
3319
|
),
|
|
2771
|
-
errorMessage && /* @__PURE__ */ (0,
|
|
3320
|
+
errorMessage && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
|
|
2772
3321
|
margin: "0.25rem 0",
|
|
2773
3322
|
padding: "0.625rem 0.875rem",
|
|
2774
3323
|
background: "#FEF2F2",
|
|
@@ -2782,21 +3331,21 @@ function InterimButtonsView({
|
|
|
2782
3331
|
gap: "0.5rem",
|
|
2783
3332
|
...bStyles.errorBanner
|
|
2784
3333
|
}, children: [
|
|
2785
|
-
/* @__PURE__ */ (0,
|
|
3334
|
+
/* @__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
3335
|
errorMessage
|
|
2787
3336
|
] }),
|
|
2788
|
-
/* @__PURE__ */ (0,
|
|
3337
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
2789
3338
|
] });
|
|
2790
3339
|
}
|
|
2791
3340
|
|
|
2792
3341
|
// src/checkout-form.tsx
|
|
2793
|
-
var
|
|
2794
|
-
var
|
|
2795
|
-
var
|
|
3342
|
+
var import_shared8 = require("@flopay/shared");
|
|
3343
|
+
var import_react9 = require("react");
|
|
3344
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2796
3345
|
var WALLET_RESUME_KEY2 = "flopay_wallet_resume";
|
|
2797
|
-
var CheckoutForm = (0,
|
|
3346
|
+
var CheckoutForm = (0, import_react9.forwardRef)(
|
|
2798
3347
|
function CheckoutForm2(props, ref) {
|
|
2799
|
-
return /* @__PURE__ */ (0,
|
|
3348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutFormInner, { ...props, innerRef: ref });
|
|
2800
3349
|
}
|
|
2801
3350
|
);
|
|
2802
3351
|
function CheckoutFormInner({
|
|
@@ -2825,27 +3374,27 @@ function CheckoutFormInner({
|
|
|
2825
3374
|
const paypalFlopay = usePayPalFloPay();
|
|
2826
3375
|
const elements = useElements();
|
|
2827
3376
|
const contextBillingUrl = useBillingApiUrl();
|
|
2828
|
-
const [processing, setProcessing] = (0,
|
|
2829
|
-
const [error, setError] = (0,
|
|
2830
|
-
const [is3DSActive, setIs3DSActive] = (0,
|
|
3377
|
+
const [processing, setProcessing] = (0, import_react9.useState)(false);
|
|
3378
|
+
const [error, setError] = (0, import_react9.useState)(null);
|
|
3379
|
+
const [is3DSActive, setIs3DSActive] = (0, import_react9.useState)(false);
|
|
2831
3380
|
const displayError = externalError ?? error;
|
|
2832
3381
|
const isSubmitting = externalProcessing ?? processing;
|
|
2833
3382
|
const isSelfContained = !onTokenizedBody;
|
|
2834
3383
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
2835
|
-
const updateError = (0,
|
|
3384
|
+
const updateError = (0, import_react9.useCallback)(
|
|
2836
3385
|
(err) => {
|
|
2837
3386
|
setError(err);
|
|
2838
3387
|
onErrorChange?.(err);
|
|
2839
3388
|
},
|
|
2840
3389
|
[onErrorChange]
|
|
2841
3390
|
);
|
|
2842
|
-
const emitDecline = (0,
|
|
3391
|
+
const emitDecline = (0, import_react9.useCallback)(
|
|
2843
3392
|
(input, overrides) => {
|
|
2844
3393
|
onDecline?.(buildDeclineEvent("card", input, overrides));
|
|
2845
3394
|
},
|
|
2846
3395
|
[onDecline]
|
|
2847
3396
|
);
|
|
2848
|
-
const processPaymentInternal = (0,
|
|
3397
|
+
const processPaymentInternal = (0, import_react9.useCallback)(
|
|
2849
3398
|
async (tokenizedBody) => {
|
|
2850
3399
|
setProcessing(true);
|
|
2851
3400
|
updateError(null);
|
|
@@ -2871,7 +3420,8 @@ function CheckoutFormInner({
|
|
|
2871
3420
|
if (response.ok) {
|
|
2872
3421
|
onComplete?.({
|
|
2873
3422
|
status: "succeeded",
|
|
2874
|
-
paymentIntentId: tokenizedBody.threeDSecureActionResultTokenId
|
|
3423
|
+
paymentIntentId: tokenizedBody.threeDSecureActionResultTokenId,
|
|
3424
|
+
paymentMethodId: resolveTokenizedPaymentMethodId(tokenizedBody)
|
|
2875
3425
|
});
|
|
2876
3426
|
return;
|
|
2877
3427
|
}
|
|
@@ -2898,7 +3448,8 @@ function CheckoutFormInner({
|
|
|
2898
3448
|
await processPaymentInternal({
|
|
2899
3449
|
id: result.paymentIntentId,
|
|
2900
3450
|
type: "card",
|
|
2901
|
-
threeDSecureActionResultTokenId: result.paymentIntentId
|
|
3451
|
+
threeDSecureActionResultTokenId: result.paymentIntentId,
|
|
3452
|
+
originalPaymentMethodId: resolveTokenizedPaymentMethodId(tokenizedBody)
|
|
2902
3453
|
});
|
|
2903
3454
|
}
|
|
2904
3455
|
} finally {
|
|
@@ -2953,7 +3504,7 @@ function CheckoutFormInner({
|
|
|
2953
3504
|
},
|
|
2954
3505
|
[baseUrl, sessionId, userId, email, firstName, lastName, chv, flopay, paypalFlopay, onComplete, onError, onDecline, updateError, emitDecline]
|
|
2955
3506
|
);
|
|
2956
|
-
const dispatchTokenizedBody = (0,
|
|
3507
|
+
const dispatchTokenizedBody = (0, import_react9.useCallback)(
|
|
2957
3508
|
(tokenizedBody) => {
|
|
2958
3509
|
if (onTokenizedBody) {
|
|
2959
3510
|
onTokenizedBody(tokenizedBody);
|
|
@@ -2963,7 +3514,7 @@ function CheckoutFormInner({
|
|
|
2963
3514
|
},
|
|
2964
3515
|
[onTokenizedBody, processPaymentInternal]
|
|
2965
3516
|
);
|
|
2966
|
-
(0,
|
|
3517
|
+
(0, import_react9.useImperativeHandle)(innerRef, () => ({
|
|
2967
3518
|
async handleNextAction(secret) {
|
|
2968
3519
|
if (!flopay) return;
|
|
2969
3520
|
setIs3DSActive(true);
|
|
@@ -2990,7 +3541,7 @@ function CheckoutFormInner({
|
|
|
2990
3541
|
}
|
|
2991
3542
|
}
|
|
2992
3543
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
2993
|
-
(0,
|
|
3544
|
+
(0, import_react9.useEffect)(() => {
|
|
2994
3545
|
if (typeof window === "undefined") return;
|
|
2995
3546
|
const stored = localStorage.getItem(WALLET_RESUME_KEY2);
|
|
2996
3547
|
if (!stored) return;
|
|
@@ -3008,7 +3559,7 @@ function CheckoutFormInner({
|
|
|
3008
3559
|
localStorage.removeItem(WALLET_RESUME_KEY2);
|
|
3009
3560
|
}
|
|
3010
3561
|
}, [sessionId, dispatchTokenizedBody]);
|
|
3011
|
-
const handleSubmit = (0,
|
|
3562
|
+
const handleSubmit = (0, import_react9.useCallback)(
|
|
3012
3563
|
async (e) => {
|
|
3013
3564
|
e.preventDefault();
|
|
3014
3565
|
if (!flopay || !elements || isSubmitting) return;
|
|
@@ -3027,7 +3578,7 @@ function CheckoutFormInner({
|
|
|
3027
3578
|
return;
|
|
3028
3579
|
}
|
|
3029
3580
|
if (!sessionId || !email) {
|
|
3030
|
-
throw new
|
|
3581
|
+
throw new import_shared8.FloPayError("Missing sessionId or email", "validation_error");
|
|
3031
3582
|
}
|
|
3032
3583
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
3033
3584
|
method: "POST",
|
|
@@ -3039,10 +3590,10 @@ function CheckoutFormInner({
|
|
|
3039
3590
|
isPaypal: false
|
|
3040
3591
|
})
|
|
3041
3592
|
});
|
|
3042
|
-
if (!intentResponse.ok) throw new
|
|
3593
|
+
if (!intentResponse.ok) throw new import_shared8.FloPayError("Failed to create payment intent", "api_error");
|
|
3043
3594
|
const intentJson = await intentResponse.json();
|
|
3044
3595
|
const intentClientSecret = intentJson.data?.id;
|
|
3045
|
-
if (!intentClientSecret) throw new
|
|
3596
|
+
if (!intentClientSecret) throw new import_shared8.FloPayError("No client_secret in payment intent response", "api_error");
|
|
3046
3597
|
const confirmResult = await flopay.confirmCardPayment({
|
|
3047
3598
|
clientSecret: intentClientSecret,
|
|
3048
3599
|
paymentMethodId: pmResult.paymentMethodId
|
|
@@ -3056,7 +3607,8 @@ function CheckoutFormInner({
|
|
|
3056
3607
|
dispatchTokenizedBody({
|
|
3057
3608
|
id: pmResult.paymentMethodId,
|
|
3058
3609
|
type: "card",
|
|
3059
|
-
threeDSecureActionResultTokenId: confirmResult.paymentIntentId
|
|
3610
|
+
threeDSecureActionResultTokenId: confirmResult.paymentIntentId,
|
|
3611
|
+
originalPaymentMethodId: pmResult.paymentMethodId
|
|
3060
3612
|
});
|
|
3061
3613
|
} catch (err) {
|
|
3062
3614
|
updateError(err instanceof Error ? err.message : "An unexpected error occurred");
|
|
@@ -3070,8 +3622,8 @@ function CheckoutFormInner({
|
|
|
3070
3622
|
[flopay, elements, isSubmitting, sessionId, email, baseUrl, isSelfContained, dispatchTokenizedBody, onError, updateError, emitDecline]
|
|
3071
3623
|
);
|
|
3072
3624
|
const isReady = flopay !== null && elements !== null;
|
|
3073
|
-
return /* @__PURE__ */ (0,
|
|
3074
|
-
(is3DSActive || isSubmitting) && /* @__PURE__ */ (0,
|
|
3625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
3626
|
+
(is3DSActive || isSubmitting) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-testid": "flopay-overlay", style: {
|
|
3075
3627
|
position: "absolute",
|
|
3076
3628
|
inset: 0,
|
|
3077
3629
|
background: "rgba(255,255,255,0.7)",
|
|
@@ -3080,12 +3632,12 @@ function CheckoutFormInner({
|
|
|
3080
3632
|
justifyContent: "center",
|
|
3081
3633
|
zIndex: 10
|
|
3082
3634
|
}, 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,
|
|
3635
|
+
!isReady && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
|
|
3636
|
+
isReady && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
3637
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PaymentElement, { options: { layout } }),
|
|
3638
|
+
showAddress && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
|
|
3639
|
+
displayError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
|
|
3640
|
+
children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3089
3641
|
"button",
|
|
3090
3642
|
{
|
|
3091
3643
|
type: "submit",
|
|
@@ -3099,9 +3651,9 @@ function CheckoutFormInner({
|
|
|
3099
3651
|
}
|
|
3100
3652
|
|
|
3101
3653
|
// src/paypal-button.tsx
|
|
3102
|
-
var
|
|
3103
|
-
var
|
|
3104
|
-
var
|
|
3654
|
+
var import_shared9 = require("@flopay/shared");
|
|
3655
|
+
var import_react10 = require("react");
|
|
3656
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
3105
3657
|
function PayPalButton({
|
|
3106
3658
|
sessionId,
|
|
3107
3659
|
billingApiUrl,
|
|
@@ -3118,11 +3670,11 @@ function PayPalButton({
|
|
|
3118
3670
|
const flopay = useFloPay();
|
|
3119
3671
|
const elements = useElements();
|
|
3120
3672
|
const contextBillingUrl = useBillingApiUrl();
|
|
3121
|
-
const [ready, setReady] = (0,
|
|
3122
|
-
const [submitting, setSubmitting] = (0,
|
|
3123
|
-
const paypalResumeAttempted = (0,
|
|
3673
|
+
const [ready, setReady] = (0, import_react10.useState)(false);
|
|
3674
|
+
const [submitting, setSubmitting] = (0, import_react10.useState)(false);
|
|
3675
|
+
const paypalResumeAttempted = (0, import_react10.useRef)(false);
|
|
3124
3676
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
3125
|
-
const processPaymentInternal = (0,
|
|
3677
|
+
const processPaymentInternal = (0, import_react10.useCallback)(
|
|
3126
3678
|
async (tokenizedBody) => {
|
|
3127
3679
|
try {
|
|
3128
3680
|
const response = await fetch(`${baseUrl}/v1/checkouts/sessions/process`, {
|
|
@@ -3155,7 +3707,7 @@ function PayPalButton({
|
|
|
3155
3707
|
},
|
|
3156
3708
|
[baseUrl, sessionId, userId, email, firstName, lastName, chv, onComplete, onErrorChange]
|
|
3157
3709
|
);
|
|
3158
|
-
const dispatchTokenizedBody = (0,
|
|
3710
|
+
const dispatchTokenizedBody = (0, import_react10.useCallback)(
|
|
3159
3711
|
(body) => {
|
|
3160
3712
|
if (onTokenizedBody) {
|
|
3161
3713
|
onTokenizedBody(body);
|
|
@@ -3165,7 +3717,7 @@ function PayPalButton({
|
|
|
3165
3717
|
},
|
|
3166
3718
|
[onTokenizedBody, processPaymentInternal]
|
|
3167
3719
|
);
|
|
3168
|
-
(0,
|
|
3720
|
+
(0, import_react10.useEffect)(() => {
|
|
3169
3721
|
if (!flopay || paypalResumeAttempted.current) return;
|
|
3170
3722
|
const params = new URLSearchParams(window.location.search);
|
|
3171
3723
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -3213,13 +3765,13 @@ function PayPalButton({
|
|
|
3213
3765
|
}
|
|
3214
3766
|
})();
|
|
3215
3767
|
}, [flopay, dispatchTokenizedBody, onErrorChange]);
|
|
3216
|
-
const handlePayPalConfirm = (0,
|
|
3768
|
+
const handlePayPalConfirm = (0, import_react10.useCallback)(async () => {
|
|
3217
3769
|
if (!flopay || !elements) return;
|
|
3218
3770
|
try {
|
|
3219
3771
|
setSubmitting(true);
|
|
3220
3772
|
onErrorChange?.(null);
|
|
3221
3773
|
if (!sessionId || !email) {
|
|
3222
|
-
throw new
|
|
3774
|
+
throw new import_shared9.FloPayError("Missing sessionId or email for PayPal payment", "validation_error");
|
|
3223
3775
|
}
|
|
3224
3776
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
3225
3777
|
method: "POST",
|
|
@@ -3231,10 +3783,10 @@ function PayPalButton({
|
|
|
3231
3783
|
isPaypal: "true"
|
|
3232
3784
|
})
|
|
3233
3785
|
});
|
|
3234
|
-
if (!intentResponse.ok) throw new
|
|
3786
|
+
if (!intentResponse.ok) throw new import_shared9.FloPayError("Failed to create payment intent", "api_error");
|
|
3235
3787
|
const intentJson = await intentResponse.json();
|
|
3236
3788
|
const intentClientSecret = intentJson.data?.id;
|
|
3237
|
-
if (!intentClientSecret) throw new
|
|
3789
|
+
if (!intentClientSecret) throw new import_shared9.FloPayError("No client_secret in response", "api_error");
|
|
3238
3790
|
const result = await flopay.confirmPayment({
|
|
3239
3791
|
clientSecret: intentClientSecret,
|
|
3240
3792
|
returnUrl: window.location.href
|
|
@@ -3256,11 +3808,11 @@ function PayPalButton({
|
|
|
3256
3808
|
}
|
|
3257
3809
|
}, [flopay, elements, sessionId, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
|
|
3258
3810
|
if (!flopay || !elements) {
|
|
3259
|
-
return /* @__PURE__ */ (0,
|
|
3811
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
|
|
3260
3812
|
}
|
|
3261
|
-
return /* @__PURE__ */ (0,
|
|
3262
|
-
!ready && /* @__PURE__ */ (0,
|
|
3263
|
-
/* @__PURE__ */ (0,
|
|
3813
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3814
|
+
!ready && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
|
|
3815
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3264
3816
|
"button",
|
|
3265
3817
|
{
|
|
3266
3818
|
type: "button",
|
|
@@ -3282,7 +3834,7 @@ function PayPalButton({
|
|
|
3282
3834
|
children: submitting ? "Processing..." : "PayPal"
|
|
3283
3835
|
}
|
|
3284
3836
|
) }),
|
|
3285
|
-
(submitting || isProcessing) && /* @__PURE__ */ (0,
|
|
3837
|
+
(submitting || isProcessing) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
3286
3838
|
position: "fixed",
|
|
3287
3839
|
inset: 0,
|
|
3288
3840
|
background: "rgba(0,0,0,0.4)",
|
|
@@ -3290,7 +3842,7 @@ function PayPalButton({
|
|
|
3290
3842
|
alignItems: "center",
|
|
3291
3843
|
justifyContent: "center",
|
|
3292
3844
|
zIndex: 1e3
|
|
3293
|
-
}, children: /* @__PURE__ */ (0,
|
|
3845
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
3294
3846
|
background: "white",
|
|
3295
3847
|
borderRadius: 8,
|
|
3296
3848
|
padding: "1.5rem",
|
|
@@ -3300,6 +3852,649 @@ function PayPalButton({
|
|
|
3300
3852
|
}, children: "Processing PayPal payment..." }) })
|
|
3301
3853
|
] });
|
|
3302
3854
|
}
|
|
3855
|
+
|
|
3856
|
+
// src/automatic-payment-button.tsx
|
|
3857
|
+
var import_react11 = require("react");
|
|
3858
|
+
var import_js3 = require("@flopay/js");
|
|
3859
|
+
var import_shared10 = require("@flopay/shared");
|
|
3860
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
3861
|
+
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
|
|
3862
|
+
var PAYPAL_RESUME_STORAGE_KEY = "flopay_automatic_payment_button_resume";
|
|
3863
|
+
function sleep2(ms) {
|
|
3864
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3865
|
+
}
|
|
3866
|
+
function coerceError(err, fallbackMessage) {
|
|
3867
|
+
if (err instanceof import_shared10.FloPayError) {
|
|
3868
|
+
return err;
|
|
3869
|
+
}
|
|
3870
|
+
return new import_shared10.FloPayError(
|
|
3871
|
+
err instanceof Error ? err.message : fallbackMessage,
|
|
3872
|
+
"api_error"
|
|
3873
|
+
);
|
|
3874
|
+
}
|
|
3875
|
+
function canUseStorage() {
|
|
3876
|
+
return typeof window !== "undefined" && typeof window.sessionStorage !== "undefined";
|
|
3877
|
+
}
|
|
3878
|
+
function shouldShowFallbackCheckout(error, sessionId) {
|
|
3879
|
+
if (!sessionId) return false;
|
|
3880
|
+
if (error.type === "validation_error") return false;
|
|
3881
|
+
if (error.checkoutMethod && error.checkoutMethod !== "card") return false;
|
|
3882
|
+
return true;
|
|
3883
|
+
}
|
|
3884
|
+
function readPayPalResumeState() {
|
|
3885
|
+
if (!canUseStorage()) return null;
|
|
3886
|
+
try {
|
|
3887
|
+
const raw = window.sessionStorage.getItem(PAYPAL_RESUME_STORAGE_KEY);
|
|
3888
|
+
if (!raw) return null;
|
|
3889
|
+
return JSON.parse(raw);
|
|
3890
|
+
} catch {
|
|
3891
|
+
return null;
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
function persistPayPalResumeState(state) {
|
|
3895
|
+
if (!canUseStorage()) return;
|
|
3896
|
+
try {
|
|
3897
|
+
window.sessionStorage.setItem(PAYPAL_RESUME_STORAGE_KEY, JSON.stringify(state));
|
|
3898
|
+
} catch (error) {
|
|
3899
|
+
console.warn("[FloPayAutomaticPaymentButton] Failed to persist PayPal resume state.", error);
|
|
3900
|
+
}
|
|
3901
|
+
}
|
|
3902
|
+
function clearPayPalResumeState() {
|
|
3903
|
+
if (!canUseStorage()) return;
|
|
3904
|
+
try {
|
|
3905
|
+
window.sessionStorage.removeItem(PAYPAL_RESUME_STORAGE_KEY);
|
|
3906
|
+
} catch (error) {
|
|
3907
|
+
console.warn("[FloPayAutomaticPaymentButton] Failed to clear PayPal resume state.", error);
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
function clearPayPalRedirectParams() {
|
|
3911
|
+
if (typeof window === "undefined") return;
|
|
3912
|
+
const url = new URL(window.location.href);
|
|
3913
|
+
const keys = ["payment_intent", "payment_intent_client_secret", "redirect_status"];
|
|
3914
|
+
let changed = false;
|
|
3915
|
+
for (const key of keys) {
|
|
3916
|
+
if (url.searchParams.has(key)) {
|
|
3917
|
+
url.searchParams.delete(key);
|
|
3918
|
+
changed = true;
|
|
3919
|
+
}
|
|
3920
|
+
}
|
|
3921
|
+
if (changed) {
|
|
3922
|
+
window.history.replaceState({}, "", url.toString());
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
3925
|
+
function resolveCreateSessionDraft(props) {
|
|
3926
|
+
if (props.createSession) {
|
|
3927
|
+
return {
|
|
3928
|
+
...props.createSession,
|
|
3929
|
+
checkoutMode: "auto"
|
|
3930
|
+
};
|
|
3931
|
+
}
|
|
3932
|
+
if (!props.clientId || !props.account || !props.successUrl || !props.cancelUrl) {
|
|
3933
|
+
return null;
|
|
3934
|
+
}
|
|
3935
|
+
return {
|
|
3936
|
+
clientId: props.clientId,
|
|
3937
|
+
items: props.items,
|
|
3938
|
+
subscriptions: props.subscriptions,
|
|
3939
|
+
account: props.account,
|
|
3940
|
+
successUrl: props.successUrl,
|
|
3941
|
+
cancelUrl: props.cancelUrl,
|
|
3942
|
+
couponCodes: props.couponCodes,
|
|
3943
|
+
tagsData: props.tagsData,
|
|
3944
|
+
utmMetadata: props.utmMetadata,
|
|
3945
|
+
checkoutMode: "auto"
|
|
3946
|
+
};
|
|
3947
|
+
}
|
|
3948
|
+
function FloPayAutomaticPaymentButton({
|
|
3949
|
+
sessionId,
|
|
3950
|
+
createSession,
|
|
3951
|
+
paymentMethodId,
|
|
3952
|
+
clientId,
|
|
3953
|
+
items,
|
|
3954
|
+
subscriptions,
|
|
3955
|
+
account,
|
|
3956
|
+
successUrl,
|
|
3957
|
+
cancelUrl,
|
|
3958
|
+
couponCodes,
|
|
3959
|
+
tagsData,
|
|
3960
|
+
utmMetadata,
|
|
3961
|
+
billingApiUrl,
|
|
3962
|
+
locale,
|
|
3963
|
+
fallbackPublishableKey,
|
|
3964
|
+
buttonsTheme,
|
|
3965
|
+
buttonsStyles: stylesOverride,
|
|
3966
|
+
onSuccess,
|
|
3967
|
+
onError,
|
|
3968
|
+
onDecline,
|
|
3969
|
+
children,
|
|
3970
|
+
disabled = false,
|
|
3971
|
+
type = "button",
|
|
3972
|
+
style,
|
|
3973
|
+
...buttonProps
|
|
3974
|
+
}) {
|
|
3975
|
+
const resolvedBillingUrl = (0, import_react11.useMemo)(
|
|
3976
|
+
() => (0, import_shared10.resolveBillingApiUrl)(billingApiUrl),
|
|
3977
|
+
[billingApiUrl]
|
|
3978
|
+
);
|
|
3979
|
+
const createSessionDraft = (0, import_react11.useMemo)(
|
|
3980
|
+
() => resolveCreateSessionDraft({
|
|
3981
|
+
createSession,
|
|
3982
|
+
clientId,
|
|
3983
|
+
items,
|
|
3984
|
+
subscriptions,
|
|
3985
|
+
account,
|
|
3986
|
+
successUrl,
|
|
3987
|
+
cancelUrl,
|
|
3988
|
+
couponCodes,
|
|
3989
|
+
tagsData,
|
|
3990
|
+
utmMetadata
|
|
3991
|
+
}),
|
|
3992
|
+
[
|
|
3993
|
+
account,
|
|
3994
|
+
cancelUrl,
|
|
3995
|
+
clientId,
|
|
3996
|
+
couponCodes,
|
|
3997
|
+
createSession,
|
|
3998
|
+
items,
|
|
3999
|
+
subscriptions,
|
|
4000
|
+
successUrl,
|
|
4001
|
+
tagsData,
|
|
4002
|
+
utmMetadata
|
|
4003
|
+
]
|
|
4004
|
+
);
|
|
4005
|
+
const [isProcessing, setIsProcessing] = (0, import_react11.useState)(false);
|
|
4006
|
+
const [overlayStatus, setOverlayStatus] = (0, import_react11.useState)(null);
|
|
4007
|
+
const [overlayError, setOverlayError] = (0, import_react11.useState)(null);
|
|
4008
|
+
const [fallbackSession, setFallbackSession] = (0, import_react11.useState)(null);
|
|
4009
|
+
const automaticPaymentToken = (0, import_react11.useMemo)(
|
|
4010
|
+
() => paymentMethodId ? {
|
|
4011
|
+
id: paymentMethodId,
|
|
4012
|
+
type: "card"
|
|
4013
|
+
} : void 0,
|
|
4014
|
+
[paymentMethodId]
|
|
4015
|
+
);
|
|
4016
|
+
const isMountedRef = (0, import_react11.useRef)(true);
|
|
4017
|
+
const resumeAttemptedRef = (0, import_react11.useRef)(false);
|
|
4018
|
+
const fallbackSessionRef = (0, import_react11.useRef)(fallbackSession);
|
|
4019
|
+
const onSuccessRef = (0, import_react11.useRef)(onSuccess);
|
|
4020
|
+
const onErrorRef = (0, import_react11.useRef)(onError);
|
|
4021
|
+
const onDeclineRef = (0, import_react11.useRef)(onDecline);
|
|
4022
|
+
(0, import_react11.useEffect)(() => {
|
|
4023
|
+
fallbackSessionRef.current = fallbackSession;
|
|
4024
|
+
}, [fallbackSession]);
|
|
4025
|
+
(0, import_react11.useEffect)(() => {
|
|
4026
|
+
onSuccessRef.current = onSuccess;
|
|
4027
|
+
}, [onSuccess]);
|
|
4028
|
+
(0, import_react11.useEffect)(() => {
|
|
4029
|
+
onErrorRef.current = onError;
|
|
4030
|
+
}, [onError]);
|
|
4031
|
+
(0, import_react11.useEffect)(() => {
|
|
4032
|
+
onDeclineRef.current = onDecline;
|
|
4033
|
+
}, [onDecline]);
|
|
4034
|
+
(0, import_react11.useEffect)(() => {
|
|
4035
|
+
isMountedRef.current = true;
|
|
4036
|
+
return () => {
|
|
4037
|
+
isMountedRef.current = false;
|
|
4038
|
+
};
|
|
4039
|
+
}, []);
|
|
4040
|
+
(0, import_react11.useEffect)(() => {
|
|
4041
|
+
if (!fallbackSession || typeof window === "undefined") {
|
|
4042
|
+
return;
|
|
4043
|
+
}
|
|
4044
|
+
const handleKeyDown = (event) => {
|
|
4045
|
+
if (event.key === "Escape") {
|
|
4046
|
+
setFallbackSession(null);
|
|
4047
|
+
}
|
|
4048
|
+
};
|
|
4049
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4050
|
+
return () => {
|
|
4051
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
4052
|
+
};
|
|
4053
|
+
}, [fallbackSession]);
|
|
4054
|
+
const emitDecline = (0, import_react11.useCallback)((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
|
|
4055
|
+
onDeclineRef.current?.(buildDeclineEvent(method, error, {
|
|
4056
|
+
code: error.code,
|
|
4057
|
+
declineCode: error.declineCode
|
|
4058
|
+
}));
|
|
4059
|
+
}, []);
|
|
4060
|
+
const showSuccess = (0, import_react11.useCallback)(async (event) => {
|
|
4061
|
+
if (!isMountedRef.current) return;
|
|
4062
|
+
setOverlayError(null);
|
|
4063
|
+
setOverlayStatus("success");
|
|
4064
|
+
await sleep2(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
4065
|
+
if (!isMountedRef.current) return;
|
|
4066
|
+
onSuccessRef.current?.(event);
|
|
4067
|
+
}, []);
|
|
4068
|
+
const showError = (0, import_react11.useCallback)(async (error, options) => {
|
|
4069
|
+
if (!isMountedRef.current) return;
|
|
4070
|
+
onErrorRef.current?.(error);
|
|
4071
|
+
if (options?.emitDecline) {
|
|
4072
|
+
emitDecline(error, options.method);
|
|
4073
|
+
}
|
|
4074
|
+
setOverlayError(error.message);
|
|
4075
|
+
setOverlayStatus("error");
|
|
4076
|
+
await sleep2(PROCESSING_OVERLAY_ERROR_DELAY_MS);
|
|
4077
|
+
}, [emitDecline]);
|
|
4078
|
+
const processResolvedSession = (0, import_react11.useCallback)(async (apiResult, resolvedSessionId) => {
|
|
4079
|
+
const session = apiResult.data.session ?? null;
|
|
4080
|
+
if (!session) {
|
|
4081
|
+
throw new import_shared10.FloPayError("No session data returned", "api_error");
|
|
4082
|
+
}
|
|
4083
|
+
if (session.status === "complete") {
|
|
4084
|
+
await showSuccess({
|
|
4085
|
+
result: { status: "succeeded" },
|
|
4086
|
+
session,
|
|
4087
|
+
sessionId: session.id || resolvedSessionId,
|
|
4088
|
+
autoCompleted: false
|
|
4089
|
+
});
|
|
4090
|
+
return;
|
|
4091
|
+
}
|
|
4092
|
+
try {
|
|
4093
|
+
const result = await processSavedPaymentForMode({
|
|
4094
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4095
|
+
sessionId: resolvedSessionId ?? session.id,
|
|
4096
|
+
session,
|
|
4097
|
+
tokenizedData: automaticPaymentToken
|
|
4098
|
+
});
|
|
4099
|
+
let paymentResult = result.type === "success" ? result.result : null;
|
|
4100
|
+
if (result.type !== "success") {
|
|
4101
|
+
const {
|
|
4102
|
+
publishableKey,
|
|
4103
|
+
paypalPublishableKey
|
|
4104
|
+
} = resolveSavedPaymentPublishableKeys(apiResult, fallbackPublishableKey);
|
|
4105
|
+
if (result.type === "paypal_redirect_required") {
|
|
4106
|
+
persistPayPalResumeState({
|
|
4107
|
+
sessionId: session.id || resolvedSessionId,
|
|
4108
|
+
publishableKey,
|
|
4109
|
+
paypalPublishableKey
|
|
4110
|
+
});
|
|
4111
|
+
}
|
|
4112
|
+
const {
|
|
4113
|
+
flopay,
|
|
4114
|
+
paypalFlopay
|
|
4115
|
+
} = await loadSavedPaymentProviders({
|
|
4116
|
+
publishableKey,
|
|
4117
|
+
paypalPublishableKey,
|
|
4118
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4119
|
+
locale
|
|
4120
|
+
});
|
|
4121
|
+
paymentResult = await handleSavedPaymentRedirectResult(result, {
|
|
4122
|
+
flopay,
|
|
4123
|
+
paypalFlopay,
|
|
4124
|
+
attempt3DS: true,
|
|
4125
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4126
|
+
sessionId: session.id || resolvedSessionId,
|
|
4127
|
+
session
|
|
4128
|
+
});
|
|
4129
|
+
if (result.type === "paypal_redirect_required") {
|
|
4130
|
+
clearPayPalResumeState();
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4133
|
+
await showSuccess({
|
|
4134
|
+
result: paymentResult ? {
|
|
4135
|
+
...paymentResult,
|
|
4136
|
+
paymentMethodId: paymentResult.paymentMethodId ?? paymentMethodId
|
|
4137
|
+
} : {
|
|
4138
|
+
status: "succeeded",
|
|
4139
|
+
paymentMethodId: paymentMethodId ?? void 0
|
|
4140
|
+
},
|
|
4141
|
+
session,
|
|
4142
|
+
sessionId: session.id || resolvedSessionId,
|
|
4143
|
+
autoCompleted: false
|
|
4144
|
+
});
|
|
4145
|
+
} catch (err) {
|
|
4146
|
+
let floPayErr = normalizeSavedPaymentError(err);
|
|
4147
|
+
const fallbackSessionId = session.id || resolvedSessionId;
|
|
4148
|
+
if (floPayErr.code === "authentication_required" && fallbackSessionId && automaticPaymentToken?.id && automaticPaymentToken.id.startsWith("pm_")) {
|
|
4149
|
+
try {
|
|
4150
|
+
const {
|
|
4151
|
+
publishableKey,
|
|
4152
|
+
paypalPublishableKey
|
|
4153
|
+
} = resolveSavedPaymentPublishableKeys(apiResult, fallbackPublishableKey);
|
|
4154
|
+
const {
|
|
4155
|
+
flopay
|
|
4156
|
+
} = await loadSavedPaymentProviders({
|
|
4157
|
+
publishableKey,
|
|
4158
|
+
paypalPublishableKey,
|
|
4159
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4160
|
+
locale
|
|
4161
|
+
});
|
|
4162
|
+
const paymentResult = await processSavedPaymentWithIntent({
|
|
4163
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4164
|
+
sessionId: fallbackSessionId,
|
|
4165
|
+
session,
|
|
4166
|
+
paymentMethodId: automaticPaymentToken.id,
|
|
4167
|
+
flopay
|
|
4168
|
+
});
|
|
4169
|
+
await showSuccess({
|
|
4170
|
+
result: {
|
|
4171
|
+
...paymentResult,
|
|
4172
|
+
paymentMethodId: paymentResult.paymentMethodId ?? paymentMethodId
|
|
4173
|
+
},
|
|
4174
|
+
session,
|
|
4175
|
+
sessionId: fallbackSessionId,
|
|
4176
|
+
autoCompleted: false
|
|
4177
|
+
});
|
|
4178
|
+
return;
|
|
4179
|
+
} catch (intentRecoveryErr) {
|
|
4180
|
+
floPayErr = normalizeSavedPaymentError(intentRecoveryErr);
|
|
4181
|
+
}
|
|
4182
|
+
}
|
|
4183
|
+
await showError(floPayErr, {
|
|
4184
|
+
emitDecline: true,
|
|
4185
|
+
method: floPayErr.checkoutMethod ?? DEFAULT_SAVED_PAYMENT_DECLINE_METHOD
|
|
4186
|
+
});
|
|
4187
|
+
if (shouldShowFallbackCheckout(floPayErr, fallbackSessionId) && fallbackSessionId && isMountedRef.current) {
|
|
4188
|
+
setFallbackSession({
|
|
4189
|
+
sessionId: fallbackSessionId,
|
|
4190
|
+
errorMessage: floPayErr.message
|
|
4191
|
+
});
|
|
4192
|
+
}
|
|
4193
|
+
}
|
|
4194
|
+
}, [
|
|
4195
|
+
fallbackPublishableKey,
|
|
4196
|
+
locale,
|
|
4197
|
+
automaticPaymentToken,
|
|
4198
|
+
paymentMethodId,
|
|
4199
|
+
resolvedBillingUrl,
|
|
4200
|
+
showError,
|
|
4201
|
+
showSuccess
|
|
4202
|
+
]);
|
|
4203
|
+
const handleButtonClick = (0, import_react11.useCallback)(async (event) => {
|
|
4204
|
+
buttonProps.onClick?.(event);
|
|
4205
|
+
if (event.defaultPrevented || disabled || isProcessing) {
|
|
4206
|
+
return;
|
|
4207
|
+
}
|
|
4208
|
+
setFallbackSession(null);
|
|
4209
|
+
if (sessionId && createSessionDraft) {
|
|
4210
|
+
const error = new import_shared10.FloPayError(
|
|
4211
|
+
"Provide either sessionId or create-session props, not both.",
|
|
4212
|
+
"validation_error"
|
|
4213
|
+
);
|
|
4214
|
+
await showError(error);
|
|
4215
|
+
if (isMountedRef.current) {
|
|
4216
|
+
setOverlayStatus(null);
|
|
4217
|
+
setOverlayError(null);
|
|
4218
|
+
}
|
|
4219
|
+
return;
|
|
4220
|
+
}
|
|
4221
|
+
if (!sessionId && !createSessionDraft) {
|
|
4222
|
+
const error = new import_shared10.FloPayError(
|
|
4223
|
+
"Provide a sessionId or the props required to create an automatic payment session.",
|
|
4224
|
+
"validation_error"
|
|
4225
|
+
);
|
|
4226
|
+
await showError(error);
|
|
4227
|
+
if (isMountedRef.current) {
|
|
4228
|
+
setOverlayStatus(null);
|
|
4229
|
+
setOverlayError(null);
|
|
4230
|
+
}
|
|
4231
|
+
return;
|
|
4232
|
+
}
|
|
4233
|
+
setIsProcessing(true);
|
|
4234
|
+
setOverlayError(null);
|
|
4235
|
+
setOverlayStatus("processing");
|
|
4236
|
+
try {
|
|
4237
|
+
const api = new import_js3.PaymentAPI(resolvedBillingUrl);
|
|
4238
|
+
if (sessionId) {
|
|
4239
|
+
const result = await api.getUnifiedCheckoutSession(sessionId);
|
|
4240
|
+
await processResolvedSession(result, sessionId);
|
|
4241
|
+
return;
|
|
4242
|
+
}
|
|
4243
|
+
try {
|
|
4244
|
+
const result = await api.createAndFetchSession(createSessionDraft);
|
|
4245
|
+
await processResolvedSession(result, result.data.session?.id ?? null);
|
|
4246
|
+
} catch (err) {
|
|
4247
|
+
if (err instanceof import_shared10.FloPayError && err.code === "session_auto_completed") {
|
|
4248
|
+
await showSuccess({
|
|
4249
|
+
result: { status: "succeeded" },
|
|
4250
|
+
session: null,
|
|
4251
|
+
sessionId: null,
|
|
4252
|
+
autoCompleted: true
|
|
4253
|
+
});
|
|
4254
|
+
return;
|
|
4255
|
+
}
|
|
4256
|
+
throw err;
|
|
4257
|
+
}
|
|
4258
|
+
} catch (err) {
|
|
4259
|
+
await showError(
|
|
4260
|
+
coerceError(err, "Automatic payment failed. Please try again.")
|
|
4261
|
+
);
|
|
4262
|
+
} finally {
|
|
4263
|
+
if (isMountedRef.current) {
|
|
4264
|
+
setOverlayStatus(null);
|
|
4265
|
+
setOverlayError(null);
|
|
4266
|
+
setIsProcessing(false);
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4269
|
+
}, [
|
|
4270
|
+
buttonProps,
|
|
4271
|
+
createSessionDraft,
|
|
4272
|
+
disabled,
|
|
4273
|
+
isProcessing,
|
|
4274
|
+
processResolvedSession,
|
|
4275
|
+
resolvedBillingUrl,
|
|
4276
|
+
sessionId,
|
|
4277
|
+
showError,
|
|
4278
|
+
showSuccess
|
|
4279
|
+
]);
|
|
4280
|
+
const handleFallbackComplete = (0, import_react11.useCallback)((result) => {
|
|
4281
|
+
const activeFallback = fallbackSessionRef.current;
|
|
4282
|
+
setFallbackSession(null);
|
|
4283
|
+
onSuccessRef.current?.({
|
|
4284
|
+
result,
|
|
4285
|
+
session: null,
|
|
4286
|
+
sessionId: activeFallback?.sessionId ?? null,
|
|
4287
|
+
autoCompleted: false
|
|
4288
|
+
});
|
|
4289
|
+
}, []);
|
|
4290
|
+
const handleFallbackError = (0, import_react11.useCallback)((error) => {
|
|
4291
|
+
onErrorRef.current?.(error);
|
|
4292
|
+
}, []);
|
|
4293
|
+
const handleFallbackDecline = (0, import_react11.useCallback)((decline) => {
|
|
4294
|
+
onDeclineRef.current?.(decline);
|
|
4295
|
+
}, []);
|
|
4296
|
+
(0, import_react11.useEffect)(() => {
|
|
4297
|
+
if (typeof window === "undefined" || resumeAttemptedRef.current) {
|
|
4298
|
+
return;
|
|
4299
|
+
}
|
|
4300
|
+
const params = new URLSearchParams(window.location.search);
|
|
4301
|
+
const clientSecret = params.get("payment_intent_client_secret");
|
|
4302
|
+
if (!clientSecret) {
|
|
4303
|
+
return;
|
|
4304
|
+
}
|
|
4305
|
+
const resumeState = readPayPalResumeState();
|
|
4306
|
+
if (!resumeState) {
|
|
4307
|
+
return;
|
|
4308
|
+
}
|
|
4309
|
+
resumeAttemptedRef.current = true;
|
|
4310
|
+
void (async () => {
|
|
4311
|
+
setIsProcessing(true);
|
|
4312
|
+
setOverlayError(null);
|
|
4313
|
+
setOverlayStatus("processing");
|
|
4314
|
+
try {
|
|
4315
|
+
if (params.get("redirect_status") === "failed") {
|
|
4316
|
+
throw Object.assign(
|
|
4317
|
+
new import_shared10.FloPayError("PayPal payment was declined. Please try again.", "api_error"),
|
|
4318
|
+
{ checkoutMethod: "paypal" }
|
|
4319
|
+
);
|
|
4320
|
+
}
|
|
4321
|
+
const {
|
|
4322
|
+
flopay,
|
|
4323
|
+
paypalFlopay
|
|
4324
|
+
} = await loadSavedPaymentProviders({
|
|
4325
|
+
publishableKey: resumeState.publishableKey,
|
|
4326
|
+
paypalPublishableKey: resumeState.paypalPublishableKey,
|
|
4327
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4328
|
+
locale
|
|
4329
|
+
});
|
|
4330
|
+
const paypalStripe = (paypalFlopay ?? flopay).getRawProvider();
|
|
4331
|
+
if (!paypalStripe) {
|
|
4332
|
+
throw Object.assign(
|
|
4333
|
+
new import_shared10.FloPayError("PayPal is not available.", "api_error"),
|
|
4334
|
+
{ checkoutMethod: "paypal" }
|
|
4335
|
+
);
|
|
4336
|
+
}
|
|
4337
|
+
const { paymentIntent, error } = await paypalStripe.retrievePaymentIntent(clientSecret);
|
|
4338
|
+
if (error) {
|
|
4339
|
+
throw Object.assign(
|
|
4340
|
+
new import_shared10.FloPayError(
|
|
4341
|
+
error.message ?? "Failed to retrieve PayPal payment status.",
|
|
4342
|
+
"api_error",
|
|
4343
|
+
{ code: error.code }
|
|
4344
|
+
),
|
|
4345
|
+
{ checkoutMethod: "paypal" }
|
|
4346
|
+
);
|
|
4347
|
+
}
|
|
4348
|
+
if (paymentIntent && (paymentIntent.status === "requires_capture" || paymentIntent.status === "succeeded" || paymentIntent.status === "processing")) {
|
|
4349
|
+
await showSuccess({
|
|
4350
|
+
result: { status: "succeeded", paymentIntentId: paymentIntent.id },
|
|
4351
|
+
session: null,
|
|
4352
|
+
sessionId: resumeState.sessionId,
|
|
4353
|
+
autoCompleted: false
|
|
4354
|
+
});
|
|
4355
|
+
} else {
|
|
4356
|
+
throw Object.assign(
|
|
4357
|
+
new import_shared10.FloPayError("PayPal payment was not completed. Please try again.", "api_error"),
|
|
4358
|
+
{ checkoutMethod: "paypal" }
|
|
4359
|
+
);
|
|
4360
|
+
}
|
|
4361
|
+
} catch (err) {
|
|
4362
|
+
const floPayErr = normalizeSavedPaymentError(err);
|
|
4363
|
+
await showError(floPayErr, {
|
|
4364
|
+
emitDecline: true,
|
|
4365
|
+
method: floPayErr.checkoutMethod ?? "paypal"
|
|
4366
|
+
});
|
|
4367
|
+
} finally {
|
|
4368
|
+
clearPayPalResumeState();
|
|
4369
|
+
clearPayPalRedirectParams();
|
|
4370
|
+
if (isMountedRef.current) {
|
|
4371
|
+
setOverlayStatus(null);
|
|
4372
|
+
setOverlayError(null);
|
|
4373
|
+
setIsProcessing(false);
|
|
4374
|
+
}
|
|
4375
|
+
}
|
|
4376
|
+
})();
|
|
4377
|
+
}, [locale, resolvedBillingUrl, showError, showSuccess]);
|
|
4378
|
+
const bStyles = (0, import_react11.useMemo)(() => {
|
|
4379
|
+
const base = (0, import_shared10.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
4380
|
+
if (!stylesOverride) return base;
|
|
4381
|
+
return {
|
|
4382
|
+
...base,
|
|
4383
|
+
...stylesOverride,
|
|
4384
|
+
cardButton: { ...base.cardButton, ...stylesOverride.cardButton }
|
|
4385
|
+
};
|
|
4386
|
+
}, [buttonsTheme, stylesOverride]);
|
|
4387
|
+
const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
4388
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
4389
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4390
|
+
"button",
|
|
4391
|
+
{
|
|
4392
|
+
...buttonProps,
|
|
4393
|
+
type,
|
|
4394
|
+
onClick: handleButtonClick,
|
|
4395
|
+
disabled: disabled || isProcessing,
|
|
4396
|
+
"aria-busy": isProcessing,
|
|
4397
|
+
style: {
|
|
4398
|
+
width: "100%",
|
|
4399
|
+
...cardButtonSizing,
|
|
4400
|
+
backgroundColor: "white",
|
|
4401
|
+
color: "#262833",
|
|
4402
|
+
border: "1px solid #d1d5db",
|
|
4403
|
+
borderRadius: "8px",
|
|
4404
|
+
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
4405
|
+
fontWeight: 600,
|
|
4406
|
+
cursor: disabled || isProcessing ? "not-allowed" : "pointer",
|
|
4407
|
+
display: "flex",
|
|
4408
|
+
alignItems: "center",
|
|
4409
|
+
justifyContent: "center",
|
|
4410
|
+
gap: "0.625rem",
|
|
4411
|
+
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
4412
|
+
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
4413
|
+
position: "relative",
|
|
4414
|
+
opacity: disabled || isProcessing ? 0.6 : 1,
|
|
4415
|
+
...bStyles.cardButton,
|
|
4416
|
+
...style
|
|
4417
|
+
},
|
|
4418
|
+
onMouseDown: (e) => {
|
|
4419
|
+
buttonProps.onMouseDown?.(e);
|
|
4420
|
+
if (!e.defaultPrevented) {
|
|
4421
|
+
e.currentTarget.style.transform = "scale(0.985)";
|
|
4422
|
+
}
|
|
4423
|
+
},
|
|
4424
|
+
onMouseUp: (e) => {
|
|
4425
|
+
buttonProps.onMouseUp?.(e);
|
|
4426
|
+
if (!e.defaultPrevented) {
|
|
4427
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
4428
|
+
}
|
|
4429
|
+
},
|
|
4430
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CardButtonContentSlot, { content: children })
|
|
4431
|
+
}
|
|
4432
|
+
),
|
|
4433
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4434
|
+
ProcessingOverlay,
|
|
4435
|
+
{
|
|
4436
|
+
status: overlayStatus,
|
|
4437
|
+
errorMessage: overlayError
|
|
4438
|
+
}
|
|
4439
|
+
),
|
|
4440
|
+
fallbackSession && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4441
|
+
"div",
|
|
4442
|
+
{
|
|
4443
|
+
"data-testid": "flopay-automatic-payment-fallback",
|
|
4444
|
+
role: "dialog",
|
|
4445
|
+
"aria-modal": "true",
|
|
4446
|
+
onClick: (event) => {
|
|
4447
|
+
if (event.target === event.currentTarget) {
|
|
4448
|
+
setFallbackSession(null);
|
|
4449
|
+
}
|
|
4450
|
+
},
|
|
4451
|
+
style: {
|
|
4452
|
+
position: "fixed",
|
|
4453
|
+
inset: 0,
|
|
4454
|
+
background: "rgba(0, 0, 0, 0.45)",
|
|
4455
|
+
display: "flex",
|
|
4456
|
+
alignItems: "center",
|
|
4457
|
+
justifyContent: "center",
|
|
4458
|
+
padding: "1.5rem",
|
|
4459
|
+
zIndex: 1100
|
|
4460
|
+
},
|
|
4461
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4462
|
+
"div",
|
|
4463
|
+
{
|
|
4464
|
+
style: {
|
|
4465
|
+
width: "100%",
|
|
4466
|
+
maxWidth: 520,
|
|
4467
|
+
maxHeight: "90vh",
|
|
4468
|
+
overflowY: "auto",
|
|
4469
|
+
background: "white",
|
|
4470
|
+
borderRadius: 20,
|
|
4471
|
+
padding: "1.5rem",
|
|
4472
|
+
boxShadow: "0 24px 80px rgba(15, 23, 42, 0.28)",
|
|
4473
|
+
display: "flex",
|
|
4474
|
+
flexDirection: "column",
|
|
4475
|
+
gap: "1rem"
|
|
4476
|
+
},
|
|
4477
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4478
|
+
FloPayCheckout,
|
|
4479
|
+
{
|
|
4480
|
+
sessionId: fallbackSession.sessionId,
|
|
4481
|
+
checkoutMode: "full",
|
|
4482
|
+
billingApiUrl: resolvedBillingUrl,
|
|
4483
|
+
fallbackPublishableKey,
|
|
4484
|
+
initialErrorMessage: fallbackSession.errorMessage,
|
|
4485
|
+
cardTitleContent: null,
|
|
4486
|
+
showSecurityFooter: false,
|
|
4487
|
+
onComplete: handleFallbackComplete,
|
|
4488
|
+
onError: handleFallbackError,
|
|
4489
|
+
onDecline: handleFallbackDecline
|
|
4490
|
+
}
|
|
4491
|
+
)
|
|
4492
|
+
}
|
|
4493
|
+
)
|
|
4494
|
+
}
|
|
4495
|
+
)
|
|
4496
|
+
] });
|
|
4497
|
+
}
|
|
3303
4498
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3304
4499
|
0 && (module.exports = {
|
|
3305
4500
|
AddressElement,
|
|
@@ -3308,6 +4503,7 @@ function PayPalButton({
|
|
|
3308
4503
|
CardExpiryElement,
|
|
3309
4504
|
CardNumberElement,
|
|
3310
4505
|
CheckoutForm,
|
|
4506
|
+
FloPayAutomaticPaymentButton,
|
|
3311
4507
|
FloPayCheckout,
|
|
3312
4508
|
FloPayProvider,
|
|
3313
4509
|
PayPalButton,
|